Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
023fd58f05 | ||
|
ad10a8f07f | ||
|
7d6cf039d4 | ||
|
f0271e17b0 | ||
|
57954816b2 | ||
|
3e4e1f9bb9 | ||
|
7340918209 | ||
|
707df4f941 | ||
|
8eb6b83411 | ||
|
e0aedd617b | ||
|
ee81620c14 | ||
|
2d027af71a | ||
|
9d5f06b810 | ||
|
b8fdcda2fb | ||
|
0dac7b7b81 | ||
|
b750e753d6 | ||
|
ee33e92bed | ||
|
7413a643f6 |
@@ -17,7 +17,7 @@ from .client import *
|
|||||||
|
|
||||||
|
|
||||||
__copyright__ = 'Copyright 2015 - {} by Taehoon Kim'.format(datetime.now().year)
|
__copyright__ = 'Copyright 2015 - {} by Taehoon Kim'.format(datetime.now().year)
|
||||||
__version__ = '1.0.20'
|
__version__ = '1.0.25'
|
||||||
__license__ = 'BSD'
|
__license__ = 'BSD'
|
||||||
__author__ = 'Taehoon Kim; Moreels Pieter-Jan; Mads Marquart'
|
__author__ = 'Taehoon Kim; Moreels Pieter-Jan; Mads Marquart'
|
||||||
__email__ = 'carpedm20@gmail.com'
|
__email__ = 'carpedm20@gmail.com'
|
||||||
|
@@ -249,8 +249,9 @@ class Client(object):
|
|||||||
r = self._cleanPost(self.req_url.LOGIN, data)
|
r = self._cleanPost(self.req_url.LOGIN, data)
|
||||||
|
|
||||||
# Usually, 'Checkpoint' will refer to 2FA
|
# Usually, 'Checkpoint' will refer to 2FA
|
||||||
if ('checkpoint' in r.url and
|
if ('checkpoint' in r.url
|
||||||
('Enter Security Code to Continue' in r.text or 'Enter Login Code to Continue' in r.text)):
|
and ('enter security code to continue' in r.text.lower()
|
||||||
|
or 'enter login code to continue' in r.text.lower())):
|
||||||
r = self._2FA(r)
|
r = self._2FA(r)
|
||||||
|
|
||||||
# Sometimes Facebook tries to show the user a "Save Device" dialog
|
# Sometimes Facebook tries to show the user a "Save Device" dialog
|
||||||
@@ -747,11 +748,12 @@ class Client(object):
|
|||||||
|
|
||||||
return list(reversed([graphql_to_message(message) for message in j['message_thread']['messages']['nodes']]))
|
return list(reversed([graphql_to_message(message) for message in j['message_thread']['messages']['nodes']]))
|
||||||
|
|
||||||
def fetchThreadList(self, offset=0, limit=20):
|
def fetchThreadList(self, offset=0, limit=20, thread_location=ThreadLocation.INBOX):
|
||||||
"""Get thread list of your facebook account
|
"""Get thread list of your facebook account
|
||||||
|
|
||||||
:param offset: The offset, from where in the list to recieve threads from
|
:param offset: The offset, from where in the list to recieve threads from
|
||||||
:param limit: Max. number of threads to retrieve. Capped at 20
|
:param limit: Max. number of threads to retrieve. Capped at 20
|
||||||
|
:param thread_location: models.ThreadLocation: INBOX, PENDING, ARCHIVED or OTHER
|
||||||
:type offset: int
|
:type offset: int
|
||||||
:type limit: int
|
:type limit: int
|
||||||
:return: :class:`models.Thread` objects
|
:return: :class:`models.Thread` objects
|
||||||
@@ -762,10 +764,15 @@ class Client(object):
|
|||||||
if limit > 20 or limit < 1:
|
if limit > 20 or limit < 1:
|
||||||
raise FBchatUserError('`limit` should be between 1 and 20')
|
raise FBchatUserError('`limit` should be between 1 and 20')
|
||||||
|
|
||||||
|
if thread_location in ThreadLocation:
|
||||||
|
loc_str = thread_location.value
|
||||||
|
else:
|
||||||
|
raise FBchatUserError('"thread_location" must be a value of ThreadLocation')
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'client' : self.client,
|
'client' : self.client,
|
||||||
'inbox[offset]' : offset,
|
loc_str + '[offset]' : offset,
|
||||||
'inbox[limit]' : limit,
|
loc_str + '[limit]' : limit,
|
||||||
}
|
}
|
||||||
|
|
||||||
j = self._post(self.req_url.THREADS, data, fix_request=True, as_json=True)
|
j = self._post(self.req_url.THREADS, data, fix_request=True, as_json=True)
|
||||||
@@ -773,6 +780,7 @@ class Client(object):
|
|||||||
raise FBchatException('Missing payload: {}, with data: {}'.format(j, data))
|
raise FBchatException('Missing payload: {}, with data: {}'.format(j, data))
|
||||||
|
|
||||||
participants = {}
|
participants = {}
|
||||||
|
if 'participants' in j['payload']:
|
||||||
for p in j['payload']['participants']:
|
for p in j['payload']['participants']:
|
||||||
if p['type'] == 'page':
|
if p['type'] == 'page':
|
||||||
participants[p['fbid']] = Page(p['fbid'], url=p['href'], photo=p['image_src'], name=p['name'])
|
participants[p['fbid']] = Page(p['fbid'], url=p['href'], photo=p['image_src'], name=p['name'])
|
||||||
@@ -782,6 +790,7 @@ class Client(object):
|
|||||||
raise FBchatException('A participant had an unknown type {}: {}'.format(p['type'], p))
|
raise FBchatException('A participant had an unknown type {}: {}'.format(p['type'], p))
|
||||||
|
|
||||||
entries = []
|
entries = []
|
||||||
|
if 'threads' in j['payload']:
|
||||||
for k in j['payload']['threads']:
|
for k in j['payload']['threads']:
|
||||||
if k['thread_type'] == 1:
|
if k['thread_type'] == 1:
|
||||||
if k['other_user_fbid'] not in participants:
|
if k['other_user_fbid'] not in participants:
|
||||||
@@ -948,9 +957,12 @@ class Client(object):
|
|||||||
)
|
)
|
||||||
}, fix_request=True, as_json=True)
|
}, fix_request=True, as_json=True)
|
||||||
# Return the image_id
|
# Return the image_id
|
||||||
|
if not mimetype == 'image/gif':
|
||||||
return j['payload']['metadata'][0]['image_id']
|
return j['payload']['metadata'][0]['image_id']
|
||||||
|
else:
|
||||||
|
return j['payload']['metadata'][0]['gif_id']
|
||||||
|
|
||||||
def sendImage(self, image_id, message=None, thread_id=None, thread_type=ThreadType.USER):
|
def sendImage(self, image_id, message=None, thread_id=None, thread_type=ThreadType.USER, is_gif=False):
|
||||||
"""
|
"""
|
||||||
Sends an already uploaded image to a thread. (Used by :func:`Client.sendRemoteImage` and :func:`Client.sendLocalImage`)
|
Sends an already uploaded image to a thread. (Used by :func:`Client.sendRemoteImage` and :func:`Client.sendLocalImage`)
|
||||||
|
|
||||||
@@ -958,6 +970,7 @@ class Client(object):
|
|||||||
:param message: Additional message
|
:param message: Additional message
|
||||||
:param thread_id: User/Group ID to send to. See :ref:`intro_threads`
|
:param thread_id: User/Group ID to send to. See :ref:`intro_threads`
|
||||||
:param thread_type: See :ref:`intro_threads`
|
:param thread_type: See :ref:`intro_threads`
|
||||||
|
:param is_gif: if sending GIF, True, else False
|
||||||
:type thread_type: models.ThreadType
|
:type thread_type: models.ThreadType
|
||||||
:return: :ref:`Message ID <intro_message_ids>` of the sent image
|
:return: :ref:`Message ID <intro_message_ids>` of the sent image
|
||||||
:raises: FBchatException if request failed
|
:raises: FBchatException if request failed
|
||||||
@@ -971,7 +984,10 @@ class Client(object):
|
|||||||
data['specific_to_list[0]'] = 'fbid:' + str(thread_id)
|
data['specific_to_list[0]'] = 'fbid:' + str(thread_id)
|
||||||
data['specific_to_list[1]'] = 'fbid:' + str(self.uid)
|
data['specific_to_list[1]'] = 'fbid:' + str(self.uid)
|
||||||
|
|
||||||
|
if not is_gif:
|
||||||
data['image_ids[0]'] = image_id
|
data['image_ids[0]'] = image_id
|
||||||
|
else:
|
||||||
|
data['gif_ids[0]'] = image_id
|
||||||
|
|
||||||
return self._doSendRequest(data)
|
return self._doSendRequest(data)
|
||||||
|
|
||||||
@@ -989,9 +1005,10 @@ class Client(object):
|
|||||||
"""
|
"""
|
||||||
thread_id, thread_type = self._getThread(thread_id, thread_type)
|
thread_id, thread_type = self._getThread(thread_id, thread_type)
|
||||||
mimetype = guess_type(image_url)[0]
|
mimetype = guess_type(image_url)[0]
|
||||||
|
is_gif = (mimetype == 'image/gif')
|
||||||
remote_image = requests.get(image_url).content
|
remote_image = requests.get(image_url).content
|
||||||
image_id = self._uploadImage(image_url, remote_image, mimetype)
|
image_id = self._uploadImage(image_url, remote_image, mimetype)
|
||||||
return self.sendImage(image_id=image_id, message=message, thread_id=thread_id, thread_type=thread_type)
|
return self.sendImage(image_id=image_id, message=message, thread_id=thread_id, thread_type=thread_type, is_gif=is_gif)
|
||||||
|
|
||||||
def sendLocalImage(self, image_path, message=None, thread_id=None, thread_type=ThreadType.USER):
|
def sendLocalImage(self, image_path, message=None, thread_id=None, thread_type=ThreadType.USER):
|
||||||
"""
|
"""
|
||||||
@@ -1007,8 +1024,9 @@ class Client(object):
|
|||||||
"""
|
"""
|
||||||
thread_id, thread_type = self._getThread(thread_id, thread_type)
|
thread_id, thread_type = self._getThread(thread_id, thread_type)
|
||||||
mimetype = guess_type(image_path)[0]
|
mimetype = guess_type(image_path)[0]
|
||||||
|
is_gif = (mimetype == 'image/gif')
|
||||||
image_id = self._uploadImage(image_path, open(image_path, 'rb'), mimetype)
|
image_id = self._uploadImage(image_path, open(image_path, 'rb'), mimetype)
|
||||||
return self.sendImage(image_id=image_id, message=message, thread_id=thread_id, thread_type=thread_type)
|
return self.sendImage(image_id=image_id, message=message, thread_id=thread_id, thread_type=thread_type, is_gif=is_gif)
|
||||||
|
|
||||||
def addUsersToGroup(self, user_ids, thread_id=None):
|
def addUsersToGroup(self, user_ids, thread_id=None):
|
||||||
"""
|
"""
|
||||||
@@ -1541,7 +1559,7 @@ class Client(object):
|
|||||||
|
|
||||||
def on2FACode(self):
|
def on2FACode(self):
|
||||||
"""Called when a 2FA code is needed to progress"""
|
"""Called when a 2FA code is needed to progress"""
|
||||||
input('Please enter your 2FA code --> ')
|
return input('Please enter your 2FA code --> ')
|
||||||
|
|
||||||
def onLoggedIn(self, email=None):
|
def onLoggedIn(self, email=None):
|
||||||
"""
|
"""
|
||||||
|
@@ -193,6 +193,13 @@ class ThreadType(Enum):
|
|||||||
GROUP = 2
|
GROUP = 2
|
||||||
PAGE = 3
|
PAGE = 3
|
||||||
|
|
||||||
|
class ThreadLocation(Enum):
|
||||||
|
"""Used to specify where a thread is located (inbox, pending, archived, other)."""
|
||||||
|
INBOX = 'inbox'
|
||||||
|
PENDING = 'pending'
|
||||||
|
ARCHIVED = 'action:archived'
|
||||||
|
OTHER = 'other'
|
||||||
|
|
||||||
class TypingStatus(Enum):
|
class TypingStatus(Enum):
|
||||||
"""Used to specify whether the user is typing or has stopped typing"""
|
"""Used to specify whether the user is typing or has stopped typing"""
|
||||||
STOPPED = 0
|
STOPPED = 0
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
requests
|
requests
|
||||||
lxml
|
lxml
|
||||||
beautifulsoup4
|
beautifulsoup4
|
||||||
enum34
|
enum34; python_version < '3.4'
|
||||||
|
17
setup.py
17
setup.py
@@ -4,22 +4,24 @@
|
|||||||
"""
|
"""
|
||||||
Setup script for fbchat
|
Setup script for fbchat
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
try:
|
try:
|
||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from distutils.core import setup
|
from distutils.core import setup
|
||||||
|
|
||||||
|
|
||||||
with open('README.rst') as f:
|
with open('README.rst') as f:
|
||||||
readme_content = f.read().strip()
|
readme_content = f.read().strip()
|
||||||
|
|
||||||
try:
|
requirements = [
|
||||||
requirements = [line.rstrip('\n') for line in open(os.path.join('fbchat.egg-info', 'requires.txt'))]
|
'requests',
|
||||||
except IOError:
|
'lxml',
|
||||||
requirements = [line.rstrip('\n') for line in open('requirements.txt')]
|
'beautifulsoup4'
|
||||||
|
]
|
||||||
|
|
||||||
|
extras_requirements = {
|
||||||
|
':python_version < "3.4"': ['enum34']
|
||||||
|
}
|
||||||
|
|
||||||
version = None
|
version = None
|
||||||
author = None
|
author = None
|
||||||
@@ -75,6 +77,7 @@ setup(
|
|||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
packages=['fbchat'],
|
packages=['fbchat'],
|
||||||
install_requires=requirements,
|
install_requires=requirements,
|
||||||
|
extras_require=extras_requirements,
|
||||||
url=source,
|
url=source,
|
||||||
version=version,
|
version=version,
|
||||||
zip_safe=True,
|
zip_safe=True,
|
||||||
|
Reference in New Issue
Block a user