Compare commits

...

5 Commits

Author SHA1 Message Date
Mads Marquart
900a9cdf72 Version up, thanks to @gave92
`fetchThreadList` is updated with a GraphQL implementation. See #241
2018-02-18 22:40:13 +01:00
Mads Marquart
611b329934 Merge pull request #259 from gave92/fetchThreadListGraphQL
Added GraphQL alternative to fetchThreadList; fixes #241
2018-02-18 22:36:23 +01:00
Mads Marquart
2642788bc1 Merged fetchThreadListGraphQL into fetchThreadList 2018-02-18 22:32:12 +01:00
Marco Gavelli
8268445f0b Changed return type for ONE_TO_ONE to User 2018-02-18 22:49:47 +01:00
Marco Gavelli
c12dcd9263 Added GraphQL alternative to fetchThreadList; fixes #241 2018-02-17 14:29:31 +01:00
4 changed files with 47 additions and 50 deletions

View File

@@ -17,7 +17,7 @@ from .client import *
__copyright__ = 'Copyright 2015 - {} by Taehoon Kim'.format(datetime.now().year)
__version__ = '1.3.1'
__version__ = '1.3.2'
__license__ = 'BSD'
__author__ = 'Taehoon Kim; Moreels Pieter-Jan; Mads Marquart'
__email__ = 'carpedm20@gmail.com'

View File

@@ -754,19 +754,23 @@ class Client(object):
return list(reversed([graphql_to_message(message) for message in j['message_thread']['messages']['nodes']]))
def fetchThreadList(self, offset=0, limit=20, thread_location=ThreadLocation.INBOX):
def fetchThreadList(self, offset=0, limit=20, thread_location=ThreadLocation.INBOX, before=None):
"""Get thread list of your facebook account
:param offset: The offset, from where in the list to recieve threads from
:param offset: Deprecated. Do not use!
:param limit: Max. number of threads to retrieve. Capped at 20
:param thread_location: models.ThreadLocation: INBOX, PENDING, ARCHIVED or OTHER
:type offset: int
:param before: A timestamp (in milliseconds), indicating from which point to retrieve threads
:type limit: int
:type before: int
:return: :class:`models.Thread` objects
:rtype: list
:raises: FBchatException if request failed
"""
if offset is not None:
log.warning('Using `offset` in `fetchThreadList` is no longer supported, since Facebook migrated to the use of GraphQL in this request. Use `before` instead')
if limit > 20 or limit < 1:
raise FBchatUserError('`limit` should be between 1 and 20')
@@ -775,52 +779,15 @@ class Client(object):
else:
raise FBchatUserError('"thread_location" must be a value of ThreadLocation')
data = {
'client' : self.client,
loc_str + '[offset]' : offset,
loc_str + '[limit]' : limit,
}
j = self.graphql_request(GraphQL(doc_id='1349387578499440', params={
'limit': limit,
'tags': [loc_str],
'before': before,
'includeDeliveryReceipts': True,
'includeSeqID': False
}))
j = self._post(self.req_url.THREADS, data, fix_request=True, as_json=True)
if j.get('payload') is None:
raise FBchatException('Missing payload: {}, with data: {}'.format(j, data))
participants = {}
if 'participants' in j['payload']:
for p in j['payload']['participants']:
if p['type'] == 'page':
participants[p['fbid']] = Page(p['fbid'], url=p['href'], photo=p['image_src'], name=p['name'])
elif p['type'] == 'user':
participants[p['fbid']] = User(p['fbid'], url=p['href'], first_name=p['short_name'], is_friend=p['is_friend'], gender=GENDERS.get(p['gender']), photo=p['image_src'], name=p['name'])
else:
raise FBchatException('A participant had an unknown type {}: {}'.format(p['type'], p))
entries = []
if 'threads' in j['payload']:
for k in j['payload']['threads']:
if k['thread_type'] == 1:
if k['other_user_fbid'] not in participants:
raise FBchatException('The thread {} was not in participants: {}'.format(k, j['payload']))
participants[k['other_user_fbid']].message_count = k['message_count']
entries.append(participants[k['other_user_fbid']])
elif k['thread_type'] == 2:
entries.append(Group(k['thread_fbid'], participants=set([p.strip('fbid:') for p in k['participants']]), photo=k['image_src'], name=k['name'], message_count=k['message_count']))
elif k['thread_type'] == 3:
entries.append(Room(
k['thread_fbid'],
participants = set(p.lstrip('fbid:') for p in k['participants']),
photo = k['image_src'],
name = k['name'],
message_count = k['message_count'],
admins = set(p.lstrip('fbid:') for p in k['admin_ids']),
approval_mode = k['approval_mode'],
approval_requests = set(p.lstrip('fbid:') for p in k['approval_queue_ids']),
join_link = k['joinable_mode']['link']
))
else:
raise FBchatException('A thread had an unknown thread type: {}'.format(k))
return entries
return [graphql_to_thread(node) for node in j['viewer']['message_threads']['nodes']]
def fetchUnread(self):
"""

View File

@@ -172,6 +172,35 @@ 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('big_image_src') is None:
thread['big_image_src'] = {}
c_info = get_customization_info(thread)
participants = [node['messaging_actor'] for node in thread['all_participants']['nodes']]
user = next(p for p in participants if p['id'] == thread['thread_key']['other_user_id'])
return User(
user['id'],
url=user.get('url'),
name=user.get('name'),
first_name=user.get('short_name'),
last_name=user.get('name').split(user.get('short_name'),1)[1].strip(),
is_friend=user.get('is_viewer_friend'),
gender=GENDERS.get(user.get('gender')),
affinity=user.get('affinity'),
nickname=c_info.get('nickname'),
color=c_info.get('color'),
emoji=c_info.get('emoji'),
own_nickname=c_info.get('own_nickname'),
photo=user['big_image_src'].get('uri'),
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'] = {}

View File

@@ -123,7 +123,8 @@ class TestFbchat(unittest.TestCase):
self.assertTrue(client.sendLocalImage(image_local_url, Message(text='test_send_image_local_to__@you★', mentions=mentions)))
def test_fetchThreadList(self):
client.fetchThreadList(offset=0, limit=20)
threads = client.fetchThreadList(limit=2)
self.assertEqual(len(threads), 2)
def test_fetchThreadMessages(self):
for thread in threads: