-> add profile pictures and message receipts
-> changes to Transwhat
This commit is contained in:
parent
8e2c03aaae
commit
995507c27f
|
@ -37,6 +37,17 @@ class SpectrumBackend:
|
|||
message = WRAP(m.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_CONV_MESSAGE)
|
||||
self.send(message)
|
||||
|
||||
def handleMessageAck(self, user, legacyName, ID):
|
||||
m = protocol_pb2.ConversationMessage()
|
||||
m.userName = user
|
||||
m.buddyName = legacyName
|
||||
m.message = ""
|
||||
m.id = ID
|
||||
|
||||
message = WRAP(m.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_CONV_MESSAGE_ACK)
|
||||
self.send(message)
|
||||
|
||||
|
||||
def handleAttention(self, user, buddyName, msg):
|
||||
m = protocol_pb2.ConversationMessage()
|
||||
m.userName = user
|
||||
|
@ -243,7 +254,16 @@ class SpectrumBackend:
|
|||
if (payload.ParseFromString(data) == False):
|
||||
#TODO: ERROR
|
||||
return
|
||||
self.handleMessageSendRequest(payload.userName, payload.buddyName, payload.message, payload.xhtml)
|
||||
self.handleMessageSendRequest(payload.userName, payload.buddyName, payload.message, payload.xhtml, payload.id)
|
||||
|
||||
def handleConvMessageAckPayload(self, data):
|
||||
payload = protocol_pb2.ConversationMessage()
|
||||
if (payload.ParseFromString(data) == False):
|
||||
#TODO: ERROR
|
||||
return
|
||||
self.handleMessageAckRequest(payload.userName, payload.buddyName, payload.id)
|
||||
|
||||
|
||||
|
||||
def handleAttentionPayload(self, data):
|
||||
payload = protocol_pb2.ConversationMessage()
|
||||
|
@ -349,7 +369,14 @@ class SpectrumBackend:
|
|||
|
||||
|
||||
wrapper = protocol_pb2.WrapperMessage()
|
||||
if (wrapper.ParseFromString(self.m_data[4:]) == False):
|
||||
try:
|
||||
parseFromString = wrapper.ParseFromString(self.m_data[4:])
|
||||
except:
|
||||
parseFromString = True
|
||||
self.logger.error("Parse from String exception")
|
||||
|
||||
|
||||
if (parseFromString == False):
|
||||
self.m_data = self.m_data[expected_size+4:]
|
||||
return
|
||||
|
||||
|
@ -393,6 +420,8 @@ class SpectrumBackend:
|
|||
self.handleFTContinuePayload(wrapper.payload)
|
||||
elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_EXIT:
|
||||
self.handleExitRequest()
|
||||
elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_CONV_MESSAGE_ACK:
|
||||
self.handleConvMessageAckPayload(wrapper.payload)
|
||||
elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_RAW_XML:
|
||||
self.handleRawXmlRequest(wrapper.payload)
|
||||
|
||||
|
@ -465,17 +494,30 @@ class SpectrumBackend:
|
|||
|
||||
raise NotImplementedError, "Implement me"
|
||||
|
||||
def handleMessageSendRequest(self, user, legacyName, message, xhtml = ""):
|
||||
def handleMessageSendRequest(self, user, legacyName, message, xhtml = "", ID = 0):
|
||||
"""
|
||||
Called when XMPP user sends message to legacy network.
|
||||
@param user: XMPP JID of user for which this event occurs.
|
||||
@param legacyName: Legacy network name of buddy or room.
|
||||
@param message: Plain text message.
|
||||
@param xhtml: XHTML message.
|
||||
@param ID: message ID
|
||||
"""
|
||||
|
||||
raise NotImplementedError, "Implement me"
|
||||
|
||||
def handleMessageAckRequest(self, user, legacyName, ID = 0):
|
||||
"""
|
||||
Called when XMPP user sends message to legacy network.
|
||||
@param user: XMPP JID of user for which this event occurs.
|
||||
@param legacyName: Legacy network name of buddy or room.
|
||||
@param ID: message ID
|
||||
"""
|
||||
|
||||
# raise NotImplementedError, "Implement me"
|
||||
pass
|
||||
|
||||
|
||||
def handleVCardRequest(self, user, legacyName, ID):
|
||||
""" Called when XMPP user requests VCard of buddy.
|
||||
@param user: XMPP JID of user for which this event occurs.
|
||||
|
|
4
bot.py
4
bot.py
|
@ -178,8 +178,8 @@ following user commands are available:
|
|||
\\lastseen request last online timestamp from buddy""")
|
||||
|
||||
def _fortune(self, database = '', prefix=''):
|
||||
if os.path.exists("/usr/share/games/fortunes/%s" % database):
|
||||
fortune = os.popen('/usr/games/fortune %s' % database).read()
|
||||
if os.path.exists("/usr/share/fortune/%s" % database):
|
||||
fortune = os.popen('/usr/bin/fortune %s' % database).read()
|
||||
self.send(prefix + fortune[:-1])
|
||||
else:
|
||||
self.send("invalid database")
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
Welcome to transWhat!
|
||||
===== NEWS ====
|
||||
- 03.06.13 transWhat service is born
|
||||
- 10.06.13 added bot user to import contacts and adjust settings, see http://2p.0l.de
|
||||
- 14.06.13 finally enable password sniffing, see http://2o.0l.de
|
||||
- 18.06.13 major deployment of development version
|
||||
|
||||
Type "\help" for a list of available commands.
|
||||
Visit http://whatsapp.0l.de for the full documentation.
|
||||
|
||||
|
|
205
session.py
205
session.py
|
@ -36,6 +36,13 @@ from group import Group
|
|||
from bot import Bot
|
||||
from constants import *
|
||||
|
||||
class MsgIDs:
|
||||
def __init__(self, xmppId, waId):
|
||||
self.xmppId = xmppId
|
||||
self.waId = waId
|
||||
self.cnt = 0
|
||||
|
||||
|
||||
class Session:
|
||||
|
||||
def __init__(self, backend, user, legacyName, extra, db):
|
||||
|
@ -54,6 +61,8 @@ class Session:
|
|||
self.presenceRequested = []
|
||||
self.offlineQueue = []
|
||||
self.groupOfflineQueue = { }
|
||||
self.msgIDs = { }
|
||||
self.shouldBeConnected = False
|
||||
|
||||
self.timer = None
|
||||
self.password = None
|
||||
|
@ -61,6 +70,7 @@ class Session:
|
|||
|
||||
self.buddies = BuddyList(legacyName, db)
|
||||
self.frontend = YowsupConnectionManager()
|
||||
self.frontend.setAutoPong(True)
|
||||
|
||||
self.bot = Bot(self)
|
||||
|
||||
|
@ -68,9 +78,11 @@ class Session:
|
|||
self.listen("auth_success", self.onAuthSuccess)
|
||||
self.listen("auth_fail", self.onAuthFailed)
|
||||
self.listen("disconnected", self.onDisconnected)
|
||||
self.listen("ping", self.onPing)
|
||||
|
||||
self.listen("contact_typing", self.onContactTyping)
|
||||
self.listen("contact_paused", self.onContactPaused)
|
||||
self.listen("contact_gotProfilePicture", self.onContactGotProfilePicture)
|
||||
|
||||
self.listen("presence_updated", self.onPrecenceUpdated)
|
||||
self.listen("presence_available", self.onPrecenceAvailable)
|
||||
|
@ -88,6 +100,14 @@ class Session:
|
|||
self.listen("group_gotParticipants", self.onGroupGotParticipants)
|
||||
self.listen("group_subjectReceived", self.onGroupSubjectReceived)
|
||||
|
||||
self.listen("group_imageReceived", self.onGroupMediaReceived)
|
||||
self.listen("group_videoReceived", self.onGroupMediaReceived)
|
||||
self.listen("group_audioReceived", self.onGroupMediaReceived)
|
||||
self.listen("group_locationReceived", self.onGroupLocationReceived)
|
||||
|
||||
self.listen("receipt_messageDelivered", self.onReceiptMessageDeliverd)
|
||||
|
||||
|
||||
self.listen("notification_groupParticipantAdded", self.onGroupParticipantAdded)
|
||||
self.listen("notification_groupParticipantRemoved", self.onGroupParticipantRemoved)
|
||||
self.listen("notification_contactProfilePictureUpdated", self.onContactProfilePictureUpdated)
|
||||
|
@ -99,16 +119,19 @@ class Session:
|
|||
def call(self, method, args = ()):
|
||||
args = [str(s) for s in args]
|
||||
self.logger.debug("%s(%s)", method, ", ".join(args))
|
||||
self.frontend.methodInterface.call(method, args)
|
||||
return self.frontend.methodInterface.call(method, args)
|
||||
|
||||
def listen(self, event, callback):
|
||||
self.frontend.signalInterface.registerListener(event, callback)
|
||||
|
||||
def logout(self):
|
||||
self.call("disconnect", ("logout",))
|
||||
self.logger.info("Logout")
|
||||
|
||||
|
||||
def login(self, password):
|
||||
self.password = utils.decodePassword(password)
|
||||
self.shouldBeConnected = True;
|
||||
self.call("auth_login", (self.legacyName, self.password))
|
||||
|
||||
def updateRoomList(self):
|
||||
|
@ -123,14 +146,13 @@ class Session:
|
|||
if buddy != "bot":
|
||||
self.logger.info("Started typing: %s to %s", self.legacyName, buddy)
|
||||
self.call("typing_send", (buddy + "@s.whatsapp.net",))
|
||||
|
||||
def sendTypingStopped(self, buddy):
|
||||
if buddy != "bot":
|
||||
self.logger.info("Stopped typing: %s to %s", self.legacyName, buddy)
|
||||
self.call("typing_paused", (buddy + "@s.whatsapp.net",))
|
||||
|
||||
def sendMessageToWA(self, sender, message):
|
||||
self.logger.info("Message sent from %s to %s: %s", self.legacyName, sender, message)
|
||||
def sendMessageToWA(self, sender, message, ID):
|
||||
self.logger.info("Message (ID: %s) send from %s to %s: %s", ID, self.legacyName, sender, message)
|
||||
message = message.encode("utf-8")
|
||||
|
||||
if sender == "bot":
|
||||
|
@ -142,30 +164,41 @@ class Session:
|
|||
else:
|
||||
room = sender
|
||||
group = self.groups[room]
|
||||
|
||||
self.backend.handleMessage(self.user, room, message, group.nick)
|
||||
self.logger.info("Group Message from %s to %s Groups: %s", group.nick , group , self.groups)
|
||||
self.backend.handleMessage(self.user, room, message.decode('utf-8'), group.nick)
|
||||
self.call("message_send", (room + "@g.us", message))
|
||||
else: # private msg
|
||||
buddy = sender
|
||||
if message == "\\lastseen":
|
||||
self.presenceRequested.append(buddy)
|
||||
self.call("presence_request", (buddy + "@s.whatsapp.net",))
|
||||
elif message == "\\gpp":
|
||||
self.logger.info("Get Profile Picture! ")
|
||||
self.sendMessageToXMPP(buddy, "Fetching Profile Picture")
|
||||
self.call("contact_getProfilePicture", (buddy + "@s.whatsapp.net",))
|
||||
else:
|
||||
self.call("message_send", (buddy + "@s.whatsapp.net", message))
|
||||
waId = self.call("message_send", (buddy + "@s.whatsapp.net", message))
|
||||
self.msgIDs[waId] = MsgIDs( ID, waId)
|
||||
self.logger.info("WA Message send to %s with ID %s", buddy, waId)
|
||||
|
||||
def sendMessageToXMPP(self, buddy, messageContent, timestamp = ""):
|
||||
if timestamp:
|
||||
timestamp = time.strftime("%Y%m%dT%H%M%S", time.gmtime(timestamp))
|
||||
|
||||
if self.initialized == False:
|
||||
self.logger.debug("Message queued from %s to %s: %s", buddy, self.legacyName, messageContent)
|
||||
self.logger.info("Message queued from %s to %s: %s", buddy, self.legacyName, messageContent)
|
||||
self.offlineQueue.append((buddy, messageContent, timestamp))
|
||||
else:
|
||||
self.logger.debug("Message sent from %s to %s: %s", buddy, self.legacyName, messageContent)
|
||||
self.logger.info("Message sent from %s to %s: %s", buddy, self.legacyName, messageContent)
|
||||
self.backend.handleMessage(self.user, buddy, messageContent, "", "", timestamp)
|
||||
|
||||
def sendGroupMessageToXMPP(self, room, buddy, messageContent, timestamp = ""):
|
||||
if timestamp:
|
||||
try:
|
||||
nick = self.buddies[buddy].nick
|
||||
except KeyError:
|
||||
nick = "unknown"
|
||||
|
||||
if timestamp:
|
||||
timestamp = time.strftime("%Y%m%dT%H%M%S", time.gmtime(timestamp))
|
||||
|
||||
if self.initialized == False:
|
||||
|
@ -174,10 +207,10 @@ class Session:
|
|||
if room not in self.groupOfflineQueue:
|
||||
self.groupOfflineQueue[room] = [ ]
|
||||
|
||||
self.groupOfflineQueue[room].append((buddy, messageContent, timestamp))
|
||||
self.groupOfflineQueue[room].append((buddy, messageContent + ": " + nick, timestamp))
|
||||
else:
|
||||
self.logger.debug("Group message sent from %s to %s: %s", buddy, room, messageContent)
|
||||
self.backend.handleMessage(self.user, room, messageContent, buddy, "", timestamp)
|
||||
self.backend.handleMessage(self.user, room, messageContent + ": " + nick, buddy, "", timestamp)
|
||||
|
||||
def changeStatus(self, status):
|
||||
if status != self.status:
|
||||
|
@ -192,7 +225,7 @@ class Session:
|
|||
def changeStatusMessage(self, statusMessage):
|
||||
if (statusMessage != self.statusMessage) or (self.initialized == False):
|
||||
self.statusMessage = statusMessage
|
||||
self.call("profile_setStatus", (statusMessage.encode("utf-8"),))
|
||||
self.call("profile_setStatus", (statusMessage.encode("utf-8"),))# FIXME
|
||||
self.logger.info("Status message changed: %s", statusMessage)
|
||||
|
||||
if self.initialized == False:
|
||||
|
@ -218,16 +251,18 @@ class Session:
|
|||
self.buddies.remove(buddy)
|
||||
self.updateRoster()
|
||||
|
||||
def joinRoom(self, room, nick):
|
||||
def joinRoom(self, room, nick, init):
|
||||
if room in self.groups:
|
||||
group = self.groups[room]
|
||||
|
||||
self.logger.info("Joining room: %s room=%s, nick=%s", self.legacyName, room, nick)
|
||||
|
||||
group.nick = nick
|
||||
|
||||
self.call("group_getParticipants", (room + "@g.us",))
|
||||
#time.sleep(2)
|
||||
if init == False:
|
||||
self.call("group_getParticipants", (room + "@g.us",)) #FIXME
|
||||
self.backend.handleSubject(self.user, room, group.subject, group.subjectOwner)
|
||||
self.backend.handleRoomNicknameChanged(self.user,room,group.subject)
|
||||
else:
|
||||
self.logger.warn("Room doesn't exist: %s", room)
|
||||
|
||||
|
@ -252,7 +287,8 @@ class Session:
|
|||
for number in add:
|
||||
buddy = self.buddies[number]
|
||||
self.backend.handleBuddyChanged(self.user, number, buddy.nick, buddy.groups, protocol_pb2.STATUS_NONE)
|
||||
self.call("presence_request", (number + "@s.whatsapp.net",)) # includes presence_subscribe
|
||||
self.call("presence_subscribe", (number + "@s.whatsapp.net",))
|
||||
self.call("presence_request", (number + "@s.whatsapp.net",)) # includes presence_subscribe FIXME
|
||||
|
||||
|
||||
# yowsup Signals
|
||||
|
@ -266,15 +302,29 @@ class Session:
|
|||
|
||||
self.call("ready")
|
||||
self.call("group_getGroups", ("participating",))
|
||||
|
||||
if self.initialized == False:
|
||||
self.sendOfflineMessages()
|
||||
self.bot.call("welcome")
|
||||
self.initialized = True
|
||||
|
||||
|
||||
def onAuthFailed(self, user, reason):
|
||||
self.logger.info("Auth failed: %s (%s)", user, reason)
|
||||
self.backend.handleDisconnected(self.user, 0, reason)
|
||||
self.password = None
|
||||
self.shouldBeConnected = False;
|
||||
|
||||
|
||||
def onDisconnected(self, reason):
|
||||
self.logger.info("Disconnected from whatsapp: %s (%s)", self.legacyName, reason)
|
||||
self.backend.handleDisconnected(self.user, 0, reason)
|
||||
#if self.shouldBeConnected == True:
|
||||
#self.call("auth_login", (self.legacyName, self.password))
|
||||
|
||||
def onPing(pingId):
|
||||
self.logger.info("Ping received")
|
||||
self.call("pong", (pingId,))
|
||||
|
||||
def onMessageReceived(self, messageId, jid, messageContent, timestamp, receiptRequested, pushName, isBroadCast):
|
||||
buddy = jid.split("@")[0]
|
||||
|
@ -287,28 +337,61 @@ class Session:
|
|||
self.logger.info("Message received from %s to %s: %s (at ts=%s)", buddy, self.legacyName, messageContent, timestamp)
|
||||
|
||||
self.sendMessageToXMPP(buddy, messageContent, timestamp)
|
||||
if receiptRequested: self.call("message_ack", (jid, messageId))
|
||||
#if receiptRequested:
|
||||
self.call("message_ack", (jid, messageId))
|
||||
|
||||
def onMediaReceived(self, messageId, jid, preview, url, size, receiptRequested, isBroadcast):
|
||||
buddy = jid.split("@")[0]
|
||||
|
||||
self.logger.info("Media received from %s: %s", buddy, url)
|
||||
self.sendMessageToXMPP(buddy, utils.shorten(url))
|
||||
if receiptRequested: self.call("message_ack", (jid, messageId))
|
||||
# self.sendMessageToXMPP(buddy, utils.shorten(url))
|
||||
self.sendMessageToXMPP(buddy, url)
|
||||
#if receiptRequested:
|
||||
self.call("message_ack", (jid, messageId))
|
||||
|
||||
def onGroupMediaReceived(self, messageId, gjid, jid, preview, url, size, receiptRequested):
|
||||
buddy = jid.split("@")[0]
|
||||
room = gjid.split("@")[0]
|
||||
|
||||
self.logger.info("Group Media message received in %s from %s: %s (%s)", room, buddy, url, preview)
|
||||
|
||||
self.sendGroupMessageToXMPP(room, buddy, url)
|
||||
#if receiptRequested:
|
||||
self.call("message_ack", (gjid, messageId))
|
||||
|
||||
|
||||
|
||||
|
||||
def onLocationReceived(self, messageId, jid, name, preview, latitude, longitude, receiptRequested, isBroadcast):
|
||||
buddy = jid.split("@")[0]
|
||||
self.logger.info("Location received from %s: %s, %s", buddy, latitude, longitude)
|
||||
|
||||
url = "http://maps.google.de?%s" % urllib.urlencode({ "q": "%s %s" % (latitude, longitude) })
|
||||
self.sendMessageToXMPP(buddy, utils.shorten(url))
|
||||
if receiptRequested: self.call("message_ack", (jid, messageId))
|
||||
# self.sendMessageToXMPP(buddy, utils.shorten(url))
|
||||
self.sendMessageToXMPP(buddy, url)
|
||||
#if receiptRequested:
|
||||
self.call("message_ack", (jid, messageId))
|
||||
|
||||
|
||||
def onGroupLocationReceived(self, messageId, gjid, jid, name, preview, latitude, longitude, receiptRequested):
|
||||
buddy = jid.split("@")[0]
|
||||
room = gjid.split("@")[0]
|
||||
|
||||
url = "http://maps.google.de?%s" % urllib.urlencode({ "q": "%s %s" % (latitude, longitude) })
|
||||
# self.sendMessageToXMPP(buddy, utils.shorten(url))
|
||||
self.sendGroupMessageToXMPP(room, buddy, url)
|
||||
#if receiptRequested:
|
||||
self.call("message_ack", (gjid, messageId))
|
||||
|
||||
|
||||
|
||||
|
||||
def onVcardReceived(self, messageId, jid, name, data, receiptRequested, isBroadcast): # TODO
|
||||
buddy = jid.split("@")[0]
|
||||
self.logger.info("VCard received from %s", buddy)
|
||||
self.sendMessageToXMPP(buddy, "Received VCard (not implemented yet)")
|
||||
if receiptRequested: self.call("message_ack", (jid, messageId))
|
||||
#if receiptRequested:
|
||||
self.call("message_ack", (jid, messageId))
|
||||
|
||||
def onContactTyping(self, jid):
|
||||
buddy = jid.split("@")[0]
|
||||
|
@ -337,7 +420,7 @@ class Session:
|
|||
if lastseen < 60:
|
||||
self.onPrecenceAvailable(jid)
|
||||
else:
|
||||
self.onPrecenceUnavailable(jid)
|
||||
self.onPrecenceUnavailable(jid, lastseen)
|
||||
|
||||
def onPrecenceAvailable(self, jid):
|
||||
buddy = jid.split("@")[0]
|
||||
|
@ -349,13 +432,14 @@ class Session:
|
|||
except KeyError:
|
||||
self.logger.error("Buddy not found: %s", buddy)
|
||||
|
||||
def onPrecenceUnavailable(self, jid):
|
||||
def onPrecenceUnavailable(self, jid, lastseen=0):
|
||||
buddy = jid.split("@")[0]
|
||||
|
||||
try:
|
||||
buddy = self.buddies[buddy]
|
||||
self.logger.info("Is unavailable: %s", buddy)
|
||||
self.backend.handleBuddyChanged(self.user, buddy.number.number, buddy.nick, buddy.groups, protocol_pb2.STATUS_XA)
|
||||
statusmsg = "Last seen: " + utils.ago(lastseen)
|
||||
self.backend.handleBuddyChanged(self.user, buddy.number.number, buddy.nick, buddy.groups, protocol_pb2.STATUS_AWAY, statusmsg)
|
||||
except KeyError:
|
||||
self.logger.error("Buddy not found: %s", buddy)
|
||||
|
||||
|
@ -363,6 +447,8 @@ class Session:
|
|||
room = gjid.split("@")[0]
|
||||
owner = owner.split("@")[0]
|
||||
subjectOwner = subjectOwner.split("@")[0]
|
||||
subject = utils.softToUni(subject)
|
||||
|
||||
|
||||
if room in self.groups:
|
||||
room = self.groups[room]
|
||||
|
@ -371,6 +457,8 @@ class Session:
|
|||
room.subject = subject
|
||||
else:
|
||||
self.groups[room] = Group(room, owner, subject, subjectOwner)
|
||||
#time.sleep(2)
|
||||
self.joinRoom(room,self.user.split("@")[0],True)
|
||||
|
||||
self.updateRoomList()
|
||||
|
||||
|
@ -387,7 +475,7 @@ class Session:
|
|||
else:
|
||||
flags = protocol_pb2.PARTICIPANT_FLAG_NONE
|
||||
|
||||
self.backend.handleParticipantChanged(self.user, buddy, room, flags, protocol_pb2.STATUS_ONLINE) # TODO check status
|
||||
self.backend.handleParticipantChanged(self.user, buddy, room, flags, protocol_pb2.STATUS_ONLINE,"Nici","") # TODO check status
|
||||
|
||||
if room in self.groupOfflineQueue:
|
||||
while self.groupOfflineQueue[room]:
|
||||
|
@ -396,30 +484,36 @@ class Session:
|
|||
self.logger.debug("Send queued group message to: %s %s %s", msg[0],msg[1], msg[2])
|
||||
|
||||
def onGroupMessageReceived(self, messageId, gjid, jid, messageContent, timestamp, receiptRequested, pushName):
|
||||
buddy = jid.split("@")[0]
|
||||
if jid != None:
|
||||
|
||||
buddy = jid.split("@")[0]
|
||||
room = gjid.split("@")[0]
|
||||
|
||||
self.logger.info("Group message received in %s from %s: %s", room, buddy, messageContent)
|
||||
|
||||
self.sendGroupMessageToXMPP(room, buddy, utils.softToUni(messageContent), timestamp)
|
||||
if receiptRequested: self.call("message_ack", (gjid, messageId))
|
||||
#if receiptRequested:
|
||||
self.call("message_ack", (gjid, messageId))
|
||||
|
||||
def onGroupSubjectReceived(self, messageId, gjid, jid, subject, timestamp, receiptRequested):
|
||||
room = gjid.split("@")[0]
|
||||
buddy = jid.split("@")[0]
|
||||
subject = utils.softToUni(subject)
|
||||
|
||||
self.backend.handleSubject(self.user, room, subject, buddy)
|
||||
if receiptRequested: self.call("subject_ack", (gjid, messageId))
|
||||
#if receiptRequested:
|
||||
self.call("subject_ack", (gjid, messageId))
|
||||
|
||||
# Yowsup Notifications
|
||||
def onGroupParticipantAdded(self, gjid, jid, author, timestamp, messageId, receiptRequested):
|
||||
room = gjid.split("@")[0]
|
||||
buddy = jid.split("@")[0]
|
||||
|
||||
loggin.info("Added % to room %s", buddy, room)
|
||||
self.logger.info("Added % to room %s", buddy, room)
|
||||
|
||||
self.backend.handleParticipantChanged(self.user, buddy, room, protocol_pb2.PARTICIPANT_FLAG_NONE, protocol_pb2.STATUS_ONLINE)
|
||||
if receiptRequested: self.call("notification_ack", (gjid, messageId))
|
||||
#if receiptRequested:
|
||||
self.call("notification_ack", (gjid, messageId))
|
||||
|
||||
def onGroupParticipantRemoved(self, gjid, jid, author, timestamp, messageId, receiptRequested):
|
||||
room = gjid.split("@")[0]
|
||||
|
@ -428,12 +522,53 @@ class Session:
|
|||
self.logger.info("Removed %s from room %s", buddy, room)
|
||||
|
||||
self.backend.handleParticipantChanged(self.user, buddy, room, protocol_pb2.PARTICIPANT_FLAG_NONE, protocol_pb2.STATUS_NONE) # TODO
|
||||
if receiptRequested: self.call("notification_ack", (gjid, messageId))
|
||||
#if receiptRequested:
|
||||
self.call("notification_ack", (gjid, messageId))
|
||||
|
||||
def onContactProfilePictureUpdated(self, jid, timestamp, messageId, pictureId, receiptRequested):
|
||||
# TODO
|
||||
if receiptRequested: self.call("notification_ack", (jid, messageId))
|
||||
buddy = jid.split("@")[0]
|
||||
self.sendMessageToXMPP(buddy, "ProfilePictureUpdate %d" % pictureId)
|
||||
self.call("contact_getProfilePicture", jid)
|
||||
#if receiptRequested:
|
||||
self.call("notification_ack", (jid, messageId))
|
||||
|
||||
def onGroupPictureUpdated(self, jid, author, timestamp, messageId, pictureId, receiptRequested):
|
||||
# TODO
|
||||
if receiptRequested: self.call("notification_ack", (jid, messageId))
|
||||
#if receiptRequested:
|
||||
self.call("notification_ack", (jid, messageId))
|
||||
|
||||
def onContactGotProfilePicture(self, jid, pictureid, filePath):
|
||||
# TODO
|
||||
buddy = jid.split("@")[0]
|
||||
self.logger.info("Got Profile Picture (id %s) %s from %s", pictureid, filePath, buddy)
|
||||
pic=file(filePath,'rb')
|
||||
blob_value = pic.read()
|
||||
sql = 'UPDATE numbers SET picture=%s WHERE number=%s'
|
||||
args = (blob_value,buddy, )
|
||||
#self.logger.info("Insert Picture SQL: %s, args: %s", sql, args)
|
||||
cursor=self.db.cursor()
|
||||
cursor.execute(sql,args)
|
||||
self.db.commit()
|
||||
|
||||
|
||||
# if receiptRequested: self.call("notification_ack", (jid, messageId))
|
||||
|
||||
def onReceiptMessageDeliverd(self, jid, msgId):
|
||||
buddy = jid.split("@")[0]
|
||||
|
||||
self.logger.info("Message Delivered Receipt (ID%s) received from %s", msgId, buddy)
|
||||
# self.call("delivered_ack", (jid, msgId)) # maybe not valid in wauth-2
|
||||
try:
|
||||
self.backend.handleMessageAck(self.user, buddy, self.msgIDs[msgId].xmppId)
|
||||
self.msgIDs[msgId].cnt = self.msgIDs[msgId].cnt +1
|
||||
if self.msgIDs[msgId].cnt == 2:
|
||||
del self.msgIDs[msgId]
|
||||
except KeyError:
|
||||
self.logger.info("Unkown WA Message ID: %s ", msgId)
|
||||
|
||||
|
||||
|
||||
# self.sendMessageToXMPP(buddy, utils.shorten(url))
|
||||
# self.sendMessageToXMPP(buddy, "*")
|
||||
# self.backend.handleMessage(self.user, buddy, "*", self.user.split("@")[0])
|
||||
|
|
11
transwhat.py
11
transwhat.py
|
@ -50,7 +50,18 @@ parser.add_argument('config', type=str)
|
|||
args, unknown = parser.parse_known_args()
|
||||
|
||||
# Logging
|
||||
|
||||
logger = logging.getLogger('Template Backend')
|
||||
logger.setLevel(logging.DEBUG)
|
||||
ch = logging.StreamHandler()
|
||||
ch.setLevel(logging.DEBUG)
|
||||
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||
ch.setFormatter(formatter)
|
||||
logger.addHandler(ch)
|
||||
logger.info("Started Backend")
|
||||
logging.basicConfig( \
|
||||
# stream = sys.stdout, \
|
||||
filename='/var/log/spectrum2/transwhat/backends/transwhat.log', \
|
||||
format = "%(asctime)-15s %(levelname)s %(name)s: %(message)s", \
|
||||
level = logging.DEBUG if args.debug else logging.INFO \
|
||||
)
|
||||
|
|
|
@ -33,6 +33,13 @@ class WhatsAppBackend(SpectrumBackend):
|
|||
def __init__(self, io, db):
|
||||
SpectrumBackend.__init__(self)
|
||||
self.logger = logging.getLogger(self.__class__.__name__)
|
||||
#self.logger = logging.getLogger('Transwhat Backend')
|
||||
#self.logger.setLevel(logging.DEBUG)
|
||||
#ch = logging.StreamHandler()
|
||||
#ch.setLevel(logging.DEBUG)
|
||||
#formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||
#ch.setFormatter(formatter)
|
||||
#self.logger.addHandler(ch)
|
||||
self.io = io
|
||||
self.db = db
|
||||
self.sessions = { }
|
||||
|
@ -41,49 +48,69 @@ class WhatsAppBackend(SpectrumBackend):
|
|||
|
||||
# RequestsHandlers
|
||||
def handleLoginRequest(self, user, legacyName, password, extra):
|
||||
self.logger.debug("handleLoginRequest(user=%s, legacyName=%s)", user, legacyName)
|
||||
self.logger.info("handleLoginRequest(user=%s, legacyName=%s)", user, legacyName)
|
||||
if user not in self.sessions:
|
||||
self.sessions[user] = Session(self, user, legacyName, extra, self.db)
|
||||
self.logger.info("handleLoginRequest Create (user=%s, legacyName=%s)", user, legacyName)
|
||||
|
||||
|
||||
self.sessions[user].login(password)
|
||||
|
||||
def handleLogoutRequest(self, user, legacyName):
|
||||
self.logger.debug("handleLogoutRequest(user=%s, legacyName=%s)", user, legacyName)
|
||||
self.logger.info("handleLogoutRequest(user=%s, legacyName=%s)", user, legacyName)
|
||||
if user in self.sessions:
|
||||
self.sessions[user].logout()
|
||||
del self.sessions[user]
|
||||
|
||||
def handleMessageSendRequest(self, user, buddy, message, xhtml = ""):
|
||||
self.logger.debug("handleMessageSendRequest(user=%s, buddy=%s, message=%s)", user, buddy, message)
|
||||
self.sessions[user].sendMessageToWA(buddy, message)
|
||||
def handleMessageSendRequest(self, user, buddy, message, xhtml = "", ID = 0):
|
||||
self.logger.debug("handleMessageSendRequest(user=%s, buddy=%s, message=%s, id=%d)", user, buddy, message, ID)
|
||||
if user not in self.sessions:
|
||||
return;
|
||||
self.sessions[user].sendMessageToWA(buddy, message, ID)
|
||||
#self.handleMessageAck(user, buddy, ID)
|
||||
|
||||
def handleJoinRoomRequest(self, user, room, nickname, pasword):
|
||||
self.logger.debug("handleJoinRoomRequest(user=%s, room=%s, nickname=%s)", user, room, nickname)
|
||||
self.sessions[user].joinRoom(room, nickname)
|
||||
if user not in self.sessions:
|
||||
return;
|
||||
self.sessions[user].joinRoom(room, nickname, False)
|
||||
|
||||
def handleStatusChangeRequest(self, user, status, statusMessage):
|
||||
self.logger.debug("handleStatusChangeRequest(user=%s, status=%d, statusMessage=%s)", user, status, statusMessage)
|
||||
if user not in self.sessions:
|
||||
return;
|
||||
self.sessions[user].changeStatusMessage(statusMessage)
|
||||
self.sessions[user].changeStatus(status)
|
||||
|
||||
def handleBuddyUpdatedRequest(self, user, buddy, nick, groups):
|
||||
self.logger.debug("handleBuddyUpdatedRequest(user=%s, buddy=%s, nick=%s, groups=%s)", user, buddy, nick, str(groups))
|
||||
if user not in self.sessions:
|
||||
return;
|
||||
self.sessions[user].updateBuddy(buddy, nick, groups)
|
||||
|
||||
def handleBuddyRemovedRequest(self, user, buddy, groups):
|
||||
self.logger.debug("handleBuddyRemovedRequest(user=%s, buddy=%s, groups=%s)", user, buddy, str(groups))
|
||||
if user not in self.sessions:
|
||||
return;
|
||||
self.sessions[user].removeBuddy(buddy)
|
||||
|
||||
def handleTypingRequest(self, user, buddy):
|
||||
self.logger.debug("handleTypingRequest(user=%s, buddy=%s)", user, buddy)
|
||||
if user not in self.sessions:
|
||||
return;
|
||||
self.sessions[user].sendTypingStarted(buddy)
|
||||
|
||||
def handleTypedRequest(self, user, buddy):
|
||||
self.logger.debug("handleTypedRequest(user=%s, buddy=%s)", user, buddy)
|
||||
if user not in self.sessions:
|
||||
return;
|
||||
self.sessions[user].sendTypingStopped(buddy)
|
||||
|
||||
def handleStoppedTypingRequest(self, user, buddy):
|
||||
self.logger.debug("handleStoppedTypingRequest(user=%s, buddy=%s)", user, buddy)
|
||||
if user not in self.sessions:
|
||||
return;
|
||||
|
||||
self.sessions[user].sendTypingStopped(buddy)
|
||||
|
||||
# TODO
|
||||
|
@ -94,29 +121,54 @@ class WhatsAppBackend(SpectrumBackend):
|
|||
pass
|
||||
|
||||
def handleVCardRequest(self, user, buddy, ID):
|
||||
pass
|
||||
self.logger.info("VCard requested for %s !!",buddy)
|
||||
if user not in self.sessions:
|
||||
return;
|
||||
self.sessions[user].call("contact_getProfilePicture", (buddy + "@s.whatsapp.net",))
|
||||
#sql = 'UPDATE numbers SET picture=%s WHERE number=%s'
|
||||
#args = (blob_value,buddy, )
|
||||
#self.logger.info("Insert Picture SQL: %s, args: %s", sql, args)
|
||||
cursor=self.db.cursor()
|
||||
cursor.execute('SELECT picture FROM numbers WHERE number=%s', (buddy,))
|
||||
#self.db.commit()
|
||||
if not (cursor.rowcount == 0):
|
||||
(pic,) = cursor.fetchone()
|
||||
#pic=file('/tmp/tmpJoMbLq','rb')
|
||||
self.handleVCard(user,ID,buddy,"","",pic)
|
||||
|
||||
|
||||
|
||||
def handleVCardUpdatedRequest(self, user, photo, nickname):
|
||||
self.logger.info("VCard update requested")
|
||||
pass
|
||||
|
||||
def handleAttentionRequest(self, user, buddy, message):
|
||||
self.logger.info("Attetion request for %s !!",buddy)
|
||||
pass
|
||||
|
||||
def handleFTStartRequest(self, user, buddy, fileName, size, ftID):
|
||||
pass
|
||||
self.logger.info("FT Start request for %s !!",buddy)
|
||||
pass
|
||||
|
||||
def handleFTFinishRequest(self, user, buddy, fileName, size, ftID):
|
||||
self.logger.info("FT Finish request for %s !!",buddy)
|
||||
pass
|
||||
|
||||
def handleFTPauseRequest(self, ftID):
|
||||
self.logger.info("FT Pause request")
|
||||
pass
|
||||
|
||||
def handleFTContinueRequest(self, ftID):
|
||||
self.logger.info("FT Continue request")
|
||||
pass
|
||||
|
||||
def handleRawXmlRequest(self, xml):
|
||||
self.logger.info("Raw XML request")
|
||||
pass
|
||||
|
||||
def handleMessageAckRequest(self, user, legacyName, ID = 0):
|
||||
self.logger.info("Meassage ACK request for %s !!",leagcyName)
|
||||
|
||||
def sendData(self, data):
|
||||
self.io.sendData(data)
|
||||
|
||||
|
|
Loading…
Reference in New Issue