parent
995507c27f
commit
c716e94c70
|
@ -3,7 +3,7 @@ import socket
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
import logging
|
||||||
import google.protobuf
|
import google.protobuf
|
||||||
|
|
||||||
def WRAP(MESSAGE, TYPE):
|
def WRAP(MESSAGE, TYPE):
|
||||||
|
@ -19,11 +19,12 @@ class SpectrumBackend:
|
||||||
@param host: Host where Spectrum2 NetworkPluginServer runs.
|
@param host: Host where Spectrum2 NetworkPluginServer runs.
|
||||||
@param port: Port.
|
@param port: Port.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.m_pingReceived = False
|
self.m_pingReceived = False
|
||||||
self.m_data = ""
|
self.m_data = ""
|
||||||
self.m_init_res = 0
|
self.m_init_res = 0
|
||||||
|
self.logger = logging.getLogger(self.__class__.__name__)
|
||||||
|
|
||||||
|
|
||||||
def handleMessage(self, user, legacyName, msg, nickname = "", xhtml = "", timestamp = ""):
|
def handleMessage(self, user, legacyName, msg, nickname = "", xhtml = "", timestamp = ""):
|
||||||
m = protocol_pb2.ConversationMessage()
|
m = protocol_pb2.ConversationMessage()
|
||||||
|
@ -251,6 +252,7 @@ class SpectrumBackend:
|
||||||
|
|
||||||
def handleConvMessagePayload(self, data):
|
def handleConvMessagePayload(self, data):
|
||||||
payload = protocol_pb2.ConversationMessage()
|
payload = protocol_pb2.ConversationMessage()
|
||||||
|
self.logger.error("handleConvMessagePayload")
|
||||||
if (payload.ParseFromString(data) == False):
|
if (payload.ParseFromString(data) == False):
|
||||||
#TODO: ERROR
|
#TODO: ERROR
|
||||||
return
|
return
|
||||||
|
@ -363,8 +365,10 @@ class SpectrumBackend:
|
||||||
if (len(self.m_data) >= 4):
|
if (len(self.m_data) >= 4):
|
||||||
expected_size = struct.unpack('!I', self.m_data[0:4])[0]
|
expected_size = struct.unpack('!I', self.m_data[0:4])[0]
|
||||||
if (len(self.m_data) - 4 < expected_size):
|
if (len(self.m_data) - 4 < expected_size):
|
||||||
|
self.logger.error("Expected Data Size Error")
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
|
self.logger.error("Data too small")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@ -378,9 +382,13 @@ class SpectrumBackend:
|
||||||
|
|
||||||
if (parseFromString == False):
|
if (parseFromString == False):
|
||||||
self.m_data = self.m_data[expected_size+4:]
|
self.m_data = self.m_data[expected_size+4:]
|
||||||
|
self.logger.error("Parse from String error")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
self.m_data = self.m_data[4+expected_size:]
|
self.m_data = self.m_data[4+expected_size:]
|
||||||
|
#self.logger.error("Data Type: %s",wrapper.type)
|
||||||
|
|
||||||
|
|
||||||
if wrapper.type == protocol_pb2.WrapperMessage.TYPE_LOGIN:
|
if wrapper.type == protocol_pb2.WrapperMessage.TYPE_LOGIN:
|
||||||
self.handleLoginPayload(wrapper.payload)
|
self.handleLoginPayload(wrapper.payload)
|
||||||
|
|
18
bot.py
18
bot.py
|
@ -48,7 +48,9 @@ class Bot():
|
||||||
"prune": self._prune,
|
"prune": self._prune,
|
||||||
"welcome": self._welcome,
|
"welcome": self._welcome,
|
||||||
"fortune": self._fortune,
|
"fortune": self._fortune,
|
||||||
"sync": self._sync
|
"sync": self._sync,
|
||||||
|
"groups": self._groups,
|
||||||
|
"getgroups": self._getgroups
|
||||||
}
|
}
|
||||||
|
|
||||||
def parse(self, message):
|
def parse(self, message):
|
||||||
|
@ -173,6 +175,8 @@ class Bot():
|
||||||
\\import [token] import buddies from Google
|
\\import [token] import buddies from Google
|
||||||
\\sync sync your imported contacts with WhatsApp
|
\\sync sync your imported contacts with WhatsApp
|
||||||
\\fortune [database] give me a quote
|
\\fortune [database] give me a quote
|
||||||
|
\\groups print all attended groups
|
||||||
|
\\getgroups get current groups from WA
|
||||||
|
|
||||||
following user commands are available:
|
following user commands are available:
|
||||||
\\lastseen request last online timestamp from buddy""")
|
\\lastseen request last online timestamp from buddy""")
|
||||||
|
@ -193,3 +197,15 @@ following user commands are available:
|
||||||
self.session.buddies.prune()
|
self.session.buddies.prune()
|
||||||
self.session.updateRoster()
|
self.session.updateRoster()
|
||||||
self.send("buddy list cleared")
|
self.send("buddy list cleared")
|
||||||
|
def _groups(self):
|
||||||
|
for group in self.session.groups:
|
||||||
|
buddy = self.session.groups[group].owner
|
||||||
|
try:
|
||||||
|
nick = self.session.buddies[buddy].nick
|
||||||
|
except KeyError:
|
||||||
|
nick = buddy
|
||||||
|
|
||||||
|
self.send(self.session.groups[group].id + " " + self.session.groups[group].subject + " Owner: " + nick )
|
||||||
|
def _getgroups(self):
|
||||||
|
self.session.call("group_getGroups", ("participating",))
|
||||||
|
|
||||||
|
|
74
session.py
74
session.py
|
@ -67,6 +67,8 @@ class Session:
|
||||||
self.timer = None
|
self.timer = None
|
||||||
self.password = None
|
self.password = None
|
||||||
self.initialized = False
|
self.initialized = False
|
||||||
|
self.lastMsgId = None
|
||||||
|
self.synced = False
|
||||||
|
|
||||||
self.buddies = BuddyList(legacyName, db)
|
self.buddies = BuddyList(legacyName, db)
|
||||||
self.frontend = YowsupConnectionManager()
|
self.frontend = YowsupConnectionManager()
|
||||||
|
@ -154,13 +156,21 @@ class Session:
|
||||||
def sendMessageToWA(self, sender, message, ID):
|
def sendMessageToWA(self, sender, message, ID):
|
||||||
self.logger.info("Message (ID: %s) send from %s to %s: %s", ID, self.legacyName, sender, message)
|
self.logger.info("Message (ID: %s) send from %s to %s: %s", ID, self.legacyName, sender, message)
|
||||||
message = message.encode("utf-8")
|
message = message.encode("utf-8")
|
||||||
|
if ID == self.lastMsgId:
|
||||||
|
return
|
||||||
|
self.lastMsgId = ID
|
||||||
|
|
||||||
if sender == "bot":
|
if sender == "bot":
|
||||||
self.bot.parse(message)
|
self.bot.parse(message)
|
||||||
elif "-" in sender: # group msg
|
elif "-" in sender: # group msg
|
||||||
if "/" in sender:
|
if "/" in sender:
|
||||||
room, buddy = sender.split("/")
|
room, nick2 = sender.split("/")
|
||||||
self.call("message_send", (buddy + "@s.whatsapp.net", message))
|
buddy2 = nick2
|
||||||
|
for buddy, buddy3 in self.buddies.iteritems():
|
||||||
|
self.logger.info("Group buddy=%s nick=%s", buddy, buddy3.nick)
|
||||||
|
if buddy3.nick == nick2:
|
||||||
|
buddy2 = buddy
|
||||||
|
self.call("message_send", (buddy2 + "@s.whatsapp.net", message))
|
||||||
else:
|
else:
|
||||||
room = sender
|
room = sender
|
||||||
group = self.groups[room]
|
group = self.groups[room]
|
||||||
|
@ -177,7 +187,11 @@ class Session:
|
||||||
self.sendMessageToXMPP(buddy, "Fetching Profile Picture")
|
self.sendMessageToXMPP(buddy, "Fetching Profile Picture")
|
||||||
self.call("contact_getProfilePicture", (buddy + "@s.whatsapp.net",))
|
self.call("contact_getProfilePicture", (buddy + "@s.whatsapp.net",))
|
||||||
else:
|
else:
|
||||||
waId = self.call("message_send", (buddy + "@s.whatsapp.net", message))
|
if ("jpg" in message) or ("webp" in message):
|
||||||
|
#waId = self.call("message_imageSend", (buddy + "@s.whatsapp.net", message, None, 0, None))
|
||||||
|
waId = self.call("message_send", (buddy + "@s.whatsapp.net", message))
|
||||||
|
else:
|
||||||
|
waId = self.call("message_send", (buddy + "@s.whatsapp.net", message))
|
||||||
self.msgIDs[waId] = MsgIDs( ID, waId)
|
self.msgIDs[waId] = MsgIDs( ID, waId)
|
||||||
self.logger.info("WA Message send to %s with ID %s", buddy, waId)
|
self.logger.info("WA Message send to %s with ID %s", buddy, waId)
|
||||||
|
|
||||||
|
@ -196,8 +210,9 @@ class Session:
|
||||||
try:
|
try:
|
||||||
nick = self.buddies[buddy].nick
|
nick = self.buddies[buddy].nick
|
||||||
except KeyError:
|
except KeyError:
|
||||||
nick = "unknown"
|
nick = buddy
|
||||||
|
|
||||||
|
buddyFull = buddy
|
||||||
if timestamp:
|
if timestamp:
|
||||||
timestamp = time.strftime("%Y%m%dT%H%M%S", time.gmtime(timestamp))
|
timestamp = time.strftime("%Y%m%dT%H%M%S", time.gmtime(timestamp))
|
||||||
|
|
||||||
|
@ -207,10 +222,10 @@ class Session:
|
||||||
if room not in self.groupOfflineQueue:
|
if room not in self.groupOfflineQueue:
|
||||||
self.groupOfflineQueue[room] = [ ]
|
self.groupOfflineQueue[room] = [ ]
|
||||||
|
|
||||||
self.groupOfflineQueue[room].append((buddy, messageContent + ": " + nick, timestamp))
|
self.groupOfflineQueue[room].append((nick, messageContent, timestamp))
|
||||||
else:
|
else:
|
||||||
self.logger.debug("Group message sent from %s to %s: %s", buddy, room, messageContent)
|
self.logger.debug("Group message sent from %s to %s: %s", buddy, room, messageContent)
|
||||||
self.backend.handleMessage(self.user, room, messageContent + ": " + nick, buddy, "", timestamp)
|
self.backend.handleMessage(self.user, room, messageContent, nick , "", timestamp)
|
||||||
|
|
||||||
def changeStatus(self, status):
|
def changeStatus(self, status):
|
||||||
if status != self.status:
|
if status != self.status:
|
||||||
|
@ -258,10 +273,16 @@ class Session:
|
||||||
self.logger.info("Joining room: %s room=%s, nick=%s", self.legacyName, room, nick)
|
self.logger.info("Joining room: %s room=%s, nick=%s", self.legacyName, room, nick)
|
||||||
|
|
||||||
group.nick = nick
|
group.nick = nick
|
||||||
|
try:
|
||||||
|
ownerNick = self.buddies[group.subjectOwner].nick
|
||||||
|
except KeyError:
|
||||||
|
ownerNick = group.subjectOwner
|
||||||
|
|
||||||
#time.sleep(2)
|
#time.sleep(2)
|
||||||
if init == False:
|
if init == False:
|
||||||
self.call("group_getParticipants", (room + "@g.us",)) #FIXME
|
self.call("group_getParticipants", (room + "@g.us",)) #FIXME
|
||||||
self.backend.handleSubject(self.user, room, group.subject, group.subjectOwner)
|
self.backend.handleSubject(self.user, room, group.subject, ownerNick)
|
||||||
|
#self.backend.handleSubject(self.user, room, group.subject, self.user)
|
||||||
self.backend.handleRoomNicknameChanged(self.user,room,group.subject)
|
self.backend.handleRoomNicknameChanged(self.user,room,group.subject)
|
||||||
else:
|
else:
|
||||||
self.logger.warn("Room doesn't exist: %s", room)
|
self.logger.warn("Room doesn't exist: %s", room)
|
||||||
|
@ -272,7 +293,13 @@ class Session:
|
||||||
old = self.buddies.keys()
|
old = self.buddies.keys()
|
||||||
self.buddies.load()
|
self.buddies.load()
|
||||||
new = self.buddies.keys()
|
new = self.buddies.keys()
|
||||||
|
contacts = new
|
||||||
|
#self.logger.info("Roster: %s", str(list(new)))
|
||||||
|
|
||||||
|
if self.synced == False:
|
||||||
|
self.call("sync_sendSync", (contacts,))
|
||||||
|
self.synced = True
|
||||||
|
#self.call("sync_sendContacts", (contacts,))
|
||||||
add = set(new) - set(old)
|
add = set(new) - set(old)
|
||||||
remove = set(old) - set(new)
|
remove = set(old) - set(new)
|
||||||
|
|
||||||
|
@ -340,7 +367,7 @@ class Session:
|
||||||
#if receiptRequested:
|
#if receiptRequested:
|
||||||
self.call("message_ack", (jid, messageId))
|
self.call("message_ack", (jid, messageId))
|
||||||
|
|
||||||
def onMediaReceived(self, messageId, jid, preview, url, size, receiptRequested, isBroadcast):
|
def onMediaReceived(self, messageId, jid, preview, url, size, caption, timestamp, receiptRequested, pushName, isBroadcast):
|
||||||
buddy = jid.split("@")[0]
|
buddy = jid.split("@")[0]
|
||||||
|
|
||||||
self.logger.info("Media received from %s: %s", buddy, url)
|
self.logger.info("Media received from %s: %s", buddy, url)
|
||||||
|
@ -349,7 +376,7 @@ class Session:
|
||||||
#if receiptRequested:
|
#if receiptRequested:
|
||||||
self.call("message_ack", (jid, messageId))
|
self.call("message_ack", (jid, messageId))
|
||||||
|
|
||||||
def onGroupMediaReceived(self, messageId, gjid, jid, preview, url, size, receiptRequested):
|
def onGroupMediaReceived(self, messageId, gjid, jid, preview, url, size, caption, timestamp, receiptRequested, pushName):
|
||||||
buddy = jid.split("@")[0]
|
buddy = jid.split("@")[0]
|
||||||
room = gjid.split("@")[0]
|
room = gjid.split("@")[0]
|
||||||
|
|
||||||
|
@ -362,31 +389,35 @@ class Session:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def onLocationReceived(self, messageId, jid, name, preview, latitude, longitude, receiptRequested, isBroadcast):
|
def onLocationReceived(self, messageId, jid, name, preview, latitude, longitude, timestamp, receiptRequested, pushName, isBroadcast):
|
||||||
buddy = jid.split("@")[0]
|
buddy = jid.split("@")[0]
|
||||||
self.logger.info("Location received from %s: %s, %s", buddy, latitude, longitude)
|
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) })
|
url = "http://maps.google.de?%s" % urllib.urlencode({ "q": "%s %s" % (latitude, longitude) })
|
||||||
|
geo = "geo:"+latitude+","+longitude
|
||||||
# self.sendMessageToXMPP(buddy, utils.shorten(url))
|
# self.sendMessageToXMPP(buddy, utils.shorten(url))
|
||||||
self.sendMessageToXMPP(buddy, url)
|
self.sendMessageToXMPP(buddy, url)
|
||||||
|
self.sendMessageToXMPP(buddy, geo)
|
||||||
#if receiptRequested:
|
#if receiptRequested:
|
||||||
self.call("message_ack", (jid, messageId))
|
self.call("message_ack", (jid, messageId))
|
||||||
|
|
||||||
|
|
||||||
def onGroupLocationReceived(self, messageId, gjid, jid, name, preview, latitude, longitude, receiptRequested):
|
def onGroupLocationReceived(self, messageId, gjid, jid, name, preview, latitude, longitude, timestamp, receiptRequested, pushName):
|
||||||
buddy = jid.split("@")[0]
|
buddy = jid.split("@")[0]
|
||||||
room = gjid.split("@")[0]
|
room = gjid.split("@")[0]
|
||||||
|
|
||||||
url = "http://maps.google.de?%s" % urllib.urlencode({ "q": "%s %s" % (latitude, longitude) })
|
url = "http://maps.google.de?%s" % urllib.urlencode({ "q": "%s %s" % (latitude, longitude) })
|
||||||
|
geo = "geo:"+latitude+","+longitude
|
||||||
# self.sendMessageToXMPP(buddy, utils.shorten(url))
|
# self.sendMessageToXMPP(buddy, utils.shorten(url))
|
||||||
self.sendGroupMessageToXMPP(room, buddy, url)
|
self.sendGroupMessageToXMPP(room, buddy, url)
|
||||||
|
self.sendGroupMessageToXMPP(room, buddy, geo)
|
||||||
#if receiptRequested:
|
#if receiptRequested:
|
||||||
self.call("message_ack", (gjid, messageId))
|
self.call("message_ack", (gjid, messageId))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def onVcardReceived(self, messageId, jid, name, data, receiptRequested, isBroadcast): # TODO
|
def onVcardReceived(self, messageId, jid, name, data, timestamp, receiptRequested, pushName, isBroadcast): # TODO
|
||||||
buddy = jid.split("@")[0]
|
buddy = jid.split("@")[0]
|
||||||
self.logger.info("VCard received from %s", buddy)
|
self.logger.info("VCard received from %s", buddy)
|
||||||
self.sendMessageToXMPP(buddy, "Received VCard (not implemented yet)")
|
self.sendMessageToXMPP(buddy, "Received VCard (not implemented yet)")
|
||||||
|
@ -469,14 +500,25 @@ class Session:
|
||||||
for jid in jids:
|
for jid in jids:
|
||||||
buddy = jid.split("@")[0]
|
buddy = jid.split("@")[0]
|
||||||
self.logger.info("Added %s to room %s", buddy, room)
|
self.logger.info("Added %s to room %s", buddy, room)
|
||||||
|
try:
|
||||||
|
nick = self.buddies[buddy].nick
|
||||||
|
except KeyError:
|
||||||
|
nick = buddy
|
||||||
|
#nick = ""
|
||||||
|
#nick = ""
|
||||||
|
buddyFull = buddy
|
||||||
if buddy == group.owner:
|
if buddy == group.owner:
|
||||||
flags = protocol_pb2.PARTICIPANT_FLAG_MODERATOR
|
flags = protocol_pb2.PARTICIPANT_FLAG_MODERATOR
|
||||||
else:
|
else:
|
||||||
flags = protocol_pb2.PARTICIPANT_FLAG_NONE
|
flags = protocol_pb2.PARTICIPANT_FLAG_NONE
|
||||||
|
if buddy == self.legacyName:
|
||||||
|
nick = group.nick
|
||||||
|
flags = protocol_pb2.PARTICIPANT_FLAG_ME
|
||||||
|
buddyFull = self.user
|
||||||
|
|
||||||
self.backend.handleParticipantChanged(self.user, buddy, room, flags, protocol_pb2.STATUS_ONLINE,"Nici","") # TODO check status
|
|
||||||
|
|
||||||
|
self.backend.handleParticipantChanged(self.user, buddyFull, room, flags, protocol_pb2.STATUS_ONLINE, buddy, nick) # TODO check status
|
||||||
|
#self.backend.handleParticipantChanged(self.user, buddy , room, flags, protocol_pb2.STATUS_ONLINE, buddy, nick) # TODO check sta
|
||||||
if room in self.groupOfflineQueue:
|
if room in self.groupOfflineQueue:
|
||||||
while self.groupOfflineQueue[room]:
|
while self.groupOfflineQueue[room]:
|
||||||
msg = self.groupOfflineQueue[room].pop(0)
|
msg = self.groupOfflineQueue[room].pop(0)
|
||||||
|
@ -552,7 +594,7 @@ class Session:
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
|
|
||||||
|
|
||||||
# if receiptRequested: self.call("notification_ack", (jid, messageId))
|
#if receiptRequested: self.call("notification_ack", (jid, messageId))
|
||||||
|
|
||||||
def onReceiptMessageDeliverd(self, jid, msgId):
|
def onReceiptMessageDeliverd(self, jid, msgId):
|
||||||
buddy = jid.split("@")[0]
|
buddy = jid.split("@")[0]
|
||||||
|
|
|
@ -63,7 +63,7 @@ class WhatsAppBackend(SpectrumBackend):
|
||||||
del self.sessions[user]
|
del self.sessions[user]
|
||||||
|
|
||||||
def handleMessageSendRequest(self, user, buddy, message, xhtml = "", ID = 0):
|
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)
|
self.logger.info("handleMessageSendRequest(user=%s, buddy=%s, message=%s, id=%s)", user, buddy, message, ID)
|
||||||
if user not in self.sessions:
|
if user not in self.sessions:
|
||||||
return;
|
return;
|
||||||
self.sessions[user].sendMessageToWA(buddy, message, ID)
|
self.sessions[user].sendMessageToWA(buddy, message, ID)
|
||||||
|
|
Loading…
Reference in New Issue