all repos — python-meme-bot @ 881781f58f4949319ef6afcbd6421c43e8a6ae24

Telegram Bot that uses PIL to compute light image processing.

python_meme_bot/bot.py (view raw)

  1from functools import partial
  2import os, logging
  3
  4
  5from dotenv import load_dotenv
  6from telegram import Update
  7from telegram.ext import ApplicationBuilder, CallbackQueryHandler, CommandHandler, MessageHandler, \
  8    PicklePersistence, filters, PersistenceInput, ContextTypes
  9from telegram.error import TelegramError
 10
 11from .utils import get_all, get_image, get_message_content
 12from .effects.functions import img_to_bio
 13from .slot import spin, autospin, bet, cash
 14from .effects import effectsDict
 15from .localization import get_localized_string as l, format_lang, get_lang, langs, lang_markup
 16
 17async def effect_handler(update: Update, context: ContextTypes.DEFAULT_TYPE, effect_name: str):
 18    try:
 19        effect_check, effect_fn = effectsDict[effect_name]
 20    except KeyError:
 21        raise TelegramError("effect not supported: " + effect_name)
 22    
 23    content, image, markup = await get_all(update, effect_check, context)
 24
 25    if image is None:
 26        await update.message.reply_text(l("no_caption", context))
 27        return
 28
 29    image = effect_fn(content, image)
 30
 31    if image is None:
 32        await update.message.reply_text(l("failed_effect", context))
 33        return
 34
 35    await update.message.reply_photo(photo=image, reply_markup=markup)
 36
 37async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
 38    await update.message.reply_text(l("welcome", context))
 39
 40
 41async def lewd(update: Update, context: ContextTypes.DEFAULT_TYPE):
 42    try:
 43        output = False if context.chat_data["lewd"] else True
 44    except KeyError:
 45        output = True
 46
 47    context.chat_data['lewd'] = output
 48    message = l("lewd_toggle", context).format(l("enabled", context) if output else l("disabled", context))
 49    await update.message.reply_text(message)
 50
 51
 52async def pic(update: Update, context: ContextTypes.DEFAULT_TYPE):
 53    image, markup = get_image(context)
 54    await update.message.reply_photo(photo=img_to_bio(image), parse_mode="markdown", reply_markup=markup)
 55
 56
 57async def caps(update: Update, context: ContextTypes.DEFAULT_TYPE):
 58    _, reply, _ = await get_message_content(update.message.reply_to_message, ' '.join(context.args))
 59    await update.message.reply_text(reply.upper())
 60
 61
 62async def _set_lang(update: Update, context: ContextTypes.DEFAULT_TYPE, lang: str):
 63    context.chat_data["lang"] = lang
 64    response = l("language_set", context).format(format_lang(lang))
 65    await update.message.reply_text(response)
 66
 67
 68async def lang(update: Update, context: ContextTypes.DEFAULT_TYPE):
 69    try:
 70        selected = str(context.args[0])
 71    except IndexError:
 72        selected = None
 73
 74    if selected is None:
 75        lang = format_lang(get_lang(context))
 76        choices = ", ".join(langs) + "."
 77        text = l("current_language", context).format(lang, choices)
 78        return await update.message.reply_text(text,reply_markup=lang_markup)
 79
 80    if selected not in langs:
 81        return await update.message.reply_text(text=l("invalid_language", context))
 82
 83    return await _set_lang(update, context, selected)
 84
 85
 86def unknown(update: Update, context: ContextTypes.DEFAULT_TYPE):
 87    logging.info(f"User {update.message.from_user.full_name} sent {update.message.text_markdown_v2} and I don't know what that means.")
 88
 89
 90async def error_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
 91    try:
 92        raise context.error
 93    except Exception as e:
 94        logging.error(str(e))
 95        await update.message.reply_text(l('error', context))
 96
 97
 98def _add_effect_handler(application: ApplicationBuilder, command: str):
 99    callback = partial(effect_handler, effect_name=command)
100
101    application.add_handler(CommandHandler(command, callback))
102    application.add_handler(MessageHandler(filters.Caption([f"/{command}"]), callback))
103
104async def keyboard_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
105    query = update.callback_query
106    data = query.data
107
108    if data.startswith("reroll"):
109        amount = int(data.split(" ")[1])
110
111        if amount <= 1:
112            return await spin(update, context)
113        return await autospin(context, update.effective_chat.id, amount)
114
115    match data:
116        case "none":
117            return query.answer(l("none_callback", context))
118        case "set_lang_en":
119            lang = "en"
120            await _set_lang(update, context, lang)
121            return await query.answer(l("language_set", context).format(format_lang(lang)))
122        case "set_lang_it":
123            lang = "it"
124            await _set_lang(update, context, lang)
125            return await query.answer(l("language_set", context).format(format_lang(lang)))
126        case other:
127            logging.error(f"unknown callback: {data}")
128
129    return await query.answer()
130
131
132def main():
133    load_dotenv()
134    logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
135
136    token = os.getenv("token")
137    pers = PersistenceInput(bot_data=False, callback_data=False)
138    persistence = PicklePersistence(filepath='bot-data.pkl', store_data=pers)
139
140    application = ApplicationBuilder().token(token).persistence(persistence).build()
141
142    application.add_error_handler(error_callback)
143    application.add_handler(CallbackQueryHandler(callback=keyboard_handler))
144
145    # commands
146    application.add_handler(CommandHandler('start', start))
147    application.add_handler(CommandHandler('lang', lang))
148    application.add_handler(CommandHandler('lewd', lewd))
149    application.add_handler(CommandHandler('caps', caps))
150    application.add_handler(CommandHandler('pic', pic))
151
152    # effects
153    _add_effect_handler(application, 'ttbt')
154    _add_effect_handler(application, 'tt')
155    _add_effect_handler(application, 'bt')
156    _add_effect_handler(application, 'splash')
157    _add_effect_handler(application, 'wot')
158    _add_effect_handler(application, 'text')
159
160    # games
161    application.add_handler(CommandHandler('spin', spin))
162    application.add_handler(CommandHandler('bet', bet))
163    application.add_handler(CommandHandler('cash', cash))
164
165    # fallback
166    application.add_handler(MessageHandler(filters.COMMAND, unknown))
167    application.run_polling()
168
169
170if __name__ == "__main__":
171    main()