mirror of
https://github.com/danielmiessler/Fabric.git
synced 2026-01-09 14:28:01 -05:00
- 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
101 lines
3.9 KiB
Go
101 lines
3.9 KiB
Go
package restapi
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/danielmiessler/fabric/internal/core"
|
|
"github.com/danielmiessler/fabric/internal/tools/youtube"
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type YouTubeHandler struct {
|
|
yt *youtube.YouTube
|
|
}
|
|
|
|
// YouTubeRequest represents a request to get a YouTube video transcript
|
|
type YouTubeRequest struct {
|
|
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" 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 {
|
|
handler := &YouTubeHandler{yt: registry.YouTube}
|
|
r.POST("/youtube/transcript", handler.Transcript)
|
|
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 {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"})
|
|
return
|
|
}
|
|
if req.URL == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "url is required"})
|
|
return
|
|
}
|
|
language := req.Language
|
|
if language == "" {
|
|
language = "en"
|
|
}
|
|
|
|
var videoID, playlistID string
|
|
var err error
|
|
if videoID, playlistID, err = h.yt.GetVideoOrPlaylistId(req.URL); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
if videoID == "" && playlistID != "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "URL is a playlist, not a video"})
|
|
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)
|
|
} else {
|
|
transcript, err = h.yt.GrabTranscript(videoID, language)
|
|
}
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, YouTubeResponse{Transcript: transcript, VideoId: videoID, Title: title, Description: description})
|
|
}
|