Compare commits

...

12 Commits

Author SHA1 Message Date
github-actions[bot]
fe0a173166 chore(release): Update version to v1.4.355 2025-12-20 07:58:09 +00:00
Kayvan Sylvan
a916137db3 Merge pull request #1890 from ksylvan/kayvan/fix-nix-flake-to-add-yt-dlp
Bundle yt-dlp with fabric in Nix flake, introduce slim variant
2025-12-19 23:55:46 -08:00
Kayvan Sylvan
333c8cd363 feat: Nix: bundle yt-dlp with fabric package + fabric-slim variant
- rename original fabric package to fabricSlim
- create fabric package as symlinkJoin of fabricSlim and yt-dlp
- add fabric-slim output for the slim variant
- update default package to point to bundled fabric
- enhance fabric meta description to note yt-dlp inclusion
- set mainProgram to fabric in bundled package
2025-12-19 23:34:19 -08:00
github-actions[bot]
294a4635de chore(release): Update version to v1.4.354 2025-12-19 18:47:36 +00:00
Kayvan Sylvan
a70431eaa5 Merge pull request #1889 from ksylvan/kayvan/add-youtube-trabscription-to-swagger
docs: Add a YouTube transcript endpoint to the Swagger UI.
2025-12-19 10:44:47 -08:00
Changelog Bot
ac57c3d2b0 chore: incoming 1889 changelog entry 2025-12-19 10:42:38 -08:00
Kayvan Sylvan
5e4e4f4bf1 docs: Add YouTube transcript endpoint to Swagger UI.
- Add `/youtube/transcript` POST endpoint to Swagger docs
- Define `YouTubeRequest` schema with URL, language, timestamps fields
- Define `YouTubeResponse` schema with transcript and metadata fields
- Add API security requirement using ApiKeyAuth
- Document 200, 400, and 500 response codes
- Add godoc comments to YouTubeHandler struct methods
- Include example values for all request/response properties
2025-12-19 10:41:55 -08:00
github-actions[bot]
96225d4aea chore(release): Update version to v1.4.353 2025-12-19 16:21:50 +00:00
Kayvan Sylvan
adcdc0cf0b Merge pull request #1887 from bvandevliet/feat/yt-title-and-description
feat: correct video title and added description to yt transcript api response
2025-12-19 08:19:15 -08:00
Changelog Bot
e3f9b12fde chore: incoming 1887 changelog entry 2025-12-19 08:16:18 -08:00
Bob Vandevliet
7fa4c0a030 Updated API documentation. 2025-12-19 13:23:44 +01:00
Bob Vandevliet
8a3fa9337c feat: correct video title (instead of id) and added description to yt transcript api response 2025-12-19 13:14:12 +01:00
10 changed files with 376 additions and 12 deletions

View File

@@ -1,5 +1,32 @@
# Changelog
## v1.4.355 (2025-12-20)
### PR [#1890](https://github.com/danielmiessler/Fabric/pull/1890) by [ksylvan](https://github.com/ksylvan): Bundle yt-dlp with fabric in Nix flake, introduce slim variant
- Added yt-dlp bundling with fabric package and introduced fabric-slim variant
- Renamed original fabric package to fabricSlim and created new fabric package as symlinkJoin of fabricSlim and yt-dlp
- Added fabric-slim output for the slim variant and updated default package to point to bundled fabric
- Enhanced fabric meta description to note yt-dlp inclusion and set mainProgram to fabric in bundled package
- Added wrapper for fabric binary to include PATH in execution environment
## v1.4.354 (2025-12-19)
### PR [#1889](https://github.com/danielmiessler/Fabric/pull/1889) by [ksylvan](https://github.com/ksylvan): docs: Add a YouTube transcript endpoint to the Swagger UI
- Add `/youtube/transcript` POST endpoint to Swagger docs
- Define `YouTubeRequest` schema with URL, language, timestamps fields
- Define `YouTubeResponse` schema with transcript and metadata fields
- Add API security requirement using ApiKeyAuth
- Document 200, 400, and 500 response codes
## v1.4.353 (2025-12-19)
### PR [#1887](https://github.com/danielmiessler/Fabric/pull/1887) by [bvandevliet](https://github.com/bvandevliet): feat: correct video title and added description to yt transcript api response
- Feat: correct video title (instead of id) and added description to yt transcript api response
- Updated API documentation.
## v1.4.352 (2025-12-18)
### PR [#1886](https://github.com/danielmiessler/Fabric/pull/1886) by [ksylvan](https://github.com/ksylvan): Enhanced Onboarding and Setup Experience

View File

@@ -1,3 +1,3 @@
package main
var version = "v1.4.352"
var version = "v1.4.355"

Binary file not shown.

View File

@@ -214,6 +214,63 @@ const docTemplate = `{
}
}
}
},
"/youtube/transcript": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "Retrieves the transcript of a YouTube video along with video metadata (title and description)",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"youtube"
],
"summary": "Get YouTube video transcript",
"parameters": [
{
"description": "YouTube transcript request with URL, language, and timestamp options",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/restapi.YouTubeRequest"
}
}
],
"responses": {
"200": {
"description": "Successful response with transcript and metadata",
"schema": {
"$ref": "#/definitions/restapi.YouTubeResponse"
}
},
"400": {
"description": "Bad request - invalid URL or playlist URL provided",
"schema": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
},
"500": {
"description": "Internal server error - failed to retrieve transcript or metadata",
"schema": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
}
}
}
},
"definitions": {
@@ -401,6 +458,54 @@ const docTemplate = `{
"type": "string"
}
}
},
"restapi.YouTubeRequest": {
"type": "object",
"required": [
"url"
],
"properties": {
"language": {
"description": "Language code for transcript (default: \"en\")",
"type": "string",
"example": "en"
},
"timestamps": {
"description": "Include timestamps in the transcript (default: false)",
"type": "boolean",
"example": false
},
"url": {
"description": "YouTube video URL (required)",
"type": "string",
"example": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}
}
},
"restapi.YouTubeResponse": {
"type": "object",
"properties": {
"description": {
"description": "Video description from YouTube metadata",
"type": "string",
"example": "This is the video description from YouTube..."
},
"title": {
"description": "Video title from YouTube metadata",
"type": "string",
"example": "Example Video Title"
},
"transcript": {
"description": "The video transcript text",
"type": "string",
"example": "This is the video transcript..."
},
"videoId": {
"description": "YouTube video ID",
"type": "string",
"example": "dQw4w9WgXcQ"
}
}
}
},
"securityDefinitions": {

View File

@@ -278,7 +278,9 @@ Extract transcripts from YouTube videos.
```json
{
"videoId": "Video ID",
"title": "Video Title",
"description" : "Video description...",
"transcript": "Full transcript text..."
}
```
@@ -335,7 +337,9 @@ Response:
```json
{
"videoId": "dQw4w9WgXcQ",
"title": "Rick Astley - Never Gonna Give You Up (Official Video)",
"description": "The official video for “Never Gonna Give You Up” by Rick Astley...",
"transcript": "We're no strangers to love. You know the rules and so do I..."
}
```

View File

@@ -208,6 +208,63 @@
}
}
}
},
"/youtube/transcript": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "Retrieves the transcript of a YouTube video along with video metadata (title and description)",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"youtube"
],
"summary": "Get YouTube video transcript",
"parameters": [
{
"description": "YouTube transcript request with URL, language, and timestamp options",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/restapi.YouTubeRequest"
}
}
],
"responses": {
"200": {
"description": "Successful response with transcript and metadata",
"schema": {
"$ref": "#/definitions/restapi.YouTubeResponse"
}
},
"400": {
"description": "Bad request - invalid URL or playlist URL provided",
"schema": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
},
"500": {
"description": "Internal server error - failed to retrieve transcript or metadata",
"schema": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
}
}
}
},
"definitions": {
@@ -395,6 +452,54 @@
"type": "string"
}
}
},
"restapi.YouTubeRequest": {
"type": "object",
"required": [
"url"
],
"properties": {
"language": {
"description": "Language code for transcript (default: \"en\")",
"type": "string",
"example": "en"
},
"timestamps": {
"description": "Include timestamps in the transcript (default: false)",
"type": "boolean",
"example": false
},
"url": {
"description": "YouTube video URL (required)",
"type": "string",
"example": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}
}
},
"restapi.YouTubeResponse": {
"type": "object",
"properties": {
"description": {
"description": "Video description from YouTube metadata",
"type": "string",
"example": "This is the video description from YouTube..."
},
"title": {
"description": "Video title from YouTube metadata",
"type": "string",
"example": "Example Video Title"
},
"transcript": {
"description": "The video transcript text",
"type": "string",
"example": "This is the video transcript..."
},
"videoId": {
"description": "YouTube video ID",
"type": "string",
"example": "dQw4w9WgXcQ"
}
}
}
},
"securityDefinitions": {

View File

@@ -127,6 +127,42 @@ definitions:
description: '"content", "error", "complete"'
type: string
type: object
restapi.YouTubeRequest:
properties:
language:
description: 'Language code for transcript (default: "en")'
example: en
type: string
timestamps:
description: 'Include timestamps in the transcript (default: false)'
example: false
type: boolean
url:
description: YouTube video URL (required)
example: https://www.youtube.com/watch?v=dQw4w9WgXcQ
type: string
required:
- url
type: object
restapi.YouTubeResponse:
properties:
description:
description: Video description from YouTube metadata
example: This is the video description from YouTube...
type: string
title:
description: Video title from YouTube metadata
example: Example Video Title
type: string
transcript:
description: The video transcript text
example: This is the video transcript...
type: string
videoId:
description: YouTube video ID
example: dQw4w9WgXcQ
type: string
type: object
host: localhost:8080
info:
contact:
@@ -262,6 +298,44 @@ paths:
summary: Apply pattern with variables
tags:
- patterns
/youtube/transcript:
post:
consumes:
- application/json
description: Retrieves the transcript of a YouTube video along with video metadata
(title and description)
parameters:
- description: YouTube transcript request with URL, language, and timestamp
options
in: body
name: request
required: true
schema:
$ref: '#/definitions/restapi.YouTubeRequest'
produces:
- application/json
responses:
"200":
description: Successful response with transcript and metadata
schema:
$ref: '#/definitions/restapi.YouTubeResponse'
"400":
description: Bad request - invalid URL or playlist URL provided
schema:
additionalProperties:
type: string
type: object
"500":
description: Internal server error - failed to retrieve transcript or metadata
schema:
additionalProperties:
type: string
type: object
security:
- ApiKeyAuth: []
summary: Get YouTube video transcript
tags:
- youtube
securityDefinitions:
ApiKeyAuth:
in: header

View File

@@ -73,14 +73,33 @@
let
pkgs = nixpkgs.legacyPackages.${system};
goVersion = getGoVersion system;
in
{
default = self.packages.${system}.fabric;
fabric = pkgs.callPackage ./nix/pkgs/fabric {
fabricSlim = pkgs.callPackage ./nix/pkgs/fabric {
go = goVersion;
inherit self;
inherit (gomod2nix.legacyPackages.${system}) buildGoApplication;
};
fabric = pkgs.symlinkJoin {
name = "fabric-${fabricSlim.version}";
inherit (fabricSlim) version;
paths = [
fabricSlim
pkgs.yt-dlp
];
nativeBuildInputs = [ pkgs.makeWrapper ];
postBuild = ''
wrapProgram $out/bin/fabric \
--prefix PATH : $out/bin
'';
meta = fabricSlim.meta // {
description = "${fabricSlim.meta.description} (includes yt-dlp)";
mainProgram = "fabric";
};
};
in
{
default = fabric;
inherit fabric;
"fabric-slim" = fabricSlim;
inherit (gomod2nix.legacyPackages.${system}) gomod2nix;
}
);

View File

@@ -12,15 +12,19 @@ type YouTubeHandler struct {
yt *youtube.YouTube
}
// YouTubeRequest represents a request to get a YouTube video transcript
type YouTubeRequest struct {
URL string `json:"url"`
Language string `json:"language"`
Timestamps bool `json:"timestamps"`
URL string `json:"url" binding:"required" example:"https://www.youtube.com/watch?v=dQw4w9WgXcQ"` // YouTube video URL (required)
Language string `json:"language,omitempty" example:"en"` // Language code for transcript (default: "en")
Timestamps bool `json:"timestamps,omitempty" example:"false"` // Include timestamps in the transcript (default: false)
}
// YouTubeResponse represents the response containing video transcript and metadata
type YouTubeResponse struct {
Transcript string `json:"transcript"`
Title string `json:"title"`
Transcript string `json:"transcript" example:"This is the video transcript..."` // The video transcript text
VideoId string `json:"videoId" example:"dQw4w9WgXcQ"` // YouTube video ID
Title string `json:"title" example:"Example Video Title"` // Video title from YouTube metadata
Description string `json:"description" example:"This is the video description from YouTube..."` // Video description from YouTube metadata
}
func NewYouTubeHandler(r *gin.Engine, registry *core.PluginRegistry) *YouTubeHandler {
@@ -29,6 +33,18 @@ func NewYouTubeHandler(r *gin.Engine, registry *core.PluginRegistry) *YouTubeHan
return handler
}
// Transcript godoc
// @Summary Get YouTube video transcript
// @Description Retrieves the transcript of a YouTube video along with video metadata (title and description)
// @Tags youtube
// @Accept json
// @Produce json
// @Param request body YouTubeRequest true "YouTube transcript request with URL, language, and timestamp options"
// @Success 200 {object} YouTubeResponse "Successful response with transcript and metadata"
// @Failure 400 {object} map[string]string "Bad request - invalid URL or playlist URL provided"
// @Failure 500 {object} map[string]string "Internal server error - failed to retrieve transcript or metadata"
// @Security ApiKeyAuth
// @Router /youtube/transcript [post]
func (h *YouTubeHandler) Transcript(c *gin.Context) {
var req YouTubeRequest
if err := c.BindJSON(&req); err != nil {
@@ -55,6 +71,20 @@ func (h *YouTubeHandler) Transcript(c *gin.Context) {
return
}
// Try to get metadata (requires valid YouTube API key), but don't fail if unavailable
// This allows the endpoint to work for transcript extraction even without API key
var metadata *youtube.VideoMetadata
var title, description string
if metadata, err = h.yt.GrabMetadata(videoID); err == nil {
// Metadata available - use title and description from API
title = metadata.Title
description = metadata.Description
} else {
// No valid API key or metadata fetch failed - fallback to videoID as title
title = videoID
description = ""
}
var transcript string
if req.Timestamps {
transcript, err = h.yt.GrabTranscriptWithTimestamps(videoID, language)
@@ -66,5 +96,5 @@ func (h *YouTubeHandler) Transcript(c *gin.Context) {
return
}
c.JSON(http.StatusOK, YouTubeResponse{Transcript: transcript, Title: videoID})
c.JSON(http.StatusOK, YouTubeResponse{Transcript: transcript, VideoId: videoID, Title: title, Description: description})
}

View File

@@ -1 +1 @@
"1.4.352"
"1.4.355"