|
1 | 1 | #!/usr/bin/env python3 |
| 2 | +""" |
| 3 | +primary entry point to the bot backend |
| 4 | +""" |
2 | 5 |
|
3 | | -import threading |
| 6 | +import os |
4 | 7 | import time |
| 8 | +import signal |
| 9 | +import logging |
5 | 10 | from collections import OrderedDict |
6 | | -import os |
7 | | -import telebot |
| 11 | +from concurrent.futures import ThreadPoolExecutor |
8 | 12 | import dotenv |
| 13 | +import telebot |
| 14 | +from telebot.types import Update |
9 | 15 | import utils |
10 | 16 |
|
| 17 | +# Load environment variables |
11 | 18 | dotenv.load_dotenv() |
12 | 19 | TOKEN = os.getenv("TOKEN") |
13 | 20 |
|
| 21 | +# Initialize the bot |
14 | 22 | bot = telebot.TeleBot(TOKEN) |
15 | 23 |
|
| 24 | +# Initialize update ID dictionary and logger |
16 | 25 | updateid_dict = OrderedDict() |
| 26 | +logging.basicConfig( |
| 27 | + level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s" |
| 28 | +) |
| 29 | + |
| 30 | +# Define maximum threads and updates to fetch |
| 31 | +MAX_THREADS = 10 |
| 32 | +MAX_UPDATES = 100 |
| 33 | + |
| 34 | +# Initialize the thread pool |
| 35 | +executor = ThreadPoolExecutor(max_workers=MAX_THREADS) |
| 36 | + |
17 | 37 |
|
| 38 | +def fetch_updates(offset): |
| 39 | + """ |
| 40 | + Fetch updates from the Telegram server. |
| 41 | + """ |
| 42 | + return ( |
| 43 | + bot.get_updates() |
| 44 | + if offset is None |
| 45 | + else bot.get_updates(offset, MAX_UPDATES, timeout=20) |
| 46 | + ) |
18 | 47 |
|
19 | | -def index(): |
| 48 | + |
| 49 | +def process_update(update: Update): |
20 | 50 | """ |
21 | | - Main function that is responsible to run the server. |
| 51 | + Process an incoming update. |
22 | 52 | """ |
| 53 | + if update.update_id not in updateid_dict: |
| 54 | + updateid_dict[update.update_id] = time.time() |
| 55 | + try: |
| 56 | + executor.submit(utils.address_query, update) |
| 57 | + except Exception as exception: |
| 58 | + logging.error( |
| 59 | + "Unable to process update {%s}: {%s}", update.update_id, exception |
| 60 | + ) |
| 61 | + |
| 62 | + if len(updateid_dict) > 50: |
| 63 | + updateid_dict.popitem(last=False) |
23 | 64 |
|
| 65 | + |
| 66 | +def run_bot(): |
| 67 | + """ |
| 68 | + Main function that runs the bot. |
| 69 | + """ |
| 70 | + logging.info("Bot is starting...") |
24 | 71 | last_update_id = None |
25 | 72 |
|
26 | | - # Keep Listening to incoming requests |
27 | 73 | while True: |
28 | | - # The following conditional ensures fetching of latest 50 updates |
29 | | - updates_list = None |
30 | | - if last_update_id is None: |
31 | | - updates_list = bot.get_updates() |
32 | | - else: |
33 | | - updates_list = bot.get_updates(last_update_id, 100, 20) |
34 | | - |
35 | | - for update in updates_list: |
36 | | - last_update_id = update.update_id |
37 | | - |
38 | | - if update.update_id not in updateid_dict.keys(): |
39 | | - updateid_dict[update.update_id] = time.time() |
40 | | - try: |
41 | | - new_thread = threading.Thread( |
42 | | - target=utils.address_query, args=(update,) |
43 | | - ) |
44 | | - new_thread.start() |
45 | | - except Exception as exception: |
46 | | - print("Unable to create a thread") |
47 | | - raise exception |
48 | | - |
49 | | - if len(updateid_dict.keys()) > 50: |
50 | | - updateid_dict.pop(list(updateid_dict.keys())[0]) |
| 74 | + try: |
| 75 | + updates_list = fetch_updates(last_update_id) |
| 76 | + for update in updates_list: |
| 77 | + last_update_id = update.update_id |
| 78 | + process_update(update) |
| 79 | + except Exception as e: |
| 80 | + logging.error("Error while fetching or processing updates: {%s}", e) |
| 81 | + time.sleep(5) # Sleep for a bit before retrying |
51 | 82 |
|
52 | 83 |
|
53 | 84 | if __name__ == "__main__": |
54 | | - index() |
| 85 | + run_bot() |
0 commit comments