@@ -15,9 +15,9 @@ from .client import *
|
|||||||
|
|
||||||
|
|
||||||
__copyright__ = 'Copyright 2015 by Taehoon Kim'
|
__copyright__ = 'Copyright 2015 by Taehoon Kim'
|
||||||
__version__ = '0.2.3'
|
__version__ = '0.3.0'
|
||||||
__license__ = 'BSD'
|
__license__ = 'BSD'
|
||||||
__author__ = 'Taehoon Kim'
|
__author__ = 'Taehoon Kim; Moreels Pieter-Jan'
|
||||||
__email__ = 'carpedm20@gmail.com'
|
__email__ = 'carpedm20@gmail.com'
|
||||||
__source__ = 'https://github.com/carpedm20/fbchat/'
|
__source__ = 'https://github.com/carpedm20/fbchat/'
|
||||||
|
|
||||||
|
117
fbchat/client.py
117
fbchat/client.py
@@ -32,6 +32,8 @@ DeliveredURL ="https://www.facebook.com/ajax/mercury/delivery_receipts.php"
|
|||||||
MarkSeenURL ="https://www.facebook.com/ajax/mercury/mark_seen.php"
|
MarkSeenURL ="https://www.facebook.com/ajax/mercury/mark_seen.php"
|
||||||
BaseURL ="https://www.facebook.com"
|
BaseURL ="https://www.facebook.com"
|
||||||
MobileURL ="https://m.facebook.com/"
|
MobileURL ="https://m.facebook.com/"
|
||||||
|
StickyURL ="https://0-edge-chat.facebook.com/pull"
|
||||||
|
PingURL ="https://0-channel-proxy-06-ash2.facebook.com/active_ping"
|
||||||
|
|
||||||
class Client(object):
|
class Client(object):
|
||||||
"""A client for the Facebook Chat (Messenger).
|
"""A client for the Facebook Chat (Messenger).
|
||||||
@@ -199,6 +201,7 @@ class Client(object):
|
|||||||
:param message: a text that you want to send
|
:param message: a text that you want to send
|
||||||
:param like: size of the like sticker you want to send
|
:param like: size of the like sticker you want to send
|
||||||
"""
|
"""
|
||||||
|
|
||||||
timestamp = now()
|
timestamp = now()
|
||||||
date = datetime.now()
|
date = datetime.now()
|
||||||
data = {
|
data = {
|
||||||
@@ -346,3 +349,117 @@ class Client(object):
|
|||||||
r = self._post(MarkSeenURL, {"seen_timestamp": 0})
|
r = self._post(MarkSeenURL, {"seen_timestamp": 0})
|
||||||
return r.ok
|
return r.ok
|
||||||
|
|
||||||
|
|
||||||
|
def ping(self, sticky):
|
||||||
|
data={
|
||||||
|
'channel': self.user_channel,
|
||||||
|
'clientid': self.client_id,
|
||||||
|
'partition': -2,
|
||||||
|
'cap': 0,
|
||||||
|
'uid': self.uid,
|
||||||
|
'sticky': sticky,
|
||||||
|
'viewer_uid': self.uid
|
||||||
|
}
|
||||||
|
r = self._get(PingURL, data)
|
||||||
|
return r.ok
|
||||||
|
|
||||||
|
|
||||||
|
def _getSticky(self):
|
||||||
|
'''
|
||||||
|
Call pull api to get sticky and pool parameter,
|
||||||
|
newer api needs these parameter to work.
|
||||||
|
'''
|
||||||
|
data={ "msgs_recv": 0 }
|
||||||
|
|
||||||
|
r = self._get(StickyURL, data)
|
||||||
|
j = get_json(r.text)
|
||||||
|
|
||||||
|
if 'lb_info' not in j:
|
||||||
|
raise Exception('Get sticky pool error')
|
||||||
|
|
||||||
|
sticky = j['lb_info']['sticky']
|
||||||
|
pool = j['lb_info']['pool']
|
||||||
|
return sticky, pool
|
||||||
|
|
||||||
|
|
||||||
|
def _pullMessage(self, sticky, pool):
|
||||||
|
'''
|
||||||
|
Call pull api with seq value to get message data.
|
||||||
|
'''
|
||||||
|
data={
|
||||||
|
"msgs_recv": 0,
|
||||||
|
"sticky_token":sticky,
|
||||||
|
"sticky_pool":pool
|
||||||
|
}
|
||||||
|
|
||||||
|
r = self._get(StickyURL, data)
|
||||||
|
j = get_json(r.text)
|
||||||
|
|
||||||
|
self.seq = j.get('seq', '0')
|
||||||
|
return j
|
||||||
|
|
||||||
|
|
||||||
|
def _parseMessage(self, content):
|
||||||
|
'''
|
||||||
|
Get message and author name from content.
|
||||||
|
May contains multiple messages in the content.
|
||||||
|
'''
|
||||||
|
if 'ms' not in content:
|
||||||
|
return
|
||||||
|
for m in content['ms']:
|
||||||
|
if m['type'] in ['m_messaging', 'messaging']:
|
||||||
|
try:
|
||||||
|
mid = m['message']['mid']
|
||||||
|
message=m['message']['body']
|
||||||
|
fbid = m['message']['sender_fbid']
|
||||||
|
name = m['message']['sender_name']
|
||||||
|
self.on_message(mid, fbid, name, message, m)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
elif m['type'] in ['typ']:
|
||||||
|
try:
|
||||||
|
fbid = m["from"]
|
||||||
|
self.on_typing(fbid)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
elif m['type'] in ['m_read_receipt']:
|
||||||
|
try:
|
||||||
|
author = m['author']
|
||||||
|
reader = m['reader']
|
||||||
|
time = m['time']
|
||||||
|
self.on_read(author, reader, time)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
print(m)
|
||||||
|
|
||||||
|
def listen(self, markAlive=True):
|
||||||
|
self.listening = True
|
||||||
|
sticky, pool = self._getSticky()
|
||||||
|
|
||||||
|
if self.debug:
|
||||||
|
print("Listening...")
|
||||||
|
|
||||||
|
while self.listening:
|
||||||
|
try:
|
||||||
|
if markAlive: self.ping(sticky)
|
||||||
|
try:
|
||||||
|
content = self._pullMessage(sticky, pool)
|
||||||
|
self._parseMessage(content)
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
continue
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
break
|
||||||
|
except requests.exceptions.Timeout:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_message(self, mid, author_id, author_name, message, metadata):
|
||||||
|
self.markAsDelivered(author_id, mid)
|
||||||
|
self.markAsRead(author_id)
|
||||||
|
print("%s said: %s"%(author_name, message))
|
||||||
|
|
||||||
|
def on_typing(self, author_id):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_read(self, author, reader, time):
|
||||||
|
pass
|
||||||
|
@@ -15,7 +15,7 @@ def now():
|
|||||||
return int(time()*1000)
|
return int(time()*1000)
|
||||||
|
|
||||||
def get_json(text):
|
def get_json(text):
|
||||||
return json.loads(re.sub(r"for.*(.*;.*;.*).*;", '', text.encode('utf-8').decode("unicode-escape"), 1))
|
return json.loads(re.sub(r"for.*(.*;.*;.*).*;", '', text.encode('utf-8').decode("unicode-escape"), 1))
|
||||||
|
|
||||||
def digit_to_char(digit):
|
def digit_to_char(digit):
|
||||||
if digit < 10:
|
if digit < 10:
|
||||||
|
Reference in New Issue
Block a user