Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
D
domotikad
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
domotika
domotikad
Commits
be595c32
Commit
be595c32
authored
Oct 17, 2016
by
Franco (nextime) Lanza
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Messenger bot starts to do the job
parent
405345c4
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
151 additions
and
87 deletions
+151
-87
domotikad.conf
conf/defaults/domotikad.conf
+5
-0
bot.py
domotika/web/bot.py
+140
-87
web.py
domotika/web/web.py
+6
-0
No files found.
conf/defaults/domotikad.conf
View file @
be595c32
...
@@ -149,3 +149,8 @@ ns2: 8.8.9.9
...
@@ -149,3 +149,8 @@ ns2: 8.8.9.9
host
:
q
.
unixmedia
.
net
host
:
q
.
unixmedia
.
net
ip
:
auto
ip
:
auto
[
messenger
]
app_secret
:
verify_token
:
page_token
:
domotika/web/bot.py
View file @
be595c32
...
@@ -3,16 +3,22 @@
...
@@ -3,16 +3,22 @@
from
nevow
import
rend
,
inevow
from
nevow
import
rend
,
inevow
from
corepost
import
Response
,
NotFoundException
,
AlreadyExistsException
from
corepost
import
Response
,
NotFoundException
,
AlreadyExistsException
from
corepost.web
import
RESTResource
,
route
,
Http
from
corepost.web
import
RESTResource
,
route
,
Http
from
corepost.convert
import
convert
ForSerialization
,
generateXml
,
convert
ToJson
from
corepost.convert
import
convertToJson
from
corepost.enums
import
MediaType
,
HttpHeader
from
corepost.enums
import
MediaType
,
HttpHeader
from
rest
import
RestCore
as
BotCore
from
dmlib.utils
import
webutils
as
wu
from
rest
import
ResponseConversion
import
hashlib
import
hashlib
import
hmac
import
hmac
import
six
import
six
try
:
#python2
from
urllib
import
urlencode
except
ImportError
:
#python3
from
urllib.parse
import
urlencode
import
logging
import
logging
log
=
logging
.
getLogger
(
'Webgui'
)
log
=
logging
.
getLogger
(
'Webgui'
)
...
@@ -20,6 +26,14 @@ log = logging.getLogger( 'Webgui' )
...
@@ -20,6 +26,14 @@ log = logging.getLogger( 'Webgui' )
BOTResource
=
RESTResource
BOTResource
=
RESTResource
class
BotCore
(
object
):
path
=
""
def
__init__
(
self
,
core
,
session
):
self
.
core
=
core
self
.
session
=
session
class
BaseBot
(
BotCore
):
class
BaseBot
(
BotCore
):
@
route
(
"/"
)
@
route
(
"/"
)
...
@@ -27,113 +41,152 @@ class BaseBot(BotCore):
...
@@ -27,113 +41,152 @@ class BaseBot(BotCore):
return
'Domotika BOTs API interface V1.0'
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
)
class
MessengerBot
(
BotCore
):
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
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
)
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
):
def
_generateAppSecProof
(
self
):
if
six
.
PY2
:
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
:
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
()
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
)
@
route
(
"/"
,
Http
.
GET
)
def
rootGet
(
self
,
request
,
*
a
,
**
kw
):
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.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'
):
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
kw
[
'hub.challenge'
]
return
Response
(
403
,
"Failed validation."
)
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
=
(
BotApiList
=
(
BaseBot
,
BaseBot
,
MessengerBot
MessengerBot
...
...
domotika/web/web.py
View file @
be595c32
...
@@ -361,6 +361,12 @@ class SessionWrapper(guard.SessionWrapper):
...
@@ -361,6 +361,12 @@ class SessionWrapper(guard.SessionWrapper):
mp
=
mediaproxy
.
MediaStreamProxy
()
mp
=
mediaproxy
.
MediaStreamProxy
()
mp
.
core
=
self
.
core
mp
.
core
=
self
.
core
return
(
mp
,
segments
[
1
:])
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
(
','
):
for
n
in
self
.
core
.
configGet
(
'proxy'
,
'localproxypathsnologin'
)
.
split
(
','
):
if
n
and
name
.
startswith
(
n
):
if
n
and
name
.
startswith
(
n
):
log
.
info
(
"Proxy Bypass localproxypathsnologin locateChild "
+
name
)
log
.
info
(
"Proxy Bypass localproxypathsnologin locateChild "
+
name
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment