Telegram bot only works for first user who starts it

I’m working on a Python telegram bot for my college assignment and having trouble with multiple users. The bot should send notifications and messages to everyone who uses it, but right now it only works for the person who started it first.

When someone else tries to use the bot while it’s already running for another user, both users stop getting responses. The Python script keeps running but the telegram bot stops sending messages to anyone.

I’m pretty new to Python so please be patient with me. I tried using asyncio but ran into too many problems and gave up on that approach.

Here’s my code:

from weather_alerts import AlertClient
import telebot
import os
from dotenv import load_dotenv
import time
import sqlite3
from datetime import datetime

# Get current time and day
today_time = datetime.now().strftime("%H:%M")
today_day = datetime.now().strftime("%A")

# Database setup
db_conn = sqlite3.connect('classes.db')
db_cursor = db_conn.cursor()

# Check if table exists
db_cursor.execute('''SELECT count(name) FROM sqlite_master WHERE type='table' AND name='classes' ''')
if db_cursor.fetchone()[0] == 1:
    print('Table "classes" already exists.')
else:
    db_cursor.execute('''CREATE TABLE classes (
               weekday TEXT,
               begin_time TEXT,
               finish_time TEXT,
               course TEXT
               )''')
    print('Table "classes" created successfully.')

# Class schedule data
class_schedule = [
    ('Monday', '09:00', '10:30', 'Mathematics'),
    ('Monday', '10:45', '12:15', 'Physics'),
    ('Monday', '12:30', '14:00', 'English'),
    ('Tuesday', '09:00', '10:30', 'Chemistry'),
    ('Tuesday', '10:45', '12:15', 'Biology'),
    ('Wednesday', '09:00', '10:30', 'History'),
    ('Wednesday', '10:45', '12:15', 'Geography'),
]

# Add data to table
for item in class_schedule:
    db_cursor.execute('''INSERT INTO classes (weekday, begin_time, finish_time, course) VALUES (?, ?, ?, ?)''', item)

db_conn.commit()

def add_new_class(weekday, begin_time, finish_time, course):
    connection = sqlite3.connect('classes.db')
    cursor = connection.cursor()
    try:
        cursor.execute('''INSERT INTO classes (weekday, begin_time, finish_time, course) VALUES (?, ?, ?, ?)''',
                      (weekday, begin_time, finish_time, course))
        connection.commit()
        print(f"Added new class: {weekday}, {begin_time} - {finish_time}, {course}")
    except sqlite3.Error as error:
        print("Error adding class:", error)
    finally:
        connection.close()

def get_next_class(msg):
    try:
        connection = sqlite3.connect('classes.db')
        cursor = connection.cursor()
        
        now_time = datetime.now().strftime("%H:%M:%S")
        now_day = datetime.now().strftime("%A")
        
        cursor.execute('SELECT * FROM classes WHERE weekday=? AND begin_time>=? ORDER BY begin_time ASC LIMIT 1',
                      (now_day, now_time))
        upcoming_class = cursor.fetchone()
        
        connection.close()
        return upcoming_class
    except sqlite3.Error as error:
        print("Error getting next class:", error)

def check_current_class(msg):
    try:
        connection = sqlite3.connect('classes.db')
        cursor = connection.cursor()
        
        now_time = datetime.now().strftime("%H:%M:%S")
        now_day = datetime.now().strftime("%A")
        
        cursor.execute('SELECT * FROM classes WHERE weekday=? AND begin_time<=? AND finish_time>=?', 
                      (now_day, now_time, now_time))
        current_class = cursor.fetchone()
        
        connection.close()
        return current_class
    except sqlite3.Error as error:
        print("Error checking current class:", error)

load_dotenv()
TOKEN = os.environ.get('TELEGRAM_TOKEN')
bot = telebot.TeleBot(TOKEN)
bot.remove_webhook()

alert_client = AlertClient(token="sample_token_12345")
processed_alerts = set()
API_DELAY = 5
is_running = False

def fetch_alerts(msg):
    region_data = alert_client.get_alert_status()
    time.sleep(API_DELAY)
    return set(str(area) for area in region_data.get_active_regions())

def send_alert_notifications(msg):
    global processed_alerts
    current_alerts = fetch_alerts(msg)
    
    new_alerts = current_alerts - processed_alerts
    ended_alerts = processed_alerts - current_alerts
    
    if new_alerts:
        for area in new_alerts:
            bot.send_message(msg.chat.id, f"Alert in {area}! Take shelter immediately!")
    
    if ended_alerts:
        for area in ended_alerts:
            bot.send_message(msg.chat.id, f"Alert in {area} has ended.")
    
    processed_alerts = current_alerts

@bot.message_handler(commands=['start'])
def handle_start(message):
    global is_running
    if not is_running:
        is_running = True
        bot.reply_to(message, "Bot started sending alerts.")
        
        while is_running:
            send_alert_notifications(message)

@bot.message_handler(commands=['stop'])
def handle_stop(message):
    global is_running
    is_running = False
    bot.reply_to(message, "Bot stopped sending alerts.")

@bot.message_handler(func=lambda msg: True)
def handle_messages(message):
    bot.reply_to(message, message.text)

bot.polling()
db_conn.commit()
db_conn.close()

The core problem here is that your global is_running variable creates conflicts between multiple users. When user A starts the bot, is_running becomes True and enters the infinite loop. If user B then tries to start the bot, the condition if not is_running fails because it’s already True from user A, so user B gets no response. Meanwhile, user A’s loop continues running but only sends messages to their specific chat ID. You should maintain separate states for each user instead of using a single global variable. Consider storing active users in a dictionary with their chat IDs as keys, then use threading or a background scheduler to check alerts for all active users periodically. I encountered this exact scenario when building a notification bot for my work team - the single global state was the culprit. Each user session needs to be tracked independently while sharing the same alert checking logic.

dude your main issue is that while loop inside the start handler - it basicaly freezes everything for other users. telegram bots can handle multiple ppl at once but you’re blocking it. try moving the alert checking outside of the message handler, maybe use a timer or something to check alerts every few seconds and send to all active users. also that global is_running thing wont work with multiple users anyway.

Looking at your code, the issue is in your /start command handler where you have a while is_running loop that blocks the entire bot. When one user starts the bot, it gets stuck in that infinite loop and can’t process any other messages or commands from different users. The telebot library is designed to handle multiple users automatically, but your blocking loop prevents this. You need to remove that while loop from the start handler and implement the alert checking differently. Consider using a separate thread or the built-in scheduler functionality to run your alert checking in the background while keeping the main polling loop free to handle all users. I had a similar problem when I first started with telegram bots - blocking loops in message handlers will always cause this kind of issue. The polling mechanism needs to stay responsive to handle concurrent users properly.