diff --git a/fbchat/client.py b/fbchat/client.py index 9dcd1ea..729c764 100644 --- a/fbchat/client.py +++ b/fbchat/client.py @@ -20,6 +20,8 @@ class Client(object): See https://fbchat.readthedocs.io for complete documentation of the API. """ + ssl_verify = True + """Verify ssl certificate, set to False to allow debugging with Fiddler""" listening = False """Whether the client is listening. Used when creating an external event loop to determine when to stop listening""" uid = None @@ -105,7 +107,7 @@ class Client(object): def _get(self, url, query=None, timeout=30, fix_request=False, as_json=False, error_retries=3): payload = self._generatePayload(query) - r = self._session.get(url, headers=self._header, params=payload, timeout=timeout) + r = self._session.get(url, headers=self._header, params=encode_params(payload), timeout=timeout, verify=self.ssl_verify) if not fix_request: return r try: @@ -117,7 +119,7 @@ class Client(object): def _post(self, url, query=None, timeout=30, fix_request=False, as_json=False, error_retries=3): payload = self._generatePayload(query) - r = self._session.post(url, headers=self._header, data=payload, timeout=timeout) + r = self._session.post(url, headers=self._header, data=encode_params(payload), timeout=timeout, verify=self.ssl_verify) if not fix_request: return r try: @@ -137,11 +139,11 @@ class Client(object): raise e def _cleanGet(self, url, query=None, timeout=30): - return self._session.get(url, headers=self._header, params=query, timeout=timeout) + return self._session.get(url, headers=self._header, params=encode_params(query), timeout=timeout, verify=self.ssl_verify) def _cleanPost(self, url, query=None, timeout=30): self.req_counter += 1 - return self._session.post(url, headers=self._header, data=query, timeout=timeout) + return self._session.post(url, headers=self._header, data=encode_params(query), timeout=timeout, verify=self.ssl_verify) def _postFile(self, url, files=None, query=None, timeout=30, fix_request=False, as_json=False, error_retries=3): payload=self._generatePayload(query) @@ -805,9 +807,7 @@ class Client(object): j = self._post(self.req_url.UNREAD_THREADS, form, fix_request=True, as_json=True) - return { - "unread_threads": j['payload']['unread_thread_fbids'] - } + return j['payload']['unread_thread_fbids'][0]['other_user_fbids'] def fetchUnseen(self): """ @@ -816,13 +816,9 @@ class Client(object): :raises: FBchatException if request failed """ - form = {} + j = self._post(self.req_url.UNSEEN_THREADS, None, fix_request=True, as_json=True) - j = self._post(self.req_url.UNSEEN_THREADS, form, fix_request=True, as_json=True) - - return { - "unseen_threads": j['payload']['unseen_thread_fbids'] - } + return j['payload']['unseen_thread_fbids'][0]['other_user_fbids'] def fetchImageUrl(self, image_id): """Fetches the url to the original image from an image attachment ID @@ -1266,7 +1262,6 @@ class Client(object): "ids[%s]" % threadID: True, "watermarkTimestamp": now(), "shouldSendReadReceipt": True, - "commerce_last_message_type": "", } r = self._post(self.req_url.READ_STATUS, data) diff --git a/fbchat/utils.py b/fbchat/utils.py index b26bf47..72bbcfe 100644 --- a/fbchat/utils.py +++ b/fbchat/utils.py @@ -9,6 +9,11 @@ import warnings import logging from .models import * +try: + from urllib.parse import urlencode +except ImportError: + from urllib import urlencode + # Python 2's `input` executes the input, whereas `raw_input` just returns the input try: input = raw_input @@ -226,3 +231,35 @@ def get_emojisize_from_tags(tags): except (KeyError, IndexError): log.exception('Could not determine emoji size from {} - {}'.format(tags, tmp)) return None + +def encode_params(data): + """Encode parameters in a piece of data. + + Will successfully encode parameters when passed as a dict or a list of + 2-tuples. Order is retained if data is a list of 2-tuples but arbitrary + if parameters are supplied as a dict. + """ + + if isinstance(data, (str, bytes)): + return data + elif hasattr(data, 'read'): + return data + elif hasattr(data, '__iter__'): + result = [] + for k, vs in list(data.items()): + if isinstance(vs, basestring) or not hasattr(vs, '__iter__'): + vs = [vs] + for v in vs: + if v is not None: + if isinstance(v, bool): + result.append( + (k.encode('utf-8') if isinstance(k, str) else k, + str(v).lower())) + else: + result.append( + (k.encode('utf-8') if isinstance(k, str) else k, + v.encode('utf-8') if isinstance(v, str) else v)) + return urlencode(result, doseq=True) + else: + return data +