From e66bda9cd80e0a28353a700dda79b82d5c8b304e Mon Sep 17 00:00:00 2001 From: annelin Date: Sun, 1 Jul 2018 21:29:34 +0000 Subject: [PATCH] =?UTF-8?q?[SVN]=20updated=20to=20version=200.3.1=20[DEP]?= =?UTF-8?q?=20[BROKE]=20new=20dependency:=20pytz=20(pip3=20install=20pytz)?= =?UTF-8?q?=20[FIX]=20fixed=20media=20downloading=20with=20telethon=200.18?= =?UTF-8?q?=20[FIX]=20now=20using=20server=20time=20zone=20in=20status=20m?= =?UTF-8?q?essages=20instead=20of=20UTC=20[UPD]=20now=20removing=20chats?= =?UTF-8?q?=20&=20supergroups=20completely=20after=20we=20leaving=20with?= =?UTF-8?q?=20!leave=20command=20[ADD]=20added=20commands:=20=20=20=20=20?= =?UTF-8?q?=20=20!remove=20=E2=80=94=20completely=20remove=20current=20use?= =?UTF-8?q?r=20from=20contact=20list=20=20=20=20=20=20=20!import=20phone?= =?UTF-8?q?=20firstname=20lastname=20=E2=80=94=20try=20to=20add=20contact?= =?UTF-8?q?=20with=20phone=20number=20(untested)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- requirements.txt | 2 +- xmpp_tg/__init__.py | 2 +- xmpp_tg/mtproto.py | 8 ++++---- xmpp_tg/utils.py | 11 +++++++++++ xmpp_tg/xmpp.py | 40 ++++++++++++++++++++++++++++++++-------- 5 files changed, 49 insertions(+), 14 deletions(-) diff --git a/requirements.txt b/requirements.txt index eeadea0..f0c23bf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ sleekxmpp==1.3.2 Telethon==0.15.5 - +pytz diff --git a/xmpp_tg/__init__.py b/xmpp_tg/__init__.py index a5f638a..88ddf29 100644 --- a/xmpp_tg/__init__.py +++ b/xmpp_tg/__init__.py @@ -1,3 +1,3 @@ from xmpp_tg.xmpp import XMPPTelegram -__version__ = '0.3.0' +__version__ = '0.3.1' diff --git a/xmpp_tg/mtproto.py b/xmpp_tg/mtproto.py index c84601f..1845ba7 100644 --- a/xmpp_tg/mtproto.py +++ b/xmpp_tg/mtproto.py @@ -27,7 +27,7 @@ import os import queue import threading import time -from xmpp_tg.utils import display_tg_name +from xmpp_tg.utils import localtime, display_tg_name from .utils import var_dump import traceback @@ -181,7 +181,7 @@ class TelegramGateClient(TelegramClient): if type(obj.status) is UserStatusOnline: self._status_updates[str(obj.user_id)] = { 'status': None, 'message': 'Online' } elif type(obj.status) is UserStatusOffline: - self._status_updates[str(obj.user_id)] = { 'status': 'xa', 'message': obj.status.was_online.strftime('Last seen at %H:%M %d/%m/%Y') } + self._status_updates[str(obj.user_id)] = { 'status': 'xa', 'message': localtime(obj.status.was_online).strftime('Last seen at %H:%M %d/%m/%Y') } elif type(obj.status) is UserStatusRecently: self._status_updates[str(obj.user_id)] = { 'status': 'away', 'message': 'Last seen recently' } else: @@ -324,7 +324,7 @@ class TelegramGateClient(TelegramClient): attr_v = self.get_document_attribute(attributes, DocumentAttributeFilename) video_file = '|File:{}'.format(attr_v.file_name) - if media.caption: + if hasattr(media, 'caption'): caption = media.caption + ' ' # Тоже свой формат @@ -335,7 +335,7 @@ class TelegramGateClient(TelegramClient): self._media_queue.put({'media': media, 'file': g_link['name']}) - if media.caption: # Если есть описание - указываем + if hasattr(media, 'caption'): # Если есть описание - указываем msg = '{} {}'.format(media.caption, msg) elif type(media) is MessageMediaContact: # Контакт (с номером) diff --git a/xmpp_tg/utils.py b/xmpp_tg/utils.py index ba640b4..d1d18db 100644 --- a/xmpp_tg/utils.py +++ b/xmpp_tg/utils.py @@ -3,9 +3,12 @@ """ import types +import time +import pytz from datetime import datetime + def display_tg_name(peer): if hasattr(peer,'title') and hasattr(peer,'broadcast') and peer.broadcast: # channel return '[C] ' + peer.title @@ -36,6 +39,14 @@ def get_contact_jid(peer, gatejid): else: return None +def localtime(utc_dt): + if time.daylight: + offsetHour = time.altzone / 3600 + else: + offsetHour = time.timezone / 3600 + local_tz = pytz.timezone('Etc/GMT%+d' % offsetHour) + local_dt = utc_dt.replace(tzinfo = pytz.utc).astimezone(local_tz) + return local_tz.normalize(local_dt) def var_dump(obj, depth=7, l=""): # fall back to repr diff --git a/xmpp_tg/xmpp.py b/xmpp_tg/xmpp.py index 8b3fa74..ecf9dd0 100644 --- a/xmpp_tg/xmpp.py +++ b/xmpp_tg/xmpp.py @@ -7,12 +7,12 @@ import sleekxmpp from sleekxmpp.componentxmpp import ComponentXMPP import xml.etree.ElementTree as ET -from telethon.tl.functions.messages import GetDialogsRequest, SendMessageRequest, ImportChatInviteRequest, GetFullChatRequest, AddChatUserRequest, DeleteChatUserRequest, CreateChatRequest +from telethon.tl.functions.messages import GetDialogsRequest, SendMessageRequest, ImportChatInviteRequest, GetFullChatRequest, AddChatUserRequest, DeleteChatUserRequest, CreateChatRequest, DeleteHistoryRequest from telethon.tl.functions.account import UpdateStatusRequest, GetAuthorizationsRequest, UpdateProfileRequest, UpdateUsernameRequest -from telethon.tl.functions.contacts import DeleteContactRequest, BlockRequest, UnblockRequest +from telethon.tl.functions.contacts import DeleteContactRequest, BlockRequest, UnblockRequest, ImportContactsRequest from telethon.tl.functions.channels import JoinChannelRequest, LeaveChannelRequest, InviteToChannelRequest, EditBannedRequest, CreateChannelRequest -from telethon.tl.types import InputPeerEmpty, InputPeerUser, InputPeerChat, InputPeerChannel +from telethon.tl.types import InputPeerEmpty, InputPeerUser, InputPeerChat, InputPeerChannel, InputPhoneContact from telethon.tl.types import User, Chat, Channel from telethon.tl.types import PeerChannel, PeerChat, PeerUser, Chat, ChatForbidden, Channel, ChannelForbidden from telethon.tl.types import UserStatusOnline, UserStatusRecently, UserStatusOffline @@ -24,7 +24,7 @@ from telethon.helpers import generate_random_long from telethon.errors import SessionPasswordNeededError from xmpp_tg.mtproto import TelegramGateClient -from xmpp_tg.utils import var_dump, display_tg_name, get_contact_jid +from xmpp_tg.utils import var_dump, display_tg_name, get_contact_jid, localtime import xmpp_tg.monkey # Патчим баги в библиотеках class XMPPTelegram(ComponentXMPP): @@ -43,7 +43,7 @@ class XMPPTelegram(ComponentXMPP): self.auto_authorize = True # self.auto_subscribe = True - + self.config = config_dict self.accounts = dict() # personal configuration per JID self.tg_connections = dict() @@ -77,7 +77,7 @@ class XMPPTelegram(ComponentXMPP): vcard = self.plugin['xep_0054'].make_vcard() vcard['FN'] = self.config['title'] - vcard['DESC'] = 'Send /help for information' + vcard['DESC'] = 'Send !help for information' self.plugin['xep_0054'].publish_vcard(jid=self.boundjid.bare, vcard=vcard) def __del__(self): @@ -268,6 +268,7 @@ class XMPPTelegram(ComponentXMPP): '!reload_dialogs - Reloads dialogs list from Telegram\n\n' '!add - Find and add Telegram contact. Any formats accepted (nickname or t.me link)\n\n' '!join - Join Telegram conference via invite link \n\n' + '!import phone firstname lastname - Add Telegram contact with phone number \n\n' '!group GroupName @InviteContact - Create a normal group\n' '!supergroup SupergroupName - Create a supergroup\n' '!channel ChannelName - Create a channel\n\n' @@ -394,6 +395,15 @@ class XMPPTelegram(ComponentXMPP): elif parsed[0] == '!about' and len(parsed) >= 2: # create new channel about = iq['body'][7:] self.tg_connections[jid].invoke(UpdateProfileRequest(about = about)) + + elif parsed[0] == '!import' and len(parsed) >= 3: # create new channel + phone = parsed[1] + firstname = parsed[2] + lastname = parsed[3] if len(parsed) > 3 else None + + contact = InputPhoneContact(client_id=generate_random_long(), phone=phone, first_name=firstname, last_name=lastname) + self.tg_connections[jid].invoke(ImportContactsRequest([contact])) + self.tg_process_dialogs(jid) else: # -------------------------------------------------- self.gate_reply_message(iq, 'Unknown command. Try !help for list all commands.') @@ -407,6 +417,7 @@ class XMPPTelegram(ComponentXMPP): '!help - Displays this text\n' '!block - Blacklists current user\n' '!unblock - Unblacklists current user\n' + '!remove - Removes history and contact from your contact list\n' ) elif parsed[0] == '!block': tg_id = int(iq['to'].node[1:]) @@ -420,6 +431,16 @@ class XMPPTelegram(ComponentXMPP): self.tg_connections[jid].invoke(UnblockRequest( InputPeerUser(tg_id, self.tg_dialogs[jid]['users'][tg_id].access_hash) ) ) self.gate_reply_message(iq, 'User %s unblacklisted!' % nickname) + elif parsed[0] == '!remove': + tg_id = int(iq['to'].node[1:]) + peer = InputPeerUser(tg_id, self.tg_dialogs[jid]['users'][tg_id].access_hash) + c_jid = get_contact_jid(self.tg_dialogs[jid]['users'][tg_id], self.boundjid.bare) + self.tg_connections[jid].invoke( DeleteContactRequest(peer) ) + self.tg_connections[jid].invoke( DeleteHistoryRequest( peer, max_id = 0, just_clear = None ) ) + self.send_presence(pto = jid, pfrom = c_jid, ptype = 'unavailable') + self.send_presence(pto = jid, pfrom = c_jid, ptype = 'unsubscribed') + self.send_presence(pto = jid, pfrom = c_jid, ptype = 'unsubscribe') + def process_chat_group_command(self, iq): @@ -436,13 +457,16 @@ class XMPPTelegram(ComponentXMPP): elif parsed[0] == '!leave': tg_id = int(iq['to'].node[1:]) if tg_id in self.tg_dialogs[jid]['supergroups']: - self.tg_connections[jid].invoke(LeaveChannelRequest( InputPeerChannel(tg_id, self.tg_dialogs[jid]['supergroups'][tg_id].access_hash) ) ) + peer = InputPeerChannel(tg_id, self.tg_dialogs[jid]['supergroups'][tg_id].access_hash) + self.tg_connections[jid].invoke( LeaveChannelRequest(peer) ) + self.tg_connections[jid].invoke( DeleteHistoryRequest( peer, max_id = 0, just_clear = None ) ) c_jid = get_contact_jid(self.tg_dialogs[jid]['supergroups'][tg_id], self.boundjid.bare) self.send_presence(pto = jid, pfrom = c_jid, ptype = 'unavailable') self.send_presence(pto = jid, pfrom = c_jid, ptype = 'unsubscribed') self.send_presence(pto = jid, pfrom = c_jid, ptype = 'unsubscribe') if tg_id in self.tg_dialogs[jid]['groups']: self.tg_connections[jid].invoke( DeleteChatUserRequest(tg_id, self.tg_connections[jid].me) ) + self.tg_connections[jid].invoke( DeleteHistoryRequest( InputPeerChat(tg_id), max_id = 0, just_clear = None ) ) c_jid = get_contact_jid(self.tg_dialogs[jid]['groups'][tg_id], self.boundjid.bare) self.send_presence(pto = jid, pfrom = c_jid, ptype = 'unavailable') self.send_presence(pto = jid, pfrom = c_jid, ptype = 'unsubscribed') @@ -603,7 +627,7 @@ class XMPPTelegram(ComponentXMPP): elif type(usr.status) is UserStatusRecently: self.send_presence(pto=jid, pfrom=u_jid, pshow='away', pstatus='Last seen recently') elif type(usr.status) is UserStatusOffline: - self.send_presence(pto=jid, pfrom=u_jid, pshow='xa', pstatus=usr.status.was_online.strftime('Last seen at %H:%M %d/%m/%Y') ) + self.send_presence(pto=jid, pfrom=u_jid, pshow='xa', pstatus=localtime(usr.status.was_online).strftime('Last seen at %H:%M %d/%m/%Y') ) else: self.send_presence(pto=jid, pfrom=u_jid, pshow='dnd', pstatus='Last seen a long time ago')