import asyncio import logging from telegram import Update from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler, MessageHandler, filters import os import json from cowmesh_router_iperf_test import CowmeshRouterIperfTester from cowmesh_pi_iperf_test import CowmeshPiIperfTester PROJECT_PATH = os.path.abspath(os.path.dirname(__file__)) SECRETS_PATH = os.path.join(PROJECT_PATH, "secrets.json") with open(SECRETS_PATH, 'r') as f: SECRETS = json.loads(f.read()) logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO ) async def start(update: Update, context: ContextTypes.DEFAULT_TYPE): await context.bot.send_message(chat_id=update.effective_chat.id, text="This is the moonlight analytics bot for mesh network diagnostics.\n\nType /help to see available commands.", message_thread_id=update.message.message_thread_id) async def caps(update: Update, context: ContextTypes.DEFAULT_TYPE): """ this is just a function to test that the bot is working as expected """ text_caps = ' '.join(context.args).upper() print("chat_id: {}".format(update.effective_chat.id)) print("message_thread_id: {}".format(update.message.message_thread_id)) await context.bot.send_message(chat_id=update.effective_chat.id, text=text_caps, message_thread_id=update.message.message_thread_id) async def router_iperf(update: Update, context: ContextTypes.DEFAULT_TYPE): time = context.args[0] if context.args else None if not time: time = 10 async def log(msg): await context.bot.send_message(chat_id=update.effective_chat.id, text=msg, message_thread_id=update.message.message_thread_id) if update.effective_chat.id != int(SECRETS["TELEGRAM_LOG_CHAT_ID"]): await log("++ can only start iperf test from Moonlight Bot group") return await log("++ starting router iperf test with {} seconds per test".format(time)) tester = CowmeshRouterIperfTester(log=log, seconds=time) await tester.run_test() await tester.output_results() async def pi_iperf(update: Update, context: ContextTypes.DEFAULT_TYPE): time = context.args[0] if context.args else None if not time: time = 10 async def log(msg): await context.bot.send_message(chat_id=update.effective_chat.id, text=msg, message_thread_id=update.message.message_thread_id) if update.effective_chat.id != int(SECRETS["TELEGRAM_LOG_CHAT_ID"]): await log("++ can only start iperf test from Moonlight Bot group") return await log("++ starting pi iperf test with {} seconds per test".format(time)) tester = CowmeshPiIperfTester(log=log, time=time) await tester.run_test() await tester.output_results() async def unknown(update: Update, context: ContextTypes.DEFAULT_TYPE): await context.bot.send_message(chat_id=update.effective_chat.id, text="Sorry, I didn't understand that, please run /help for a list of available commands.", message_thread_id=update.message.message_thread_id) def about_message(): msg = "This is a bot designed to help measure the performance of a mesh network through active testing. " \ "Every night the bot runs a network test using iperf to measure the connectivity between all the nodes in the mesh, " \ "and logs the result to this channel. " \ "Members of this channel can also initiate a new network iperf test at any time by sending a message to this channel, " \ "with the command /iperf . " \ "Telegram users outside of this channel cannot initiate a test, to help keep the network secure from being " \ "overrun by malicious users. " \ "The network test runs at night because that is when the fewest people are using the network, and so is more likely to " \ "give consistent results with less random variability. " \ "Please be mindful of initiating too many iperf tests during the day, as it uses a lot of network resources " \ "to run the test and could interfere with the internet connections of people using the network. " return msg def help_message(): msg = "This bot runs an iperf test every night and logs the results here. You can also initiate a new test using the command /iperf " \ "or read a longer message explaining how this bot works by typing the command /readme." return msg async def about(update: Update, context: ContextTypes.DEFAULT_TYPE): text = about_message() await context.bot.send_message(chat_id=update.effective_chat.id, text=text, message_thread_id=update.message.message_thread_id) async def help_fun(update: Update, context: ContextTypes.DEFAULT_TYPE): text = help_message() await context.bot.send_message(chat_id=update.effective_chat.id, text=text, message_thread_id=update.message.message_thread_id) async def nightly_router_iperf(time=10): token = SECRETS["TELEGRAM_TOKEN"] application = ApplicationBuilder().token(token).build() chat_id = SECRETS["TELEGRAM_LOG_CHAT_ID"] message_thread_id = SECRETS.get("TELEGRAM_LOG_MESSAGE_THREAD_ID") bot = application.bot async def log(msg): await bot.send_message(chat_id=chat_id, text=msg, message_thread_id=message_thread_id) await log("☾☾ starting nightly router-to-router iperf test with {} seconds per test") tester = CowmeshRouterIperfTester(log=log, time=time) await tester.run_test() await tester.output_results() async def nightly_pi_iperf(time=10): token = SECRETS["TELEGRAM_TOKEN"] application = ApplicationBuilder().token(token).build() chat_id = SECRETS["TELEGRAM_LOG_CHAT_ID"] message_thread_id = SECRETS.get("TELEGRAM_LOG_MESSAGE_THREAD_ID") bot = application.bot async def log(msg): await bot.send_message(chat_id=chat_id, text=msg, message_thread_id=message_thread_id) await log("☾☾ starting nightly computer-to-computer iperf test with {} seconds per test".format(time)) tester = CowmeshPiIperfTester(log=log, time=time) await tester.run_test() await tester.output_results() def init_bot_listener(): token = SECRETS["TELEGRAM_TOKEN"] application = ApplicationBuilder().token(token).build() start_handler = CommandHandler('start', start) application.add_handler(start_handler) caps_handler = CommandHandler('caps', caps) application.add_handler(caps_handler) about_handler = CommandHandler('readme', about) application.add_handler(about_handler) help_handler = CommandHandler('help', help_fun) application.add_handler(help_handler) iperf_handler = CommandHandler('iperf', router_iperf) application.add_handler(iperf_handler) pi_iperf_handler = CommandHandler('pi_iperf', pi_iperf) application.add_handler(pi_iperf_handler) unknown_handler = MessageHandler(filters.COMMAND, unknown) application.add_handler(unknown_handler) application.run_polling() if __name__ == '__main__': init_bot_listener()