///
The `bot.py` script serves as the central operational component of the Air Quality Telegram Bot, orchestrating data fetching, message generation, and scheduling. It is structured around two main class
58 views
~58 views from guests
Guest views are estimated from total page views. These include anonymous visitors and users who weren't logged in when they viewed the page.
The bot.py script serves as the central operational component of the Air Quality Telegram Bot, orchestrating data fetching, message generation, and scheduling. It is structured around two main classes: Message for handling multilingual text content and Main for managing the bot's lifecycle, API interactions, and scheduling.
Message ClassThe Message class is responsible for encapsulating all the textual content the bot sends, ensuring multilingual support across Khmer (kh), English (en), Japanese (jp), and German (de).
The class initializes with two core dictionaries: self.verdict and self.advice. These dictionaries map AQI categories (e.g., "good", "moderate", "unhealthy") to corresponding verdicts and actionable advice in each of the four supported languages.
self.verdict structure snippet:
self.advice structure snippet:
get_aqi_category MethodThis method takes an Air Quality Index (AQI) value (aqius) as input and maps it to one of the predefined air quality categories (e.g., "good", "moderate", "unhealthy"). It uses a series of if-elif statements to determine the category based on standard AQI ranges.
morning_message(self, aqius): A lambda function that constructs a welcoming "Good morning" message, including the current AQI, its category, and associated advice, formatted in all four languages.signoff(self): A lambda function that generates a "Good night" sign-off message, indicating the bot's operational hours and when it will resume, also in four languages.update(self, aqius, mainus, aqius_prior, mainus_prior, hour, minute, change): This method is central to generating regular air quality updates. It takes the current and prior AQI values (aqius, aqius_prior), timestamp, and a change tuple (indicating if AQI is 'improving', 'deteriorating', or 'stagnant', and if the category changed) to create a detailed message. It dynamically selects from different message templates based on whether the AQI category changed or if the value changed significantly within the same category. The output is a dictionary containing the formatted update message for each language.Main ClassThe Main class initializes and controls the Telegram bot, handling API calls, message sending, and the main scheduling loop.
Upon instantiation, the Main class:
keys.json (which stores the aqius_prior value).API_KEY, BOT_TOKEN, and CHAT_ID from environment variables, as described in [Getting Started].pyTelegramBotAPI client (self.intell1slt_bot).Message class (self.msg) to handle text generation.712191968 in the provided code, but can be self.CHAT_ID).get_phnom_penh_aq MethodThis method is responsible for making API requests to the AirVisual API to fetch the current air quality data for Phnom Penh. It includes retry logic, attempting the API call up to 5 times with a 2-second delay between attempts, to handle transient network issues or API rate limits. It returns the current AQI US value (aqius) and the main pollutant (mainus).
send_message and send_only_message Methodssend_message(self, image_file_name, message): This method sends both an image and a text message to the configured Telegram chat. It loads the image from the ./labels/ directory based on the image_file_name (derived from the AQI category, e.g., good.png). It also incorporates retry logic for sending both the photo and the text, waiting 2 seconds between attempts.send_only_message(self, message): Similar to send_message, but only sends a text message, typically used for non-visual updates like the sign-off message. It also includes retry logic.update MethodThis method performs the logic for determining how the air quality has changed and formats the update message:
self.aqius (current AQI) with self.aqius_prior (previous AQI).
less than or equal to 2 and the category is the same, the change is "stagnant" (["stagnant", "samecat", "samecat"]).self.aqius has increased by more than 2 points and the category is the same, it's "deteriorating" within the same category (["deteriorating", "samecat", "samecat"]).self.aqius has decreased by more than 2 points and the category is the same, it's "improving" within the same category (["improving", "samecat", "samecat"]).previous_category and current_category.self.msg.update (from the Message class) to generate the final multilingual update message, passing the determined change status, current and prior AQI values, and the timestamp.aqius_prior value in keys.json and in the Main instance to reflect the new current AQI, ensuring the next comparison is accurate.main method)The main method contains the bot's continuous operation loop. It constantly checks the current time and triggers actions based on specific time conditions and the current AQI category, as described in the [Overview] page.
Morning Message (Daily at 6:00 AM):
hour == 6, minute == 0, and seconds == 0, the bot fetches the latest AQI.aqius_prior is reset to 0 to ensure the first update after the morning message is always treated as a new reading.self.msg.morning_message and sent with an image corresponding to the AQI category.Regular Updates (6:00 AM to 9:00 PM):
6 <= hour < 21 and minute is a multiple of 5 (minute % 5 == 0) with seconds == 0, the bot fetches new AQI data.minute % 60 == 0).minute % 30 == 0).minute % 15 == 0).minute % 10 == 0).minute % 5 == 0).self.update method is called to generate the multilingual message, and self.send_message sends the image and text.Sign-off Message (Daily at 9:00 PM):
hour == 21, minute == 0, and seconds == 0, the bot sends a "Good night" sign-off message using self.msg.signoff and self.send_only_message.A time.sleep(0.1) at the end of the loop ensures the bot doesn't consume excessive CPU cycles when no actions are due, and time.sleep(65) after sending a message provides a buffer to avoid hitting rate limits.