Commit 7ec449b1 authored by zeroone2numeral2's avatar zeroone2numeral2
Browse files

first commit

parents
*.pyc
*.log
\ No newline at end of file
MIT License
Copyright (c) 2018 zeroone2numeral2
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
### sed/regex Telegram bot
Inspired to [@regexbot](https://t.me/regexbot)
To run the bot, export a `TG_TOKEN` envinronment variable or set it manually in `bot/__init__.py`. Then start the process with `python3 bot.py`
***
Telegram bot [here](https://t.me/sedbbot)
### Feature requests/issues
This bot was a one-shot try and will not be developed any further. But if you find a bug/have a question, feel free to open an issue
\ No newline at end of file
import logging
import importlib
from telegram.ext.dispatcher import run_async
from bot import updater
from bot import dispatcher
logging.basicConfig(format='[%(asctime)s][%(name)s] %(message)s', level=logging.INFO)
logger = logging.getLogger(__name__)
@run_async
def error_callback(bot, update, error):
pass # p-t-b's logger already logs this to the console
def main():
for modname in ["sed", "help", "yesno"]:
module = getattr(importlib.import_module('bot.modules.{}'.format(modname)), "module")
logger.info("module imported: %s (handlers: %d)", module.name, len(module.handlers))
for handler in module.handlers:
dispatcher.add_handler(handler)
dispatcher.add_error_handler(error_callback)
updater.start_polling(clean=True)
updater.idle()
if __name__ == '__main__':
main()
\ No newline at end of file
import os
from telegram.ext import Updater
updater = Updater(token=os.environ.get('TG_TOKEN') or "")
dispatcher = updater.dispatcher
from telegram.ext import Filters
from telegram.ext import BaseFilter
class _Reply_text(BaseFilter):
name = 'Filters.reply_text'
def filter(self, message):
if message.reply_to_message:
return bool(message.reply_to_message.text or message.reply_to_message.caption)
return False
Filters.reply_text = _Reply_text()
import re
from telegram import Update
from telegram.ext import RegexHandler
class FilteredRegexHandler(RegexHandler):
def __init__(self, *args, **kwargs):
self.filters = kwargs.pop("filters")
RegexHandler.__init__(self, *args, **kwargs)
def check_update(self, update):
if not isinstance(update, Update) and not update.effective_message:
return False
if self.filters:
message = update.effective_message
if isinstance(self.filters, list):
res = any(func(message) for func in self.filters)
else:
res = self.filters(message)
if not res:
return False
if any([self.message_updates and update.message,
self.edited_updates and (update.edited_message or update.edited_channel_post),
self.channel_post_updates and update.channel_post]) and \
update.effective_message.text:
match = re.match(self.pattern, update.effective_message.text)
return bool(match)
return False
\ No newline at end of file
import logging
from telegram.ext import CommandHandler
from telegram.ext import CallbackQueryHandler
from telegram.ext.dispatcher import run_async
from telegram import InlineKeyboardMarkup
from telegram import InlineKeyboardButton
from telegram import ParseMode
from bot.customfilters import Filters
from bot import strings as s
logger = logging.getLogger(__name__)
extended_help_markup = InlineKeyboardMarkup([
[InlineKeyboardButton("extended help", callback_data="extend")]
])
short_help_markup = InlineKeyboardMarkup([
[InlineKeyboardButton("reduce", callback_data="reduce")]
])
@run_async
def help_message(bot, update):
logger.info("/help or /start command")
update.message.reply_markdown(s.help_short,
reply_markup=extended_help_markup)
@run_async
def on_extended_help_button(bot, update):
logger.info("extend help")
update.callback_query.message.edit_text(s.help_extended,
reply_markup=short_help_markup, parse_mode=ParseMode.MARKDOWN)
@run_async
def on_short_help_button(bot, update):
logger.info("reduce help")
update.callback_query.message.edit_text(s.help_short,
reply_markup=extended_help_markup, parse_mode=ParseMode.MARKDOWN)
class module:
name = "help"
handlers = (
CommandHandler(["start", "help"], help_message, filters=Filters.private),
CallbackQueryHandler(on_extended_help_button, pattern='^extend$'),
CallbackQueryHandler(on_short_help_button, pattern='^reduce$'),
)
\ No newline at end of file
import logging
from html import escape as html_escape
from telegram.ext.dispatcher import run_async
from telegram.error import BadRequest
from telegram.constants import MAX_MESSAGE_LENGTH
from bot.customfilters import Filters
from bot.regexer import Regex
from bot.filteredregexhandler import FilteredRegexHandler
from bot import strings as s
logger = logging.getLogger(__name__)
COMMAND_REGEX = r"^([s*]?/?)/((?:\\/|[^/])+)/((?:\\/|[^/])*)(?:/(.*))?"
MODES = {
"": "<b>Did you mean:</b>\n{}",
"s": "{}",
"*": "*{}"
}
def get_response(mode, string):
mode = mode.replace("/", "")
return MODES[mode].format(html_escape(string))
@run_async
def on_sed(bot, update, groups):
text = update.message.reply_to_message.text or update.message.reply_to_message.caption
mode = groups[0]
pattern = groups[1]
replacement = groups[2].replace('\\/', '/') # ??? https://github.com/SijmenSchoon/regexbot/blob/master/regexbot.py#L25
flags = groups[3] if len(groups) > 3 else None
logger.info("\nmode: %s\ntext: %s\npattern: %s\nreplacement: %s\nflags: %s",
mode,
text,
pattern,
replacement,
flags
)
regex = Regex(text, pattern, replacement, flags)
try:
new_string, n_subs = regex.subn()
logger.info("re.subn result:\nnew_string: %s\nn_subs: %d", new_string, n_subs)
except Exception as e:
logger.info("re.subn exception: %s", str(e), exc_info=True)
#update.message.reply_text(s.oopsie_woopsie) # might be the user who fucked up the regex
return # don't proceed further
if n_subs > 0:
if len(new_string) > MAX_MESSAGE_LENGTH:
logger.info("result too long: substringing...")
new_string = new_string[:MAX_MESSAGE_LENGTH-16] # -16: "*Did you mean:*\n"
update.message.reply_to_message.reply_html(get_response(mode, new_string))
if mode.endswith("/"): # try to delete the command
try:
update.message.delete()
except BadRequest as e: # the bot doesn't have the permission to delete the message
logger.info("exception while trying to delete a message: %s", e)
class module:
name = "sed"
handlers = (
FilteredRegexHandler(COMMAND_REGEX, on_sed, pass_groups=True,
filters=Filters.reply_text),
)
\ No newline at end of file
import logging
from random import choice
from telegram.ext.dispatcher import run_async
from telegram.ext import RegexHandler
from bot.customfilters import Filters
from bot import strings as s
logger = logging.getLogger(__name__)
YESNO_REGEX = r".*(?:y(?:es)?\/no?|no?\/y(?:es)?)$"
@run_async
def on_yesno(bot, update):
logger.info("yes/no")
reply = choice(s.yesno_list)
update.message.reply_text(reply)
class module:
name = "yesno"
handlers = (
RegexHandler(YESNO_REGEX, on_yesno),
)
\ No newline at end of file
import re
import logging
logger = logging.getLogger(__name__)
REGEX_FLAGS = "ilmsax"
FLAGS_DICT = {
"i": re.I,
"l": re.L,
"m": re.M,
"s": re.S,
"a": re.A,
"x": re.X
}
class Regex():
def __init__(self, string, pattern, repl, flags=None):
self.string = string
self.pattern = pattern
self.repl = repl
self.count = 1 # by default, make just one replacement, unless the "g" flag is passed
self.flags = 0 # default value for the "flags" argument of re.sub/re.subn
if flags:
for flag in flags:
logger.info("elaborating flag: %s", flag)
flag_lower = flag.lower()
if flag_lower == "g": # re.G: don't return after the first match
logger.info("<g> flag found")
self.count = 0 # passing count=0 to resub/re.subn will make it not return after the first match
if flag_lower in REGEX_FLAGS:
self.flags |= FLAGS_DICT[flag_lower] # biwise-concatenete the re.FLAG object
def subn(self, escape_html=False):
return re.subn(
self.pattern,
self.repl,
self.string,
flags=self.flags,
count=self.count
)
def sub(self, escape_html=False):
return re.sub(
self.pattern,
self.repl,
self.string,
flags=self.flags,
count=self.count
)
dym = "<b>Did you mean:</b>"
help_short = """\
Simple sed-like bot, using [Python's regular expressions](https://docs.python.org/3/howto/regex.html)
Usage: `s/pattern/replacement/flags` (flags are optional)
[source code](https://github.com/zeroone2numeral2/regex-bot)\
"""
help_extended = """\
*Avaliable commands flavours*:
`s/pattern/repl/flags`: returns simple replacement
`/pattern/repl/flags`: "_Did you mean:_" reply
`*/pattern/repl/flags`: returns replacement with a leading \*
Works just in reply of another message/media with caption. In groups, the bot will quote the replied-to message.
*Command deletion*:
replace the first / with a double / to force the bot to delete your message automatically \
(obviously, the bot must be granted the permission to delete messages)
Examples:
`s//pattern/replacement`
`//pattern/replacement`
`*//pattern/replacement`
*About flags*:
the third argument (flags) is optional.
You can use one or more flags - just pass the corresponding letter(s) \
([flags docs](https://docs.python.org/3/howto/regex.html#compilation-flags)).
You can also pass the `g` flag for the match to be global (do not stop after the first match).
Unknown flags will be ignored
*yes/no*
Write `y/n` or `yes/no` at the end of a message to get a random positive/negative answer from the bot\
"""
oopsie_woopsie = """OOPSIE WOOPSIE!! \
Uwu We made a fucky wucky!! \
A wittle fucko boingo! \
The code monkeys at our headquarters are working VEWY HAWD to fix this!\
"""
yesno_list = (
'Yes.',
'No.',
'Absolutely.',
'In your dreams.'
)
\ No newline at end of file
python-telegram-bot
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment