Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
19c875c18a | ||
|
12bbc0058c | ||
|
9c81806b95 | ||
|
45303005b8 | ||
|
881aa9adce | ||
|
4714be5697 | ||
|
cb7f4a72d7 | ||
|
fb63ff0db8 | ||
|
c5f447e20b | ||
|
b4d3769fd5 |
@@ -1,5 +1,5 @@
|
||||
[bumpversion]
|
||||
current_version = 1.9.0
|
||||
current_version = 1.9.5
|
||||
commit = True
|
||||
tag = True
|
||||
|
||||
|
@@ -13,7 +13,7 @@ from ._client import Client
|
||||
from ._util import log # TODO: Remove this (from examples too)
|
||||
|
||||
__title__ = "fbchat"
|
||||
__version__ = "1.9.0"
|
||||
__version__ = "1.9.5"
|
||||
__description__ = "Facebook Chat (Messenger) for Python"
|
||||
|
||||
__copyright__ = "Copyright 2015 - 2019 by Taehoon Kim"
|
||||
|
@@ -2271,6 +2271,16 @@ class Client(object):
|
||||
elif delta_class == "ForcedFetch":
|
||||
mid = delta.get("messageId")
|
||||
if mid is None:
|
||||
if delta["threadKey"] is not None:
|
||||
# Looks like the whole delta is metadata in this case
|
||||
thread_id, thread_type = getThreadIdAndThreadType(delta)
|
||||
self.onPendingMessage(
|
||||
thread_id=thread_id,
|
||||
thread_type=thread_type,
|
||||
metadata=delta,
|
||||
msg=delta,
|
||||
)
|
||||
else:
|
||||
self.onUnknownMesssageType(msg=delta)
|
||||
else:
|
||||
thread_id = str(delta["threadKey"]["threadFbId"])
|
||||
@@ -2727,6 +2737,14 @@ class Client(object):
|
||||
msg=delta,
|
||||
)
|
||||
|
||||
# New pending message
|
||||
elif delta_class == "ThreadFolder" and delta.get("folder") == "FOLDER_PENDING":
|
||||
# Looks like the whole delta is metadata in this case
|
||||
thread_id, thread_type = getThreadIdAndThreadType(delta)
|
||||
self.onPendingMessage(
|
||||
thread_id=thread_id, thread_type=thread_type, metadata=delta, msg=delta
|
||||
)
|
||||
|
||||
# Unknown message type
|
||||
else:
|
||||
self.onUnknownMesssageType(msg=delta)
|
||||
@@ -2768,9 +2786,15 @@ class Client(object):
|
||||
msg=m,
|
||||
)
|
||||
|
||||
elif topic == "jewel_requests_add":
|
||||
# Other notifications
|
||||
elif topic == "/legacy_web":
|
||||
# Friend request
|
||||
if m["type"] == "jewel_requests_add":
|
||||
from_id = m["from"]
|
||||
# TODO: from_id = str(from_id)
|
||||
self.onFriendRequest(from_id=from_id, msg=m)
|
||||
else:
|
||||
self.onUnknownMesssageType(msg=m)
|
||||
|
||||
# Chat timestamp / Buddylist overlay
|
||||
elif topic == "/orca_presence":
|
||||
@@ -2835,7 +2859,7 @@ class Client(object):
|
||||
self._mqtt.set_chat_on(self._markAlive)
|
||||
|
||||
# TODO: Remove on_error param
|
||||
return self._mqtt.loop_once(on_error=self.onListenError)
|
||||
return self._mqtt.loop_once(on_error=lambda e: self.onListenError(exception=e))
|
||||
|
||||
def stopListening(self):
|
||||
"""Stop the listening loop."""
|
||||
@@ -2943,6 +2967,21 @@ class Client(object):
|
||||
"""
|
||||
log.info("{} from {} in {}".format(message_object, thread_id, thread_type.name))
|
||||
|
||||
def onPendingMessage(
|
||||
self, thread_id=None, thread_type=None, metadata=None, msg=None
|
||||
):
|
||||
"""Called when the client is listening, and somebody that isn't
|
||||
connected with you on either Facebook or Messenger sends a message.
|
||||
After that, you need to use fetchThreadList to actually read the message.
|
||||
|
||||
Args:
|
||||
thread_id: Thread ID that the message was sent to. See :ref:`intro_threads`
|
||||
thread_type (ThreadType): Type of thread that the message was sent to. See :ref:`intro_threads`
|
||||
metadata: Extra metadata about the message
|
||||
msg: A full set of the data received
|
||||
"""
|
||||
log.info("New pending message from {}".format(thread_id))
|
||||
|
||||
def onColorChange(
|
||||
self,
|
||||
mid=None,
|
||||
|
@@ -31,9 +31,9 @@ class Mqtt(object):
|
||||
transport="websockets",
|
||||
)
|
||||
mqtt.enable_logger()
|
||||
# mqtt.max_inflight_messages_set(20)
|
||||
# mqtt.max_queued_messages_set(0) # unlimited
|
||||
# mqtt.message_retry_set(5)
|
||||
# mqtt.max_inflight_messages_set(20) # The rest will get queued
|
||||
# mqtt.max_queued_messages_set(0) # Unlimited messages can be queued
|
||||
# mqtt.message_retry_set(20) # Retry sending for at least 20 seconds
|
||||
# mqtt.reconnect_delay_set(min_delay=1, max_delay=120)
|
||||
# TODO: Is region (lla | atn | odn | others?) important?
|
||||
mqtt.tls_set()
|
||||
@@ -74,8 +74,8 @@ class Mqtt(object):
|
||||
def _on_message_handler(self, client, userdata, message):
|
||||
# Parse payload JSON
|
||||
try:
|
||||
j = _util.parse_json(message.payload)
|
||||
except _exception.FBchatFacebookError:
|
||||
j = _util.parse_json(message.payload.decode("utf-8"))
|
||||
except (_exception.FBchatFacebookError, UnicodeDecodeError):
|
||||
log.exception("Failed parsing MQTT data on %s as JSON", message.topic)
|
||||
return
|
||||
|
||||
@@ -122,6 +122,13 @@ class Mqtt(object):
|
||||
raise
|
||||
|
||||
def _on_connect_handler(self, client, userdata, flags, rc):
|
||||
if rc == 21:
|
||||
raise _exception.FBchatException(
|
||||
"Failed connecting. Maybe your cookies are wrong?"
|
||||
)
|
||||
if rc != 0:
|
||||
return # Don't try to send publish if the connection failed
|
||||
|
||||
# configure receiving messages.
|
||||
payload = {
|
||||
"sync_api_version": 10,
|
||||
@@ -228,7 +235,9 @@ class Mqtt(object):
|
||||
|
||||
headers = {
|
||||
# TODO: Make this access thread safe
|
||||
"Cookie": _util.get_cookie_header(self._state._session, self._HOST),
|
||||
"Cookie": _util.get_cookie_header(
|
||||
self._state._session, "https://edge-chat.facebook.com/chat"
|
||||
),
|
||||
"User-Agent": self._state._session.headers["User-Agent"],
|
||||
"Origin": "https://www.facebook.com",
|
||||
"Host": self._HOST,
|
||||
@@ -250,16 +259,19 @@ class Mqtt(object):
|
||||
return False # Stop listening
|
||||
|
||||
if rc != paho.mqtt.client.MQTT_ERR_SUCCESS:
|
||||
err = paho.mqtt.client.error_string(rc)
|
||||
|
||||
# If known/expected error
|
||||
if rc in [paho.mqtt.client.MQTT_ERR_CONN_LOST]:
|
||||
log.warning(err)
|
||||
if rc == paho.mqtt.client.MQTT_ERR_CONN_LOST:
|
||||
log.warning("Connection lost, retrying")
|
||||
elif rc == paho.mqtt.client.MQTT_ERR_NOMEM:
|
||||
# This error is wrongly classified
|
||||
# See https://github.com/eclipse/paho.mqtt.python/issues/340
|
||||
log.warning("Connection error, retrying")
|
||||
else:
|
||||
log.warning("MQTT Error: %s", err)
|
||||
err = paho.mqtt.client.error_string(rc)
|
||||
log.error("MQTT Error: %s", err)
|
||||
# For backwards compatibility
|
||||
if on_error:
|
||||
on_error(exception=FBchatException("MQTT Error {}".format(err)))
|
||||
on_error(_exception.FBchatException("MQTT Error {}".format(err)))
|
||||
|
||||
# Wait before reconnecting
|
||||
self._mqtt._reconnect_wait()
|
||||
@@ -273,8 +285,8 @@ class Mqtt(object):
|
||||
paho.mqtt.client.socket.error,
|
||||
OSError,
|
||||
paho.mqtt.client.WebsocketConnectionError,
|
||||
):
|
||||
log.debug("MQTT reconnection failed")
|
||||
) as e:
|
||||
log.debug("MQTT reconnection failed: %s", e)
|
||||
|
||||
return True # Keep listening
|
||||
|
||||
|
@@ -70,10 +70,11 @@ def strip_json_cruft(text):
|
||||
raise FBchatException("No JSON object found: {!r}".format(text))
|
||||
|
||||
|
||||
def get_cookie_header(session, host):
|
||||
def get_cookie_header(session, url):
|
||||
"""Extract a cookie header from a requests session."""
|
||||
# The cookies are extracted this way to make sure they're escaped correctly
|
||||
return requests.cookies.get_cookie_header(
|
||||
session.cookies, requests.Request("GET", host),
|
||||
session.cookies, requests.Request("GET", url),
|
||||
)
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user