Update client.py

This commit is contained in:
kapi2289
2018-07-31 00:03:19 +02:00
committed by GitHub
parent f6f47b5500
commit 21a443baf2

View File

@@ -11,6 +11,7 @@ from .utils import *
from .models import *
from .graphql import *
import time
import ast
try:
from urllib.parse import urlparse, parse_qs
except ImportError:
@@ -185,6 +186,25 @@ class Client(object):
"""
return self.graphql_requests(query)[0]
def _forcedFetch(self, thread_id, mid):
full_data = {
"av": self.uid,
"batch_name": "MessengerMessageDFFFetcher",
"queries": """{
"o0": {
"doc_id": "1768656253222505",
"query_params": {
"thread_and_message_id": {
"thread_id": "%s",
"message_id": "%s"
}
}
}
}""" % (thread_id, mid)
}
r = self._post(self.req_url.GRAPHQL, full_data, fix_request=False, as_json=True)
return ast.literal_eval(get_decoded_r(r).replace("\n","").replace("\r","").replace(" ","").replace("}{", ",").replace(":null", ":None").replace("true", "True").replace("false", "False"))
"""
END INTERNAL REQUEST METHODS
"""
@@ -1066,7 +1086,7 @@ class Client(object):
data['action_type'] = 'ma-type:log-message'
data['log_message_type'] = 'log:subscribe'
if type(user_ids) is not list:
if not isinstance(user_ids, list):
user_ids = [user_ids]
# Make list of users unique
@@ -1098,6 +1118,25 @@ class Client(object):
j = self._post(self.req_url.REMOVE_USER, data, fix_request=True, as_json=True)
def _adminStatus(self, admin_ids, admin, thread_id=None):
thread_id, thread_type = self._getThread(thread_id, None)
data = {
"add": str(admin).lower(),
"thread_fbid": thread_id
}
if not isinstance(admin_ids, list):
admin_ids = [admin_ids]
# Make list of admins unique
admin_ids = set(admin_ids)
for i, admin_id in enumerate(admin_ids):
data['admin_ids[' + str(i) + ']'] = str(admin_id)
j = self._post(self.req_url.SAVE_ADMINS, data, fix_request=True, as_json=True)
def addGroupAdmins(self, admin_ids, thread_id=None):
"""
Sets specifed user as a group admin.
@@ -1106,49 +1145,17 @@ class Client(object):
:param thread_id: Group ID to remove people from. See :ref:`intro_threads`
:raises: FBchatException if request failed
"""
thread_id, thread_type = self._getThread(thread_id, None)
data = {
"add": "true",
"thread_fbid": thread_id
}
if type(admin_ids) is not list:
admin_ids = [admin_ids]
# Make list of admins unique
admin_ids = set(admin_ids)
for i, admin_id in enumerate(admin_ids):
data['admin_ids[' + str(i) + ']'] = str(admin_id)
j = self._post(self.req_url.SAVE_ADMINS, data, fix_request=True, as_json=True)
self._adminStatus(admin_ids, True, thread_id)
def removeGroupAdmins(self, admin_ids, thread_id=None):
"""
Removes group admin from specifed user.
Removes admin status from specifed user.
:param admin_ids: One or more user IDs to remove admin
:param thread_id: Group ID to remove people from. See :ref:`intro_threads`
:raises: FBchatException if request failed
"""
thread_id, thread_type = self._getThread(thread_id, None)
data = {
"add": "false",
"thread_fbid": thread_id
}
if type(admin_ids) is not list:
admin_ids = [admin_ids]
# Make list of admins unique
admin_ids = set(admin_ids)
for i, admin_id in enumerate(admin_ids):
data['admin_ids[' + str(i) + ']'] = str(admin_id)
j = self._post(self.req_url.SAVE_ADMINS, data, fix_request=True, as_json=True)
self._adminStatus(admin_ids, False, thread_id)
def changeGroupApprovalMode(self, approval_mode, thread_id=None):
"""
@@ -1430,7 +1437,7 @@ class Client(object):
r = self._post(self.req_url.DELIVERED, data)
return r.ok
def markAsRead(self, thread_id):
def markAsRead(self, thread_id=None):
"""
Mark a thread as read
All messages inside the thread will be marked as read
@@ -1439,6 +1446,7 @@ class Client(object):
:return: Whether the request was successful
:raises: FBchatException if request failed
"""
thread_id, thread_type = self._getThread(thread_id, None)
data = {
"ids[%s]" % thread_id: 'true',
"watermarkTimestamp": now(),
@@ -1517,7 +1525,7 @@ class Client(object):
r = self._post(self.req_url.UNBLOCK_USER, data)
return r.ok
def moveThread(self, location, thread_id=None):
def moveThreads(self, location, thread_ids=None):
"""
Moves the thread to specifed location
@@ -1528,6 +1536,12 @@ class Client(object):
:return: Whether the request was successful
:raises: FBchatException if request failed
"""
if not isinstance(thread_ids, list):
thread_ids = [thread_ids]
# Make list of admins unique
thread_ids = set(thread_ids)
if location == ThreadLocation.PENDING:
location = ThreadLocation.OTHER
if location in ThreadLocation:
@@ -1535,19 +1549,18 @@ class Client(object):
else:
raise FBchatUserError('"location" must be a value of ThreadLocation')
if location == ThreadLocation.ARCHIVED:
data_archive = {
"ids[{}]".format(thread_id): 'true'
}
data_archive = dict()
data_unpin = dict()
for thread_id in thread_ids:
data_archive["ids[{}]".format(thread_id)] = 'true'
data_unpin["ids[{}]".format(thread_id)] = 'false'
r_archive = self._post(self.req_url.ARCHIVED_STATUS, data_archive)
data_unpin = {
"ids[{}]".format(thread_id): 'false'
}
r_unpin = self._post(self.req_url.PINNED_STATUS, data_unpin)
return r_archive.ok and r_unpin.ok
else:
data = {
"{}[0]".format(loc_str): thread_id
}
data = dict()
for i, thread_id in enumerate(thread_ids):
data["{}[{}]".format(loc_str, i)] = thread_id
r = self._post(self.req_url.MOVE_THREAD, data)
return r.ok
@@ -1667,11 +1680,18 @@ class Client(object):
self.onTitleChange(mid=mid, author_id=author_id, new_title=new_title, thread_id=thread_id,
thread_type=thread_type, ts=ts, metadata=metadata, msg=m)
# Thread image change
# Forced fetch
elif delta.get("class") == "ForcedFetch":
mid = delta.get("messageId")
thread_id = str(delta['threadKey']['threadFbId'])
self.onImageChange(mid=mid, thread_id=thread_id)
fetch_info = self._forcedFetch(thread_id, mid)
fetch_data = fetch_info["o0"]["data"]["message"]
author_id = fetch_data["message_sender"]["id"]
ts = fetch_data["timestamp_precise"]
if fetch_data.get("__typename") == "ThreadImageMessage":
# Thread image change
image_id = fetch_data["image_with_metadata"]["legacy_attachment_id"]
self.onImageChange(mid=mid, image_id=image_id, author_id=author_id, thread_id=thread_id, ts=ts)
# Nickname change
elif delta_type == "change_thread_nickname":
@@ -1732,6 +1752,21 @@ class Client(object):
# thread_id, thread_type = getThreadIdAndThreadType(delta)
self.onMarkedSeen(threads=threads, seen_ts=seen_ts, ts=delivered_ts, metadata=delta, msg=m)
# Game played
elif delta.get("type") == "instant_game_update":
game_id = delta["untypedData"]["game_id"]
game_name = delta["untypedData"]["game_name"]
score = delta["untypedData"].get("score")
if score is not None:
score = int(score)
leaderboard = delta["untypedData"].get("leaderboard")
if leaderboard is not None:
leaderboard = ast.literal_eval(leaderboard.replace(":null",":None"))["scores"]
thread_id, thread_type = getThreadIdAndThreadType(metadata)
self.onGamePlayed(mid=mid, author_id=author_id, game_id=game_id, game_name=game_name,
score=score, leaderboard=leaderboard, thread_id=thread_id,
thread_type=thread_type, ts=ts, metadata=metadata, msg=m)
# New message
elif delta.get("class") == "NewMessage":
@@ -2016,16 +2051,17 @@ class Client(object):
log.info("Title change from {} in {} ({}): {}".format(author_id, thread_id, thread_type.name, new_title))
def onImageChange(self, mid=None, thread_id=None):
def onImageChange(self, mid=None, image_id=None, author_id=None, thread_id=None, ts=None):
"""
.. todo::
Add author_id and image_id
Called when the client is listening, and somebody changes the image of a thread
:param mid: The action ID
:param image_id: The ID of the new image
:param author_id: The ID of the person who changed the image
:param thread_id: Thread ID that the action was sent to. See :ref:`intro_threads`
:param ts: A timestamp of the action
"""
log.info("Image change in {}".format(author_id, thread_id))
log.info("{} changed thread image in {}".format(author_id, thread_id))
def onNicknameChange(self, mid=None, author_id=None, changed_for=None, new_nickname=None, thread_id=None, thread_type=ThreadType.USER, ts=None, metadata=None, msg=None):
@@ -2195,6 +2231,24 @@ class Client(object):
:type thread_type: models.ThreadType
"""
pass
def onGamePlayed(self, mid=None, author_id=None, game_id=None, game_name=None, score=None, leaderboard=None, thread_id=None, thread_type=None, ts=None, metadata=None, msg=None):
"""
Called when the client is listening, and somebody plays a game
:param mid: The action ID
:param author_id: The ID of the person who played the game
:param game_id: The ID of the game
:param game_name: Name of the game
:param score: Score obtained in the game
:param leaderboard: Actual leaderboard of the game in the thread
:param thread_type: Type of thread that the action was sent to. See :ref:`intro_threads`
:param ts: A timestamp of the action
:param metadata: Extra metadata about the action
:param msg: A full set of the data recieved
:type thread_type: models.ThreadType
"""
log.info("{} played \"{}\" in {} ({})".format(author_id, game_name, thread_id, thread_type.name))
def onQprimer(self, ts=None, msg=None):
"""