[SVN] Release 0.3.2

[FIX] Fixed roster exchange request after transport boot-up
[ADD] Added optional profile pictures downloading to V-Cards; you need to add `enable_avatars`(bool) to database or just remove and re-create db file to enable it
This commit is contained in:
annelin
2018-07-02 00:51:22 +00:00
parent e66bda9cd8
commit f0ef3abb9c
3 changed files with 60 additions and 13 deletions

View File

@@ -1,7 +1,10 @@
import sqlite3
import re
import sys
import os
import io
import time
import hashlib
import sleekxmpp
from sleekxmpp.componentxmpp import ComponentXMPP
@@ -49,7 +52,6 @@ class XMPPTelegram(ComponentXMPP):
self.tg_connections = dict()
self.tg_phones = dict()
self.tg_dialogs = dict()
self.contact_list = dict()
self.db_connection = self.init_database()
@@ -65,6 +67,7 @@ class XMPPTelegram(ComponentXMPP):
self.add_event_handler('got_online', self.handle_online)
self.add_event_handler('got_offline', self.handle_offline)
self.add_event_handler('session_start', self.handle_start)
self.plugin['xep_0030'].add_identity(
category='gateway',
@@ -526,7 +529,7 @@ class XMPPTelegram(ComponentXMPP):
self.tg_connections[jid].invoke(UpdateStatusRequest(offline=False))
# Получаем и обрабатываем список диалогов
self.tg_process_dialogs(jid)
self.tg_process_dialogs(jid, sync_roster = False)
# Регистрируем обработчик обновлений в Telegram
self.tg_connections[jid].add_update_handler(self.tg_connections[jid].xmpp_update_handler)
@@ -559,6 +562,8 @@ class XMPPTelegram(ComponentXMPP):
def tg_process_dialogs(self, jid, sync_roster = True):
print('Processing dialogs...')
# Инициализируем словари для диалогов
self.tg_dialogs[jid] = dict()
self.tg_dialogs[jid]['raw'] = list()
@@ -594,6 +599,9 @@ class XMPPTelegram(ComponentXMPP):
vcard = self.plugin['xep_0054'].make_vcard()
u_jid = get_contact_jid(usr, self.boundjid.bare)
# make vcard #
vcard['JABBERID'] = u_jid
if usr.deleted:
rostername = "Deleted Account"
vcard['FN'] = 'Deleted account'
@@ -612,11 +620,18 @@ class XMPPTelegram(ComponentXMPP):
vcard['DESC'] += ' [Bot]'
vcard['NICKNAME'] = vcard['FN']
# add photo to VCard #
photo, photosha1hash = self.get_peer_photo(jid, usr) if sync_roster else (None, None)
if photo:
vcard['PHOTO']['TYPE'] = 'image/jpeg'
vcard['PHOTO']['BINVAL'] = photo
vcard['JABBERID'] = u_jid
self.plugin['xep_0054'].publish_vcard(jid=u_jid, vcard=vcard)
self.plugin['xep_0172'].publish_nick(nick=vcard['FN'], ifrom=u_jid)
self.publish_photo(jid, u_jid, photosha1hash) if photosha1hash else None
# add it to contect list & avatar download queue #
self.contact_list[jid][u_jid] = rostername
if usr.bot:
@@ -645,17 +660,25 @@ class XMPPTelegram(ComponentXMPP):
if cht and cht.id:
rostername = display_tg_name(cht)
c_jid = get_contact_jid(cht, self.boundjid.bare)
u_jid = get_contact_jid(cht, self.boundjid.bare)
vcard = self.plugin['xep_0054'].make_vcard()
vcard['FN'] = rostername
vcard['NICKNAME'] = rostername
vcard['JABBERID'] = c_jid
self.plugin['xep_0054'].publish_vcard(jid=c_jid, vcard=vcard)
self.plugin['xep_0172'].publish_nick(nick=vcard['FN'], ifrom=c_jid)
vcard['JABBERID'] = u_jid
# add photo to VCard #
photo, photosha1hash = self.get_peer_photo(jid, cht) if sync_roster else (None, None)
if photo:
vcard['PHOTO']['TYPE'] = 'image/jpeg'
vcard['PHOTO']['BINVAL'] = photo
self.plugin['xep_0054'].publish_vcard(jid=u_jid, vcard=vcard)
self.plugin['xep_0172'].publish_nick(nick=vcard['FN'], ifrom=u_jid)
self.publish_photo(jid, u_jid, photosha1hash) if photosha1hash else None
self.contact_list[jid][c_jid] = rostername
self.send_presence(pto=jid, pfrom=c_jid, pshow = 'chat', pstatus = cht.title)
self.contact_list[jid][u_jid] = rostername
self.send_presence(pto=jid, pfrom=u_jid, pshow = 'chat', pstatus = cht.title)
if len(dlgs.dialogs) == 0: # Если все диалоги получены - прерываем цикл
if sync_roster and 'use_roster_exchange' in self.accounts[jid] and self.accounts[jid]['use_roster_exchange'] == 'true':
@@ -691,6 +714,30 @@ class XMPPTelegram(ComponentXMPP):
"""
self.send_message(mto=iq['from'], mfrom=self.config['jid'], mtype='chat', mbody=msg)
def get_peer_photo(self, jid, peer):
# we are able to disable this shit #
if not 'enable_avatars' in self.accounts[jid] or self.accounts[jid]['enable_avatars'] != 'true':
return (None, None)
data = io.BytesIO()
self.tg_connections[jid].download_profile_photo(peer, file = data)
data.flush()
if isinstance(data, io.BytesIO) and data.getbuffer().nbytes > 0:
image = data.getvalue()
image_sha1 = hashlib.sha1(image).hexdigest()
return (image, image_sha1)
else:
return (None, None)
def publish_photo(self, jid, fromjid, photo):
presence = sleekxmpp.Presence()
presence['to'] = jid
presence['from'] = fromjid
presence.appendxml(ET.fromstring("<x xmlns='vcard-temp:x:update'><photo>%s</photo></x>" % photo))
self.send(presence)
def init_database(self):
"""
Инициализация БД
@@ -705,6 +752,6 @@ class XMPPTelegram(ComponentXMPP):
conn = sqlite3.connect(self.config['db_connect'], isolation_level=None, check_same_thread=False)
conn.row_factory = dict_factory
conn.execute("CREATE TABLE IF NOT EXISTS accounts(jid VARCHAR(255), tg_phone VARCHAR(25), use_roster_exchange BOOLEAN default false, keep_online BOOLEAN default false, status_update_interval INTEGER default 60)")
conn.execute("CREATE TABLE IF NOT EXISTS accounts(jid VARCHAR(255), tg_phone VARCHAR(25), use_roster_exchange BOOLEAN default false, keep_online BOOLEAN default false, status_update_interval INTEGER default 60, enable_avatars BOOLEAN default false)")
return conn