Better code organization

parent f4087849
......@@ -941,7 +941,7 @@ def getVoiceCommandList():
def getScreenshotUri(target):
qstring="select screenshot from mediasources where button_name LIKE '"+target+"%' limit 1"
qstring="select screenshot from mediasources where button_name LIKE '"+target+"%'"
return runQuery(qstring)
def getClimaUniques():
......
......@@ -2455,13 +2455,16 @@ class domotikaService(service.Service):
def web_on_getScreenshotList(self, screenshot=True):
return dmdb.getScreenshotList(screenshot=screenshot)
def web_on_getScreenshot(self, target):
def web_on_getScreenshot(self, target, callback=None):
def imageReturn(img):
return img
def prepareScreenshot(res):
if res:
return wu.getPage(res[0][0]).addCallback(imageReturn)
return False
if callback == None:
if res:
return wu.getPage(res[0][0]).addCallback(imageReturn)
return False
for r in res:
wu.getPage(r[0]).addCallback(callback)
return dmdb.getScreenshotUri(target).addCallback(prepareScreenshot)
def web_on_getClimaUniques(self):
......
from zope.interface import Interface, implements
from twisted.python import components
from nevow import rend, inevow
from corepost import Response, NotFoundException, AlreadyExistsException
......@@ -16,6 +17,8 @@ from Queue import Queue
import uuid
from domotika.singleton import messengerlinks
from StringIO import StringIO
import imghdr
_MESSENGER_LINKS = messengerlinks.MessengerLinkRegistry()
_MESSENGER_PSID = messengerlinks.MessengerPSIDRegistry()
......@@ -33,6 +36,114 @@ log = logging.getLogger( 'Webgui' )
BOTResource = RESTResource
class IBotProtoInterface(Interface):
def getUsername(self, uid):
""" get a username from uid """
def isLogged(self, uid):
""" return True if it's a know user """
def sendAPI(self, payload, req_uri):
""" Send request to the API """
def receivedAuthentication(self, msg):
""" receive auth message """
def receivedTextMessage(self, msg):
""" receive text message """
def receivedDeliveryConfirmation(self, msg):
""" receive delivery confirmation """
def receivedPostback(self, msg):
""" receive a postback message """
def receivedAccountLink(self, msg):
""" receive account linking message """
def sendCommandList(self, recipient_id):
""" send command list to the user """
def sendScreenshotList(self, recipient_id):
""" send a list of screenshots available """
def sendScreenshot(self, recipient_id, target):
""" send one or more screenshots """
def sendClima(self, recipient_id):
""" send Clima status """
def sendMessage(self, recipient_id, message):
""" send a text message """
def sendImageMessage(self, recipient_id, imguri):
""" send an image link """
def sendImageMessageData(self, recipient_id, imagedata, mtype):
""" send an image by data """
def sendAuthRequest(self, recipient_id):
""" send login request """
class BotProto(object):
def __init__(self, core):
self.core = core
def botCommandParser(self, uid, txt):
def voiceResult(res):
log.info('VoiceResult: '+str(res))
if len(res) > 0:
if res[0] == 'Ok' and len(res) > 1:
try:
result = 'ho eseguito "'+" ".join(res[1]['clean'])+'"'
except:
pass
else:
result = 'Spiacente, non ho trovato un comando corrispondente'
self.sendMessage(uid, result)
txt = unicode(txt.lower())
if not self.isLogged(uid):
if txt == u'hello' or txt == u'ciao':
self.sendMessage(uid, 'Hello, how can i help you?')
elif txt == u'?' or txt == u'help':
self.sendMessage(uid, 'you can\'t do that.')
elif txt == u'login':
self.sendAuthRequest(uid)
else:
self.sendMessage(uid, txt+u" come se fosse antani")
else:
if txt == u'hello' or txt == u'ciao':
self.sendMessage(uid, 'Hello %s, how can i help you?' %(self.getUsername(uid)))
elif txt == u'?' or txt == u'help':
self.sendMessage(uid, 'Ok, devo ancora implementare l\'aiuto! Sorry for that!')
self.sendMessage(uid, 'Anyway, i comandi che hai sono: "command list", "screenshot list", "screenshot" e "clima".')
self.sendMessage(uid, 'Qualsiasi altro comando viene interpretato come un potenziale comando vocale.')
elif txt == u'logout':
self.sendMessage(uid, 'Ok, devo ancora implementare anche il logout')
elif txt == u'login':
self.sendMessage(uid, 'Sei gia\' loggato, %s!' %(self.getUsername(uid)))
elif txt == u'command list' or txt == 'cmd list':
self.sendCommandList(uid)
elif txt == u'screenshot list' or txt==u'ss list':
self.sendScreenshotList(uid)
elif txt.startswith('screenshot ') or txt.startswith('ss '):
self.sendScreenshot(uid, " ".join(txt.split()[1:]))
elif txt == u'clima':
self.sendClima(uid)
else:
self.core.voiceReceived(txt, confidence=1.0, lang="it").addCallback(voiceResult)
class BotCore(object):
path = ""
......@@ -76,26 +187,30 @@ class MessengerMessage(object):
self.payload = payload
self.uri = uri
class MessengerCore(object):
class MessengerConf(object):
def _cfgGet(self, keyword):
return self.core.configGet('messenger', keyword)
class MessengerBot(BotCore, MessengerCore):
class MessengerBotAdapter(MessengerConf):
implements(IBotProtoInterface)
path = "messenger"
graphuri = 'https://graph.facebook.com/v2.6'
sendQueue = Queue()
sendlock = False
#graphuri = 'http://192.168.4.2/v2.6'
def __init__(self, orig):
self.orig = orig
self.core = orig.core
@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
......@@ -109,6 +224,7 @@ class MessengerBot(BotCore, MessengerCore):
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.debug('Messenger BOT Datasent OK')
log.debug(res)
......@@ -125,10 +241,8 @@ class MessengerBot(BotCore, MessengerCore):
def _sendRaw(self):
if not self.sendQueue.empty() and not self.sendLock:
message = self.sendQueue.get()
return wu.getPage(message.uri, method='POST', headers=message.headers,
postdata=message.payload).addCallbacks(self._dataSent, self._dataError)
return wu.getPage(message.uri, method='POST', headers=message.headers,
postdata=message.payload).addCallbacks(self._dataSent, self._dataError)
def sendAPI(self, payload, req_uri='/me/messages'):
request_endpoint = self.graphuri+req_uri
......@@ -137,112 +251,23 @@ class MessengerBot(BotCore, MessengerCore):
ctype={"Content-Type": "application/json"}
return wu.getPage(request_uri, method='POST', headers=ctype, postdata=convertToJson(payload)).addCallbacks(self._dataSent, self._dataError)
def getUsername(self, uid):
return _MESSENGER_PSID.get_link(uid)
@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')
@route("/loginfailed")
def loginFailed(self, request, *a, **kw):
k = kw.keys()
if 'account_linking_token' in k and 'redirect_uri' in k:
log.info("Passed linking uri "+kw['redirect_uri'])
luri=kw['redirect_uri']
log.info("Authorization failed: redirecting to "+luri)
return Response(302, 'Authorization failed', headers={'Location': luri})
return Response(200, "Authorization failed." )
def isLogged(self, uid):
return _MESSENGER_PSID.linkid_exists(uid)
def receivedAuthentication(self, msg):
log.info("Messenger bot received authentication: "+str(msg))
def receivedMessage(self, msg):
def voiceResult(res):
log.info('VoiceResult: '+str(res))
if len(res) > 0:
if res[0] == 'Ok' and len(res) > 1:
try:
result = 'ho eseguito "'+" ".join(res[1]['clean'])+'"'
except:
pass
else:
result = 'Spiacente, non ho trovato un comando corrispondente'
self.sendMessage(msg['sender']['id'], result)
def receivedTextMessage(self, msg):
log.info("Messenger bot received message: "+str(msg))
message = u'Received: '+unicode(msg['message']['text'])
txt = unicode(msg['message']['text'])
senderid = msg['sender']['id']
if not 'is_echo' in msg['message'].keys() or not msg['message']['is_echo']:
if not _MESSENGER_PSID.linkid_exists(senderid):
log.info(_MESSENGER_PSID.links)
if txt == u'hello' or txt == u'ciao':
self.sendMessage(senderid, 'Hello, how can i help you?')
elif txt == u'?' or txt == u'help':
self.sendMessage(senderid, 'you can\'t do that.')
elif txt == u'login':
self.sendAuthRequest(senderid)
else:
self.sendMessage(senderid, txt+" come se fosse antani")
else:
if txt == u'hello' or txt == u'ciao':
self.sendMessage(senderid, 'Hello %s, how can i help you?' %(_MESSENGER_PSID.get_link(senderid)))
elif txt == u'?' or txt == u'help':
self.sendMessage(senderid, 'Ok, devo ancora implementare l\'aiuto! Sorry for that!')
self.sendMessage(senderid, 'Anyway, i comandi che hai sono: "command list", "screenshot list", "screenshot" e "clima".')
self.sendMessage(senderid, 'Qualsiasi altro comando viene interpretato come un potenziale comando vocale.')
elif txt == u'logout':
self.sendMessage(senderid, 'Ok, devo ancora implementare anche il logout')
elif txt == u'command list' or txt == 'cmd list':
self.sendCommandList(senderid)
elif txt == u'screenshot list' or txt==u'ss list':
self.sendScreenshotList(senderid)
elif txt.startswith('screenshot ') or txt.startswith('ss '):
self.sendScreenshot(senderid, " ".join(txt.split()[1:]))
elif txt == u'clima':
self.sendClima(senderid)
else:
self.core.voiceReceived(txt, confidence=1.0, lang="it").addCallback(voiceResult)
message = u'Received: '+unicode(msg['message']['text'])
txt = unicode(msg['message']['text']).lower()
botCommandParser(self, senderid, txt)
def receivedDeliveryConfirmation(self, msg):
log.info("Messenger bot received delivery confirmation: "+str(msg))
......@@ -280,13 +305,13 @@ class MessengerBot(BotCore, MessengerCore):
def sendScreenshot(self, recipient_id, target):
def pushImage(res):
if res:
self.sendImageMessageData(recipient_id, res)
self.sendImageMessageData(recipient_id, res)
else:
self.sendMessage(recipient_id, 'Cannot retrieve image of '+str(target))
if target.endswith('%'):
target=target[:-1]
if len(target) > 0:
self.core.getScreenshot(target).addCallback(pushImage)
self.core.getScreenshot(target, pushImage)
def sendClima(self, recipient_id):
def pushClima(res):
......@@ -318,7 +343,7 @@ class MessengerBot(BotCore, MessengerCore):
payload = {
'recipient': {
'id': recipient_id
},
},
'message': {
'attachment': {
'type': 'image',
......@@ -330,19 +355,22 @@ class MessengerBot(BotCore, MessengerCore):
}
return self.sendAPI(payload)
def sendImageMessageData(self, recipient_id, imagedata):
payload = {
'recipient': {
'id': recipient_id
},
'message': {
'attachment': {
'type': 'image',
'payload': {}
}
}
}
fname=str(uuid.uuid4().get_hex())+'.jpg'
def sendImageMessageData(self, recipient_id, imagedata, mtype=None):
if not imagedata:
return
if mtype == None:
ft = imghdr.what(None, imagedata)
log.info("FILE TYPE: "+str(ft))
if ft in ['jpeg', 'gif', 'png']:
mtype=ft
else:
log.warning("Image mimetype doesn't seems to be valid: "+str(ft))
log.warning("Assuming it's a jpeg.")
mtype='jpeg'
fname=str(uuid.uuid4().get_hex())+mtype
bond="------------------------"+str(uuid.uuid4().get_hex())[:16]
data="--"+bond+"\r\n"
data+="Content-Disposition: form-data; name=\"recipient\"\r\n\r\n"
......@@ -352,7 +380,7 @@ class MessengerBot(BotCore, MessengerCore):
data+='{"attachment":{"type":"image", "payload":{}}}'+"\r\n"
data+="--"+bond+"\r\n"
data+='Content-Disposition: form-data; name="filedata"; filename="'+fname+'"'+"\r\n"
data+='Content-Type: image/jpeg'+"\r\n\r\n"
data+='Content-Type: image/'+mtype+"\r\n\r\n"
data+=str(imagedata)
data+="\r\n--"+bond+"--\r\n"
headers={
......@@ -362,17 +390,16 @@ class MessengerBot(BotCore, MessengerCore):
request_endpoint=self.graphuri+'/me/messages'
request_uri = request_endpoint+'?'+urlencode(self.auth_args)
return wu.getPage(request_uri, agent="curl/7.50.1", method='POST', headers=headers,
return wu.getPage(request_uri, agent="curl/7.50.1", method='POST', headers=headers,
postdata=data, expect100=True).addCallbacks(self._dataSent, self._dataError)
def sendAuthRequest(self, recipient_id):
payload = {
'recipient': {
'id': recipient_id
},
},
'message': {
"attachment": {
"attachment": {
"type": "template",
"payload": {
"template_type": "generic",
......@@ -389,9 +416,73 @@ class MessengerBot(BotCore, MessengerCore):
}
}
return self.sendAPI(payload)
components.registerAdapter(
MessengerBotAdapter,
BotProto,
IBotProtoInterface
)
class MessengerBot(BotCore, MessengerConf):
path = "messenger"
@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))
botproto = BotProto(self.core)
botiface = IBotProtoInterface(botproto)
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:
botiface.receivedAuthentication(message)
elif 'message' in msgkeys:
botiface.receivedTextMessage(message)
elif 'delivery' in msgkeys:
botiface.receivedDeliveryConfirmation(message)
elif 'postback' in msgkeys:
botiface.receivedPostback(message)
elif 'read' in msgkeys:
botiface.receivedMessageRead(message)
elif 'account_linking' in msgkeys:
botiface.receivedAccountLink(message)
else:
log.info("Received unknow messaging webhook for messenger BOT: "+str(kw))
#except:
# pass
return Response(200, 'OK')
@route("/loginfailed")
def loginFailed(self, request, *a, **kw):
k = kw.keys()
if 'account_linking_token' in k and 'redirect_uri' in k:
log.info("Passed linking uri "+kw['redirect_uri'])
luri=kw['redirect_uri']
log.info("Authorization failed: redirecting to "+luri)
return Response(302, 'Authorization failed', headers={'Location': luri})
return Response(200, "Authorization failed." )
class MessengerBotAuth(BotCore, MessengerCore):
class MessengerBotAuth(BotCore, MessengerConf):
path="messenger"
......
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