diff --git a/fbchat/client.py b/fbchat/client.py index 46981550..8e995148 100644 --- a/fbchat/client.py +++ b/fbchat/client.py @@ -12,8 +12,6 @@ from .graphql import * import time - - class Client(object): """A client for the Facebook Chat (Messenger). @@ -735,14 +733,16 @@ def fetchThreadMessages(self, thread_id=None, limit=20, before=None): :param limit: Max. number of messages to retrieve :param before: A timestamp, indicating from which point to retrieve messages :type limit: int - :type before: int + :type before: datetime :return: :class:`models.Message` objects :rtype: list :raises: FBchatException if request failed """ - thread_id, thread_type = self._getThread(thread_id, None) + if before is not None: + before = int(unix_time_millis(before)) + j = self.graphql_request(GraphQL(doc_id='1386147188135407', params={ 'id': thread_id, 'message_limit': limit, @@ -764,7 +764,7 @@ def fetchThreadList(self, offset=None, limit=20, thread_location=ThreadLocation. :param thread_location: models.ThreadLocation: INBOX, PENDING, ARCHIVED or OTHER :param before: A timestamp (in milliseconds), indicating from which point to retrieve threads :type limit: int - :type before: int + :type before: datetime :return: :class:`models.Thread` objects :rtype: list :raises: FBchatException if request failed @@ -781,6 +781,9 @@ def fetchThreadList(self, offset=None, limit=20, thread_location=ThreadLocation. else: raise FBchatUserError('"thread_location" must be a value of ThreadLocation') + if before is not None: + before = unix_time_millis(before) + j = self.graphql_request(GraphQL(doc_id='1349387578499440', params={ 'limit': limit, 'tags': [loc_str], diff --git a/fbchat/graphql.py b/fbchat/graphql.py index 323a0467..d6d5fe4c 100644 --- a/fbchat/graphql.py +++ b/fbchat/graphql.py @@ -5,6 +5,7 @@ import re from .models import * from .utils import * +from datetime import datetime # Shameless copy from https://stackoverflow.com/a/8730674 FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL @@ -141,7 +142,9 @@ def graphql_to_message(message): ) rtn.uid = str(message.get('message_id')) rtn.author = str(message.get('message_sender').get('id')) - rtn.timestamp = message.get('timestamp_precise') + + rtn.timestamp = millis_to_datetime(message.get('timestamp_precise')) + if message.get('unread') is not None: rtn.is_read = not message['unread'] rtn.reactions = {str(r['user']['id']):MessageReaction(r['reaction']) for r in message.get('message_reactions')} @@ -183,7 +186,7 @@ def graphql_to_thread(thread): user = next(p for p in participants if p['id'] == thread['thread_key']['other_user_id']) last_message_timestamp = None if 'last_message' in thread: - last_message_timestamp = thread['last_message']['nodes'][0]['timestamp_precise'] + last_message_timestamp = millis_to_datetime(thread['last_message']['nodes'][0]['timestamp_precise']) return User( user['id'], @@ -211,7 +214,7 @@ def graphql_to_group(group): c_info = get_customization_info(group) last_message_timestamp = None if 'last_message' in group: - last_message_timestamp = group['last_message']['nodes'][0]['timestamp_precise'] + last_message_timestamp = millis_to_datetime(group['last_message']['nodes'][0]['timestamp_precise']) return Group( group['thread_key']['thread_fbid'], participants=set([node['messaging_actor']['id'] for node in group['all_participants']['nodes']]), diff --git a/fbchat/utils.py b/fbchat/utils.py index 87eef262..d71c013b 100644 --- a/fbchat/utils.py +++ b/fbchat/utils.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals import re import json +from datetime import datetime from time import time from random import random import warnings @@ -29,6 +30,9 @@ handler = logging.StreamHandler() log.addHandler(handler) +# Unix epoch +epoch = datetime.utcfromtimestamp(0) + #: Default list of user agents USER_AGENTS = [ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36", @@ -233,3 +237,11 @@ def get_emojisize_from_tags(tags): except (KeyError, IndexError): log.exception('Could not determine emoji size from {} - {}'.format(tags, tmp)) return None + +def unix_time_millis(dt): + return (dt - epoch).total_seconds() * 1000.0 + +def millis_to_datetime(t): + if isinstance(t, str): + t = float(t) + return datetime.fromtimestamp(t / 1000.0)