Merge branch 'development' into master
This commit is contained in:
@@ -15,7 +15,7 @@ from .client import *
|
||||
|
||||
|
||||
__copyright__ = 'Copyright 2015 by Taehoon Kim'
|
||||
__version__ = '0.10.1'
|
||||
__version__ = '0.10.3'
|
||||
__license__ = 'BSD'
|
||||
__author__ = 'Taehoon Kim; Moreels Pieter-Jan'
|
||||
__email__ = 'carpedm20@gmail.com'
|
||||
|
901
fbchat/client.py
901
fbchat/client.py
File diff suppressed because it is too large
Load Diff
57
fbchat/event_hook.py
Normal file
57
fbchat/event_hook.py
Normal file
@@ -0,0 +1,57 @@
|
||||
import inspect
|
||||
|
||||
|
||||
class EventHook(object):
|
||||
"""
|
||||
A simple implementation of the Observer-Pattern.
|
||||
The user can specify an event signature upon inizializazion,
|
||||
defined by kwargs in the form of argumentname=class (e.g. id=int).
|
||||
The arguments' types are not checked in this implementation though.
|
||||
Callables with a fitting signature can be added with += or removed with -=.
|
||||
All listeners can be notified by calling the EventHook class with fitting
|
||||
arguments.
|
||||
|
||||
Thanks http://stackoverflow.com/a/35957226/5556222
|
||||
"""
|
||||
|
||||
def __init__(self, **signature):
|
||||
self._signature = signature
|
||||
self._argnames = set(signature.keys())
|
||||
self._handlers = []
|
||||
|
||||
def _kwargs_str(self):
|
||||
return ", ".join(k+"="+v.__name__ for k, v in self._signature.items())
|
||||
|
||||
def __iadd__(self, handler):
|
||||
params = inspect.signature(handler).parameters
|
||||
valid = True
|
||||
argnames = set(n for n in params.keys())
|
||||
if argnames != self._argnames:
|
||||
valid = False
|
||||
for p in params.values():
|
||||
if p.kind == p.VAR_KEYWORD:
|
||||
valid = True
|
||||
break
|
||||
if p.kind not in (p.POSITIONAL_OR_KEYWORD, p.KEYWORD_ONLY):
|
||||
valid = False
|
||||
break
|
||||
if not valid:
|
||||
raise ValueError("Listener must have these arguments: (%s)"
|
||||
% self._kwargs_str())
|
||||
self._handlers.append(handler)
|
||||
return self
|
||||
|
||||
def __isub__(self, handler):
|
||||
self._handlers.remove(handler)
|
||||
return self
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
if args or set(kwargs.keys()) != self._argnames:
|
||||
raise ValueError("This EventHook must be called with these " +
|
||||
"keyword arguments: (%s)" % self._kwargs_str() +
|
||||
", but was called with: (%s)" %self._signature)
|
||||
for handler in self._handlers[:]:
|
||||
handler(**kwargs)
|
||||
|
||||
def __repr__(self):
|
||||
return "EventHook(%s)" % self._kwargs_str()
|
@@ -1,15 +1,8 @@
|
||||
from __future__ import unicode_literals
|
||||
import sys
|
||||
from enum import Enum
|
||||
|
||||
class Base():
|
||||
def __repr__(self):
|
||||
uni = self.__unicode__()
|
||||
return uni.encode('utf-8') if sys.version_info < (3, 0) else uni
|
||||
|
||||
def __unicode__(self):
|
||||
return u'<%s %s (%s)>' % (self.type.upper(), self.name, self.url)
|
||||
|
||||
class User(Base):
|
||||
class User:
|
||||
def __init__(self, data):
|
||||
if data['type'] != 'user':
|
||||
raise Exception("[!] %s <%s> is not a user" % (data['text'], data['path']))
|
||||
@@ -19,13 +12,85 @@ class User(Base):
|
||||
self.url = data['path']
|
||||
self.name = data['text']
|
||||
self.score = data['score']
|
||||
|
||||
self.data = data
|
||||
|
||||
class Thread():
|
||||
def __repr__(self):
|
||||
uni = self.__unicode__()
|
||||
return uni.encode('utf-8') if sys.version_info < (3, 0) else uni
|
||||
|
||||
def __unicode__(self):
|
||||
return u'<%s %s (%s)>' % (self.type.upper(), self.name, self.url)
|
||||
|
||||
@staticmethod
|
||||
def adaptFromChat(user_in_chat):
|
||||
""" Adapts user info from chat to User model acceptable initial dict
|
||||
|
||||
:param user_in_chat: user info from chat
|
||||
|
||||
'dir': None,
|
||||
'mThumbSrcSmall': None,
|
||||
'is_friend': False,
|
||||
'is_nonfriend_messenger_contact': True,
|
||||
'alternateName': '',
|
||||
'i18nGender': 16777216,
|
||||
'vanity': '',
|
||||
'type': 'friend',
|
||||
'searchTokens': ['Voznesenskij', 'Sergej'],
|
||||
'thumbSrc': 'https://fb-s-b-a.akamaihd.net/h-ak-xfa1/v/t1.0-1/c9.0.32.32/p32x32/10354686_10150004552801856_220367501106153455_n.jpg?oh=71a87d76d4e4d17615a20c43fb8dbb47&oe=59118CE4&__gda__=1493753268_ae75cef40e9785398e744259ccffd7ff',
|
||||
'mThumbSrcLarge': None,
|
||||
'firstName': 'Sergej',
|
||||
'name': 'Sergej Voznesenskij',
|
||||
'uri': 'https://www.facebook.com/profile.php?id=100014812758264',
|
||||
'id': '100014812758264',
|
||||
'gender': 2
|
||||
"""
|
||||
|
||||
return {
|
||||
'type': 'user',
|
||||
'uid': user_in_chat['id'],
|
||||
'photo': user_in_chat['thumbSrc'],
|
||||
'path': user_in_chat['uri'],
|
||||
'text': user_in_chat['name'],
|
||||
'score': '',
|
||||
'data': user_in_chat,
|
||||
}
|
||||
|
||||
|
||||
class Thread:
|
||||
def __init__(self, **entries):
|
||||
self.__dict__.update(entries)
|
||||
|
||||
class Message():
|
||||
class Message:
|
||||
def __init__(self, **entries):
|
||||
self.__dict__.update(entries)
|
||||
|
||||
class ThreadType(Enum):
|
||||
USER = 1
|
||||
GROUP = 2
|
||||
|
||||
class TypingStatus(Enum):
|
||||
DELETED = 0
|
||||
TYPING = 1
|
||||
|
||||
class EmojiSize(Enum):
|
||||
LARGE = {
|
||||
'value': '369239383222810',
|
||||
'name': 'large'
|
||||
}
|
||||
MEDIUM = {
|
||||
'value': '369239343222814',
|
||||
'name': 'medium'
|
||||
}
|
||||
SMALL = {
|
||||
'value': '369239263222822',
|
||||
'name': 'small'
|
||||
}
|
||||
|
||||
LIKES = {
|
||||
'l': EmojiSize.LARGE,
|
||||
'm': EmojiSize.MEDIUM,
|
||||
's': EmojiSize.SMALL
|
||||
}
|
||||
LIKES['large'] = LIKES['l']
|
||||
LIKES['medium'] =LIKES['m']
|
||||
LIKES['small'] = LIKES['s']
|
||||
|
@@ -1,8 +0,0 @@
|
||||
LIKES={
|
||||
'l': '369239383222810',
|
||||
'm': '369239343222814',
|
||||
's': '369239263222822'
|
||||
}
|
||||
LIKES['large'] = LIKES['l']
|
||||
LIKES['medium'] =LIKES['m']
|
||||
LIKES['small'] = LIKES['s']
|
@@ -2,6 +2,7 @@ import re
|
||||
import json
|
||||
from time import time
|
||||
from random import random
|
||||
import warnings
|
||||
USER_AGENTS = [
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/601.1.10 (KHTML, like Gecko) Version/8.0.5 Safari/601.1.10",
|
||||
@@ -25,6 +26,7 @@ GENDERS = {
|
||||
11: 'unknown_plural',
|
||||
}
|
||||
|
||||
|
||||
def now():
|
||||
return int(time()*1000)
|
||||
|
||||
@@ -39,7 +41,7 @@ def digit_to_char(digit):
|
||||
return str(digit)
|
||||
return chr(ord('a') + digit - 10)
|
||||
|
||||
def str_base(number,base):
|
||||
def str_base(number, base):
|
||||
if number < 0:
|
||||
return '-' + str_base(-number, base)
|
||||
(d, m) = divmod(number, base)
|
||||
@@ -50,15 +52,42 @@ def str_base(number,base):
|
||||
def generateMessageID(client_id=None):
|
||||
k = now()
|
||||
l = int(random() * 4294967295)
|
||||
return ("<%s:%s-%s@mail.projektitan.com>" % (k, l, client_id));
|
||||
return "<%s:%s-%s@mail.projektitan.com>" % (k, l, client_id)
|
||||
|
||||
def getSignatureID():
|
||||
return hex(int(random() * 2147483648))
|
||||
|
||||
def generateOfflineThreadingID() :
|
||||
def generateOfflineThreadingID():
|
||||
ret = now()
|
||||
value = int(random() * 4294967295);
|
||||
value = int(random() * 4294967295)
|
||||
string = ("0000000000000000000000" + bin(value))[-22:]
|
||||
msgs = bin(ret) + string
|
||||
return str(int(msgs,2))
|
||||
return str(int(msgs, 2))
|
||||
|
||||
def isUserToThreadType(is_user):
|
||||
return ThreadType.USER if is_user else ThreadType.GROUP
|
||||
|
||||
def deprecation(name, deprecated_in=None, details='', stacklevel=3):
|
||||
"""This is a function which should be used to mark parameters as deprecated.
|
||||
It will result in a warning being emmitted when the parameter is used.
|
||||
"""
|
||||
warning = "{} is deprecated".format(name)
|
||||
if deprecated_in:
|
||||
warning += ' in v. {}'.format(deprecated_in)
|
||||
if details:
|
||||
warning += '. {}'.format(details)
|
||||
|
||||
warnings.simplefilter('always', DeprecationWarning)
|
||||
warnings.warn(warning, category=DeprecationWarning, stacklevel=stacklevel)
|
||||
warnings.simplefilter('default', DeprecationWarning)
|
||||
|
||||
def deprecated(deprecated_in=None, details=''):
|
||||
"""This is a decorator which can be used to mark functions as deprecated.
|
||||
It will result in a warning being emmitted when the decorated function is used.
|
||||
"""
|
||||
def wrap(func, *args, **kwargs):
|
||||
def wrapped_func(*args, **kwargs):
|
||||
deprecation(func.__qualname__, deprecated_in, details, stacklevel=2)
|
||||
return func(*args, **kwargs)
|
||||
return wrapped_func
|
||||
return wrap
|
||||
|
Reference in New Issue
Block a user