Move error handling functions to _exception
This commit is contained in:
@@ -429,7 +429,7 @@ class Client:
|
|||||||
image_id = str(image_id)
|
image_id = str(image_id)
|
||||||
data = {"photo_id": str(image_id)}
|
data = {"photo_id": str(image_id)}
|
||||||
j = self.session._post("/mercury/attachments/photo/", data)
|
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)
|
url = _util.get_jsmods_require(j, 3)
|
||||||
if url is None:
|
if url is None:
|
||||||
@@ -625,7 +625,7 @@ class Client:
|
|||||||
"https://{}-edge-chat.facebook.com/active_ping".format(self._pull_channel),
|
"https://{}-edge-chat.facebook.com/active_ping".format(self._pull_channel),
|
||||||
data,
|
data,
|
||||||
)
|
)
|
||||||
_util.handle_payload_error(j)
|
_exception.handle_payload_error(j)
|
||||||
|
|
||||||
def _pull_message(self):
|
def _pull_message(self):
|
||||||
"""Call pull api to fetch message data."""
|
"""Call pull api to fetch message data."""
|
||||||
@@ -640,7 +640,7 @@ class Client:
|
|||||||
j = self.session._get(
|
j = self.session._get(
|
||||||
"https://{}-edge-chat.facebook.com/pull".format(self._pull_channel), data
|
"https://{}-edge-chat.facebook.com/pull".format(self._pull_channel), data
|
||||||
)
|
)
|
||||||
_util.handle_payload_error(j)
|
_exception.handle_payload_error(j)
|
||||||
return j
|
return j
|
||||||
|
|
||||||
def _parse_delta(self, delta):
|
def _parse_delta(self, delta):
|
||||||
|
@@ -54,6 +54,14 @@ class ExternalError(FacebookError):
|
|||||||
return self.message
|
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
|
@attrs_exception
|
||||||
class InvalidParameters(ExternalError):
|
class InvalidParameters(ExternalError):
|
||||||
"""Raised by Facebook if:
|
"""Raised by Facebook if:
|
||||||
@@ -79,4 +87,51 @@ class PleaseRefresh(ExternalError):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
code = attr.ib(1357004)
|
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)
|
||||||
|
@@ -46,9 +46,9 @@ def response_to_json(content):
|
|||||||
if "error_results" in x:
|
if "error_results" in x:
|
||||||
del rtn[-1]
|
del rtn[-1]
|
||||||
continue
|
continue
|
||||||
_util.handle_payload_error(x)
|
_exception.handle_payload_error(x)
|
||||||
[(key, value)] = x.items()
|
[(key, value)] = x.items()
|
||||||
_util.handle_graphql_errors(value)
|
_exception.handle_graphql_errors(value)
|
||||||
if "response" in value:
|
if "response" in value:
|
||||||
rtn[int(key[1:])] = value["response"]
|
rtn[int(key[1:])] = value["response"]
|
||||||
else:
|
else:
|
||||||
|
@@ -2,7 +2,16 @@ import attr
|
|||||||
import enum
|
import enum
|
||||||
from string import Formatter
|
from string import Formatter
|
||||||
from ._core import log, attrs_default
|
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
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
@@ -112,7 +121,7 @@ class Message:
|
|||||||
"variables": _util.json_minimal({"data": data}),
|
"variables": _util.json_minimal({"data": data}),
|
||||||
}
|
}
|
||||||
j = self.session._payload_post("/webgraphql/mutation", data)
|
j = self.session._payload_post("/webgraphql/mutation", data)
|
||||||
_util.handle_graphql_errors(j)
|
_exception.handle_graphql_errors(j)
|
||||||
|
|
||||||
def fetch(self) -> "MessageData":
|
def fetch(self) -> "MessageData":
|
||||||
"""Fetch fresh `MessageData` object."""
|
"""Fetch fresh `MessageData` object."""
|
||||||
|
@@ -293,7 +293,7 @@ class Session:
|
|||||||
|
|
||||||
def _payload_post(self, url, data, files=None):
|
def _payload_post(self, url, data, files=None):
|
||||||
j = self._post(url, data, files=files)
|
j = self._post(url, data, files=files)
|
||||||
_util.handle_payload_error(j)
|
_exception.handle_payload_error(j)
|
||||||
try:
|
try:
|
||||||
return j["payload"]
|
return j["payload"]
|
||||||
except (KeyError, TypeError) as e:
|
except (KeyError, TypeError) as e:
|
||||||
|
@@ -5,13 +5,7 @@ import random
|
|||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
|
||||||
from ._core import log
|
from ._core import log
|
||||||
from ._exception import (
|
from . import _exception
|
||||||
FBchatException,
|
|
||||||
FBchatFacebookError,
|
|
||||||
FBchatInvalidParameters,
|
|
||||||
FBchatNotLoggedIn,
|
|
||||||
FBchatPleaseRefresh,
|
|
||||||
)
|
|
||||||
|
|
||||||
from typing import Iterable, Optional
|
from typing import Iterable, Optional
|
||||||
|
|
||||||
@@ -57,8 +51,8 @@ def strip_json_cruft(text):
|
|||||||
"""Removes `for(;;);` (and other cruft) that preceeds JSON responses."""
|
"""Removes `for(;;);` (and other cruft) that preceeds JSON responses."""
|
||||||
try:
|
try:
|
||||||
return text[text.index("{") :]
|
return text[text.index("{") :]
|
||||||
except ValueError:
|
except ValueError as e:
|
||||||
raise FBchatException("No JSON object found: {!r}".format(text))
|
raise _exception.ParseError("No JSON object found", data=text) from e
|
||||||
|
|
||||||
|
|
||||||
def get_decoded_r(r):
|
def get_decoded_r(r):
|
||||||
@@ -72,8 +66,8 @@ def get_decoded(content):
|
|||||||
def parse_json(content):
|
def parse_json(content):
|
||||||
try:
|
try:
|
||||||
return json.loads(content)
|
return json.loads(content)
|
||||||
except ValueError:
|
except ValueError as e:
|
||||||
raise FBchatFacebookError("Error while parsing JSON: {!r}".format(content))
|
raise _exception.ParseError("Error while parsing JSON", data=content) from e
|
||||||
|
|
||||||
|
|
||||||
def digit_to_char(digit):
|
def digit_to_char(digit):
|
||||||
@@ -109,67 +103,16 @@ def generate_offline_threading_id():
|
|||||||
return str(int(msgs, 2))
|
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):
|
def check_request(r):
|
||||||
check_http_code(r.status_code)
|
_exception.handle_http_error(r.status_code)
|
||||||
content = get_decoded_r(r)
|
content = get_decoded_r(r)
|
||||||
check_content(content)
|
check_content(content)
|
||||||
return 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):
|
def check_content(content, as_json=True):
|
||||||
if content is None or len(content) == 0:
|
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):
|
def to_json(content):
|
||||||
|
Reference in New Issue
Block a user