import secrets import expenses from expenses import SharedExpense, Debit, Credit from db import Database from telegram.ext import Updater from telegram.ext import MessageHandler, Filters from telegram.ext import CommandHandler from parsimonious import ParseError import logging from enum import Enum from functools import partial Result = Enum('MsgResult', 'OK DENY ERROR') logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S', level=logging.INFO) def log_chat_msg(result, update, additional_message=''): if type(additional_message) is None: additional_message = '' msg = f'{update.effective_chat.id}:{update.effective_chat.username} \ | {result} | "{update.message.text} | {additional_message}"' if result == Result.OK: logging.info(msg) elif result == Result.DENY: logging.info(msg) elif result == Result.ERROR: logging.error(msg) else: assert False def authorized_ids_only(f): def invalid_id(update, context): context.bot.send_message(chat_id=update.effective_chat.id, text="Sorry, you are not authorized to use this bot") def log_to_shared_group(context, msg): context.bot.send_message(chat_id=secrets.sharedgroup_id, text=msg) def decorated(*args, **kwargs): update, context = args[0], args[1] chat_id = update.effective_chat.id if chat_id in secrets.authorized_ids: try: log_msg = f(*args, **kwargs) log_chat_msg(Result.OK, update, additional_message=log_msg) except Exception as e: log_chat_msg(Result.ERROR, update, additional_message=str(e)) finally: issuer = f'{update.effective_chat.username}' group_msg = f'{issuer} wrote: "{update.message.text}"' log_to_shared_group(context, group_msg) else: log_chat_msg(Result.DENY, update) return invalid_id(update, context) return decorated @authorized_ids_only def start(update, context): context.bot.send_message(chat_id=update.effective_chat.id, text="Quanti pan au chocolat hai comprato oggi?") @authorized_ids_only def help_command(update, context): msg = 'write (+|-) amount reason' context.bot.send_message(chat_id=update.effective_chat.id, text=msg) @authorized_ids_only def main_command(update, context, store): issuer = f'{update.effective_chat.id}:{update.effective_chat.username}' msg = update.message.text try: expense = expenses.parse(msg) store.write_expense(issuer, expense) msg_to_user = f'Wrote {expense} to the store' context.bot.send_message(chat_id=update.effective_chat.id, text=msg_to_user) return '' except ParseError as e: msg_to_user = f'Wrong format for msg' context.bot.send_message(chat_id=update.effective_chat.id, text=msg_to_user) return f'ParseError: {e}' @authorized_ids_only def report_command(update, context, store): print(update.effective_chat.id) report = store.report() msg = '' for issuer, (expenses, credits, debits) in report.items(): msg += f'{issuer}: \n\ Spese comuni: {expenses}, Crediti: {credits}, Debiti: {debits}\n' context.bot.send_message(chat_id=update.effective_chat.id, text=msg) if __name__ == '__main__': updater = Updater(token=secrets.token, use_context=True) dispatcher = updater.dispatcher start_handler = CommandHandler('start', start) dispatcher.add_handler(start_handler) help_handler = CommandHandler('help', help_command) dispatcher.add_handler(help_handler) with Database('storage.bin') as store: main_with_store = lambda *args, **kwargs: main_command(*args, store, **kwargs) main_handler = MessageHandler(Filters.text, main_with_store) report_with_store = lambda *args, **kwargs: report_command(*args, store, **kwargs) dispatcher.add_handler(CommandHandler('report', report_with_store)) dispatcher.add_handler(main_handler) updater.start_polling() # loop updater.idle() # avoid exiting the with block