diff --git a/docs/supportedsites.md b/docs/supportedsites.md index 50ad231c..90a20202 100644 --- a/docs/supportedsites.md +++ b/docs/supportedsites.md @@ -214,7 +214,7 @@ Consider all sites to be NSFW unless otherwise known. Gfycat https://gfycat.com/ - individual Images, Search Results, User Profiles + Collections, individual Images, Search Results, User Profiles diff --git a/gallery_dl/extractor/gfycat.py b/gallery_dl/extractor/gfycat.py index 501d1146..f81bc885 100644 --- a/gallery_dl/extractor/gfycat.py +++ b/gallery_dl/extractor/gfycat.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright 2017-2021 Mike Fährmann +# Copyright 2017-2022 Mike Fährmann # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as @@ -73,7 +73,7 @@ class GfycatUserExtractor(GfycatExtractor): """Extractor for gfycat user profiles""" subcategory = "user" directory_fmt = ("{category}", "{username|userName}") - pattern = r"(?:https?://)?gfycat\.com/@([^/?#]+)" + pattern = r"(?:https?://)?gfycat\.com/@([^/?#]+)/?(?:$|\?|#)" test = ("https://gfycat.com/@gretta", { "pattern": r"https://giant\.gfycat\.com/[A-Za-z]+\.mp4", "count": ">= 100", @@ -86,6 +86,34 @@ class GfycatUserExtractor(GfycatExtractor): return GfycatAPI(self).user(self.key) +class GfycatCollectionExtractor(GfycatExtractor): + """Extractor for gfycat collections""" + subcategory = "collection" + directory_fmt = ("{category}", "{collection_owner}", + "{collection_name|collection_id}") + pattern = (r"(?:https?://)?gfycat\.com/@([^/?#]+)/collections" + r"/(\w+)(?:/([^/?#]+))?") + test = ("https://gfycat.com/@reactions/collections/nHgy2DtE/no-text", { + "pattern": r"https://\w+\.gfycat\.com/[A-Za-z]+\.mp4", + "count": ">= 100", + }) + + def __init__(self, match): + GfycatExtractor.__init__(self, match) + self.collection_id = match.group(2) + self.collection_name = match.group(3) + + def metadata(self): + return { + "collection_owner": self.key, + "collection_name" : self.collection_name, + "collection_id" : self.collection_id, + } + + def gfycats(self): + return GfycatAPI(self).collection(self.key, self.collection_id) + + class GfycatSearchExtractor(GfycatExtractor): """Extractor for gfycat search results""" subcategory = "search" @@ -188,6 +216,12 @@ class GfycatAPI(): params = {"count": 100} return self._pagination(endpoint, params) + def collection(self, user, collection): + endpoint = "/v1/users/{}/collections/{}/gfycats".format( + user, collection) + params = {"count": 100} + return self._pagination(endpoint, params) + def search(self, query): endpoint = "/v1/gfycats/search" params = {"search_text": query, "count": 150}