[SVN] Release 0.3.5

[ADD] Add possibility to edit and delete last messages.
      Syntax is sed-like:    "!s/find/replace/"
      Examples:

      `!s/mistake/corrected` to correct misspelled word
      `!s//sorry I meant something completely different` to correct the whole message
      `!s//` to delete message and revoke it from peer

       Any regular expressions that fits python re. library also supported
This commit is contained in:
annelin
2018-07-02 16:26:08 +00:00
parent 1d61392db2
commit b17870cbdd
2 changed files with 60 additions and 5 deletions

View File

@@ -1,3 +1,3 @@
from xmpp_tg.xmpp import XMPPTelegram from xmpp_tg.xmpp import XMPPTelegram
__version__ = '0.3.4' __version__ = '0.3.5'

View File

@@ -10,10 +10,10 @@ import sleekxmpp
from sleekxmpp.componentxmpp import ComponentXMPP from sleekxmpp.componentxmpp import ComponentXMPP
import xml.etree.ElementTree as ET 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.account import UpdateStatusRequest, GetAuthorizationsRequest, UpdateProfileRequest, UpdateUsernameRequest
from telethon.tl.functions.contacts import DeleteContactRequest, BlockRequest, UnblockRequest, ImportContactsRequest 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 InputPeerEmpty, InputPeerUser, InputPeerChat, InputPeerChannel, InputPhoneContact
from telethon.tl.types import User, Chat, Channel from telethon.tl.types import User, Chat, Channel
@@ -172,6 +172,9 @@ class XMPPTelegram(ComponentXMPP):
elif type(result) is UpdateShortSentMessage: # ЛС / Группа elif type(result) is UpdateShortSentMessage: # ЛС / Группа
msg_id = result.id 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: # if msg_id:
# # Отправляем ответ с ID отправленного сообщения # # Отправляем ответ с ID отправленного сообщения
# self.send_message(mto=iq['from'], mfrom=iq['to'], mtype='chat', # self.send_message(mto=iq['from'], mfrom=iq['to'], mtype='chat',
@@ -431,6 +434,7 @@ class XMPPTelegram(ComponentXMPP):
if parsed[0] == '!help': if parsed[0] == '!help':
self.gate_reply_message(iq, '=== Available dialog commands ===:\n\n' self.gate_reply_message(iq, '=== Available dialog commands ===:\n\n'
'!help - Displays this text\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' '!block - Blacklists current user\n'
'!unblock - Unblacklists current user\n' '!unblock - Unblacklists current user\n'
'!remove - Removes history and contact from your contact list\n' '!remove - Removes history and contact from your contact list\n'
@@ -457,6 +461,20 @@ class XMPPTelegram(ComponentXMPP):
self.send_presence(pto = jid, pfrom = c_jid, ptype = 'unsubscribed') self.send_presence(pto = jid, pfrom = c_jid, ptype = 'unsubscribed')
self.send_presence(pto = jid, pfrom = c_jid, ptype = 'unsubscribe') 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): def process_chat_group_command(self, iq):
@@ -466,6 +484,7 @@ class XMPPTelegram(ComponentXMPP):
if parsed[0] == '!help': if parsed[0] == '!help':
self.gate_reply_message(iq, '=== Available chat commands ===:\n\n' self.gate_reply_message(iq, '=== Available chat commands ===:\n\n'
'!help - Displays this text\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' '!leave - Leaves current group or supergroup\n'
'!invite - Invites user to group\n' '!invite - Invites user to group\n'
'!kick - Kicks user to group\n' '!kick - Kicks user to group\n'
@@ -511,6 +530,25 @@ class XMPPTelegram(ComponentXMPP):
if type(invited_user) == User: if type(invited_user) == User:
self.tg_connections[jid].invoke( DeleteChatUserRequest(tg_id, kicked_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): def spawn_tg_client(self, jid, phone):
@@ -583,6 +621,7 @@ class XMPPTelegram(ComponentXMPP):
self.tg_dialogs[jid]['users'] = dict() self.tg_dialogs[jid]['users'] = dict()
self.tg_dialogs[jid]['groups'] = dict() self.tg_dialogs[jid]['groups'] = dict()
self.tg_dialogs[jid]['supergroups'] = dict() self.tg_dialogs[jid]['supergroups'] = dict()
self.tg_dialogs[jid]['messages'] = dict()
# Оффсеты для получения диалогов # Оффсеты для получения диалогов
last_peer = InputPeerEmpty() last_peer = InputPeerEmpty()
@@ -743,6 +782,22 @@ class XMPPTelegram(ComponentXMPP):
else: else:
return (None, None) 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): def publish_photo(self, jid, fromjid, photo):
presence = sleekxmpp.Presence() presence = sleekxmpp.Presence()
presence['to'] = jid presence['to'] = jid