1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
# coding: utf-8
# This file is a part of VK4XMPP transport
# © simpleApps, 2014 (30.08.14 14:58PM GMT) — 2015.
from hashlib import sha1
"""
Implements XEP-0153: vCard-Based Avatars
"""
class AvatarHash(object):
def __init__(self):
runDatabaseQuery("create table if not exists avatar_hash "
"(id text unique, sha text, updated integer)", set=True)
self.baseHash = self.hashPhotos([{"uid": TransportID, "photo": URL_VCARD_NO_IMAGE}])
self.pending = set([])
join = lambda uids: ",".join([str(uid) for uid in uids])
join = staticmethod(join)
def getLocalHashes(self, uids):
data = runDatabaseQuery("select id, sha, updated from avatar_hash where id in (%s)" % self.join(uids)) or []
result = {}
for key in data:
uid, (sha, updated) = int(key[0]), key[1:]
if (time.time() - updated) >= PHOTO_LIFE_DURATION: # Better to send something instead of nothing
self.pending.add(uid)
result[uid] = sha
result.update(self.baseHash)
return result
def getPhotos(self, user, uids=None):
length = len(uids)
data = []
if length > PHOTO_REQUEST_LIMIT:
for i in xrange(0, length, PHOTO_REQUEST_LIMIT):
current = uids[i:i+PHOTO_REQUEST_LIMIT]
data += self.sendPhotoRequest(user, current)
else:
data = self.sendPhotoRequest(user, uids)
return data
def sendPhotoRequest(self, user, uids):
data = user.vk.method("execute.getPhotos",
{"users": self.join(uids), "size": PhotoSize}) or []
return data
def hashPhotos(self, photos):
result = {}
for key in photos:
url, uid = key["photo"], key["uid"]
result[uid] = sha1(utils.getLinkData(url, False)).hexdigest()
return result
def getHashes(self, user, uids):
photos = self.getPhotos(user, uids)
hashes = self.hashPhotos(photos)
date = time.time()
return (hashes, date)
def makeHashes(self, user, uids=None):
uids = uids or user.friends.keys()
local = self.getLocalHashes(uids)
if len(local) > 1:
for uid in uids:
if uid not in local:
self.pending.add(uid)
else:
logger.debug("avatar_hash: updating hash database for user (jid: %s)", user.source)
hashes, date = self.getHashes(user, uids)
if hashes:
sql = "insert into avatar_hash (id, sha, updated) values "
for uid, value in hashes.iteritems():
sql += "(%s, %s, %s)," % (uid, repr(value), date)
local[uid] = value
runDatabaseQuery(sql[:-1], set=True)
local.update(self.baseHash)
return local
def updateHashes(self, user):
hashes, date = self.getHashes(user, list(self.pending))
for uid, hash in hashes.iteritems():
runDatabaseQuery("update avatar_hash set sha=?, updated=? where id=?", (hash, date, uid), set=True)
def addPresenceHash(prs, destination, source):
if destination in Users and not prs.getType():
user = Users[destination]
if user.settings.avatar_hash:
x = prs.setTag("x", namespace=xmpp.NS_VCARD_UPDATE)
uid = vk2xmpp(source)
hashes = getattr(user, "hashes", {})
if not hashes:
user.hashes = hashes = Avatars.getLocalHashes(user.friends)
hash = hashes.get(uid)
if hash:
x.setTagData("photo", hash)
@utils.threaded
def handleQueue():
while ALIVE:
if Queue:
user = Queue.pop()
user.hashes = Avatars.makeHashes(user)
if Avatars.pending:
utils.runThread(Avatars.updateHashes, (user,))
Avatars.pending = set([])
time.sleep(10)
def addUserToQueue(user):
Queue.add(user)
if isdef("ENABLE_PHOTO_HASHES") and ENABLE_PHOTO_HASHES:
if not isdef("PHOTO_REQUEST_LIMIT"):
PHOTO_REQUEST_LIMIT = 280 # 280 folks
if not isdef("PHOTO_LIFE_DURATION"):
PHOTO_LIFE_DURATION = 604800 # 1 week
Avatars = AvatarHash()
Queue = set([])
GLOBAL_USER_SETTINGS["avatar_hash"] = {"label": "Show my friends avatars", "value": 0}
logger.debug("extension avatar_hash is loaded")
registerHandler("evt01", handleQueue)
registerHandler("evt05", addUserToQueue)
registerHandler("prs02", addPresenceHash)
else:
del AvatarHash, addPresenceHash, handleQueue, addUserToQueue
|