diff --git a/xmpp_tg/__init__.py b/xmpp_tg/__init__.py index 1874bf8..fbcf852 100644 --- a/xmpp_tg/__init__.py +++ b/xmpp_tg/__init__.py @@ -1,3 +1,3 @@ from xmpp_tg.xmpp import XMPPTelegram -__version__ = '0.3.4' +__version__ = '0.3.5' diff --git a/xmpp_tg/xmpp.py b/xmpp_tg/xmpp.py index 8eed3fe..73213cb 100644 --- a/xmpp_tg/xmpp.py +++ b/xmpp_tg/xmpp.py @@ -10,10 +10,10 @@ import sleekxmpp from sleekxmpp.componentxmpp import ComponentXMPP import xml.etree.ElementTree as ET -from telethon.tl.functions.messages import GetDialogsRequest, SendMessageRequest, SendMediaRequest, ImportChatInviteRequest, GetFullChatRequest, AddChatUserRequest, DeleteChatUserRequest, CreateChatRequest, DeleteHistoryRequest +from telethon.tl.functions.messages import GetDialogsRequest, SendMessageRequest, SendMediaRequest, EditMessageRequest, DeleteMessagesRequest, 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, ImportContactsRequest -from telethon.tl.functions.channels import JoinChannelRequest, LeaveChannelRequest, InviteToChannelRequest, EditBannedRequest, CreateChannelRequest +from telethon.tl.functions.channels import JoinChannelRequest, LeaveChannelRequest, InviteToChannelRequest, EditBannedRequest, CreateChannelRequest, DeleteMessagesRequest as DeleteMessagesChannel from telethon.tl.types import InputPeerEmpty, InputPeerUser, InputPeerChat, InputPeerChannel, InputPhoneContact from telethon.tl.types import User, Chat, Channel @@ -171,7 +171,10 @@ class XMPPTelegram(ComponentXMPP): msg_id = upd.id elif type(result) is UpdateShortSentMessage: # ЛС / Группа msg_id = result.id - + + # last message id for current peer + self.tg_dialogs[jid]['messages'][tg_id] = {'id': msg_id, 'body': msg} + # if msg_id: # # Отправляем ответ с ID отправленного сообщения # self.send_message(mto=iq['from'], mfrom=iq['to'], mtype='chat', @@ -431,6 +434,7 @@ class XMPPTelegram(ComponentXMPP): if parsed[0] == '!help': self.gate_reply_message(iq, '=== Available dialog commands ===:\n\n' '!help - Displays this text\n' + '!s/find/replace - Edit last message. Use empty `find` to edit whole message and empty `replace` to delete it.\n' '!block - Blacklists current user\n' '!unblock - Unblacklists current user\n' '!remove - Removes history and contact from your contact list\n' @@ -457,7 +461,21 @@ class XMPPTelegram(ComponentXMPP): self.send_presence(pto = jid, pfrom = c_jid, ptype = 'unsubscribed') self.send_presence(pto = jid, pfrom = c_jid, ptype = 'unsubscribe') - + elif iq['body'].startswith('!s/'): + tg_id = int(iq['to'].node[1:]) + peer = InputPeerUser(tg_id, self.tg_dialogs[jid]['users'][tg_id].access_hash) + + msg_id, edited = self.edit_message(jid, tg_id, iq['body']) + if not edited: return + + # and send it + if edited != '' and edited != ' ': + self.tg_dialogs[jid]['messages'][tg_id]["body"] = edited + self.tg_connections[jid].invoke( EditMessageRequest(peer, msg_id, message = edited) ) + else: + del(self.tg_dialogs[jid]['messages'][tg_id]) + self.tg_connections[jid].invoke( DeleteMessagesRequest([msg_id], revoke = True) ) + def process_chat_group_command(self, iq): parsed = iq['body'].split(' ') @@ -466,6 +484,7 @@ class XMPPTelegram(ComponentXMPP): if parsed[0] == '!help': self.gate_reply_message(iq, '=== Available chat commands ===:\n\n' '!help - Displays this text\n' + '!s/find/replace - Edit last message. Use empty `find` to edit whole message and empty `replace` to delete it.\n' '!leave - Leaves current group or supergroup\n' '!invite - Invites user to group\n' '!kick - Kicks user to group\n' @@ -511,6 +530,25 @@ class XMPPTelegram(ComponentXMPP): if type(invited_user) == User: self.tg_connections[jid].invoke( DeleteChatUserRequest(tg_id, kicked_user) ) + elif iq['body'].startswith('!s/'): + tg_id = int(iq['to'].node[1:]) + peer = InputPeerChannel(tg_id, self.tg_dialogs[jid]['supergroups'][tg_id].access_hash) if tg_id in self.tg_dialogs[jid]['supergroups'] else InputPeerChat(tg_id) + + msg_id, edited = self.edit_message(jid, tg_id, iq['body']) + if not edited: return + + # and send it + if edited != '' and edited != ' ': + self.tg_dialogs[jid]['messages'][tg_id]["body"] = edited + self.tg_connections[jid].invoke( EditMessageRequest(peer, msg_id, message = edited) ) + else: + del(self.tg_dialogs[jid]['messages'][tg_id]) + if isinstance(peer, InputPeerChannel): + self.tg_connections[jid].invoke( DeleteMessagesChannel(peer, [msg_id]) ) + else: + self.tg_connections[jid].invoke( DeleteMessagesRequest([msg_id], revoke = True) ) + + def spawn_tg_client(self, jid, phone): @@ -583,6 +621,7 @@ class XMPPTelegram(ComponentXMPP): self.tg_dialogs[jid]['users'] = dict() self.tg_dialogs[jid]['groups'] = dict() self.tg_dialogs[jid]['supergroups'] = dict() + self.tg_dialogs[jid]['messages'] = dict() # Оффсеты для получения диалогов last_peer = InputPeerEmpty() @@ -743,6 +782,22 @@ class XMPPTelegram(ComponentXMPP): else: return (None, None) + def edit_message(self, jid, tg_id, message): + + # get last message to this peer + if not tg_id in self.tg_dialogs[jid]['messages']: + return (None, None) + + msg_id = self.tg_dialogs[jid]['messages'][tg_id]["id"] + msg_body = self.tg_dialogs[jid]['messages'][tg_id]["body"] + + # edit this message + pattern = message.split('/') + replace = ' ' if pattern[2] == '' else '/'.join(pattern[2:]) # no empty regexp — replace with whitespace + edited = re.sub(r'%s' % pattern[1], replace, msg_body, re.I) if pattern[1] != '' else replace # if no pattern specified — edit whole message + + return (msg_id, edited) + def publish_photo(self, jid, fromjid, photo): presence = sleekxmpp.Presence() presence['to'] = jid