diff --git a/fbchat/client.py b/fbchat/client.py index 778849a..e23e24f 100644 --- a/fbchat/client.py +++ b/fbchat/client.py @@ -553,6 +553,7 @@ class Client(object): elif node['__typename'] == 'Group': # We don't handle Facebook "Groups" pass + # TODO Add Rooms else: log.warning('Unknown __typename: {} in {}'.format(repr(node['__typename']), node)) @@ -707,6 +708,9 @@ class Client(object): if entry.get('thread_type') == 'GROUP': _id = entry['thread_key']['thread_fbid'] rtn[_id] = graphql_to_group(entry) + elif entry.get('thread_type') == 'ROOM': + _id = entry['thread_key']['thread_fbid'] + rtn[_id] = graphql_to_room(entry) elif entry.get('thread_type') == 'ONE_TO_ONE': _id = entry['thread_key']['other_user_id'] if pages_and_users.get(_id) is None: @@ -791,6 +795,9 @@ class Client(object): 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'])) + # TODO + elif k['thread_type'] == 4: + 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'])) else: raise FBchatException('A thread had an unknown thread type: {}'.format(k)) diff --git a/fbchat/graphql.py b/fbchat/graphql.py index 857d19e..821cdb4 100644 --- a/fbchat/graphql.py +++ b/fbchat/graphql.py @@ -42,7 +42,7 @@ def get_customization_info(thread): 'emoji': info.get('emoji'), 'color': graphql_color_to_enum(info.get('outgoing_bubble_color')) } - if thread.get('thread_type') == 'GROUP' or thread.get('is_group_thread') or thread.get('thread_key', {}).get('thread_fbid'): + if thread.get('thread_type') in ('GROUP', 'ROOM') or thread.get('is_group_thread') or thread.get('thread_key', {}).get('thread_fbid'): rtn['nicknames'] = {} for k in info.get('participant_customizations', []): rtn['nicknames'][k['participant_id']] = k.get('nickname') @@ -118,6 +118,26 @@ def graphql_to_group(group): message_count=group.get('messages_count') ) +def graphql_to_room(room): + if room.get('image') is None: + room['image'] = {} + c_info = get_customization_info(room) + return Room( + room['thread_key']['thread_fbid'], + participants=set([node['messaging_actor']['id'] for node in room['all_participants']['nodes']]), + nicknames=c_info.get('nicknames'), + color=c_info.get('color'), + emoji=c_info.get('emoji'), + photo=room['image'].get('uri'), + name=room.get('name'), + message_count=room.get('messages_count'), + admins = set([node.get('id') for node in room.get('thread_admins')]), + approval_mode = bool(room.get('approval_mode')), + approval_requests = set([node.get('id') for node in room['thread_queue_metatdata'].get('approval_requests')), + join_link = room['joinable_mode'].get('link'), + privacy_mode = bool(room.get('privacy_mode')), + ) + def graphql_to_page(page): if page.get('profile_picture') is None: page['profile_picture'] = {} diff --git a/fbchat/models.py b/fbchat/models.py index c61ceb1..613629f 100644 --- a/fbchat/models.py +++ b/fbchat/models.py @@ -109,6 +109,28 @@ class Group(Thread): self.emoji = emoji +class Room(Group): + # Set containing user IDs of thread admins + admins = set + # True if users need approval to join + approval_mode = bool + # Set containing user IDs requesting to join + approval_requests = set + # Link for joining room + join_link = str + # True is room is not discoverable + privacy_mode = bool + + def __init__(self, uid, admins=set(), approval_mode=None, approval_requests=set(), join_link=None, privacy_mode=None, **kwargs): + """Represents a Facebook room. Inherits `Group`""" + super(Room, self).__init__(ThreadType.ROOM, uid, **kwargs) + self.admins = admins + self.approval_mode = approval_mode + self.approval_requests = approval_requests + self.join_link = join_link + self.privacy_mode = privacy_mode + + class Page(Thread): #: The page's custom url url = str @@ -192,6 +214,7 @@ class ThreadType(Enum): USER = 1 GROUP = 2 PAGE = 3 + ROOM = 4 class TypingStatus(Enum): """Used to specify whether the user is typing or has stopped typing"""