Sync to maraid/fbchat

Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
2023-03-28 11:49:48 +03:00
parent 55712756d7
commit 356db553b7
3 changed files with 78 additions and 13 deletions

View File

@@ -125,20 +125,12 @@ class Message:
def react(self, reaction: Optional[str]):
"""React to the message, or removes reaction.
Currently, you can use "", "😍", "😆", "😮", "😢", "😠", "👍" or "👎". It
should be possible to add support for more, but we haven't figured that out yet.
Args:
reaction: Reaction emoji to use, or if ``None``, removes reaction.
Example:
>>> message.react("😍")
"""
if reaction and reaction not in SENDABLE_REACTIONS:
raise ValueError(
"Invalid reaction! Please use one of: {}".format(SENDABLE_REACTIONS)
)
data = {
"action": "ADD_REACTION" if reaction else "REMOVE_REACTION",
"client_mutation_id": "1",

View File

@@ -16,8 +16,10 @@ from typing import Optional, Mapping, Callable, Any
SERVER_JS_DEFINE_REGEX = re.compile(
r'(?:"ServerJS".{,100}\.handle\({.*"define":)|(?:require\("ServerJSDefine"\)\)?\.handleDefines\()'
)
r'(?:"ServerJS".{,100}\.handle\({.*"define":)'
r'|(?:ServerJS.{,100}\.handleWithCustomApplyEach\(ScheduledApplyEach,{.*"define":)'
r'|(?:require\("ServerJSDefine"\)\)?\.handleDefines\()'
r'|(?:"require":\[\["ScheduledServerJS".{,100}"define":)')
SERVER_JS_DEFINE_JSON_DECODER = json.JSONDecoder()
@@ -36,8 +38,6 @@ def parse_server_js_define(html: str) -> Mapping[str, Any]:
raise _exception.ParseError("Could not find any ServerJSDefine", data=html)
if len(define_splits) < 2:
raise _exception.ParseError("Could not find enough ServerJSDefine", data=html)
if len(define_splits) > 2:
raise _exception.ParseError("Found too many ServerJSDefine", data=define_splits)
# Parse entries (should be two)
for entry in define_splits:
try:
@@ -311,6 +311,21 @@ class Session:
data=data,
allow_redirects=False,
cookies=login_cookies(_util.now()),
headers={
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36",
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"accept-language": "en-HU,en;q=0.9,hu-HU;q=0.8,hu;q=0.7,en-US;q=0.6",
"cache-control": "max-age=0",
"origin": "https://www.messenger.com",
"referer": "https://www.messenger.com/login/",
"sec-ch-ua": '" Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"',
"sec-ch-ua-mobile": "?0",
"sec-fetch-dest": "document",
"sec-fetch-mode": "navigate",
"sec-fetch-site": "same-origin",
"sec-fetch-user": "?1",
"upgrade-insecure-requests": "1"
}
)
except requests.RequestException as e:
_exception.handle_requests_error(e)
@@ -411,7 +426,7 @@ class Session:
# Make a request to the main page to retrieve ServerJSDefine entries
try:
r = session.get(prefix_url("/"), allow_redirects=False)
r = session.get(prefix_url("/"), allow_redirects=True)
except requests.RequestException as e:
_exception.handle_requests_error(e)
_exception.handle_http_error(r.status_code)
@@ -532,3 +547,10 @@ class Session:
return message_ids[0]
except (KeyError, IndexError, TypeError) as e:
raise _exception.ParseError("No message IDs could be found", data=j) from e
def _uri_share_data(self, data):
data["image_height"] = 960
data["image_width"] = 960
data["__user"] = self.user.id
j = self._post("/message_share_attachment/fromURI/", data)
return j["payload"]["share_data"]

View File

@@ -105,6 +105,7 @@ class ThreadABC(metaclass=abc.ABCMeta):
mentions: Iterable["_models.Mention"] = None,
files: Iterable[Tuple[str, str]] = None,
reply_to_id: str = None,
uri: str = None
) -> str:
"""Send a message to the thread.
@@ -114,6 +115,7 @@ class ThreadABC(metaclass=abc.ABCMeta):
files: Optional tuples, each containing an uploaded file's ID and mimetype.
See `ThreadABC.send_files` for an example.
reply_to_id: Optional message to reply to
uri: Uri to formulate a sharable attachment with
Example:
Send a message with a mention to a thread.
@@ -139,6 +141,9 @@ class ThreadABC(metaclass=abc.ABCMeta):
if files:
data["has_attachment"] = True
if uri:
data.update(self._generate_shareable_attachment(uri))
for i, (file_id, mimetype) in enumerate(files or ()):
data["{}s[{}]".format(_util.mimetype_to_key(mimetype), i)] = file_id
@@ -236,6 +241,52 @@ class ThreadABC(metaclass=abc.ABCMeta):
"""
return self.send_text(text=None, files=files)
def send_uri(self, uri: str, **kwargs):
"""Send a uri preview to a thread.
Args:
uri: uri to preview
"""
if kwargs.get('text') is None:
kwargs['text'] = None
self.send_text(uri=uri, **kwargs)
def _generate_shareable_attachment(self, uri):
"""Send a uri preview to a thread.
Args:
uri: uri to preview
Returns:
:ref:`Message ID <intro_message_ids>` of the sent message
Raises:
FBchatException: If request failed
"""
url_data = self.session._uri_share_data({"uri": uri})
data = self._to_send_data()
data["action_type"] = "ma-type:user-generated-message"
data["shareable_attachment[share_type]"] = url_data["share_type"]
# Most uri params will come back as dict
if isinstance(url_data["share_params"], dict):
data["has_attachment"] = True
for key in url_data["share_params"]:
if isinstance(url_data["share_params"][key], dict):
for key2 in url_data["share_params"][key]:
data[
"shareable_attachment[share_params][{}][{}]".format(
key, key2
)
] = url_data["share_params"][key][key2]
else:
data[
"shareable_attachment[share_params][{}]".format(key)
] = url_data["share_params"][key]
# Some (such as facebook profile pages) will just be a list
else:
data["has_attachment"] = False
for index, val in enumerate(url_data["share_params"]):
data["shareable_attachment[share_params][{}]".format(index)] = val
return data
# xmd = {"quick_replies": []}
# for quick_reply in quick_replies:
# # TODO: Move this to `_quick_reply.py`