rename 'StopExtraction' to 'AbortExtraction'
for cases where StopExtraction was used to report errors
This commit is contained in:
@@ -351,13 +351,11 @@ def main():
|
||||
else:
|
||||
input_manager.success()
|
||||
|
||||
except exception.StopExtraction:
|
||||
pass
|
||||
except exception.TerminateExtraction:
|
||||
pass
|
||||
except exception.RestartExtraction:
|
||||
log.debug("Restarting '%s'", url)
|
||||
continue
|
||||
except exception.ControlException:
|
||||
pass
|
||||
except exception.NoExtractorError:
|
||||
log.error("Unsupported URL '%s'", url)
|
||||
retval |= 64
|
||||
|
||||
@@ -47,6 +47,7 @@ class GalleryDLException(Exception):
|
||||
message = f"{message.__class__.__name__}: {message}"
|
||||
if fmt and self.msgfmt is not None:
|
||||
message = self.msgfmt.replace("{}", message)
|
||||
self.message = message
|
||||
Exception.__init__(self, message)
|
||||
|
||||
|
||||
@@ -151,11 +152,6 @@ class ControlException(GalleryDLException):
|
||||
class StopExtraction(ControlException):
|
||||
"""Stop data extraction"""
|
||||
|
||||
def __init__(self, message=None, *args):
|
||||
ControlException.__init__(self)
|
||||
self.message = message % args if args else message
|
||||
self.code = 1 if message else 0
|
||||
|
||||
|
||||
class AbortExtraction(ExtractionError, ControlException):
|
||||
"""Abort data extraction due to an error"""
|
||||
|
||||
@@ -144,7 +144,7 @@ class Ao3WorkExtractor(Ao3Extractor):
|
||||
page = response.text
|
||||
if len(page) < 20000 and \
|
||||
'<h2 class="landmark heading">Adult Content Warning</' in page:
|
||||
raise exception.StopExtraction("Adult Content")
|
||||
raise exception.AbortExtraction("Adult Content")
|
||||
|
||||
extr = text.extract_from(page)
|
||||
|
||||
|
||||
@@ -171,9 +171,8 @@ class ArcaliveAPI():
|
||||
return data
|
||||
|
||||
self.log.debug("Server response: %s", data)
|
||||
msg = data.get("message")
|
||||
raise exception.StopExtraction(
|
||||
"API request failed%s", ": " + msg if msg else "")
|
||||
msg = f": {msg}" if (msg := data.get("message")) else ""
|
||||
raise exception.AbortExtraction(f"API request failed{msg}")
|
||||
|
||||
def _pagination(self, endpoint, params, key):
|
||||
while True:
|
||||
|
||||
@@ -112,7 +112,7 @@ class BilibiliAPI():
|
||||
|
||||
if data["code"] != 0:
|
||||
self.extractor.log.debug("Server response: %s", data)
|
||||
raise exception.StopExtraction("API request failed")
|
||||
raise exception.AbortExtraction("API request failed")
|
||||
|
||||
return data
|
||||
|
||||
@@ -140,8 +140,8 @@ class BilibiliAPI():
|
||||
page, "window.__INITIAL_STATE__=", "};") + "}")
|
||||
except Exception:
|
||||
if "window._riskdata_" not in page:
|
||||
raise exception.StopExtraction(
|
||||
"%s: Unable to extract INITIAL_STATE data", article_id)
|
||||
raise exception.AbortExtraction(
|
||||
f"{article_id}: Unable to extract INITIAL_STATE data")
|
||||
self.extractor.wait(seconds=300)
|
||||
|
||||
def user_favlist(self):
|
||||
@@ -163,8 +163,9 @@ class BilibiliAPI():
|
||||
|
||||
if data["code"] != 0:
|
||||
self.extractor.log.debug("Server response: %s", data)
|
||||
raise exception.StopExtraction("API request failed,Are you login?")
|
||||
raise exception.AbortExtraction(
|
||||
"API request failed. Are you logges in?")
|
||||
try:
|
||||
return data["data"]["profile"]["mid"]
|
||||
except Exception:
|
||||
raise exception.StopExtraction("API request failed")
|
||||
raise exception.AbortExtraction("API request failed")
|
||||
|
||||
@@ -95,7 +95,7 @@ class BlueskyExtractor(Extractor):
|
||||
uri = record["value"]["subject"]["uri"]
|
||||
if "/app.bsky.feed.post/" in uri:
|
||||
yield from self.api.get_post_thread_uri(uri, depth)
|
||||
except exception.StopExtraction:
|
||||
except exception.ControlException:
|
||||
pass # deleted post
|
||||
except Exception as exc:
|
||||
self.log.debug(record, exc_info=exc)
|
||||
@@ -579,7 +579,7 @@ class BlueskyAPI():
|
||||
msg = f"{msg} ({response.status_code} {response.reason})"
|
||||
|
||||
self.extractor.log.debug("Server response: %s", response.text)
|
||||
raise exception.StopExtraction(msg)
|
||||
raise exception.AbortExtraction(msg)
|
||||
|
||||
def _pagination(self, endpoint, params,
|
||||
key="feed", root=None, check_empty=False):
|
||||
|
||||
@@ -381,7 +381,7 @@ class BoostyAPI():
|
||||
|
||||
else:
|
||||
self.extractor.log.debug(response.text)
|
||||
raise exception.StopExtraction("API request failed")
|
||||
raise exception.AbortExtraction("API request failed")
|
||||
|
||||
def _pagination(self, endpoint, params, transform=None, key=None):
|
||||
if "is_only_allowed" not in params and self.extractor.only_allowed:
|
||||
|
||||
@@ -124,7 +124,7 @@ class BunkrAlbumExtractor(LolisafeAlbumExtractor):
|
||||
pass
|
||||
else:
|
||||
if not DOMAINS:
|
||||
raise exception.StopExtraction(
|
||||
raise exception.AbortExtraction(
|
||||
"All Bunkr domains require solving a CF challenge")
|
||||
|
||||
# select alternative domain
|
||||
@@ -169,7 +169,7 @@ class BunkrAlbumExtractor(LolisafeAlbumExtractor):
|
||||
info[-1], "%H:%M:%S %d/%m/%Y")
|
||||
|
||||
yield file
|
||||
except exception.StopExtraction:
|
||||
except exception.ControlException:
|
||||
raise
|
||||
except Exception as exc:
|
||||
self.log.error("%s: %s", exc.__class__.__name__, exc)
|
||||
|
||||
@@ -336,8 +336,8 @@ class Extractor():
|
||||
if input is None:
|
||||
input = output.TTY_STDIN
|
||||
if not input:
|
||||
raise exception.StopExtraction(
|
||||
"User input required (%s)", prompt.strip(" :"))
|
||||
raise exception.AbortExtraction(
|
||||
f"User input required ({prompt.strip(' :')})")
|
||||
|
||||
def _get_auth_info(self):
|
||||
"""Return authentication information as (username, password) tuple"""
|
||||
|
||||
@@ -126,7 +126,7 @@ class DeviantartExtractor(Extractor):
|
||||
self.group = False
|
||||
elif group == "skip":
|
||||
self.log.info("Skipping group '%s'", self.user)
|
||||
raise exception.StopExtraction()
|
||||
raise exception.AbortExtraction()
|
||||
else:
|
||||
self.subcategory = "group-" + self.subcategory
|
||||
self.group = True
|
||||
@@ -1373,7 +1373,7 @@ class DeviantartSearchExtractor(DeviantartExtractor):
|
||||
response = self.request(url, params=params)
|
||||
|
||||
if response.history and "/users/login" in response.url:
|
||||
raise exception.StopExtraction("HTTP redirect to login page")
|
||||
raise exception.AbortExtraction("HTTP redirect to login page")
|
||||
page = response.text
|
||||
|
||||
for dev in DeviantartDeviationExtractor.pattern.findall(
|
||||
|
||||
@@ -165,7 +165,7 @@ class DiscordExtractor(Extractor):
|
||||
yield from self.extract_channel(
|
||||
channel["channel_id"], safe=True)
|
||||
elif not safe:
|
||||
raise exception.StopExtraction(
|
||||
raise exception.AbortExtraction(
|
||||
"This channel type is not supported."
|
||||
)
|
||||
except exception.HttpError as exc:
|
||||
|
||||
@@ -59,7 +59,7 @@ class ExhentaiExtractor(Extractor):
|
||||
def login(self):
|
||||
"""Login and set necessary cookies"""
|
||||
if self.LIMIT:
|
||||
raise exception.StopExtraction("Image limit reached!")
|
||||
raise exception.AbortExtraction("Image limit reached!")
|
||||
|
||||
if self.cookies_check(self.cookies_names):
|
||||
return
|
||||
@@ -178,7 +178,7 @@ class ExhentaiGalleryExtractor(ExhentaiExtractor):
|
||||
self.image_token = text.extr(gpage, 'hentai.org/s/', '"')
|
||||
if not self.image_token:
|
||||
self.log.debug("Page content:\n%s", gpage)
|
||||
raise exception.StopExtraction(
|
||||
raise exception.AbortExtraction(
|
||||
"Failed to extract initial image token")
|
||||
ipage = self._image_page()
|
||||
else:
|
||||
@@ -186,7 +186,7 @@ class ExhentaiGalleryExtractor(ExhentaiExtractor):
|
||||
part = text.extr(ipage, 'hentai.org/g/', '"')
|
||||
if not part:
|
||||
self.log.debug("Page content:\n%s", ipage)
|
||||
raise exception.StopExtraction(
|
||||
raise exception.AbortExtraction(
|
||||
"Failed to extract gallery token")
|
||||
self.gallery_token = part.split("/")[1]
|
||||
gpage = self._gallery_page()
|
||||
@@ -301,7 +301,7 @@ class ExhentaiGalleryExtractor(ExhentaiExtractor):
|
||||
|
||||
data = self.request_json(self.api_url, method="POST", json=data)
|
||||
if "error" in data:
|
||||
raise exception.StopExtraction(data["error"])
|
||||
raise exception.AbortExtraction(data["error"])
|
||||
|
||||
return data["gmetadata"][0]
|
||||
|
||||
@@ -326,8 +326,8 @@ class ExhentaiGalleryExtractor(ExhentaiExtractor):
|
||||
data["_fallback"] = self._fallback_1280(nl, self.image_num)
|
||||
except IndexError:
|
||||
self.log.debug("Page content:\n%s", page)
|
||||
raise exception.StopExtraction(
|
||||
"Unable to parse image info for '%s'", url)
|
||||
raise exception.AbortExtraction(
|
||||
f"Unable to parse image info for '{url}'")
|
||||
|
||||
data["num"] = self.image_num
|
||||
data["image_token"] = self.key_start = extr('var startkey="', '";')
|
||||
@@ -377,8 +377,8 @@ class ExhentaiGalleryExtractor(ExhentaiExtractor):
|
||||
nl, request["page"], imgkey)
|
||||
except IndexError:
|
||||
self.log.debug("Page content:\n%s", page)
|
||||
raise exception.StopExtraction(
|
||||
"Unable to parse image info for '%s'", url)
|
||||
raise exception.AbortExtraction(
|
||||
f"Unable to parse image info for '{url}'")
|
||||
|
||||
data["num"] = request["page"]
|
||||
data["image_token"] = imgkey
|
||||
@@ -401,7 +401,7 @@ class ExhentaiGalleryExtractor(ExhentaiExtractor):
|
||||
if " requires GP" in page:
|
||||
gp = self.config("gp")
|
||||
if gp == "stop":
|
||||
raise exception.StopExtraction("Not enough GP")
|
||||
raise exception.AbortExtraction("Not enough GP")
|
||||
elif gp == "wait":
|
||||
self.input("Press ENTER to continue.")
|
||||
return response.url
|
||||
@@ -463,7 +463,7 @@ class ExhentaiGalleryExtractor(ExhentaiExtractor):
|
||||
|
||||
if not action or action == "stop":
|
||||
ExhentaiExtractor.LIMIT = True
|
||||
raise exception.StopExtraction(msg)
|
||||
raise exception.AbortExtraction(msg)
|
||||
|
||||
self.log.warning(msg)
|
||||
if action == "wait":
|
||||
|
||||
@@ -219,17 +219,16 @@ class FacebookExtractor(Extractor):
|
||||
res = self.request(url, **kwargs)
|
||||
|
||||
if res.url.startswith(self.root + "/login"):
|
||||
raise exception.AuthenticationError(
|
||||
"You must be logged in to continue viewing images." +
|
||||
LEFT_OFF_TXT
|
||||
raise exception.LoginRequires(
|
||||
f"You must be logged in to continue viewing images."
|
||||
f"{LEFT_OFF_TXT}"
|
||||
)
|
||||
|
||||
if b'{"__dr":"CometErrorRoot.react"}' in res.content:
|
||||
raise exception.StopExtraction(
|
||||
"You've been temporarily blocked from viewing images. "
|
||||
"\nPlease try using a different account, "
|
||||
"using a VPN or waiting before you retry." +
|
||||
LEFT_OFF_TXT
|
||||
raise exception.AbortExtraction(
|
||||
f"You've been temporarily blocked from viewing images.\n"
|
||||
f"Please try using a different account, "
|
||||
f"using a VPN or waiting before you retry.{LEFT_OFF_TXT}"
|
||||
)
|
||||
|
||||
return res
|
||||
|
||||
@@ -451,7 +451,7 @@ class FlickrAPI(oauth.OAuth1API):
|
||||
raise exception.AuthenticationError(msg)
|
||||
elif data["code"] == 99:
|
||||
raise exception.AuthorizationError(msg)
|
||||
raise exception.StopExtraction("API request failed: %s", msg)
|
||||
raise exception.AbortExtraction(f"API request failed: {msg}")
|
||||
return data
|
||||
|
||||
def _pagination(self, method, params, key="photos"):
|
||||
|
||||
@@ -95,7 +95,7 @@ class GofileFolderExtractor(Extractor):
|
||||
raise exception.NotFoundError("content")
|
||||
if response["status"] == "error-passwordRequired":
|
||||
raise exception.AuthorizationError("Password required")
|
||||
raise exception.StopExtraction(
|
||||
"%s failed (Status: %s)", endpoint, response["status"])
|
||||
raise exception.AbortExtraction(
|
||||
f"{endpoint} failed (Status: {response['status']})")
|
||||
|
||||
return response["data"]
|
||||
|
||||
@@ -184,7 +184,7 @@ class IdolcomplexTagExtractor(IdolcomplexExtractor):
|
||||
|
||||
tags = self.tags.split()
|
||||
if not self.logged_in and len(tags) > 4:
|
||||
raise exception.StopExtraction(
|
||||
raise exception.AbortExtraction(
|
||||
"Non-members can only search up to 4 tags at once")
|
||||
return {"search_tags": " ".join(tags)}
|
||||
|
||||
|
||||
@@ -152,4 +152,4 @@ class ImagechestAPI():
|
||||
|
||||
else:
|
||||
self.extractor.log.debug(response.text)
|
||||
raise exception.StopExtraction("API request failed")
|
||||
raise exception.AbortExtraction("API request failed")
|
||||
|
||||
@@ -31,7 +31,7 @@ class ImagefapExtractor(Extractor):
|
||||
msg = text.extr(response.text, '<div class="mt-4', '<')
|
||||
if msg:
|
||||
msg = " ".join(msg.partition(">")[2].split())
|
||||
raise exception.StopExtraction("'%s'", msg)
|
||||
raise exception.AbortExtraction(f"'{msg}'")
|
||||
self.log.warning("HTTP redirect to %s", response.url)
|
||||
|
||||
return response
|
||||
|
||||
@@ -350,7 +350,7 @@ class InkbunnyAPI():
|
||||
self.authenticate(invalidate=True)
|
||||
continue
|
||||
|
||||
raise exception.StopExtraction(data.get("error_message"))
|
||||
raise exception.AbortExtraction(data.get("error_message"))
|
||||
|
||||
def _pagination_search(self, params):
|
||||
params["page"] = 1
|
||||
|
||||
@@ -136,9 +136,9 @@ class InstagramExtractor(Extractor):
|
||||
else:
|
||||
page = None
|
||||
|
||||
if page:
|
||||
raise exception.StopExtraction("HTTP redirect to %s page (%s)",
|
||||
page, url.partition("?")[0])
|
||||
if page is not None:
|
||||
raise exception.AbortExtraction(
|
||||
f"HTTP redirect to {page} page ({url.partition('?')[0]})")
|
||||
|
||||
www_claim = response.headers.get("x-ig-set-www-claim")
|
||||
if www_claim is not None:
|
||||
@@ -979,7 +979,7 @@ class InstagramGraphqlAPI():
|
||||
self.user_id = api.user_id
|
||||
|
||||
def _unsupported(self, _=None):
|
||||
raise exception.StopExtraction("Unsupported with GraphQL API")
|
||||
raise exception.AbortExtraction("Unsupported with GraphQL API")
|
||||
|
||||
def highlights_tray(self, user_id):
|
||||
query_hash = "d4d88dc1500312af6f937f7b804c68c3"
|
||||
@@ -1065,9 +1065,10 @@ class InstagramGraphqlAPI():
|
||||
if not info["has_next_page"]:
|
||||
return extr._update_cursor(None)
|
||||
elif not data["edges"]:
|
||||
s = "" if self.extractor.item.endswith("s") else "s"
|
||||
raise exception.StopExtraction(
|
||||
"%s'%s posts are private", self.extractor.item, s)
|
||||
user = self.extractor.item
|
||||
s = "" if user.endswith("s") else "s"
|
||||
raise exception.AbortExtraction(
|
||||
f"{user}'{s} posts are private")
|
||||
|
||||
variables["after"] = extr._update_cursor(info["end_cursor"])
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ class LofterAPI():
|
||||
|
||||
if info["meta"]["status"] != 200:
|
||||
self.extractor.log.debug("Server response: %s", info)
|
||||
raise exception.StopExtraction("API request failed")
|
||||
raise exception.AbortExtraction("API request failed")
|
||||
|
||||
return info["response"]
|
||||
|
||||
|
||||
@@ -32,9 +32,9 @@ class LusciousExtractor(Extractor):
|
||||
|
||||
if response.status_code >= 400:
|
||||
self.log.debug("Server response: %s", response.text)
|
||||
raise exception.StopExtraction(
|
||||
"GraphQL query failed ('%s %s')",
|
||||
response.status_code, response.reason)
|
||||
raise exception.AbortExtraction(
|
||||
f"GraphQL query failed "
|
||||
f"('{response.status_code} {response.reason}')")
|
||||
|
||||
return response.json()["data"]
|
||||
|
||||
|
||||
@@ -112,10 +112,10 @@ class MangadexChapterExtractor(MangadexExtractor):
|
||||
data = self._transform(chapter)
|
||||
|
||||
if data.get("_external_url") and not data["count"]:
|
||||
raise exception.StopExtraction(
|
||||
"Chapter %s%s is not available on MangaDex and can instead be "
|
||||
"read on the official publisher's website at %s.",
|
||||
data["chapter"], data["chapter_minor"], data["_external_url"])
|
||||
raise exception.AbortExtraction(
|
||||
f"Chapter {data['chapter']}{data['chapter_minor']} is not "
|
||||
f"available on MangaDex and can instead be read on the "
|
||||
f"official publisher's website at {data['_external_url']}.")
|
||||
|
||||
yield Message.Directory, data
|
||||
|
||||
@@ -356,8 +356,8 @@ class MangadexAPI():
|
||||
|
||||
msg = ", ".join('{title}: "{detail}"'.format_map(error)
|
||||
for error in response.json()["errors"])
|
||||
raise exception.StopExtraction(
|
||||
"%s %s (%s)", response.status_code, response.reason, msg)
|
||||
raise exception.AbortExtraction(
|
||||
f"{response.status_code} {response.reason} ({msg})")
|
||||
|
||||
def _pagination_chapters(self, endpoint, params=None, auth=False):
|
||||
if params is None:
|
||||
|
||||
@@ -176,8 +176,8 @@ class MangaparkMangaExtractor(MangaparkBase, Extractor):
|
||||
not lang or data["lang"] == lang):
|
||||
return data["id"]
|
||||
|
||||
raise exception.StopExtraction(
|
||||
"'%s' does not match any available source", source)
|
||||
raise exception.AbortExtraction(
|
||||
f"'{source}' does not match any available source")
|
||||
|
||||
|
||||
QUERIES = {
|
||||
|
||||
@@ -315,10 +315,9 @@ class MastodonAPI():
|
||||
if code < 400:
|
||||
return response
|
||||
if code == 401:
|
||||
raise exception.StopExtraction(
|
||||
"Invalid or missing access token.\n"
|
||||
"Run 'gallery-dl oauth:mastodon:%s' to obtain one.",
|
||||
self.extractor.instance)
|
||||
raise exception.AbortExtraction(
|
||||
f"Invalid or missing access token.\nRun 'gallery-dl oauth:"
|
||||
f"mastodon:{self.extractor.instance}' to obtain one.")
|
||||
if code == 404:
|
||||
raise exception.NotFoundError()
|
||||
if code == 429:
|
||||
@@ -327,7 +326,7 @@ class MastodonAPI():
|
||||
"%Y-%m-%dT%H:%M:%S.%fZ",
|
||||
))
|
||||
continue
|
||||
raise exception.StopExtraction(response.json().get("error"))
|
||||
raise exception.AbortExtraction(response.json().get("error"))
|
||||
|
||||
def _pagination(self, endpoint, params):
|
||||
url = endpoint
|
||||
|
||||
@@ -366,7 +366,7 @@ class NewgroundsExtractor(Extractor):
|
||||
return
|
||||
if "errors" in data:
|
||||
msg = ", ".join(text.unescape(e) for e in data["errors"])
|
||||
raise exception.StopExtraction(msg)
|
||||
raise exception.AbortExtraction(msg)
|
||||
|
||||
items = data.get("items")
|
||||
if not items:
|
||||
|
||||
@@ -386,8 +386,8 @@ class OAuthMastodon(OAuthBase):
|
||||
data = self.request_json(url, method="POST", data=data)
|
||||
|
||||
if "client_id" not in data or "client_secret" not in data:
|
||||
raise exception.StopExtraction(
|
||||
"Failed to register new application: '%s'", data)
|
||||
raise exception.AbortExtraction(
|
||||
f"Failed to register new application: '{data}'")
|
||||
|
||||
data["client-id"] = data.pop("client_id")
|
||||
data["client-secret"] = data.pop("client_secret")
|
||||
|
||||
@@ -306,7 +306,7 @@ class PatreonExtractor(Extractor):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
raise exception.StopExtraction("Unable to extract bootstrap data")
|
||||
raise exception.AbortExtraction("Unable to extract bootstrap data")
|
||||
|
||||
|
||||
class PatreonCreatorExtractor(PatreonExtractor):
|
||||
@@ -354,21 +354,21 @@ class PatreonCreatorExtractor(PatreonExtractor):
|
||||
data = None
|
||||
data = self._extract_bootstrap(page)
|
||||
return data["campaign"]["data"]["id"]
|
||||
except exception.StopExtraction:
|
||||
except exception.ControlException:
|
||||
pass
|
||||
except Exception as exc:
|
||||
if data:
|
||||
self.log.debug(data)
|
||||
raise exception.StopExtraction(
|
||||
"Unable to extract campaign ID (%s: %s)",
|
||||
exc.__class__.__name__, exc)
|
||||
raise exception.AbortExtraction(
|
||||
f"Unable to extract campaign ID "
|
||||
f"({exc.__class__.__name__}: {exc})")
|
||||
|
||||
# Next.js 13
|
||||
if cid := text.extr(
|
||||
page, r'{\"value\":{\"campaign\":{\"data\":{\"id\":\"', '\\"'):
|
||||
return cid
|
||||
|
||||
raise exception.StopExtraction("Failed to extract campaign ID")
|
||||
raise exception.AbortExtraction("Failed to extract campaign ID")
|
||||
|
||||
def _get_filters(self, query):
|
||||
return "".join(
|
||||
|
||||
@@ -175,7 +175,7 @@ class PexelsAPI():
|
||||
|
||||
else:
|
||||
self.extractor.log.debug(response.text)
|
||||
raise exception.StopExtraction("API request failed")
|
||||
raise exception.AbortExtraction("API request failed")
|
||||
|
||||
def _pagination(self, endpoint, params):
|
||||
while True:
|
||||
|
||||
@@ -160,8 +160,7 @@ class PhilomenaAPI():
|
||||
|
||||
# error
|
||||
self.extractor.log.debug(response.content)
|
||||
raise exception.StopExtraction(
|
||||
"%s %s", response.status_code, response.reason)
|
||||
raise exception.HttpError("", response)
|
||||
|
||||
def _pagination(self, endpoint, params):
|
||||
extr = self.extractor
|
||||
|
||||
@@ -543,7 +543,7 @@ class PinterestAPI():
|
||||
resource = self.extractor.subcategory.rpartition("-")[2]
|
||||
raise exception.NotFoundError(resource)
|
||||
self.extractor.log.debug("Server response: %s", response.text)
|
||||
raise exception.StopExtraction("API request failed")
|
||||
raise exception.AbortExtraction("API request failed")
|
||||
|
||||
def _pagination(self, resource, options):
|
||||
while True:
|
||||
|
||||
@@ -694,7 +694,7 @@ class PixivRankingExtractor(PixivExtractor):
|
||||
try:
|
||||
self.mode = mode = mode_map[mode]
|
||||
except KeyError:
|
||||
raise exception.StopExtraction("Invalid mode '%s'", mode)
|
||||
raise exception.AbortExtraction(f"Invalid mode '{mode}'")
|
||||
|
||||
date = query.get("date")
|
||||
if date:
|
||||
@@ -747,7 +747,7 @@ class PixivSearchExtractor(PixivExtractor):
|
||||
try:
|
||||
self.word = query["word"]
|
||||
except KeyError:
|
||||
raise exception.StopExtraction("Missing search term")
|
||||
raise exception.AbortExtraction("Missing search term")
|
||||
|
||||
sort = query.get("order", "date_d")
|
||||
sort_map = {
|
||||
@@ -760,7 +760,7 @@ class PixivSearchExtractor(PixivExtractor):
|
||||
try:
|
||||
self.sort = sort = sort_map[sort]
|
||||
except KeyError:
|
||||
raise exception.StopExtraction("Invalid search order '%s'", sort)
|
||||
raise exception.AbortExtraction(f"Invalid search order '{sort}'")
|
||||
|
||||
target = query.get("s_mode", "s_tag_full")
|
||||
target_map = {
|
||||
@@ -771,7 +771,7 @@ class PixivSearchExtractor(PixivExtractor):
|
||||
try:
|
||||
self.target = target = target_map[target]
|
||||
except KeyError:
|
||||
raise exception.StopExtraction("Invalid search mode '%s'", target)
|
||||
raise exception.AbortExtraction(f"Invalid search mode '{target}'")
|
||||
|
||||
self.date_start = query.get("scd")
|
||||
self.date_end = query.get("ecd")
|
||||
@@ -1288,7 +1288,7 @@ class PixivAppAPI():
|
||||
self.extractor.wait(seconds=300)
|
||||
continue
|
||||
|
||||
raise exception.StopExtraction("API request failed: %s", error)
|
||||
raise exception.AbortExtraction(f"API request failed: {error}")
|
||||
|
||||
def _pagination(self, endpoint, params,
|
||||
key_items="illusts", key_data=None):
|
||||
|
||||
@@ -53,8 +53,8 @@ class PixnetExtractor(Extractor):
|
||||
|
||||
pnext = text.extr(page, 'class="nextBtn"', '>')
|
||||
if pnext is None and 'name="albumpass">' in page:
|
||||
raise exception.StopExtraction(
|
||||
"Album %s is password-protected.", self.item_id)
|
||||
raise exception.AbortExtraction(
|
||||
f"Album {self.item_id} is password-protected.")
|
||||
if "href" not in pnext:
|
||||
return
|
||||
url = self.root + text.extr(pnext, 'href="', '"')
|
||||
|
||||
@@ -102,8 +102,8 @@ class PostmillSubmissionsExtractor(PostmillExtractor):
|
||||
if response.history:
|
||||
redirect_url = response.url
|
||||
if redirect_url == self.root + "/login":
|
||||
raise exception.StopExtraction(
|
||||
"HTTP redirect to login page (%s)", redirect_url)
|
||||
raise exception.AbortExtraction(
|
||||
f"HTTP redirect to login page ({redirect_url})")
|
||||
page = response.text
|
||||
|
||||
for nav in text.extract_iter(page,
|
||||
|
||||
@@ -37,9 +37,9 @@ class ReadcomiconlineBase():
|
||||
"the CAPTCHA, and press ENTER to continue", response.url)
|
||||
self.input()
|
||||
else:
|
||||
raise exception.StopExtraction(
|
||||
"Redirect to \n%s\nVisit this URL in your browser and "
|
||||
"solve the CAPTCHA to continue", response.url)
|
||||
raise exception.AbortExtraction(
|
||||
f"Redirect to \n{response.url}\nVisit this URL in your "
|
||||
f"browser and solve the CAPTCHA to continue")
|
||||
|
||||
|
||||
class ReadcomiconlineIssueExtractor(ReadcomiconlineBase, ChapterExtractor):
|
||||
|
||||
@@ -507,7 +507,8 @@ class RedditAPI():
|
||||
try:
|
||||
data = response.json()
|
||||
except ValueError:
|
||||
raise exception.StopExtraction(text.remove_html(response.text))
|
||||
raise exception.AbortExtraction(
|
||||
text.remove_html(response.text))
|
||||
|
||||
if "error" in data:
|
||||
if data["error"] == 403:
|
||||
@@ -515,7 +516,7 @@ class RedditAPI():
|
||||
if data["error"] == 404:
|
||||
raise exception.NotFoundError()
|
||||
self.log.debug(data)
|
||||
raise exception.StopExtraction(data.get("message"))
|
||||
raise exception.AbortExtraction(data.get("message"))
|
||||
return data
|
||||
|
||||
def _pagination(self, endpoint, params):
|
||||
|
||||
@@ -308,7 +308,7 @@ class SankakuAPI():
|
||||
("unauthorized", "invalid-token", "invalid_token")):
|
||||
_authenticate_impl.invalidate(self.username)
|
||||
continue
|
||||
raise exception.StopExtraction(code)
|
||||
raise exception.AbortExtraction(code)
|
||||
return data
|
||||
|
||||
def _pagination(self, endpoint, params):
|
||||
|
||||
@@ -45,8 +45,8 @@ class SeigaExtractor(Extractor):
|
||||
url = f"{self.root}/image/source/{image_id}"
|
||||
location = self.request_location(url, notfound="image")
|
||||
if "nicovideo.jp/login" in location:
|
||||
raise exception.StopExtraction(
|
||||
"HTTP redirect to login page (%s)", location.partition("?")[0])
|
||||
raise exception.AbortExtraction(
|
||||
f"HTTP redirect to login page ({location.partition('?')[0]})")
|
||||
return location.replace("/o/", "/priv/", 1)
|
||||
|
||||
def login(self):
|
||||
|
||||
@@ -211,9 +211,9 @@ class SmugmugAPI(oauth.OAuth1API):
|
||||
if data["Code"] == 404:
|
||||
raise exception.NotFoundError()
|
||||
if data["Code"] == 429:
|
||||
raise exception.StopExtraction("Rate limit reached")
|
||||
raise exception.AbortExtraction("Rate limit reached")
|
||||
self.log.debug(data)
|
||||
raise exception.StopExtraction("API request failed")
|
||||
raise exception.AbortExtraction("API request failed")
|
||||
|
||||
def _expansion(self, endpoint, expands, params=None):
|
||||
endpoint = self._extend(endpoint, expands)
|
||||
|
||||
@@ -74,7 +74,7 @@ class SteamgriddbExtractor(Extractor):
|
||||
def _call(self, endpoint, **kwargs):
|
||||
data = self.request_json(self.root + endpoint, **kwargs)
|
||||
if not data["success"]:
|
||||
raise exception.StopExtraction(data["error"])
|
||||
raise exception.AbortExtraction(data["error"])
|
||||
return data["data"]
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ class SteamgriddbAssetsExtractor(SteamgriddbExtractor):
|
||||
id = int(match[2])
|
||||
self.game_id = id if list_type == "game" else None
|
||||
self.collection_id = id if list_type == "collection" else None
|
||||
self.page = int(match[3] or 1)
|
||||
self.page = int(p) if (p := match[3]) else 1
|
||||
|
||||
def assets(self):
|
||||
limit = 48
|
||||
@@ -96,7 +96,7 @@ class SteamgriddbAssetsExtractor(SteamgriddbExtractor):
|
||||
sort = self.config("sort", "score_desc")
|
||||
if sort not in ("score_desc", "score_asc", "score_old_desc",
|
||||
"score_old_asc", "age_desc", "age_asc"):
|
||||
raise exception.StopExtractor("Invalid sort '%s'", sort)
|
||||
raise exception.AbortExtraction(f"Invalid sort '{sort}'")
|
||||
|
||||
json = {
|
||||
"static" : self.config("static", True),
|
||||
@@ -149,7 +149,7 @@ class SteamgriddbAssetsExtractor(SteamgriddbExtractor):
|
||||
|
||||
for i in value:
|
||||
if i not in valid_values:
|
||||
raise exception.StopExtraction("Invalid %s '%s'", type_name, i)
|
||||
raise exception.AbortExtraction(f"Invalid {type_name} '{i}'")
|
||||
|
||||
return value
|
||||
|
||||
|
||||
@@ -65,8 +65,8 @@ class SubscribestarExtractor(Extractor):
|
||||
if response.history and (
|
||||
"/verify_subscriber" in response.url or
|
||||
"/age_confirmation_warning" in response.url):
|
||||
raise exception.StopExtraction(
|
||||
"HTTP redirect to %s", response.url)
|
||||
raise exception.AbortExtraction(
|
||||
f"HTTP redirect to {response.url}")
|
||||
|
||||
content = response.content
|
||||
if len(content) < 250 and b">redirected<" in content:
|
||||
|
||||
@@ -86,9 +86,9 @@ class TsuminoGalleryExtractor(TsuminoBase, GalleryExtractor):
|
||||
response = self.request(url, headers=headers, fatal=False)
|
||||
|
||||
if "/Auth/" in response.url:
|
||||
raise exception.StopExtraction(
|
||||
"Failed to get gallery JSON data. Visit '%s' in a browser "
|
||||
"and solve the CAPTCHA to continue.", response.url)
|
||||
raise exception.AbortExtraction(
|
||||
f"Failed to get gallery JSON data. Visit '{response.url}' "
|
||||
f"in a browser and solve the CAPTCHA to continue.")
|
||||
|
||||
page = response.text
|
||||
tpl, pos = text.extract(page, 'data-cdn="', '"')
|
||||
@@ -155,8 +155,8 @@ class TsuminoSearchExtractor(TsuminoBase, Extractor):
|
||||
return self._parse_simple(query)
|
||||
return self._parse_jsurl(query)
|
||||
except Exception as exc:
|
||||
raise exception.StopExtraction(
|
||||
"Invalid search query '%s' (%s)", query, exc)
|
||||
raise exception.AbortExtraction(
|
||||
f"Invalid search query '{query}' ({exc})")
|
||||
|
||||
def _parse_simple(self, query):
|
||||
"""Parse search query with format '?<key>=value>'"""
|
||||
|
||||
@@ -499,8 +499,8 @@ class TumblrAPI(oauth.OAuth1API):
|
||||
continue
|
||||
|
||||
t = (datetime.now() + timedelta(0, float(reset))).time()
|
||||
raise exception.StopExtraction(
|
||||
"Aborting - Rate limit will reset at %s",
|
||||
raise exception.AbortExtraction(
|
||||
f"Aborting - Rate limit will reset at "
|
||||
f"{t.hour:02}:{t.minute:02}:{t.second:02}")
|
||||
|
||||
# hourly rate limit
|
||||
@@ -510,7 +510,7 @@ class TumblrAPI(oauth.OAuth1API):
|
||||
self.extractor.wait(seconds=reset)
|
||||
continue
|
||||
|
||||
raise exception.StopExtraction(data)
|
||||
raise exception.AbortExtraction(data)
|
||||
|
||||
def _pagination(self, endpoint, params,
|
||||
blog=None, key="posts", cache=False):
|
||||
|
||||
@@ -154,8 +154,7 @@ class TwibooruAPI():
|
||||
|
||||
# error
|
||||
self.extractor.log.debug(response.content)
|
||||
raise exception.StopExtraction(
|
||||
"%s %s", response.status_code, response.reason)
|
||||
raise exception.HttpError("", response)
|
||||
|
||||
def _pagination(self, endpoint, params):
|
||||
extr = self.extractor
|
||||
|
||||
@@ -725,7 +725,7 @@ class TwitterTimelineExtractor(TwitterExtractor):
|
||||
return self.api.user_media
|
||||
if strategy == "with_replies":
|
||||
return self.api.user_tweets_and_replies
|
||||
raise exception.StopExtraction("Invalid strategy '%s'", strategy)
|
||||
raise exception.AbortExtraction(f"Invalid strategy '{strategy}'")
|
||||
|
||||
|
||||
class TwitterTweetsExtractor(TwitterExtractor):
|
||||
@@ -940,8 +940,8 @@ class TwitterTweetExtractor(TwitterExtractor):
|
||||
try:
|
||||
self._assign_user(tweet["core"]["user_results"]["result"])
|
||||
except KeyError:
|
||||
raise exception.StopExtraction(
|
||||
"'%s'", tweet.get("reason") or "Unavailable")
|
||||
raise exception.AbortExtraction(
|
||||
f"'{tweet.get('reason') or 'Unavailable'}'")
|
||||
|
||||
yield tweet
|
||||
|
||||
@@ -1253,7 +1253,7 @@ class TwitterAPI():
|
||||
raise exception.AuthorizationError("NSFW Tweet")
|
||||
if reason == "Protected":
|
||||
raise exception.AuthorizationError("Protected Tweet")
|
||||
raise exception.StopExtraction("Tweet unavailable ('%s')", reason)
|
||||
raise exception.AbortExtraction(f"Tweet unavailable ('{reason}')")
|
||||
|
||||
return tweet
|
||||
|
||||
@@ -1634,8 +1634,8 @@ class TwitterAPI():
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
raise exception.StopExtraction(
|
||||
"%s %s (%s)", response.status_code, response.reason, errors)
|
||||
raise exception.AbortExtraction(
|
||||
f"{response.status_code} {response.reason} ({errors})")
|
||||
|
||||
def _pagination_legacy(self, endpoint, params):
|
||||
extr = self.extractor
|
||||
@@ -1809,7 +1809,7 @@ class TwitterAPI():
|
||||
raise exception.AuthorizationError(
|
||||
f"{user['screen_name']}'s Tweets are protected")
|
||||
|
||||
raise exception.StopExtraction(
|
||||
raise exception.AbortExtraction(
|
||||
"Unable to retrieve Tweets from this timeline")
|
||||
|
||||
tweets = []
|
||||
@@ -1988,7 +1988,7 @@ class TwitterAPI():
|
||||
def _handle_ratelimit(self, response):
|
||||
rl = self.extractor.config("ratelimit")
|
||||
if rl == "abort":
|
||||
raise exception.StopExtraction("Rate limit exceeded")
|
||||
raise exception.AbortExtraction("Rate limit exceeded")
|
||||
elif rl and isinstance(rl, str) and rl.startswith("wait:"):
|
||||
until = None
|
||||
seconds = text.parse_float(rl.partition(":")[2]) or 60.0
|
||||
@@ -2172,7 +2172,7 @@ def _login_impl(extr, username, password):
|
||||
raise exception.AuthenticationError(
|
||||
"No 'auth_token' cookie received")
|
||||
else:
|
||||
raise exception.StopExtraction("Unrecognized subtask %s", subtask)
|
||||
raise exception.AbortExtraction(f"Unrecognized subtask {subtask}")
|
||||
|
||||
inputs = {"subtask_id": subtask}
|
||||
inputs.update(data)
|
||||
|
||||
@@ -40,5 +40,5 @@ class UrlshortenerLinkExtractor(UrlshortenerExtractor):
|
||||
location = self.request_location(
|
||||
url, headers=self.config_instance("headers"), notfound="URL")
|
||||
if not location:
|
||||
raise exception.StopExtraction("Unable to resolve short URL")
|
||||
raise exception.AbortExtraction("Unable to resolve short URL")
|
||||
yield Message.Queue, location, {}
|
||||
|
||||
@@ -96,8 +96,8 @@ class VkExtractor(Extractor):
|
||||
response = self.request(
|
||||
url, method="POST", headers=headers, data=data)
|
||||
if response.history and "/challenge.html" in response.url:
|
||||
raise exception.StopExtraction(
|
||||
"HTTP redirect to 'challenge' page<:\n%s", response.url)
|
||||
raise exception.AbortExtraction(
|
||||
f"HTTP redirect to 'challenge' page:\n{response.url}")
|
||||
|
||||
payload = response.json()["payload"][1]
|
||||
if len(payload) < 4:
|
||||
|
||||
@@ -200,9 +200,9 @@ class WallhavenAPI():
|
||||
continue
|
||||
|
||||
self.extractor.log.debug("Server response: %s", response.text)
|
||||
raise exception.StopExtraction(
|
||||
"API request failed (%s %s)",
|
||||
response.status_code, response.reason)
|
||||
raise exception.AbortExtraction(
|
||||
f"API request failed "
|
||||
f"({response.status_code} {response.reason})")
|
||||
|
||||
def _pagination(self, endpoint, params=None, metadata=None):
|
||||
if params is None:
|
||||
|
||||
@@ -40,8 +40,8 @@ class WebtoonsBase():
|
||||
def request(self, url, **kwargs):
|
||||
response = Extractor.request(self, url, **kwargs)
|
||||
if response.history and "/ageGate" in response.url:
|
||||
raise exception.StopExtraction(
|
||||
"HTTP redirect to age gate check ('%s')", response.url)
|
||||
raise exception.AbortExtraction(
|
||||
f"HTTP redirect to age gate check ('{response.url}')")
|
||||
return response
|
||||
|
||||
|
||||
|
||||
@@ -46,9 +46,9 @@ class WeiboExtractor(Extractor):
|
||||
|
||||
if response.history:
|
||||
if "login.sina.com" in response.url:
|
||||
raise exception.StopExtraction(
|
||||
"HTTP redirect to login page (%s)",
|
||||
response.url.partition("?")[0])
|
||||
raise exception.AbortExtraction(
|
||||
f"HTTP redirect to login page "
|
||||
f"({response.url.partition('?')[0]})")
|
||||
if "passport.weibo.com" in response.url:
|
||||
self._sina_visitor_system(response)
|
||||
response = Extractor.request(self, url, **kwargs)
|
||||
@@ -179,8 +179,8 @@ class WeiboExtractor(Extractor):
|
||||
if not data.get("ok"):
|
||||
self.log.debug(response.content)
|
||||
if "since_id" not in params: # first iteration
|
||||
raise exception.StopExtraction(
|
||||
'"%s"', data.get("msg") or "unknown error")
|
||||
raise exception.AbortExtraction(
|
||||
f'"{data.get("msg") or "unknown error"}"')
|
||||
|
||||
data = data["data"]
|
||||
statuses = data["list"]
|
||||
|
||||
@@ -51,7 +51,7 @@ class WikimediaExtractor(BaseExtractor):
|
||||
response = self.request(url, method="HEAD", fatal=None)
|
||||
if response.status_code < 400:
|
||||
return url
|
||||
raise exception.StopExtraction("Unable to find API endpoint")
|
||||
raise exception.AbortExtraction("Unable to find API endpoint")
|
||||
|
||||
def prepare(self, image):
|
||||
"""Adjust the content of an image object"""
|
||||
|
||||
@@ -38,7 +38,7 @@ class XfolioExtractor(Extractor):
|
||||
response = Extractor.request(self, url, **kwargs)
|
||||
|
||||
if "/system/recaptcha" in response.url:
|
||||
raise exception.StopExtraction("Bot check / CAPTCHA page")
|
||||
raise exception.AbortExtraction("Bot check / CAPTCHA page")
|
||||
|
||||
return response
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ class YoutubeDLExtractor(Extractor):
|
||||
ytdl_instance.get_info_extractor(self.ytdl_ie_key),
|
||||
False, {}, True)
|
||||
except ytdl_module.utils.YoutubeDLError:
|
||||
raise exception.StopExtraction("Failed to extract video data")
|
||||
raise exception.AbortExtraction("Failed to extract video data")
|
||||
|
||||
if not info_dict:
|
||||
return
|
||||
|
||||
@@ -238,7 +238,7 @@ class ZerochanTagExtractor(ZerochanExtractor):
|
||||
self.log.warning("HTTP redirect to %s", url)
|
||||
if self.config("redirects"):
|
||||
continue
|
||||
raise exception.StopExtraction()
|
||||
raise exception.AbortExtraction()
|
||||
|
||||
data = response.json()
|
||||
try:
|
||||
|
||||
@@ -153,9 +153,10 @@ class Job():
|
||||
try:
|
||||
for msg in extractor:
|
||||
self.dispatch(msg)
|
||||
except exception.StopExtraction as exc:
|
||||
if exc.message:
|
||||
log.error(exc.message)
|
||||
except exception.StopExtraction:
|
||||
pass
|
||||
except exception.AbortExtraction as exc:
|
||||
log.error(exc.message)
|
||||
self.status |= exc.code
|
||||
except (exception.TerminateExtraction, exception.RestartExtraction):
|
||||
raise
|
||||
|
||||
@@ -189,7 +189,7 @@ class UpdateExtractor(Extractor):
|
||||
try:
|
||||
path_repo = REPOS[repo or "stable"]
|
||||
except KeyError:
|
||||
raise exception.StopExtraction("Invalid channel '%s'", repo)
|
||||
raise exception.AbortExtraction(f"Invalid channel '{repo}'")
|
||||
|
||||
path_tag = tag if tag == "latest" else "tags/" + tag
|
||||
url = f"{self.root_api}/repos/{path_repo}/releases/{path_tag}"
|
||||
|
||||
@@ -41,7 +41,7 @@ def construct_YoutubeDL(module, obj, user_opts, system_opts=None):
|
||||
try:
|
||||
opts = parse_command_line(module, argv) if argv else user_opts
|
||||
except SystemExit:
|
||||
raise exception.StopExtraction("Invalid command-line option")
|
||||
raise exception.AbortExtraction("Invalid command-line option")
|
||||
|
||||
if opts.get("format") is None:
|
||||
opts["format"] = config("format")
|
||||
|
||||
Reference in New Issue
Block a user