Move error handling functions to _exception

This commit is contained in:
Mads Marquart
2020-01-15 11:05:59 +01:00
parent 3445eccc32
commit 3cdd646c37
6 changed files with 80 additions and 73 deletions

View File

@@ -429,7 +429,7 @@ class Client:
image_id = str(image_id)
data = {"photo_id": str(image_id)}
j = self.session._post("/mercury/attachments/photo/", data)
_util.handle_payload_error(j)
_exception.handle_payload_error(j)
url = _util.get_jsmods_require(j, 3)
if url is None:
@@ -625,7 +625,7 @@ class Client:
"https://{}-edge-chat.facebook.com/active_ping".format(self._pull_channel),
data,
)
_util.handle_payload_error(j)
_exception.handle_payload_error(j)
def _pull_message(self):
"""Call pull api to fetch message data."""
@@ -640,7 +640,7 @@ class Client:
j = self.session._get(
"https://{}-edge-chat.facebook.com/pull".format(self._pull_channel), data
)
_util.handle_payload_error(j)
_exception.handle_payload_error(j)
return j
def _parse_delta(self, delta):

View File

@@ -54,6 +54,14 @@ class ExternalError(FacebookError):
return self.message
@attrs_exception
class GraphQLError(ExternalError):
"""Raised by Facebook if there was an error in the GraphQL query."""
# TODO: Add `summary`, `severity` and `description`
# TODO: Handle multiple errors
@attrs_exception
class InvalidParameters(ExternalError):
"""Raised by Facebook if:
@@ -79,4 +87,51 @@ class PleaseRefresh(ExternalError):
"""
code = attr.ib(1357004)
message = attr.ib("Please try closing and re-opening your browser window.")
def handle_payload_error(j):
if "error" not in j:
return
code = j["error"]
if code == 1357001:
error_cls = NotLoggedIn
elif code == 1357004:
error_cls = PleaseRefresh
elif code in (1357031, 1545010, 1545003):
error_cls = InvalidParameters
else:
error_cls = ExternalError
# TODO: Use j["errorSummary"]
# "errorDescription" is in the users own language!
raise error_cls(
"Error sending request: {}".format(j["errorDescription"]), code=code
)
def handle_graphql_errors(j):
errors = []
if j.get("error"):
errors = [j["error"]]
if "errors" in j:
errors = j["errors"]
if errors:
error = errors[0] # TODO: Handle multiple errors
# TODO: Use `summary`, `severity` and `description`
raise GraphQLError(
"GraphQL error: {} / {!r}".format(
error.get("message"), error.get("debug_info")
),
code=error.get("code"),
)
def handle_http_error(code):
msg = "Error when sending request: Got {} response.".format(code)
if code == 404:
raise HTTPError(
msg + " This is either because you specified an invalid URL, or because"
" you provided an invalid id (Facebook usually require integer ids)",
status_code=code,
)
if 400 <= code < 600:
raise HTTPError(msg, status_code=code)

View File

@@ -46,9 +46,9 @@ def response_to_json(content):
if "error_results" in x:
del rtn[-1]
continue
_util.handle_payload_error(x)
_exception.handle_payload_error(x)
[(key, value)] = x.items()
_util.handle_graphql_errors(value)
_exception.handle_graphql_errors(value)
if "response" in value:
rtn[int(key[1:])] = value["response"]
else:

View File

@@ -2,7 +2,16 @@ import attr
import enum
from string import Formatter
from ._core import log, attrs_default
from . import _util, _session, _attachment, _location, _file, _quick_reply, _sticker
from . import (
_exception,
_util,
_session,
_attachment,
_location,
_file,
_quick_reply,
_sticker,
)
from typing import Optional
@@ -112,7 +121,7 @@ class Message:
"variables": _util.json_minimal({"data": data}),
}
j = self.session._payload_post("/webgraphql/mutation", data)
_util.handle_graphql_errors(j)
_exception.handle_graphql_errors(j)
def fetch(self) -> "MessageData":
"""Fetch fresh `MessageData` object."""

View File

@@ -293,7 +293,7 @@ class Session:
def _payload_post(self, url, data, files=None):
j = self._post(url, data, files=files)
_util.handle_payload_error(j)
_exception.handle_payload_error(j)
try:
return j["payload"]
except (KeyError, TypeError) as e:

View File

@@ -5,13 +5,7 @@ import random
import urllib.parse
from ._core import log
from ._exception import (
FBchatException,
FBchatFacebookError,
FBchatInvalidParameters,
FBchatNotLoggedIn,
FBchatPleaseRefresh,
)
from . import _exception
from typing import Iterable, Optional
@@ -57,8 +51,8 @@ def strip_json_cruft(text):
"""Removes `for(;;);` (and other cruft) that preceeds JSON responses."""
try:
return text[text.index("{") :]
except ValueError:
raise FBchatException("No JSON object found: {!r}".format(text))
except ValueError as e:
raise _exception.ParseError("No JSON object found", data=text) from e
def get_decoded_r(r):
@@ -72,8 +66,8 @@ def get_decoded(content):
def parse_json(content):
try:
return json.loads(content)
except ValueError:
raise FBchatFacebookError("Error while parsing JSON: {!r}".format(content))
except ValueError as e:
raise _exception.ParseError("Error while parsing JSON", data=content) from e
def digit_to_char(digit):
@@ -109,67 +103,16 @@ def generate_offline_threading_id():
return str(int(msgs, 2))
def handle_payload_error(j):
if "error" not in j:
return
error = j["error"]
if j["error"] == 1357001:
error_cls = FBchatNotLoggedIn
elif j["error"] == 1357004:
error_cls = FBchatPleaseRefresh
elif j["error"] in (1357031, 1545010, 1545003):
error_cls = FBchatInvalidParameters
else:
error_cls = FBchatFacebookError
# TODO: Use j["errorSummary"]
# "errorDescription" is in the users own language!
raise error_cls(
"Error #{} when sending request: {}".format(error, j["errorDescription"]),
fb_error_code=error,
fb_error_message=j["errorDescription"],
)
def handle_graphql_errors(j):
errors = []
if j.get("error"):
errors = [j["error"]]
if "errors" in j:
errors = j["errors"]
if errors:
error = errors[0] # TODO: Handle multiple errors
# TODO: Use `summary`, `severity` and `description`
raise FBchatFacebookError(
"GraphQL error #{}: {} / {!r}".format(
error.get("code"), error.get("message"), error.get("debug_info")
),
fb_error_code=error.get("code"),
fb_error_message=error.get("message"),
)
def check_request(r):
check_http_code(r.status_code)
_exception.handle_http_error(r.status_code)
content = get_decoded_r(r)
check_content(content)
return content
def check_http_code(code):
msg = "Error when sending request: Got {} response.".format(code)
if code == 404:
raise FBchatFacebookError(
msg + " This is either because you specified an invalid URL, or because"
" you provided an invalid id (Facebook usually requires integer ids).",
request_status_code=code,
)
if 400 <= code < 600:
raise FBchatFacebookError(msg, request_status_code=code)
def check_content(content, as_json=True):
if content is None or len(content) == 0:
raise FBchatFacebookError("Error when sending request: Got empty response")
raise _exception.HTTPError("Error when sending request: Got empty response")
def to_json(content):