Download whatsapp profile pictures
Everytime the user requests a VCard the profile pictures are updated. The sha1hash hash of the picture is calculated and stored in buddy.
This commit is contained in:
parent
d2efa0dd7b
commit
4fd313e516
31
buddy.py
31
buddy.py
|
@ -48,7 +48,7 @@ class Number():
|
||||||
|
|
||||||
|
|
||||||
class Buddy():
|
class Buddy():
|
||||||
def __init__(self, owner, number, nick, groups, id, db):
|
def __init__(self, owner, number, nick, groups, image_hash, id, db):
|
||||||
self.id = id
|
self.id = id
|
||||||
self.db = db
|
self.db = db
|
||||||
|
|
||||||
|
@ -56,14 +56,16 @@ class Buddy():
|
||||||
self.owner = owner
|
self.owner = owner
|
||||||
self.number = number
|
self.number = number
|
||||||
self.groups = groups
|
self.groups = groups
|
||||||
|
self.image_hash = image_hash
|
||||||
|
|
||||||
def update(self, nick, groups):
|
def update(self, nick, groups, image_hash):
|
||||||
self.nick = nick
|
self.nick = nick
|
||||||
self.groups = groups
|
self.groups = groups
|
||||||
|
self.image_hash = image_hash
|
||||||
|
|
||||||
groups = u",".join(groups).encode("latin-1")
|
groups = u",".join(groups).encode("latin-1")
|
||||||
cur = self.db.cursor()
|
cur = self.db.cursor()
|
||||||
cur.execute("UPDATE buddies SET nick = %s, groups = %s WHERE owner_id = %s AND buddy_id = %s", (self.nick, groups, self.owner.id, self.number.id))
|
cur.execute("UPDATE buddies SET nick = %s, groups = %s, image_hash = %s WHERE owner_id = %s AND buddy_id = %s", (self.nick, groups, image_hash, self.owner.id, self.number.id))
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
|
@ -73,13 +75,13 @@ class Buddy():
|
||||||
self.id = None
|
self.id = None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create(owner, number, nick, groups, db):
|
def create(owner, number, nick, groups, image_hash, db):
|
||||||
groups = u",".join(groups).encode("latin-1")
|
groups = u",".join(groups).encode("latin-1")
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
cur.execute("REPLACE buddies (owner_id, buddy_id, nick, groups) VALUES (%s, %s, %s, %s)", (owner.id, number.id, nick, groups))
|
cur.execute("REPLACE buddies (owner_id, buddy_id, nick, groups, image_hash) VALUES (%s, %s, %s, %s, %s)", (owner.id, number.id, nick, groups, image_hash))
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
return Buddy(owner, number, nick, groups, cur.lastrowid, db)
|
return Buddy(owner, number, nick, groups, image_hash, cur.lastrowid, db)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s (nick=%s, id=%s)" % (self.number, self.nick, self.id)
|
return "%s (nick=%s, id=%s)" % (self.number, self.nick, self.id)
|
||||||
|
@ -99,7 +101,8 @@ class BuddyList(dict):
|
||||||
n.number AS number,
|
n.number AS number,
|
||||||
b.nick AS nick,
|
b.nick AS nick,
|
||||||
b.groups AS groups,
|
b.groups AS groups,
|
||||||
n.state AS state
|
n.state AS state,
|
||||||
|
b.image_hash AS image_hash
|
||||||
FROM buddies AS b
|
FROM buddies AS b
|
||||||
LEFT JOIN numbers AS n
|
LEFT JOIN numbers AS n
|
||||||
ON b.buddy_id = n.id
|
ON b.buddy_id = n.id
|
||||||
|
@ -109,20 +112,20 @@ class BuddyList(dict):
|
||||||
ORDER BY b.owner_id DESC""", self.owner.id)
|
ORDER BY b.owner_id DESC""", self.owner.id)
|
||||||
|
|
||||||
for i in range(cur.rowcount):
|
for i in range(cur.rowcount):
|
||||||
id, number, nick, groups, state = cur.fetchone()
|
id, number, nick, groups, state, image_hash = cur.fetchone()
|
||||||
self[number] = Buddy(self.owner, Number(number, state, self.db), nick.decode('latin1'), groups.split(","), id, self.db)
|
self[number] = Buddy(self.owner, Number(number, state, self.db), nick.decode('latin1'), groups.split(","), image_hash, id, self.db)
|
||||||
|
|
||||||
def update(self, number, nick, groups):
|
def update(self, number, nick, groups, image_hash):
|
||||||
if number in self:
|
if number in self:
|
||||||
buddy = self[number]
|
buddy = self[number]
|
||||||
buddy.update(nick, groups)
|
buddy.update(nick, groups, image_hash)
|
||||||
else:
|
else:
|
||||||
buddy = self.add(number, nick, groups, 1)
|
buddy = self.add(number, nick, groups, 1, image_hash)
|
||||||
|
|
||||||
return buddy
|
return buddy
|
||||||
|
|
||||||
def add(self, number, nick, groups = [], state = 0):
|
def add(self, number, nick, groups = [], state = 0, image_hash = ""):
|
||||||
return Buddy.create(self.owner, Number(number, state, self.db), nick, groups, self.db)
|
return Buddy.create(self.owner, Number(number, state, self.db), nick, groups, image_hash, self.db)
|
||||||
|
|
||||||
def remove(self, number):
|
def remove(self, number):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -13,6 +13,7 @@ CREATE TABLE IF NOT EXISTS `buddies` (
|
||||||
`buddy_id` int(11) NOT NULL,
|
`buddy_id` int(11) NOT NULL,
|
||||||
`nick` varchar(255) NOT NULL,
|
`nick` varchar(255) NOT NULL,
|
||||||
`groups` varchar(255) NOT NULL,
|
`groups` varchar(255) NOT NULL,
|
||||||
|
`image_hash` varchar(40),
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||||
|
|
||||||
|
|
19
session.py
19
session.py
|
@ -110,6 +110,7 @@ class Session(YowsupApp):
|
||||||
for number in add:
|
for number in add:
|
||||||
buddy = self.buddies[number]
|
buddy = self.buddies[number]
|
||||||
self.subscribePresence(number)
|
self.subscribePresence(number)
|
||||||
|
self.backend.handleBuddyChanged(self.user, number, buddy.nick, buddy.groups, protocol_pb2.STATUS_NONE, iconHash = buddy.image_hash if buddy.image_hash is not None else "")
|
||||||
self.requestLastSeen(number, self._lastSeen)
|
self.requestLastSeen(number, self._lastSeen)
|
||||||
|
|
||||||
def _lastSeen(self, number, seconds):
|
def _lastSeen(self, number, seconds):
|
||||||
|
@ -368,9 +369,9 @@ class Session(YowsupApp):
|
||||||
self.backend.handleMessage(self.user, msg[0], msg[1], "", "", msg[2])
|
self.backend.handleMessage(self.user, msg[0], msg[1], "", "", msg[2])
|
||||||
|
|
||||||
# also for adding a new buddy
|
# also for adding a new buddy
|
||||||
def updateBuddy(self, buddy, nick, groups):
|
def updateBuddy(self, buddy, nick, groups, image_hash =""):
|
||||||
if buddy != "bot":
|
if buddy != "bot":
|
||||||
self.buddies.update(buddy, nick, groups)
|
self.buddies.update(buddy, nick, groups, image_hash)
|
||||||
self.updateRoster()
|
self.updateRoster()
|
||||||
|
|
||||||
def removeBuddy(self, buddy):
|
def removeBuddy(self, buddy):
|
||||||
|
@ -391,6 +392,20 @@ class Session(YowsupApp):
|
||||||
self.backend.handleSubject(self.user, room, group.subject, group.subjectOwner)
|
self.backend.handleSubject(self.user, room, group.subject, group.subjectOwner)
|
||||||
else:
|
else:
|
||||||
self.logger.warn("Room doesn't exist: %s", room)
|
self.logger.warn("Room doesn't exist: %s", room)
|
||||||
|
|
||||||
|
def requestVCard(self, buddy, ID):
|
||||||
|
|
||||||
|
def onSuccess(response, request):
|
||||||
|
self.logger.debug('Sending VCard (%s) with image id %s',
|
||||||
|
ID, response.pictureId)
|
||||||
|
image_hash = utils.sha1hash(response.pictureData)
|
||||||
|
self.logger.debug('Image hash is %s', image_hash)
|
||||||
|
self.backend.handleVCard(self.user, ID, buddy, "", "", response.pictureData)
|
||||||
|
obuddy = self.buddies[buddy]
|
||||||
|
self.updateBuddy(buddy, obuddy.nick, obuddy.groups, image_hash)
|
||||||
|
|
||||||
|
self.logger.debug('Requesting profile picture of %s', buddy)
|
||||||
|
self.requestProfilePicture(buddy, onSuccess = onSuccess)
|
||||||
|
|
||||||
# Not used
|
# Not used
|
||||||
def onLocationReceived(self, messageId, jid, name, preview, latitude, longitude, receiptRequested, isBroadcast):
|
def onLocationReceived(self, messageId, jid, name, preview, latitude, longitude, receiptRequested, isBroadcast):
|
||||||
|
|
4
utils.py
4
utils.py
|
@ -26,6 +26,7 @@ import urllib
|
||||||
import json
|
import json
|
||||||
import e4u
|
import e4u
|
||||||
import base64
|
import base64
|
||||||
|
import hashlib
|
||||||
|
|
||||||
def shorten(url):
|
def shorten(url):
|
||||||
url = urllib.urlopen("http://d.0l.de/add.json?type=URL&rdata=%s" % urllib.quote(url))
|
url = urllib.urlopen("http://d.0l.de/add.json?type=URL&rdata=%s" % urllib.quote(url))
|
||||||
|
@ -61,3 +62,6 @@ def softToUni(message):
|
||||||
|
|
||||||
def decodePassword(password):
|
def decodePassword(password):
|
||||||
return base64.b64decode(bytes(password.encode("utf-8")))
|
return base64.b64decode(bytes(password.encode("utf-8")))
|
||||||
|
|
||||||
|
def sha1hash(data):
|
||||||
|
return hashlib.sha1(data).hexdigest()
|
||||||
|
|
|
@ -101,6 +101,10 @@ class WhatsAppBackend(SpectrumBackend):
|
||||||
self.logger.debug("handleStoppedTypingRequest(user=%s, buddy=%s)", user, buddy)
|
self.logger.debug("handleStoppedTypingRequest(user=%s, buddy=%s)", user, buddy)
|
||||||
self.sessions[user].sendTypingStopped(buddy)
|
self.sessions[user].sendTypingStopped(buddy)
|
||||||
|
|
||||||
|
def handleVCardRequest(self, user, buddy, ID):
|
||||||
|
self.logger.debug("handleVCardRequest(user=%s, buddy=%s, ID=%s)", user, buddy, ID)
|
||||||
|
self.sessions[user].requestVCard(buddy, ID)
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
def handleBuddyBlockToggled(self, user, buddy, blocked):
|
def handleBuddyBlockToggled(self, user, buddy, blocked):
|
||||||
pass
|
pass
|
||||||
|
@ -108,9 +112,6 @@ class WhatsAppBackend(SpectrumBackend):
|
||||||
def handleLeaveRoomRequest(self, user, room):
|
def handleLeaveRoomRequest(self, user, room):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def handleVCardRequest(self, user, buddy, ID):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def handleVCardUpdatedRequest(self, user, photo, nickname):
|
def handleVCardUpdatedRequest(self, user, photo, nickname):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -206,13 +206,24 @@ class YowsupApp(object):
|
||||||
- failure: (func) called when request has failed
|
- failure: (func) called when request has failed
|
||||||
"""
|
"""
|
||||||
iq = LastseenIqProtocolEntity(phoneNumber + '@s.whatsapp.net')
|
iq = LastseenIqProtocolEntity(phoneNumber + '@s.whatsapp.net')
|
||||||
self.sendIq(iq, self._lastSeenSuccess(success), failure)
|
self.sendIq(iq, onSuccess = self._lastSeenSuccess(success), onError = failure)
|
||||||
|
|
||||||
def _lastSeenSuccess(self, success):
|
def _lastSeenSuccess(self, success):
|
||||||
def func(response, request):
|
def func(response, request):
|
||||||
success(response._from.split('@')[0], response.seconds)
|
success(response._from.split('@')[0], response.seconds)
|
||||||
return func
|
return func
|
||||||
|
|
||||||
|
def requestProfilePicture(self, phoneNumber, onSuccess = None, onFailure = None):
|
||||||
|
"""
|
||||||
|
Requests profile picture of whatsapp user
|
||||||
|
Args:
|
||||||
|
- phoneNumber: (str) the phone number of the user
|
||||||
|
- success: (func) called when request is successfully processed.
|
||||||
|
- failure: (func) called when request has failed
|
||||||
|
"""
|
||||||
|
iq = GetPictureIqProtocolEntity(phoneNumber + '@s.whatsapp.net')
|
||||||
|
self.sendIq(iq, onSuccess = onSuccess, onError = onFailure)
|
||||||
|
|
||||||
def onAuthSuccess(self, status, kind, creation, expiration, props, nonce, t):
|
def onAuthSuccess(self, status, kind, creation, expiration, props, nonce, t):
|
||||||
"""
|
"""
|
||||||
Called when login is successful.
|
Called when login is successful.
|
||||||
|
|
Loading…
Reference in a new issue