async def record_machine_info(info): global q await q.put({ "coll": f"netprobe", "doc": get_config(NODE_NAME), "data": info, })
async def start_telegram(): global client loop = asyncio.get_event_loop() logging.info(f"Telegram loop: {loop}") client = TelegramClient( StringSession(get_config(TELEGRAM_SESSION_ID)), get_config(TELEGRAM_API_ID), get_config(TELEGRAM_API_HASH), loop=loop, ) client.add_event_handler(rollcall, events.NewMessage(pattern=r".*roll\s?call.*")) client.add_event_handler(time_reply, events.NewMessage(pattern=r".*time.*")) client.add_event_handler( handle_get_last_probe, events.NewMessage(pattern=r".*(get )?(latest|last) (probe|report).*"), ) client.add_event_handler(handle_run_probe, events.NewMessage(pattern=r".*run probe.*")) client.add_event_handler( handle_get_ip, events.NewMessage(pattern=r".*get [iI][pP].*"), ) client.add_event_handler(handle_pip_list, events.NewMessage(pattern=r".*pip list\s*")) client.add_event_handler(handle_pip_upgrade, events.NewMessage(pattern=r".*pip upgrade\s*")) client.add_event_handler(handle_reboot, events.NewMessage(pattern=r".*reboot\s*")) client.add_event_handler(handle_help, events.NewMessage(pattern=r".*help\s*")) await client.start() if bool(get_config(ANNOUNCE_START) or DEFAULT_ANNOUNCE_START) is True: await client.send_message( "@buildchimp", f"*{get_config(NODE_NAME)}* is online! 🎉") logging.info("Telegram client should be running.") await client.run_until_disconnected()
async def iwlist_scan(): device = get_config(WIFI_DEVICE) or DEFAULT_WIFI_DEVICE # logging.info(f"Using WiFi device: {device}") command = f"/usr/sbin/iwlist {device} scan" logging.info(f">>>START WiFi scanning...\n\n {command}\n\n") process = await asyncio.create_subprocess_shell( command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, ) scan_output, stderr = await process.communicate() # logging.info("Retrieving output from command") err = stderr.decode("utf-8") out = scan_output.decode("utf-8") # logging.info(f"output from wifi scan:\n\n{out}\n\n") # logging.info(f"error output from wifi scan:\n\n{err}\n\n") if process.returncode != 0: logging.error(f"Failed to scan for WiFi: {err.strip()}") return [] else: lines = out.splitlines() result = [] current = None for line in lines: if re.match(r"\s*Cell \d+ - Address: [:0-9a-fA-F]{17}\s*", line): # logging.info("Detected new network") if current is not None and len(current.keys()) > 2: # logging.info(f"Appending current network: {current}") result.append(current) current = {} else: parts = [p.strip() for p in re.split(r"\s*[:=]\s*", line)] if parts[0] == "ESSID": current["ssid"] = parts[1][1:-1] elif parts[0] == "Quality": qparts = [p.strip() for p in re.split(r"[ /]", parts[1])] strength = round((int(qparts[0]) / int(qparts[1])) * 100) current["str"] = strength elif parts[0] == "Channel": current["chan"] = int(parts[1]) # logging.info( # f"<<<DONE WiFi scanning, {len(result)} networks found:\n\n{result}\n\n" # ) return result
async def _directed_at_me(event): global client node_name = get_config(NODE_NAME) logging.warning(f"Handle for node: {node_name}: {event.raw_text}") me = await client.get_me() for e, txt in event.get_entities_text(): if (type(e) == MessageEntityMention and txt[1:] == me.username and node_name in event.raw_text): logging.warning("This message is directed at me.") return True return False
async def report_loop(): global last_report logging.info("Starting reporting loop") await start_database() while True: try: start = time.time() last_report = await run_probes() # await report_results(last_report, q) timeout = int( get_config(REPORTER_TIMEOUT) or DEFAULT_REPORTER_TIMEOUT) elapsed = time.time() - start if timeout > elapsed > timeout / 2: timeout = round(timeout - elapsed) logging.info(f"Reporting loop sleeping {timeout} seconds") await asyncio.sleep(timeout) except KeyboardInterrupt: break
async def get_my_ip(): ip_reflector = get_config(IP_REFLECTOR) async with ClientSession() as session: async with session.get(ip_reflector) as response: data = await response.json() return data.get("ipv4")
async def start_database(): count = int(get_config(WRITER_COUNT) or DEFAULT_WRITER_COUNT) for i in range(count): asyncio.create_task(consumer(i, q))
async def rollcall(event): node_name = get_config(NODE_NAME) for e, txt in event.get_entities_text(): print(type(e)) await event.reply(f"*{node_name}* is online!")