[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,3 +1,3 @@
from xmpp_tg.xmpp import XMPPTelegram from xmpp_tg.xmpp import XMPPTelegram
__version__ = '0.3.1' __version__ = '0.3.2'

View File

@@ -59,8 +59,8 @@ class TelegramGateClient(TelegramClient):
def xmpp_update_handler(self, obj): def xmpp_update_handler(self, obj):
print("We have received update for <%s>" % self.jid) # print("We have received update for <%s>" % self.jid)
print(obj) # print(obj)
# we have received some updates, so we're logined and can get <me> object and start mtd / upd threads # # we have received some updates, so we're logined and can get <me> object and start mtd / upd threads #
if not self.me: if not self.me:

View File

@@ -1,7 +1,10 @@
import sqlite3 import sqlite3
import re import re
import sys import sys
import os
import io
import time import time
import hashlib
import sleekxmpp import sleekxmpp
from sleekxmpp.componentxmpp import ComponentXMPP from sleekxmpp.componentxmpp import ComponentXMPP
@@ -49,7 +52,6 @@ class XMPPTelegram(ComponentXMPP):
self.tg_connections = dict() self.tg_connections = dict()
self.tg_phones = dict() self.tg_phones = dict()
self.tg_dialogs = dict() self.tg_dialogs = dict()
self.contact_list = dict() self.contact_list = dict()
self.db_connection = self.init_database() 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_online', self.handle_online)
self.add_event_handler('got_offline', self.handle_offline) self.add_event_handler('got_offline', self.handle_offline)
self.add_event_handler('session_start', self.handle_start) self.add_event_handler('session_start', self.handle_start)
self.plugin['xep_0030'].add_identity( self.plugin['xep_0030'].add_identity(
category='gateway', category='gateway',
@@ -526,7 +529,7 @@ class XMPPTelegram(ComponentXMPP):
self.tg_connections[jid].invoke(UpdateStatusRequest(offline=False)) self.tg_connections[jid].invoke(UpdateStatusRequest(offline=False))
# Получаем и обрабатываем список диалогов # Получаем и обрабатываем список диалогов
self.tg_process_dialogs(jid) self.tg_process_dialogs(jid, sync_roster = False)
# Регистрируем обработчик обновлений в Telegram # Регистрируем обработчик обновлений в Telegram
self.tg_connections[jid].add_update_handler(self.tg_connections[jid].xmpp_update_handler) 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): def tg_process_dialogs(self, jid, sync_roster = True):
print('Processing dialogs...')
# Инициализируем словари для диалогов # Инициализируем словари для диалогов
self.tg_dialogs[jid] = dict() self.tg_dialogs[jid] = dict()
self.tg_dialogs[jid]['raw'] = list() self.tg_dialogs[jid]['raw'] = list()
@@ -594,6 +599,9 @@ class XMPPTelegram(ComponentXMPP):
vcard = self.plugin['xep_0054'].make_vcard() vcard = self.plugin['xep_0054'].make_vcard()
u_jid = get_contact_jid(usr, self.boundjid.bare) u_jid = get_contact_jid(usr, self.boundjid.bare)
# make vcard #
vcard['JABBERID'] = u_jid
if usr.deleted: if usr.deleted:
rostername = "Deleted Account" rostername = "Deleted Account"
vcard['FN'] = 'Deleted account' vcard['FN'] = 'Deleted account'
@@ -612,11 +620,18 @@ class XMPPTelegram(ComponentXMPP):
vcard['DESC'] += ' [Bot]' vcard['DESC'] += ' [Bot]'
vcard['NICKNAME'] = vcard['FN'] 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_0054'].publish_vcard(jid=u_jid, vcard=vcard)
self.plugin['xep_0172'].publish_nick(nick=vcard['FN'], ifrom=u_jid) 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 self.contact_list[jid][u_jid] = rostername
if usr.bot: if usr.bot:
@@ -645,17 +660,25 @@ class XMPPTelegram(ComponentXMPP):
if cht and cht.id: if cht and cht.id:
rostername = display_tg_name(cht) 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 = self.plugin['xep_0054'].make_vcard()
vcard['FN'] = rostername vcard['FN'] = rostername
vcard['NICKNAME'] = rostername vcard['NICKNAME'] = rostername
vcard['JABBERID'] = c_jid vcard['JABBERID'] = u_jid
self.plugin['xep_0054'].publish_vcard(jid=c_jid, vcard=vcard)
self.plugin['xep_0172'].publish_nick(nick=vcard['FN'], ifrom=c_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.contact_list[jid][u_jid] = rostername
self.send_presence(pto=jid, pfrom=c_jid, pshow = 'chat', pstatus = cht.title) self.send_presence(pto=jid, pfrom=u_jid, pshow = 'chat', pstatus = cht.title)
if len(dlgs.dialogs) == 0: # Если все диалоги получены - прерываем цикл if len(dlgs.dialogs) == 0: # Если все диалоги получены - прерываем цикл
if sync_roster and 'use_roster_exchange' in self.accounts[jid] and self.accounts[jid]['use_roster_exchange'] == 'true': 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) 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): 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 = sqlite3.connect(self.config['db_connect'], isolation_level=None, check_same_thread=False)
conn.row_factory = dict_factory 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 return conn