Simple utilities bot for Telegram. /ping, /whoami and such.
at main 80 lines 2.0 kB view raw
1import asyncio 2import logging 3import platform 4import signal 5from pathlib import Path 6 7import click 8import coloredlogs 9import tomllib 10 11from bot import PingBot 12 13logger = logging.getLogger(__name__) 14 15 16def load_config(config_path: Path | None) -> dict: 17 assert config_path is not None 18 with open(config_path, "rb") as f: 19 return tomllib.load(f) 20 21 22def _raise_exit(): 23 raise SystemExit 24 25 26async def run_bot(bot: PingBot) -> None: 27 async with bot.app: 28 await bot.start_app() 29 # wait for shutdown signal 30 stop_event = asyncio.Event() 31 32 def signal_handler(sig, frame): 33 logger.info("received shutdown signal") 34 stop_event.set() 35 36 signal.signal(signal.SIGINT, signal_handler) 37 signal.signal(signal.SIGTERM, signal_handler) 38 39 await stop_event.wait() 40 await bot.stop_app() 41 42 43@click.command() 44@click.option( 45 "--config", 46 type=click.Path(exists=True, path_type=Path), 47 default="./config.toml", 48 help="path to config.toml file (default: ./config.toml)", 49) 50@click.option("--token", help="telegram bot token (overrides config file)") 51def main(config: Path | None, token: str | None) -> None: 52 if not token and not (config and config.exists()): 53 raise click.UsageError( 54 ( 55 "must provide either --token, --config or a valid config file " 56 "at ./config.toml" 57 ) 58 ) 59 60 bot_name = "Telegram Bot" 61 if token: 62 bot_token = token 63 else: 64 cfg = load_config(config) 65 bot_token = cfg["telegram"]["token"] 66 bot_name = cfg.get("telegram", {}).get("name", bot_name) 67 68 log_format = ( 69 "[{}][%(asctime)s]%(name)s::%(levelname)s:%(message)s" 70 ).format(bot_name.upper()) 71 72 logging.basicConfig(format=log_format, level=logging.INFO) 73 coloredlogs.install(level=logging.INFO, fmt=log_format) 74 75 bot = PingBot(bot_token, bot_name) 76 asyncio.run(run_bot(bot)) 77 78 79if __name__ == "__main__": 80 main()