From f1ab8c39fb3cd5a438a883575c17047166fdacca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20F=C3=A4hrmann?= Date: Mon, 26 May 2025 11:17:50 +0200 Subject: [PATCH] [kemonoparty] add 'artists' extractor (#7582) --- docs/supportedsites.md | 4 +-- gallery_dl/extractor/kemonoparty.py | 42 ++++++++++++++++++++++++++ test/results/kemonoparty.py | 46 +++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 2 deletions(-) diff --git a/docs/supportedsites.md b/docs/supportedsites.md index cc4b74ed..57d313e4 100644 --- a/docs/supportedsites.md +++ b/docs/supportedsites.md @@ -190,7 +190,7 @@ Consider all listed sites to potentially be NSFW. Coomer https://coomer.su/ - Favorites, Posts, User Profiles + Artists, Favorites, Posts, User Profiles Supported @@ -496,7 +496,7 @@ Consider all listed sites to potentially be NSFW. Kemono https://kemono.su/ - Discord Servers, Favorites, Posts, User Profiles + Artists, Discord Servers, Favorites, Posts, User Profiles Supported diff --git a/gallery_dl/extractor/kemonoparty.py b/gallery_dl/extractor/kemonoparty.py index 2e85553b..9b2e8e1b 100644 --- a/gallery_dl/extractor/kemonoparty.py +++ b/gallery_dl/extractor/kemonoparty.py @@ -528,6 +528,44 @@ class KemonopartyFavoriteExtractor(KemonopartyExtractor): yield Message.Queue, url, post +class KemonopartyArtistsExtractor(KemonopartyExtractor): + """Extractor for kemono artists""" + subcategory = "artists" + pattern = BASE_PATTERN + r"/artists(?:\?([^#]+))?" + example = "https://kemono.su/artists" + + def items(self): + params = text.parse_query(self.groups[2]) + users = self.api.creators() + + if params.get("service"): + service = params["service"].lower() + users = [user for user in users + if user["service"] == service] + + if params.get("q"): + q = params["q"].lower() + users = [user for user in users + if q in user["name"].lower()] + + sort = params.get("sort_by") or "favorited" + order = params.get("order") or "desc" + users.sort(key=lambda user: user[sort] or util.NONE, + reverse=(order != "asc")) + + for user in users: + service = user["service"] + if service == "discord": + user["_extractor"] = KemonopartyDiscordServerExtractor + url = "{}/discord/server/{}".format( + self.root, user["id"]) + else: + user["_extractor"] = KemonopartyUserExtractor + url = "{}/{}/user/{}".format( + self.root, service, user["id"]) + yield Message.Queue, url, user + + class KemonoAPI(): """Interface for the Kemono API v1.1.0 @@ -547,6 +585,10 @@ class KemonoAPI(): endpoint = "/file/" + file_hash return self._call(endpoint) + def creators(self): + endpoint = "/creators.txt" + return self._call(endpoint) + def creator_posts(self, service, creator_id, offset=0, query=None, tags=None): endpoint = "/{}/user/{}".format(service, creator_id) diff --git a/test/results/kemonoparty.py b/test/results/kemonoparty.py index 93ce4ed7..86293600 100644 --- a/test/results/kemonoparty.py +++ b/test/results/kemonoparty.py @@ -680,4 +680,50 @@ __tests__ = ( "#class" : kemonoparty.KemonopartyFavoriteExtractor, }, +{ + "#url" : "https://kemono.su/artists?q=aMSa", + "#category": ("", "kemonoparty", "artists"), + "#class" : kemonoparty.KemonopartyArtistsExtractor, + "#pattern" : kemonoparty.KemonopartyUserExtractor.pattern, + "#urls" : ( + "https://kemono.su/patreon/user/91205314", + "https://kemono.su/patreon/user/51528107", + "https://kemono.su/fanbox/user/12812028", + "https://kemono.su/patreon/user/35237747", + "https://kemono.su/patreon/user/8296916", + "https://kemono.su/patreon/user/155095324", + "https://kemono.su/patreon/user/75988930", + "https://kemono.su/patreon/user/93703989", + "https://kemono.su/patreon/user/100292687", + "https://kemono.su/patreon/user/138609443", + "https://kemono.su/patreon/user/61646879", + "https://kemono.su/patreon/user/110669843", + "https://kemono.su/patreon/user/44343773", + "https://kemono.su/patreon/user/77920059", + "https://kemono.su/patreon/user/102386631", + ), + + "favorited": int, + "id" : str, + "indexed" : int, + "name" : str, + "service" : {"patreon", "fanbox"}, + "updated" : int, +}, + +{ + "#url" : "https://kemono.su/artists?q=Axe&service=discord&sort_by=name&order=asc", + "#category": ("", "kemonoparty", "artists"), + "#class" : kemonoparty.KemonopartyArtistsExtractor, + "#pattern" : kemonoparty.KemonopartyDiscordServerExtractor.pattern, + "#urls" : "https://kemono.su/discord/server/1168450323023663164", + + "favorited": range(40, 80), + "id" : "1168450323023663164", + "indexed" : 1710201675, + "name" : "Axel Colored Workshop", + "service" : "discord", + "updated" : range(1740000000, 2000000000), +}, + )