diff --git a/xmpp_tg/xmpp.py b/xmpp_tg/xmpp.py index 53966fb..2669745 100644 --- a/xmpp_tg/xmpp.py +++ b/xmpp_tg/xmpp.py @@ -8,7 +8,11 @@ import xml.etree.ElementTree as ET from telethon.tl.functions.messages import GetDialogsRequest, SendMessageRequest from telethon.tl.functions.account import UpdateStatusRequest, GetAuthorizationsRequest +from telethon.tl.functions.contacts import DeleteContactRequest +from telethon.tl.functions.channels import JoinChannelRequest, LeaveChannelRequest + from telethon.tl.types import InputPeerEmpty, InputPeerUser, InputPeerChat, InputPeerChannel +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 from telethon.tl.types import Updates, UpdateShortSentMessage, UpdateMessageID @@ -52,9 +56,9 @@ class XMPPTelegram(ComponentXMPP): self.register_plugin('xep_0172') # NickNames self.add_event_handler('message', self.message) - self.add_event_handler('presence', self.event_presence) self.add_event_handler('presence_unsubscribe', self.event_presence_unsub) self.add_event_handler('presence_unsubscribed', self.event_presence_unsub) + self.add_event_handler('presence', self.event_presence) 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) @@ -169,20 +173,21 @@ class XMPPTelegram(ComponentXMPP): :return: """ ptype = presence['type'] + - if ptype == 'subscribe': - print('Send SUBSCRIBED') + # handle "online" to transport: + if ptype == 'available' and presence['to'].bare == self.boundjid.bare: + self.handle_online(presence) + elif ptype == 'subscribe': self.send_presence(pto=presence['from'].bare, pfrom=presence['to'].bare, ptype='subscribed') elif ptype == 'subscribed': self.send_presence(pto=presence['from'].bare, pfrom=presence['to'].bare, ptype='subscribee') - pass elif ptype == 'unsubscribe': pass elif ptype == 'unsubscribed': pass elif ptype == 'probe': self.send_presence(pto=presence['from'], pfrom=presence['to'], ptype='available') - pass elif ptype == 'unavailable': pass else: @@ -196,6 +201,11 @@ class XMPPTelegram(ComponentXMPP): :return: """ jid = event['from'].bare + to = event['to'].bare + + # maybe if i'll ignore it — it will go ahead + if to != self.boundjid.bare: + return if jid not in self.tg_connections: result = self.db_connection.execute("SELECT * FROM accounts WHERE jid = ?", (jid,)).fetchone() @@ -206,8 +216,9 @@ class XMPPTelegram(ComponentXMPP): if not (self.tg_connections[jid].is_connected()): self.tg_connections[jid].connect() self.tg_connections[jid].invoke(UpdateStatusRequest(offline=False)) - self.send_presence(pto=jid, pfrom=self.boundjid.bare, ptype='online', pstatus='connected') - self.tg_process_dialogs(jid) + + self.send_presence(pto=jid, pfrom=self.boundjid.bare, ptype='online', pstatus='connected') + self.tg_process_dialogs(jid) def handle_offline(self, event): @@ -217,6 +228,10 @@ class XMPPTelegram(ComponentXMPP): :return: """ jid = event['from'].bare + + # keep telegram online ? + if self.config['xmpp_keep_online']: + return if jid in self.tg_connections: self.tg_connections[jid].invoke(UpdateStatusRequest(offline=True)) @@ -239,23 +254,25 @@ class XMPPTelegram(ComponentXMPP): :param iq: :return: """ - parced = iq['body'].split(' ') + parsed = iq['body'].split(' ') jid = iq['from'].bare - if parced[0] == '!help': + if parsed[0] == '!help': self.gate_reply_message(iq, 'Available command:\n\n' '!help - Displays this text\n' '!login +123456789 - Initiates Telegram session\n' '!code 12345 - Entering one-time code during auth\n' - '!password abc123 - Entering password during two-factor auth\n' + #'!password abc123 - Entering password during two-factor auth\n' '!list_sessions - List all created sessions at Telegram servers\n' - '!delete_session 123 - Delete session\n' + #'!delete_session 123 - Delete session\n' '!logout - Deletes current Telegram session at gate\n' '!reload_dialogs - Reloads dialogs list from Telegram\n\n' - '!create_group - Initiates group creation\n' - '!create_channel - Initiates channel creation\n\n' - '!change_name first last - Changes your name in Telegram\n' - '!change_username username - Changes your @username in Telegram\n' + '!add - Find and add Telegram contact. Any formats accepted (nickname or t.me link)\n\n' + '!del - Removes Telegram contact or leaves a chat. Any formats accepted (nickname or t.me link) \n\n' + #'!create_group - Initiates group creation\n' + #'!create_channel - Initiates channel creation\n\n' + #'!change_name first last - Changes your name in Telegram\n' + #'!change_username username - Changes your @username in Telegram\n' # '!blocked_users_list\n' # '!blocked_users_add\n' # '!blocked_users_remove\n' @@ -274,31 +291,31 @@ class XMPPTelegram(ComponentXMPP): # '!account_selfdestruct_setting_status\n' # '!account_selfdestruct_setting_set\n' ) - elif parced[0] == '!login': # -------------------------------------------------- + elif parsed[0] == '!login': # -------------------------------------------------- self.gate_reply_message(iq, 'Please wait...') - self.spawn_tg_client(jid, parced[1]) + self.spawn_tg_client(jid, parsed[1]) if self.tg_connections[jid].is_user_authorized(): self.send_presence(pto=jid, pfrom=self.boundjid.bare, ptype='online', pstatus='connected') self.gate_reply_message(iq, 'You are already authenticated in Telegram.') else: - self.tg_connections[jid].send_code_request(parced[1]) + self.tg_connections[jid].send_code_request(parsed[1]) self.gate_reply_message(iq, 'Gate is connected. Telegram should send SMS message to you.') self.gate_reply_message(iq, 'Please enter one-time code via !code 12345.') - elif parced[0] in ['!code', '!password']: # -------------------------------------------------- + elif parsed[0] in ['!code', '!password']: # -------------------------------------------------- if not self.tg_connections[jid].is_user_authorized(): - if parced[0] == '!code': + if parsed[0] == '!code': try: self.gate_reply_message(iq, 'Trying authenticate...') - self.tg_connections[jid].sign_in(self.tg_phones[jid], parced[1]) + self.tg_connections[jid].sign_in(self.tg_phones[jid], parsed[1]) except SessionPasswordNeededError: self.gate_reply_message(iq, 'Two-factor authentication detected.') self.gate_reply_message(iq, 'Please enter your password via !password abc123.') return - if parced[0] == '!password': + if parsed[0] == '!password': self.gate_reply_message(iq, 'Checking password...') - self.tg_connections[jid].sign_in(password=parced[1]) + self.tg_connections[jid].sign_in(password=parsed[1]) if self.tg_connections[jid].is_user_authorized(): self.send_presence(pto=jid, pfrom=self.boundjid.bare, ptype='online', pstatus='connected') @@ -309,82 +326,117 @@ class XMPPTelegram(ComponentXMPP): self.gate_reply_message(iq, 'Authentication failed.') else: self.gate_reply_message(iq, 'You are already authenticated. Please use !logout before new login.') - elif parced[0] == '!list_sessions': # -------------------------------------------------- + elif parsed[0] == '!list_sessions': # -------------------------------------------------- if not self.tg_connections[jid].is_user_authorized(): self.gate_reply_message(iq, 'Error.') return sessions = self.tg_connections[jid].invoke(GetAuthorizationsRequest()) print(sessions.__dict__) - elif parced[0] == '!reload_dialogs': + elif parsed[0] == '!reload_dialogs': if not self.tg_connections[jid].is_user_authorized(): self.gate_reply_message(iq, 'Error.') return self.tg_process_dialogs(jid) self.gate_reply_message(iq, 'Dialogs reloaded.') - elif parced[0] == '!logout': # -------------------------------------------------- + elif parsed[0] == '!logout': # -------------------------------------------------- self.tg_connections[jid].log_out() self.db_connection.execute("DELETE FROM accounts WHERE jid = ?", (jid,)) self.gate_reply_message(iq, 'Your Telegram session was deleted') + elif parsed[0] == '!add': # add user + result = self.tg_connections[jid].get_entity(parsed[1]) + if type(result) == User: + tg_peer = InputPeerUser( result.id, result.access_hash ) + result = self.tg_connections[jid].invoke( SendMessageRequest(tg_peer, 'Hello! I just want to add you in my contact list.', generate_random_long() ) ) + elif type(result) == Channel: + tg_peer = InputPeerChannel( result.id, result.access_hash ) + self.tg_connections[jid].invoke(JoinChannelRequest( InputPeerChannel(result.id, result.access_hash) ) ) + else: + self.gate_reply_message(iq, 'Sorry, nothing found.') + return + + self.tg_process_dialogs(jid) + + elif parsed[0] == '!del': # add user + result = self.tg_connections[jid].get_entity(parsed[1]) + if type(result) == User: + tg_peer = InputPeerUser( result.id, result.access_hash ) + req = self.tg_connections[jid].invoke( DeleteContactRequest(tg_peer) ) + print(req) + prefix = 'u' + elif type(result) == Channel: + tg_peer = InputPeerChannel( result.id, result.access_hash ) + self.tg_connections[jid].invoke(LeaveChannelRequest( InputPeerChannel(result.id, result.access_hash) ) ) + prefix = 'c' if result.broadcast else 's' + else: + self.gate_reply_message(iq, 'Sorry, nothing found.') + return + + presence_from = prefix + str(result.id) + '@' + self.boundjid.bare + self.send_presence(pto=jid, pfrom=presence_from, ptype='unavailable') + self.send_presence(pto=jid, pfrom=presence_from, ptype='unsubscribed') + self.send_presence(pto=jid, pfrom=presence_from, ptype='unsubscribe') + + else: # -------------------------------------------------- self.gate_reply_message(iq, 'Unknown command. Try !help for list all commands.') def process_chat_user_command(self, iq): - parced = [] + parsed = [] - if parced[0] == '!search': + if parsed[0] == '!search': pass - elif parced[0] == '!get_history': + elif parsed[0] == '!get_history': pass - elif parced[0] == '!forward_messages': + elif parsed[0] == '!forward_messages': pass - elif parced[0] == '!delete_messages': + elif parsed[0] == '!delete_messages': pass - elif parced[0] == '!block_status': + elif parsed[0] == '!block_status': pass - elif parced[0] == '!block_set': + elif parsed[0] == '!block_set': pass - elif parced[0] == '!block_unser': + elif parsed[0] == '!block_unser': pass - elif parced[0] == '!clear_history': + elif parsed[0] == '!clear_history': pass - elif parced[0] == '!delete_conversation': + elif parsed[0] == '!delete_conversation': pass - elif parced[0] == '!help': + elif parsed[0] == '!help': pass def process_chat_group_command(self, iq): - parced = [] + parsed = [] - if parced[0] == '!search': + if parsed[0] == '!search': pass - elif parced[0] == '!get_history': + elif parsed[0] == '!get_history': pass - elif parced[0] == '!forward_messages': + elif parsed[0] == '!forward_messages': pass - elif parced[0] == '!delete_messages': + elif parsed[0] == '!delete_messages': pass - elif parced[0] == '!pin_message': + elif parsed[0] == '!pin_message': pass - elif parced[0] == '!unpin_message': + elif parsed[0] == '!unpin_message': pass - elif parced[0] == '!leave_group': + elif parsed[0] == '!leave_group': pass - elif parced[0] == '!add_members': + elif parsed[0] == '!add_members': pass - elif parced[0] == '!bans_list': + elif parsed[0] == '!bans_list': pass - elif parced[0] == '!ban_user': + elif parsed[0] == '!ban_user': pass - elif parced[0] == '!unban_user': + elif parsed[0] == '!unban_user': pass - elif parced[0] == '!restrict_user': + elif parsed[0] == '!restrict_user': pass - elif parced[0] == '!unrestrict_user': + elif parsed[0] == '!unrestrict_user': pass - elif parced[0] == '!get_recent_actions': + elif parsed[0] == '!get_recent_actions': pass - elif parced[0] == '!get_recent_actions': + elif parsed[0] == '!get_recent_actions': pass def spawn_tg_client(self, jid, phone):