diff --git a/ext/instagram/util.go b/ext/instagram/util.go index 5691728..7cd9abd 100644 --- a/ext/instagram/util.go +++ b/ext/instagram/util.go @@ -58,8 +58,6 @@ func ParseGQLMedia( ctx *models.DownloadContext, data *Media, ) ([]*models.Media, error) { - var mediaList []*models.Media - var caption string if data.EdgeMediaToCaption != nil && len(data.EdgeMediaToCaption.Edges) > 0 { caption = data.EdgeMediaToCaption.Edges[0].Node.Text @@ -84,8 +82,7 @@ func ParseGQLMedia( Height: int64(data.Dimensions.Height), }) - mediaList = append(mediaList, media) - + return []*models.Media{media}, nil case "GraphImage", "XDTGraphImage": media := ctx.Extractor.NewMedia(contentID, contentURL) media.SetCaption(caption) @@ -96,12 +93,14 @@ func ParseGQLMedia( URL: []string{data.DisplayURL}, }) - mediaList = append(mediaList, media) - + return []*models.Media{media}, nil case "GraphSidecar", "XDTGraphSidecar": if data.EdgeSidecarToChildren != nil && len(data.EdgeSidecarToChildren.Edges) > 0 { - for _, edge := range data.EdgeSidecarToChildren.Edges { - node := edge.Node + edges := data.EdgeSidecarToChildren.Edges + mediaList := make([]*models.Media, 0, len(edges)) + + for i := range edges { + node := edges[i].Node media := ctx.Extractor.NewMedia(contentID, contentURL) media.SetCaption(caption) @@ -128,10 +127,11 @@ func ParseGQLMedia( mediaList = append(mediaList, media) } + return mediaList, nil } } - return mediaList, nil + return nil, fmt.Errorf("unknown media type: %s", data.Typename) } func ParseEmbedGQL( diff --git a/ext/ninegag/main.go b/ext/ninegag/main.go index 64b8a57..baf2b44 100644 --- a/ext/ninegag/main.go +++ b/ext/ninegag/main.go @@ -42,8 +42,6 @@ var Extractor = &models.Extractor{ } func MediaListFromAPI(ctx *models.DownloadContext) ([]*models.Media, error) { - var mediaList []*models.Media - contentID := ctx.MatchedContentID contentURL := ctx.MatchedContentURL @@ -84,12 +82,12 @@ func MediaListFromAPI(ctx *models.DownloadContext) ([]*models.Media, error) { media.AddFormat(format) } } - if len(media.Formats) > 0 { - mediaList = append(mediaList, media) + return []*models.Media{media}, nil } - return mediaList, nil + // no media found + return nil, nil } func GetPostData(postID string) (*Post, error) { diff --git a/ext/pinterest/main.go b/ext/pinterest/main.go index 5b03358..81e7a05 100644 --- a/ext/pinterest/main.go +++ b/ext/pinterest/main.go @@ -87,9 +87,9 @@ var Extractor = &models.Extractor{ func ExtractPinMedia(ctx *models.DownloadContext) ([]*models.Media, error) { pinID := ctx.MatchedContentID contentURL := ctx.MatchedContentURL - client := util.GetHTTPClient(ctx.Extractor.CodeName) + session := util.GetHTTPClient(ctx.Extractor.CodeName) - pinData, err := GetPinData(client, pinID) + pinData, err := GetPinData(session, pinID) if err != nil { return nil, err } @@ -160,7 +160,7 @@ func ExtractPinMedia(ctx *models.DownloadContext) ([]*models.Media, error) { } func GetPinData( - client models.HTTPClient, + session models.HTTPClient, pinID string, ) (*PinData, error) { params := BuildPinRequestParams(pinID) @@ -179,7 +179,7 @@ func GetPinData( // fix 403 error req.Header.Set("X-Pinterest-PWS-Handler", "www/[username].js") - resp, err := client.Do(req) + resp, err := session.Do(req) if err != nil { return nil, fmt.Errorf("failed to send request: %w", err) } diff --git a/ext/reddit/main.go b/ext/reddit/main.go index 6e59770..2d8c432 100644 --- a/ext/reddit/main.go +++ b/ext/reddit/main.go @@ -81,7 +81,7 @@ var Extractor = &models.Extractor{ } func MediaListFromAPI(ctx *models.DownloadContext) ([]*models.Media, error) { - client := util.GetHTTPClient(ctx.Extractor.CodeName) + session := util.GetHTTPClient(ctx.Extractor.CodeName) host := ctx.MatchedGroups["host"] slug := ctx.MatchedGroups["slug"] @@ -89,7 +89,7 @@ func MediaListFromAPI(ctx *models.DownloadContext) ([]*models.Media, error) { contentID := ctx.MatchedContentID contentURL := ctx.MatchedContentURL - manifest, err := GetRedditData(client, host, slug, false) + manifest, err := GetRedditData(session, host, slug, false) if err != nil { return nil, err } @@ -102,16 +102,12 @@ func MediaListFromAPI(ctx *models.DownloadContext) ([]*models.Media, error) { title := data.Title isNsfw := data.Over18 - var mediaList []*models.Media - if !data.IsVideo { // check for single photo if data.Preview != nil && len(data.Preview.Images) > 0 { media := ctx.Extractor.NewMedia(contentID, contentURL) media.SetCaption(title) - if isNsfw { - media.NSFW = true - } + media.NSFW = isNsfw image := data.Preview.Images[0] @@ -130,8 +126,7 @@ func MediaListFromAPI(ctx *models.DownloadContext) ([]*models.Media, error) { media.AddFormat(format) } - mediaList = append(mediaList, media) - return mediaList, nil + return []*models.Media{media}, nil } // check for MP4 variant (animated GIF) @@ -145,8 +140,7 @@ func MediaListFromAPI(ctx *models.DownloadContext) ([]*models.Media, error) { Thumbnail: []string{util.FixURL(image.Source.URL)}, }) - mediaList = append(mediaList, media) - return mediaList, nil + return []*models.Media{media}, nil } // regular photo @@ -156,39 +150,45 @@ func MediaListFromAPI(ctx *models.DownloadContext) ([]*models.Media, error) { URL: []string{util.FixURL(image.Source.URL)}, }) - mediaList = append(mediaList, media) - return mediaList, nil + return []*models.Media{media}, nil } // check for gallery/collection if len(data.MediaMetadata) > 0 { - for key, obj := range data.MediaMetadata { - if obj.E == "Image" { - media := ctx.Extractor.NewMedia(key, contentURL) - media.SetCaption(title) - if isNsfw { - media.NSFW = true - } + // known issue: collection is unordered + collection := data.MediaMetadata + mediaList := make([]*models.Media, 0, len(collection)) + for _, obj := range collection { + media := ctx.Extractor.NewMedia(contentID, contentURL) + media.SetCaption(title) + media.NSFW = isNsfw + + switch obj.Type { + case "Image": media.AddFormat(&models.MediaFormat{ FormatID: "photo", Type: enums.MediaTypePhoto, - URL: []string{util.FixURL(obj.S.U)}, + URL: []string{util.FixURL(obj.Media.URL)}, + }) + case "AnimatedImage": + media.AddFormat(&models.MediaFormat{ + FormatID: "video", + Type: enums.MediaTypeVideo, + VideoCodec: enums.MediaCodecAVC, + AudioCodec: enums.MediaCodecAAC, + URL: []string{util.FixURL(obj.Media.MP4)}, }) - - mediaList = append(mediaList, media) } + mediaList = append(mediaList, media) } - return mediaList, nil } } else { // video media := ctx.Extractor.NewMedia(contentID, contentURL) media.SetCaption(title) - if isNsfw { - media.NSFW = true - } + media.NSFW = isNsfw var redditVideo *Video @@ -218,16 +218,16 @@ func MediaListFromAPI(ctx *models.DownloadContext) ([]*models.Media, error) { media.AddFormat(format) } - mediaList = append(mediaList, media) - return mediaList, nil + return []*models.Media{media}, nil } } - return mediaList, nil + // no media found + return nil, nil } func GetRedditData( - client models.HTTPClient, + session models.HTTPClient, host string, slug string, raise bool, @@ -248,7 +248,7 @@ func GetRedditData( req.AddCookie(cookie) } - res, err := client.Do(req) + res, err := session.Do(req) if err != nil { return nil, fmt.Errorf("failed to send request: %w", err) } @@ -264,7 +264,7 @@ func GetRedditData( altHost = "www.reddit.com" } - return GetRedditData(client, altHost, slug, true) + return GetRedditData(session, altHost, slug, true) } var response Response diff --git a/ext/reddit/models.go b/ext/reddit/models.go index 37e89eb..8672668 100644 --- a/ext/reddit/models.go +++ b/ext/reddit/models.go @@ -71,10 +71,11 @@ type VideoPreview struct { type MediaMetadata struct { Status string `json:"status"` - E string `json:"e"` - S struct { - U string `json:"u"` - X int64 `json:"x"` - Y int64 `json:"y"` + Type string `json:"e"` + Media struct { + MP4 string `json:"mp4"` + URL string `json:"u"` + Width int64 `json:"x"` + Height int64 `json:"y"` } `json:"s"` } diff --git a/ext/redgifs/main.go b/ext/redgifs/main.go index 6173458..e721041 100644 --- a/ext/redgifs/main.go +++ b/ext/redgifs/main.go @@ -48,7 +48,6 @@ var Extractor = &models.Extractor{ } func MediaListFromAPI(ctx *models.DownloadContext) ([]*models.Media, error) { - var mediaList []*models.Media client := util.GetHTTPClient(ctx.Extractor.CodeName) response, err := GetVideo( @@ -109,11 +108,7 @@ func MediaListFromAPI(ctx *models.DownloadContext) ([]*models.Media, error) { } } - if len(media.Formats) > 0 { - mediaList = append(mediaList, media) - } - - return mediaList, nil + return []*models.Media{media}, nil } func GetVideo( diff --git a/ext/redgifs/util.go b/ext/redgifs/util.go index 2bf186b..b28a046 100644 --- a/ext/redgifs/util.go +++ b/ext/redgifs/util.go @@ -12,22 +12,22 @@ import ( var accessToken *Token -func GetAccessToken(client models.HTTPClient) (*Token, error) { +func GetAccessToken(session models.HTTPClient) (*Token, error) { if accessToken == nil || time.Now().Unix() >= accessToken.ExpiresIn { - if err := RefreshAccessToken(client); err != nil { + if err := RefreshAccessToken(session); err != nil { return nil, err } } return accessToken, nil } -func RefreshAccessToken(client models.HTTPClient) error { +func RefreshAccessToken(session models.HTTPClient) error { req, err := http.NewRequest(http.MethodGet, tokenEndpoint, nil) if err != nil { return fmt.Errorf("failed to create request: %w", err) } req.Header.Set("User-Agent", util.ChromeUA) - res, err := client.Do(req) + res, err := session.Do(req) if err != nil { return fmt.Errorf("failed to send request: %w", err) } diff --git a/ext/tiktok/main.go b/ext/tiktok/main.go index b773288..e269a52 100644 --- a/ext/tiktok/main.go +++ b/ext/tiktok/main.go @@ -78,8 +78,6 @@ var Extractor = &models.Extractor{ func MediaListFromAPI(ctx *models.DownloadContext) ([]*models.Media, error) { client := util.GetHTTPClient(ctx.Extractor.CodeName) - var mediaList []*models.Media - details, err := GetVideoAPI( client, ctx.MatchedContentID) if err != nil { @@ -119,10 +117,12 @@ func MediaListFromAPI(ctx *models.DownloadContext) ([]*models.Media, error) { } media.AddFormat(format) } - mediaList = append(mediaList, media) + return []*models.Media{media}, nil } else { images := details.ImagePostInfo.Images - for _, image := range images { + mediaList := make([]*models.Media, 0, len(images)) + for i := range images { + image := images[i] media := ctx.Extractor.NewMedia( ctx.MatchedContentID, ctx.MatchedContentURL, @@ -135,8 +135,8 @@ func MediaListFromAPI(ctx *models.DownloadContext) ([]*models.Media, error) { }) mediaList = append(mediaList, media) } + return mediaList, nil } - return mediaList, nil } func GetVideoAPI(