sed: refactor to look more like current reegee code

master
Dan Elkouby 2020-08-02 14:01:02 +00:00
parent 269a2ab1ae
commit 22c9942c2d
1 changed files with 75 additions and 57 deletions

View File

@ -1,16 +1,18 @@
"""
Become @regexbot when the bot is missing
"""
from collections import defaultdict, deque
import re
import regex
import regex as re
from collections import defaultdict, deque
from telethon import events, utils
from telethon.tl import types, functions
from uniborg import util
HEADER = "「sed」\n"
SED_PATTERN = r'^s/((?:\\/|[^/])+)/((?:\\/|[^/])*)(/.*)?'
GROUP0_RE = re.compile(r'(?<!\\)((?:\\\\)*)\\0')
HEADER = '「sed」\n'
KNOWN_RE_BOTS = re.compile(
r'(regex|moku|ou|BananaButler_|rgx|l4mR)bot',
flags=re.IGNORECASE
@ -22,13 +24,20 @@ KNOWN_RE_BOTS = re.compile(
last_msgs = defaultdict(lambda: deque(maxlen=10))
@util.sync_timeout(1)
def doit(chat_id, match, original):
fr = match.group(1)
def cleanup_pattern(match):
from_ = match.group(1)
to = match.group(2)
to = (to
.replace('\\/', '/')
.replace('\\0', '\\g<0>'))
to = to.replace('\\/', '/')
to = GROUP0_RE.sub(r'\1\\g<0>', to)
return from_, to
#@util.sync_timeout(1)
async def doit(message, match):
fr, to = cleanup_pattern(match)
try:
fl = match.group(3)
if fl is None:
@ -40,34 +49,49 @@ def doit(chat_id, match, original):
# Build Python regex flags
count = 1
flags = 0
for f in fl:
for f in fl.lower():
if f == 'i':
flags |= regex.IGNORECASE
flags |= re.IGNORECASE
elif f == 'm':
flags |= re.MULTILINE
elif f == 's':
flags |= re.DOTALL
elif f == 'g':
count = 0
elif f == 'x':
flags |= re.VERBOSE
else:
return None, f"Unknown flag: {f}"
await message.reply(f'{HEADER}Unknown flag: {f}')
return
def actually_doit(original):
try:
s = original.message
def substitute(m):
if s := m.raw_text:
if s.startswith(HEADER):
s = s[len(HEADER):]
s, i = regex.subn(fr, to, s, count=count, flags=flags)
if i > 0:
return original, s
except Exception as e:
return None, f"u dun goofed m8: {str(e)}"
return None, None
else:
return None
if original is not None:
return actually_doit(original)
# Try matching the last few messages
for original in last_msgs[chat_id]:
m, s = actually_doit(original)
if s is not None:
return m, s
return None, None
s, i = re.subn(fr, to, s, count=count, flags=flags)
if i > 0:
return s
try:
msg = None
substitution = None
if message.is_reply:
msg = await message.get_reply_message()
substitution = substitute(msg)
else:
for msg in reversed(last_msgs[message.chat_id]):
substitution = substitute(msg)
if substitution is not None:
break # msg is also set
if substitution is not None:
return await msg.reply(f'{HEADER}{substitution}', parse_mode=None)
except Exception as e:
await message.reply(f'{HEADER}fuck me: {e}')
async def group_has_sedbot(group):
@ -80,21 +104,7 @@ async def group_has_sedbot(group):
return any(KNOWN_RE_BOTS.match(x.username or '') for x in full.users)
@borg.on(events.NewMessage)
async def on_message(event):
last_msgs[event.chat_id].appendleft(event.message)
@borg.on(events.MessageEdited)
async def on_edit(event):
for m in last_msgs[event.chat_id]:
if m.id == event.id:
m.raw_text = event.raw_text
break
@borg.on(events.NewMessage(
pattern=re.compile(r"^s/((?:\\/|[^/])+)/((?:\\/|[^/])*)(/.*)?")))
async def on_regex(event):
async def sed(event):
if event.fwd_from:
return
if not event.is_private:
@ -103,17 +113,25 @@ async def on_regex(event):
if await group_has_sedbot(await event.get_input_chat()):
return
chat_id = utils.get_peer_id(await event.get_input_chat())
m, s = doit(chat_id, event.pattern_match, await event.get_reply_message())
if m is not None:
s = f"{HEADER}{s}"
out = await borg.send_message(
await event.get_input_chat(), s, reply_to=m.id, parse_mode=None
)
last_msgs[chat_id].appendleft(out)
elif s is not None:
await event.reply(s)
message = await doit(event.message, event.pattern_match)
if message:
last_msgs[event.chat_id].append(message)
# Don't save sed commands or we would be able to sed those
raise events.StopPropagation
@borg.on(events.NewMessage)
async def catch_all(event):
last_msgs[event.chat_id].append(event.message)
@borg.on(events.MessageEdited)
async def catch_edit(event):
for i, message in enumerate(last_msgs[event.chat_id]):
if message.id == event.id:
last_msgs[event.chat_id][i] = event.message
borg.on(events.NewMessage(pattern=SED_PATTERN))(sed)
borg.on(events.MessageEdited(pattern=SED_PATTERN))(sed)