Added support for sending images

This commit is contained in:
John Westhoff
2016-08-12 01:19:11 -04:00
committed by John Westhoff
2 changed files with 82 additions and 18 deletions

View File

@@ -15,7 +15,7 @@ from .client import *
__copyright__ = 'Copyright 2015 by Taehoon Kim'
__version__ = '0.3.1'
__version__ = '0.4.0'
__license__ = 'BSD'
__author__ = 'Taehoon Kim; Moreels Pieter-Jan'
__email__ = 'carpedm20@gmail.com'

View File

@@ -6,15 +6,18 @@
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.
"""
import requests
import json
from uuid import uuid1
from random import random, choice
from datetime import datetime
from bs4 import BeautifulSoup as bs
from mimetypes import guess_type
from .utils import *
from .models import *
@@ -34,6 +37,8 @@ BaseURL ="https://www.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"
UploadURL ="https://upload.facebook.com/ajax/mercury/upload.php"
class Client(object):
"""A client for the Facebook Chat (Messenger).
@@ -118,6 +123,11 @@ class Client(object):
self.req_counter += 1
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):
if not (self.email and self.password):
raise Exception("id and password or config is needed")
@@ -195,21 +205,30 @@ class Client(object):
users.append(User(entry))
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
: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_type: determines if the recipient_id is for user or thread
: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()
date = datetime.now()
data = {
'client' : self.client,
'message_batch[0][action_type]' : 'ma-type:user-generated-message',
'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][timestamp]' : timestamp,
'message_batch[0][timestamp_absolute]' : 'Today',
@@ -229,9 +248,13 @@ class Client(object):
'message_batch[0][message_id]' : generateMessageID(self.client_id),
'message_batch[0][manual_retry_cnt]' : '0',
'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:
try:
sticker = LIKES[like.lower()]
@@ -243,6 +266,39 @@ class Client(object):
r = self._post(SendURL, data)
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):
"""Get the info of one Thread
@@ -428,21 +484,29 @@ class Client(object):
name = m['message']['sender_name']
self.on_message(mid, fbid, name, message, m)
elif m['type'] in ['typ']:
self.on_typing(m["from"])
self.on_typing(m.get("from"))
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']:
viewer = m['realtime_viewer_fbid']
unseen = m['unseen']
unread = m['unread']
other_unseen = m['other_unseen']
other_unread = m['other_unread']
timestamp = m['seen_timestamp']
viewer = m.get('realtime_viewer_fbid')
unseen = m.get('unseen')
unread = m.get('unread')
other_unseen = m.get('other_unseen')
other_unread = m.get('other_unread')
timestamp = m.get('seen_timestamp')
self.on_inbox(viewer, unseen, unread, other_unseen, other_unread, timestamp)
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:
print(m)
if self.debug:
print(m)
except Exception as e:
self.on_message_error(e, m)