Messenger bot starts to do the job

parent 405345c4
......@@ -149,3 +149,8 @@ ns2: 8.8.9.9
host: q.unixmedia.net
ip: auto
[messenger]
app_secret:
verify_token:
page_token:
......@@ -3,16 +3,22 @@
from nevow import rend, inevow
from corepost import Response, NotFoundException, AlreadyExistsException
from corepost.web import RESTResource, route, Http
from corepost.convert import convertForSerialization, generateXml, convertToJson
from corepost.convert import convertToJson
from corepost.enums import MediaType, HttpHeader
from rest import RestCore as BotCore
from rest import ResponseConversion
from dmlib.utils import webutils as wu
import hashlib
import hmac
import six
try:
#python2
from urllib import urlencode
except ImportError:
#python3
from urllib.parse import urlencode
import logging
log = logging.getLogger( 'Webgui' )
......@@ -20,6 +26,14 @@ log = logging.getLogger( 'Webgui' )
BOTResource = RESTResource
class BotCore(object):
path = ""
def __init__(self, core, session):
self.core = core
self.session = session
class BaseBot(BotCore):
@route("/")
......@@ -27,113 +41,152 @@ class BaseBot(BotCore):
return 'Domotika BOTs API interface V1.0'
def messengerWrapResponse(f=None, uri=False, res_filter=None, *a, **kw):
if f and not callable(f):
uri=f
f=None
if f is None:
return partial(wrapResponse, uri=uri, *a, **kw)
def okResponse(res, u):
if isinstance(res, ResponseConversion):
entity=res.entity
if res_filter and callable(res_filter):
entity=res_filter(entity)
elif res_filter and hasattr(res_filter, '__iter__'):
for fil in res_filter:
if callable(fil):
entity=fil(entity)
entity={'result': 'succeed', 'data': entity, 'ts': time.time()}
if int(res.code) >= 400:
entity['result']='fail'
if uri:
entity['uri']=uri
elif u:
entity['uri']=u
r = ResponseConversion(res.request, res.code, entity, res.headers, res.ctype).getResponse()
else:
if res_filter and callable(res_filter):
res=res_filter(res)
elif res_filter and hasattr(res_filter, '__iter__'):
for fil in res_filter:
if callable(fil):
res=fil(res)
r={'result': 'succeed', 'data': res, 'ts': time.time()}
if uri:
r['uri']=uri
elif u:
r['uri']=u
return r
def errorResponse(res, u):
if isinstance(res, ResponseConversion):
entity={'result': 'fail', 'data': res.entity, 'ts': time.time()}
if uri:
entity['uri']=uri
elif u:
entity['uri']=u
r = ResponseConversion(res.request, res.code, entity, res.headers, res.ctype).getResponse()
else:
r={'result': 'fail', 'data': res, 'ts': time.time()}
if uri:
r['uri']=uri
elif u:
r['uri']=u
return r
def messengerValidator():
def checkRequest(f):
def new_f(self, request, *a, **kw):
if 'x-hub-signature' in request.getAllHeaders().keys():
hubsig=request.getHeader('x-hub-signature')
try:
hash_method, hub_signature = hubsig.split('=')
except:
pass
else:
digest_module = getattr(hashlib, hash_method)
hmac_object = hmac.new(str(self._cfgGet('app_secret')), unicode(request.content.getvalue()), digest_module)
generated_hash = hmac_object.hexdigest()
if hub_signature == generated_hash:
return f(self, request, *a, **kw)
return Response(200, "Failed validation." )
new_f.funct_name = f.func_name
return new_f
return checkRequest
@wraps(f)
def decorate(*a, **kw):
ruri=False
if len(a) > 1 and isinstance(a[1], Request):
ruri=a[1].uri
ret=defer.maybeDeferred(f, *a, **kw)
ret.addCallback(okResponse, ruri)
ret.addErrback(errorResponse, ruri)
return ret
class MessengerBot(BotCore):
return decorate
path = "messenger"
graphuri = 'https://graph.facebook.com/v2.6'
#graphuri = 'http://192.168.4.2/v2.6'
def __init__(self, *a, **kw):
super(MessengerBot, self).__init__(*a, **kw)
class MessengerBot(BotCore):
@property
def auth_args(self):
if not hasattr(self, '_auth_args'):
auth = {
'access_token': unicode(self._cfgGet('page_token'))
}
if self._cfgGet('app_secret') is not None and len(self._cfgGet('app_secret'))>0:
appsecret_proof = self._generateAppSecProof()
auth['appsecret_proof'] = appsecret_proof
self._auth_args = auth
return self._auth_args
path = "/messenger"
def _getCfg(self, keyword):
def _cfgGet(self, keyword):
return self.core.configGet('messenger', keyword)
def _validateHubSig(self, request_payload, hub_signature_header):
try:
hash_method, hub_signature = hub_signature_header.split('=')
except:
pass
else:
digest_module = getattr(hashlib, hash_method)
hmac_object = hmac.new(str(self._cfgGet('app_secret')), unicode(request_payload), digest_module)
generated_hash = hmac_object.hexdigest()
if hub_signature == generated_hash:
return True
return False
def _generateAppSecProof(self):
if six.PY2:
hmac_object = hmac.new(str(self._cfgGet('app_key')), unicode(self._cfgGet('page_token')), hashlib.sha256)
hmac_object = hmac.new(str(self._cfgGet('app_secret')), unicode(self._cfgGet('page_token')), hashlib.sha256)
else:
hmac_object = hmac.new(bytearray(self._cfgGet('app_key'), 'utf8'), str(self._cfgGet('page_token')).encode('utf8'), hashlib.sha256)
hmac_object = hmac.new(bytearray(self._cfgGet('app_secret'), 'utf8'), str(self._cfgGet('page_token')).encode('utf8'), hashlib.sha256)
return hmac_object.hexdigest()
def _dataSent(self, res):
log.info('OKOKOKOKOKOKOKOKOKOKOKOKOKOKOKOKOKOKOKOKOKOKOKOKOKOKOKOKOKOKOKOKOKOKOKOK')
log.info(res)
def _dataError(self, res):
log.info('=======================================================================')
log.info(res)
log.info(res.value.reasons[0].printTraceback())
def sendAPI(self, payload, req_uri='/me/messages'):
request_endpoint = self.graphuri+req_uri
request_uri = request_endpoint+'?'+urlencode(self.auth_args)
log.info("Sending message to "+str(request_uri)+" : "+str(convertToJson(payload)))
ctype={"Content-Type": "application/json"}
return wu.getPage(request_uri, method='POST', headers=ctype, postdata=convertToJson(payload)).addCallbacks(self._dataSent, self._dataError)
@route("/", Http.GET)
def rootGet(self, request, *a, **kw):
if 'hub.mode' in kw.keys() and kw['hub.mode'] == 'subscribe' and 'hub.challenge' in kw.keys():
if 'hub.verify_token' in kw.keys() and kw['hub.verify_token'] == self._cfgGet('verify_token'):
log.info("New verification request for Messenger BOT: "+str(kw))
return kw['hub.challenge']
return Response(403, "Failed validation." )
@route("/", Http.POST)
@messengerValidator()
def rootPost(self, request, *a, **kw):
log.debug("New messenger bot request: "+str(kw))
if 'object' in kw.keys() and kw['object'] == 'page' and 'entry' in kw.keys():
for entry in kw['entry']:
#try:
if True:
pageID=entry['id']
timestamp=entry['time']
messaging=entry['messaging']
for message in messaging:
msgkeys = message.keys()
if 'optin' in msgkeys:
self.receivedAuthentication(message)
elif 'message' in msgkeys:
self.receivedMessage(message)
elif 'delivery' in msgkeys:
self.receivedDeliveryConfirmation(message)
elif 'postback' in msgkeys:
self.receivedPostback(message)
elif 'read' in msgkeys:
self.receivedMessageRead(message)
elif 'account_linking' in msgkeys:
self.receivedAccountLink(message)
else:
log.info("Received unknow messaging webhook for messenger BOT: "+str(kw))
#except:
# pass
return Response(200, 'OK')
def receivedAuthentication(self, msg):
pass
def receivedMessage(self, msg):
log.info("Messenger bot received message: "+str(msg))
message = u'Received: '+unicode(msg['message']['text'])
if not 'is_echo' in msg['message'].keys() or not msg['message']['is_echo']:
self.sendMessage(msg['sender']['id'], message)
def receivedDeliveryConfirmation(self, msg):
pass
def receivedPostback(self, msg):
pass
def receivedMessageRead(self, msg):
log.info("Messenger bot received message read: "+str(msg))
def receivedAccountLink(self, msg):
pass
def sendMessage(self, recipient_id, message):
payload = {
'recipient': {
'id': recipient_id
},
'message': {
'text': message
}
}
return self.sendAPI(payload)
BotApiList=(
BaseBot,
MessengerBot
......
......@@ -361,6 +361,12 @@ class SessionWrapper(guard.SessionWrapper):
mp = mediaproxy.MediaStreamProxy()
mp.core = self.core
return (mp, segments[1:])
if name.startswith('bot'):
# Bypass for chat bots
chatbot = bot.BotPages()
chatbot.core = self.core
return (chatbot, segments[1:])
for n in self.core.configGet('proxy', 'localproxypathsnologin').split(','):
if n and name.startswith(n):
log.info("Proxy Bypass localproxypathsnologin locateChild "+name)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment