From c12dcd9263002424cbdadf4fda291da688d230b7 Mon Sep 17 00:00:00 2001 From: Marco Gavelli Date: Sat, 17 Feb 2018 14:29:31 +0100 Subject: [PATCH] Added GraphQL alternative to fetchThreadList; fixes #241 --- fbchat/client.py | 30 ++++++++++++++++++++++++++++++ fbchat/graphql.py | 20 ++++++++++++++++++++ tests.py | 4 ++++ 3 files changed, 54 insertions(+) diff --git a/fbchat/client.py b/fbchat/client.py index 71f99d3..6471543 100644 --- a/fbchat/client.py +++ b/fbchat/client.py @@ -754,6 +754,36 @@ class Client(object): return list(reversed([graphql_to_message(message) for message in j['message_thread']['messages']['nodes']])) + def fetchThreadListGraphQL(self, limit=20, thread_location=ThreadLocation.INBOX, before=None): + """Get thread list of your facebook account + + :param limit: Max. number of threads to retrieve. Capped at 20 + :param thread_location: models.ThreadLocation: INBOX, PENDING, ARCHIVED or OTHER + :param before: A timestamp, indicating from which point to retrieve messages + :type limit: int + :type before: int + :return: :class:`models.Thread` objects + :rtype: list + :raises: FBchatException if request failed + """ + + if limit > 20 or limit < 1: + raise FBchatUserError('`limit` should be between 1 and 20') + + if thread_location in ThreadLocation: + loc_str = thread_location.value + else: + raise FBchatUserError('"thread_location" must be a value of ThreadLocation') + + j = self.graphql_request(GraphQL(doc_id='1349387578499440', params={ + 'limit': limit, + 'tags': [loc_str], + 'before': before, + 'includeDeliveryReceipts': True, + 'includeSeqID': False})) + + return [graphql_to_thread(node) for node in j['viewer']['message_threads']['nodes']] + def fetchThreadList(self, offset=0, limit=20, thread_location=ThreadLocation.INBOX): """Get thread list of your facebook account diff --git a/fbchat/graphql.py b/fbchat/graphql.py index 33c3e6b..75df1b4 100644 --- a/fbchat/graphql.py +++ b/fbchat/graphql.py @@ -172,6 +172,26 @@ def graphql_to_user(user): message_count=user.get('messages_count') ) +def graphql_to_thread(thread): + if thread['thread_type'] == 'GROUP': + return graphql_to_group(thread) + elif thread['thread_type'] == 'ONE_TO_ONE': + if thread.get('image') is None: + thread['image'] = {} + c_info = get_customization_info(thread) + return Group( + thread['thread_key']['other_user_id'], + participants=set([node['messaging_actor']['id'] for node in thread['all_participants']['nodes']]), + nicknames=c_info.get('nicknames'), + color=c_info.get('color'), + emoji=c_info.get('emoji'), + photo=thread['image'].get('uri'), + name=thread.get('name'), + message_count=thread.get('messages_count') + ) + else: + raise FBchatException('Unknown thread type: {}, with data: {}'.format(thread.get('thread_type'), thread)) + def graphql_to_group(group): if group.get('image') is None: group['image'] = {} diff --git a/tests.py b/tests.py index 08a101b..a02f9fe 100644 --- a/tests.py +++ b/tests.py @@ -122,6 +122,10 @@ class TestFbchat(unittest.TestCase): self.assertTrue(client.sendRemoteImage(image_url, Message(text='test_send_image_remote_to_@you★', mentions=mentions))) self.assertTrue(client.sendLocalImage(image_local_url, Message(text='test_send_image_local_to__@you★', mentions=mentions))) + def test_fetchThreadListGraphQL(self): + threads = client.fetchThreadListGraphQL(limit=10) + self.assertEqual(len(threads), 10) + def test_fetchThreadList(self): client.fetchThreadList(offset=0, limit=20)