Added support for sending images
This commit is contained in:
@@ -15,7 +15,7 @@ from .client import *
|
|||||||
|
|
||||||
|
|
||||||
__copyright__ = 'Copyright 2015 by Taehoon Kim'
|
__copyright__ = 'Copyright 2015 by Taehoon Kim'
|
||||||
__version__ = '0.3.1'
|
__version__ = '0.4.0'
|
||||||
__license__ = 'BSD'
|
__license__ = 'BSD'
|
||||||
__author__ = 'Taehoon Kim; Moreels Pieter-Jan'
|
__author__ = 'Taehoon Kim; Moreels Pieter-Jan'
|
||||||
__email__ = 'carpedm20@gmail.com'
|
__email__ = 'carpedm20@gmail.com'
|
||||||
|
@@ -6,15 +6,18 @@
|
|||||||
|
|
||||||
Facebook Chat (Messenger) for Python
|
Facebook Chat (Messenger) for Python
|
||||||
|
|
||||||
:copyright: (c) 2015 by Taehoon Kim.
|
:copyright: (c) 2015 by Taehoon Kim.
|
||||||
|
:copyright: (c) 2015-2016 by PidgeyL.
|
||||||
:license: BSD, see LICENSE for more details.
|
:license: BSD, see LICENSE for more details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
import json
|
||||||
from uuid import uuid1
|
from uuid import uuid1
|
||||||
from random import random, choice
|
from random import random, choice
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from bs4 import BeautifulSoup as bs
|
from bs4 import BeautifulSoup as bs
|
||||||
|
from mimetypes import guess_type
|
||||||
|
|
||||||
from .utils import *
|
from .utils import *
|
||||||
from .models import *
|
from .models import *
|
||||||
@@ -34,6 +37,8 @@ BaseURL ="https://www.facebook.com"
|
|||||||
MobileURL ="https://m.facebook.com/"
|
MobileURL ="https://m.facebook.com/"
|
||||||
StickyURL ="https://0-edge-chat.facebook.com/pull"
|
StickyURL ="https://0-edge-chat.facebook.com/pull"
|
||||||
PingURL ="https://0-channel-proxy-06-ash2.facebook.com/active_ping"
|
PingURL ="https://0-channel-proxy-06-ash2.facebook.com/active_ping"
|
||||||
|
UploadURL ="https://upload.facebook.com/ajax/mercury/upload.php"
|
||||||
|
|
||||||
|
|
||||||
class Client(object):
|
class Client(object):
|
||||||
"""A client for the Facebook Chat (Messenger).
|
"""A client for the Facebook Chat (Messenger).
|
||||||
@@ -117,7 +122,12 @@ class Client(object):
|
|||||||
def _cleanPost(self, url, query=None, timeout=30):
|
def _cleanPost(self, url, query=None, timeout=30):
|
||||||
self.req_counter += 1
|
self.req_counter += 1
|
||||||
return self._session.post(url, headers=self._header, data=query, timeout=timeout)
|
return self._session.post(url, headers=self._header, data=query, timeout=timeout)
|
||||||
|
|
||||||
|
def _postFile(self, url, files=None, timeout=30):
|
||||||
|
payload=self._generatePayload(None)
|
||||||
|
return self._session.post(url, data=payload, timeout=timeout, files=files)
|
||||||
|
|
||||||
|
|
||||||
def login(self):
|
def login(self):
|
||||||
if not (self.email and self.password):
|
if not (self.email and self.password):
|
||||||
raise Exception("id and password or config is needed")
|
raise Exception("id and password or config is needed")
|
||||||
@@ -195,21 +205,30 @@ class Client(object):
|
|||||||
users.append(User(entry))
|
users.append(User(entry))
|
||||||
return users # have bug TypeError: __repr__ returned non-string (type bytes)
|
return users # have bug TypeError: __repr__ returned non-string (type bytes)
|
||||||
|
|
||||||
def send(self, thread_id, message=None, like=None):
|
def send(self, recipient_id, message=None, message_type='user', like=None, image_id=None):
|
||||||
"""Send a message with given thread id
|
"""Send a message with given thread id
|
||||||
|
|
||||||
:param thread_id: a thread id that you want to send a message
|
:param recipient_id: the user id or thread id that you want to send a message to
|
||||||
:param message: a text that you want to send
|
:param message: a text that you want to send
|
||||||
|
:param message_type: determines if the recipient_id is for user or thread
|
||||||
:param like: size of the like sticker you want to send
|
:param like: size of the like sticker you want to send
|
||||||
|
:param image_id: id for the image to send, gotten from the UploadURL
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if message_type.lower() == 'group':
|
||||||
|
thread_id = recipient_id
|
||||||
|
user_id = None
|
||||||
|
else:
|
||||||
|
thread_id = None
|
||||||
|
user_id = recipient_id
|
||||||
|
|
||||||
timestamp = now()
|
timestamp = now()
|
||||||
date = datetime.now()
|
date = datetime.now()
|
||||||
data = {
|
data = {
|
||||||
'client' : self.client,
|
'client' : self.client,
|
||||||
'message_batch[0][action_type]' : 'ma-type:user-generated-message',
|
'message_batch[0][action_type]' : 'ma-type:user-generated-message',
|
||||||
'message_batch[0][author]' : 'fbid:' + str(self.uid),
|
'message_batch[0][author]' : 'fbid:' + str(self.uid),
|
||||||
'message_batch[0][specific_to_list][0]' : 'fbid:' + str(thread_id),
|
'message_batch[0][specific_to_list][0]' : 'fbid:' + str(recipient_id),
|
||||||
'message_batch[0][specific_to_list][1]' : 'fbid:' + str(self.uid),
|
'message_batch[0][specific_to_list][1]' : 'fbid:' + str(self.uid),
|
||||||
'message_batch[0][timestamp]' : timestamp,
|
'message_batch[0][timestamp]' : timestamp,
|
||||||
'message_batch[0][timestamp_absolute]' : 'Today',
|
'message_batch[0][timestamp_absolute]' : 'Today',
|
||||||
@@ -229,8 +248,12 @@ class Client(object):
|
|||||||
'message_batch[0][message_id]' : generateMessageID(self.client_id),
|
'message_batch[0][message_id]' : generateMessageID(self.client_id),
|
||||||
'message_batch[0][manual_retry_cnt]' : '0',
|
'message_batch[0][manual_retry_cnt]' : '0',
|
||||||
'message_batch[0][thread_fbid]' : thread_id,
|
'message_batch[0][thread_fbid]' : thread_id,
|
||||||
'message_batch[0][has_attachment]' : False
|
'message_batch[0][has_attachment]' : image_id != None,
|
||||||
|
'message_batch[0][other_user_fbid]' : user_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if image_id:
|
||||||
|
data['message_batch[0][image_ids][0]'] = image_id
|
||||||
|
|
||||||
if like:
|
if like:
|
||||||
try:
|
try:
|
||||||
@@ -243,7 +266,40 @@ class Client(object):
|
|||||||
r = self._post(SendURL, data)
|
r = self._post(SendURL, data)
|
||||||
return r.ok
|
return r.ok
|
||||||
|
|
||||||
|
def sendRemoteImage(self, recipient_id, message=None, message_type='user', image=''):
|
||||||
|
"""Send an image from a URL
|
||||||
|
|
||||||
|
:param recipient_id: the user id or thread id that you want to send a message to
|
||||||
|
:param message: a text that you want to send
|
||||||
|
:param message_type: determines if the recipient_id is for user or thread
|
||||||
|
:param image: URL for an image to download and send
|
||||||
|
"""
|
||||||
|
mimetype = guess_type(image)[0]
|
||||||
|
remote_image = requests.get(image).content
|
||||||
|
image_id = self.uploadImage({'file': (image, remote_image, mimetype)})
|
||||||
|
return self.send(recipient_id, message, message_type, None, image_id)
|
||||||
|
|
||||||
|
def sendLocalImage(self, recipient_id, message=None, message_type='user', image=''):
|
||||||
|
"""Send an image from a file path
|
||||||
|
|
||||||
|
:param recipient_id: the user id or thread id that you want to send a message to
|
||||||
|
:param message: a text that you want to send
|
||||||
|
:param message_type: determines if the recipient_id is for user or thread
|
||||||
|
:param image: path to a local image to send
|
||||||
|
"""
|
||||||
|
mimetype = guess_type(image)[0]
|
||||||
|
image_id = self.uploadImage({'file': (image, open(image), mimetype)})
|
||||||
|
return self.send(recipient_id, message, message_type, None, image_id)
|
||||||
|
|
||||||
|
def uploadImage(self, image):
|
||||||
|
"""Upload an image and get the image_id for sending in a message
|
||||||
|
|
||||||
|
:param image: a tuple of (file name, data, mime type) to upload to facebook
|
||||||
|
"""
|
||||||
|
r = self._postFile(UploadURL, image)
|
||||||
|
# Strip the start and parse out the returned image_id
|
||||||
|
return json.loads(r._content[9:])['payload']['metadata'][0]['image_id']
|
||||||
|
|
||||||
def getThreadInfo(self, userID, start, end=None):
|
def getThreadInfo(self, userID, start, end=None):
|
||||||
"""Get the info of one Thread
|
"""Get the info of one Thread
|
||||||
|
|
||||||
@@ -428,21 +484,29 @@ class Client(object):
|
|||||||
name = m['message']['sender_name']
|
name = m['message']['sender_name']
|
||||||
self.on_message(mid, fbid, name, message, m)
|
self.on_message(mid, fbid, name, message, m)
|
||||||
elif m['type'] in ['typ']:
|
elif m['type'] in ['typ']:
|
||||||
self.on_typing(m["from"])
|
self.on_typing(m.get("from"))
|
||||||
elif m['type'] in ['m_read_receipt']:
|
elif m['type'] in ['m_read_receipt']:
|
||||||
self.on_read(m['realtime_viewer_fbid'], m['reader'], m['time'])
|
self.on_read(m.get('realtime_viewer_fbid'), m.get('reader'), m.get('time'))
|
||||||
elif m['type'] in ['inbox']:
|
elif m['type'] in ['inbox']:
|
||||||
viewer = m['realtime_viewer_fbid']
|
viewer = m.get('realtime_viewer_fbid')
|
||||||
unseen = m['unseen']
|
unseen = m.get('unseen')
|
||||||
unread = m['unread']
|
unread = m.get('unread')
|
||||||
other_unseen = m['other_unseen']
|
other_unseen = m.get('other_unseen')
|
||||||
other_unread = m['other_unread']
|
other_unread = m.get('other_unread')
|
||||||
timestamp = m['seen_timestamp']
|
timestamp = m.get('seen_timestamp')
|
||||||
self.on_inbox(viewer, unseen, unread, other_unseen, other_unread, timestamp)
|
self.on_inbox(viewer, unseen, unread, other_unseen, other_unread, timestamp)
|
||||||
elif m['type'] in ['qprimer']:
|
elif m['type'] in ['qprimer']:
|
||||||
self.on_qprimer(m['made'])
|
self.on_qprimer(m.get('made'))
|
||||||
|
elif m['type'] in ['delta']:
|
||||||
|
if 'messageMetadata' in m['delta']:
|
||||||
|
mid = m['delta']['messageMetadata']['messageId']
|
||||||
|
message = m['delta']['body']
|
||||||
|
fbid = m['delta']['messageMetadata']['threadKey']['otherUserFbId']
|
||||||
|
name = None
|
||||||
|
self.on_message(mid, fbid, name, message, m)
|
||||||
else:
|
else:
|
||||||
print(m)
|
if self.debug:
|
||||||
|
print(m)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.on_message_error(e, m)
|
self.on_message_error(e, m)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user