summaryrefslogtreecommitdiffstats
path: root/gallery_dl/extractor/vsco.py
diff options
context:
space:
mode:
Diffstat (limited to 'gallery_dl/extractor/vsco.py')
-rw-r--r--gallery_dl/extractor/vsco.py58
1 files changed, 26 insertions, 32 deletions
diff --git a/gallery_dl/extractor/vsco.py b/gallery_dl/extractor/vsco.py
index 524bd81..42839a8 100644
--- a/gallery_dl/extractor/vsco.py
+++ b/gallery_dl/extractor/vsco.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright 2019-2023 Mike Fährmann
+# Copyright 2019-2025 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
@@ -8,7 +8,7 @@
"""Extractors for https://vsco.co/"""
-from .common import Extractor, Message
+from .common import Extractor, Message, Dispatch
from .. import text, util
BASE_PATTERN = r"(?:https?://)?(?:www\.)?vsco\.co"
@@ -25,7 +25,7 @@ class VscoExtractor(Extractor):
def __init__(self, match):
Extractor.__init__(self, match)
- self.user = match.group(1).lower()
+ self.user = match[1].lower()
def items(self):
videos = self.config("videos", True)
@@ -47,7 +47,7 @@ class VscoExtractor(Extractor):
base = img["responsive_url"].partition("/")[2]
cdn, _, path = base.partition("/")
if cdn.startswith("aws"):
- url = "https://image-{}.vsco.co/{}".format(cdn, path)
+ url = f"https://image-{cdn}.vsco.co/{path}"
elif cdn.isdecimal():
url = "https://image.vsco.co/" + base
elif img["responsive_url"].startswith("http"):
@@ -79,11 +79,11 @@ class VscoExtractor(Extractor):
def _extract_preload_state(self, url):
page = self.request(url, notfound=self.subcategory).text
return util.json_loads(text.extr(page, "__PRELOADED_STATE__ = ", "<")
- .replace('"prevPageToken":undefined,', ''))
+ .replace('":undefined', '":null'))
def _pagination(self, url, params, token, key, extra=None):
headers = {
- "Referer" : "{}/{}".format(self.root, self.user),
+ "Referer" : f"{self.root}/{self.user}",
"Authorization" : "Bearer " + token,
"X-Client-Platform": "web",
"X-Client-Build" : "1",
@@ -93,7 +93,7 @@ class VscoExtractor(Extractor):
yield from map(self._transform_media, extra)
while True:
- data = self.request(url, params=params, headers=headers).json()
+ data = self.request_json(url, params=params, headers=headers)
medias = data.get(key)
if not medias:
return
@@ -109,8 +109,7 @@ class VscoExtractor(Extractor):
yield from medias
params["page"] += 1
- @staticmethod
- def _transform_media(media):
+ def _transform_media(self, media):
if "responsiveUrl" not in media:
return None
media["_id"] = media["id"]
@@ -122,8 +121,7 @@ class VscoExtractor(Extractor):
media["image_meta"] = media.get("imageMeta")
return media
- @staticmethod
- def _transform_video(media):
+ def _transform_video(self, media):
media["is_video"] = True
media["grid_name"] = ""
media["video_url"] = media["playback_url"]
@@ -132,17 +130,13 @@ class VscoExtractor(Extractor):
return media
-class VscoUserExtractor(VscoExtractor):
+class VscoUserExtractor(Dispatch, VscoExtractor):
"""Extractor for a vsco user profile"""
- subcategory = "user"
pattern = USER_PATTERN + r"/?$"
example = "https://vsco.co/USER"
- def initialize(self):
- pass
-
def items(self):
- base = "{}/{}/".format(self.root, self.user)
+ base = f"{self.root}/{self.user}/"
return self._dispatch_extractors((
(VscoAvatarExtractor , base + "avatar"),
(VscoGalleryExtractor , base + "gallery"),
@@ -158,12 +152,12 @@ class VscoGalleryExtractor(VscoExtractor):
example = "https://vsco.co/USER/gallery"
def images(self):
- url = "{}/{}/gallery".format(self.root, self.user)
+ url = f"{self.root}/{self.user}/gallery"
data = self._extract_preload_state(url)
tkn = data["users"]["currentUser"]["tkn"]
sid = str(data["sites"]["siteByUsername"][self.user]["site"]["id"])
- url = "{}/api/3.0/medias/profile".format(self.root)
+ url = f"{self.root}/api/3.0/medias/profile"
params = {
"site_id" : sid,
"limit" : "14",
@@ -182,14 +176,14 @@ class VscoCollectionExtractor(VscoExtractor):
example = "https://vsco.co/USER/collection/1"
def images(self):
- url = "{}/{}/collection/1".format(self.root, self.user)
+ url = f"{self.root}/{self.user}/collection/1"
data = self._extract_preload_state(url)
tkn = data["users"]["currentUser"]["tkn"]
cid = (data["sites"]["siteByUsername"][self.user]
["site"]["siteCollectionId"])
- url = "{}/api/2.0/collections/{}/medias".format(self.root, cid)
+ url = f"{self.root}/api/2.0/collections/{cid}/medias"
params = {"page": 2, "size": "20"}
return self._pagination(url, params, tkn, "medias", (
data["medias"]["byId"][mid["id"]]["media"]
@@ -207,7 +201,7 @@ class VscoSpaceExtractor(VscoExtractor):
example = "https://vsco.co/spaces/a1b2c3d4e5f"
def images(self):
- url = "{}/spaces/{}".format(self.root, self.user)
+ url = f"{self.root}/spaces/{self.user}"
data = self._extract_preload_state(url)
tkn = data["users"]["currentUser"]["tkn"]
@@ -221,14 +215,14 @@ class VscoSpaceExtractor(VscoExtractor):
space = data["spaces"]["byId"][sid]
space["postsList"] = [posts[pid] for pid in space["postsList"]]
- url = "{}/grpc/spaces/{}/posts".format(self.root, sid)
+ url = f"{self.root}/grpc/spaces/{sid}/posts"
params = {}
return self._pagination(url, params, tkn, space)
def _pagination(self, url, params, token, data):
headers = {
"Accept" : "application/json",
- "Referer" : "{}/spaces/{}".format(self.root, self.user),
+ "Referer" : f"{self.root}/spaces/{self.user}",
"Content-Type" : "application/json",
"Authorization": "Bearer " + token,
}
@@ -244,7 +238,7 @@ class VscoSpaceExtractor(VscoExtractor):
return
params["cursor"] = cursor["postcursorcontext"]["postId"]
- data = self.request(url, params=params, headers=headers).json()
+ data = self.request_json(url, params=params, headers=headers)
class VscoSpacesExtractor(VscoExtractor):
@@ -254,7 +248,7 @@ class VscoSpacesExtractor(VscoExtractor):
example = "https://vsco.co/USER/spaces"
def items(self):
- url = "{}/{}/spaces".format(self.root, self.user)
+ url = f"{self.root}/{self.user}/spaces"
data = self._extract_preload_state(url)
tkn = data["users"]["currentUser"]["tkn"]
@@ -267,12 +261,12 @@ class VscoSpacesExtractor(VscoExtractor):
"Authorization": "Bearer " + tkn,
}
# this would theoretically need to be paginated
- url = "{}/grpc/spaces/user/{}".format(self.root, uid)
- data = self.request(url, headers=headers).json()
+ url = f"{self.root}/grpc/spaces/user/{uid}"
+ data = self.request_json(url, headers=headers)
for space in data["spacesWithRoleList"]:
space = space["space"]
- url = "{}/spaces/{}".format(self.root, space["id"])
+ url = f"{self.root}/spaces/{space['id']}"
space["_extractor"] = VscoSpaceExtractor
yield Message.Queue, url, space
@@ -284,7 +278,7 @@ class VscoAvatarExtractor(VscoExtractor):
example = "https://vsco.co/USER/avatar"
def images(self):
- url = "{}/{}/gallery".format(self.root, self.user)
+ url = f"{self.root}/{self.user}/gallery"
page = self.request(url).text
piid = text.extr(page, '"profileImageId":"', '"')
@@ -312,7 +306,7 @@ class VscoImageExtractor(VscoExtractor):
example = "https://vsco.co/USER/media/0123456789abcdef"
def images(self):
- url = "{}/{}/media/{}".format(self.root, self.user, self.groups[1])
+ url = f"{self.root}/{self.user}/media/{self.groups[1]}"
data = self._extract_preload_state(url)
media = data["medias"]["byId"].popitem()[1]["media"]
return (self._transform_media(media),)
@@ -325,7 +319,7 @@ class VscoVideoExtractor(VscoExtractor):
example = "https://vsco.co/USER/video/012345678-9abc-def0"
def images(self):
- url = "{}/{}/video/{}".format(self.root, self.user, self.groups[1])
+ url = f"{self.root}/{self.user}/video/{self.groups[1]}"
data = self._extract_preload_state(url)
media = data["medias"]["byId"].popitem()[1]["media"]