Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Telegram Chatbot Issue

I have a telegram bot (@TEVOProjAttBot) I created to upload event attendances on Google sheet. However, the commands "/start", "/help", "/add" doesn't work as it should, it doesn't run the functions I wrote in the Python code. I think there is a programming logic mistake I'm making. How should I correct either code?

Screenshot of Messages with Bot

Below is my python code for the main.py file, and the 'credentials.json' file is working fine and installed in the same folder as the main.py file.

from typing import Final

# pip install python-telegram-bot
from telegram import Update
from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes

print('Bot is now starting up...')

API_TOKEN: Final = 'MY_TOKEN'
BOT_HANDLE: Final = '@TEVOProjAttBot'


# Command to start the bot
async def initiate_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text('Greetings! I am your Projected Attendance bot. How can I assist you today?')


# Command to provide help information
async def assist_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text('Here comes the help')


# Command for custom functionality
async def personalize_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text('This is a custom command, you can put whatever you want here.')


async def generate_response(user_input: str) -> str:
    # Custom logic for response generation
    normalized_input: str = user_input.lower()

    if 'hi' in normalized_input:
        return 'Hello!'

    if 'how are you doing' in normalized_input:
        return 'I am functioning properly!'

    if 'i would like to subscribe' in normalized_input:
        return 'Sure go ahead!'

    return 'I did not catch that, could you please rephrase?'


async def process_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
    # Extract details of the incoming message
    chat_type: str = update.message.chat.type
    text: str = update.message.text

    # Logging for troubleshooting
    print(f'User ({update.message.chat.id}) in {chat_type}: "{text}"')

    # Handle group messages only if bot is mentioned
    if chat_type == 'group':
        if BOT_HANDLE in text:
            cleaned_text: str = text.replace(BOT_HANDLE, '').strip()
            response: str = generate_response(cleaned_text)
        else:
            return  # Ignore messages where bot is not mentioned in a group
    else:
        response: str = generate_response(text)

    # Reply to the user
    print('Bot response:', response)
    await update.message.reply_text(response)


# Log errors
async def log_error(update: Update, context: ContextTypes.DEFAULT_TYPE):
    print(f'Update {update} caused error {context.error}')

# Google Sheet access
import gspread
from oauth2client.service_account import ServiceAccountCredentials

scope = ["https://spreadsheets.google.com/feeds",
         "https://www.googleapis.com/auth/drive",
         "https://www.googleapis.com/auth/spreadsheets"]

credentials = ServiceAccountCredentials.from_json_keyfile_name('credentials.json', scope)
client = gspread.authorize(credentials)

sheet = client.open("Projected Attendance List").sheet1
sheet_ = client.open("Projected Attendance List").sheet2

# Get summary
async def get_data(update: Update, context: ContextTypes.DEFAULT_TYPE):
    rows = sheet.get_all_values()
    response = "\n".join([", ".join(row) for row in rows])
    update.message.reply_text(f"📊 Sheet Data Obtained!")

getter = Updater('MY_TOKEN')
getter.start_polling()
getter.idle()

async def get_summary(update: Update, context: ContextTypes.DEFAULT_TYPE):
    rows = sheet_.get_all_values()
    response = "\n".join([", ".join(row) for row in rows])
    update.message.reply_text(f"📊 Sheet Data:\n{response}")

updater = Updater('MY_TOKEN')
updater.start_polling()
updater.idle()

# Add new row
async def add_entry(update: Update, context: ContextTypes.DEFAULT_TYPE):
    args = context.args
    if len(args) >= 4:
        name, CG, category, date = args[0], args[1], args[2], args[3]
        sheet.append_row([name, CG, category, date])
        update.message.reply_text("✅ New entry added.")
    else:
        update.message.reply_text("❗ Usage: /add John A0 NF 05102025")

# Delete a particular row
async def remove_row(update: Update, context: ContextTypes.DEFAULT_TYPE):
    args = context.args
    no_of_rows = len(sheet.col_values(1))
    if len(args) == 4:
        name = args[0]
        CG = args[1]
        date = args[3]
        rows_to_delete = []
        for row in range(no_of_rows, -1, -1):
            row_values_list = sheet.row_values(row)
            if row_values_list[0] == name and row_values_list[1] == CG and row_values_list[3] == date:
                rows_to_delete.append(row)
        for row in rows_to_delete:
            sheet.delete_rows(row)
        update.message.reply_text(f"📝 Delete rows ({name},{CG},{date})")
    else:
        update.message.reply_text("❗ Usage: /delete David A0 05102025")

# Start the bot
if __name__ == '__main__':
    app = Application.builder().token(API_TOKEN).build()

    # Register command handlers
    app.add_handler(CommandHandler('start', initiate_command))
    app.add_handler(CommandHandler('help', assist_command))
    app.add_handler(CommandHandler('access', get_data))
    app.add_handler(CommandHandler('projected', get_summary))
    app.add_handler(CommandHandler('add', add_entry))
    app.add_handler(CommandHandler('delete', remove_row))

    # Register message handler
    app.add_handler(MessageHandler(filters.TEXT, process_message))

    # Register error handler
    app.add_error_handler(log_error)

    print('Starting polling...')
    # Run the bot
    app.run_polling(poll_interval=2)

I also show my App Script of the Google Sheet below. I think the settings on the Google cloud console should be correct, I connected the Google Drive and Google Sheets API to the project, and created the 'credentials.json' file correctly.

var token = "MY_TOKEN";
var telegramUrl = "https://api.telegram.org/bot" + token;
var webAppUrl = "https://script.google.com/macros/s/AKfycbzxYOhndsh7SLgCeulgvIlm6dGVpl_kJKM9l1S6eT0_E_NebwtZ_F_zzxF2gLxPCH6l/exec";
var ssID = "1KE2sJTNXif1KNJot1m6hVhWEOggprIiwh1lj8wqOYLw";

function myFunction() {
  var url = telegramUrl + "/getMe";
  var response = UrlFetchApp.fetch(url);
  Logger.log(response.getContentText());
}

function setWebhook() {
  var url = telegramUrl + "/setWebhook?url=" + webAppUrl;
  var response = UrlFetchApp.fetch(url);
  Logger.log(response.getContentText());
}

function sendText(id,text) {
  var url = telegramUrl + "/sendMessage?chat_id=" + id + "&text=" + text;
  var response = UrlFetchApp.fetch(url);
  Logger.log(response.getContentText());
}

function doGet(e) {
  return HtmlService.createHtmlOutput("Hi there")
}

function doPost(e) {
  // this is where telegram works
  var data = JSON.parse(e.postData.contents);
  var text = data.message.text;
  var id = data.message.chat.id;
  var name = data.message.chat.first_name + " " + data.message.chat.last_name;
  var answer = "Hi " + name + ", thank you for your comment " + text;
  sendText(id,answer);
  SpreadsheetApp.openById(ssId).getSheets()[0].appendRow([new Date(),id,name,text,answer]);

  if(/^@/.test(text)) {
    var sheetName = text.slice(1).split(" ")[0];
    var sheet = SpreadsheetApp.openById(ssId).getSheetByName(sheetName) ? SpreadsheetApp.openById(ssId).getSheetByName(sheetName) : SpreadsheetApp.openById(ssId).insertSheet(sheetName);
    var comment = text.split(" ").slice(1).join(" ");
    sheet.appendRow([new Date(),id,name,comment,answer]);
  }
}
like image 655
Jin Siang Avatar asked Oct 30 '25 05:10

Jin Siang


1 Answers

I ran into this same problem yesterday. It took me a long time to figure it out, and in the end, I solved it in a really stupid way.

Telegram is currently having trouble with IPv6. I disabled IPv6 in the VPS config file, and everything worked fine.

Try this:

5. Problem with IPv6 and Telegram API

Some VPS hosting services use IPv6 by default. In October 2025, Telegram began to experience instability over IPv6, causing ConnectTimeout and start_tls.failed errors.

sudo nano /etc/sysctl.conf

Add at the end

net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
sudo sysctl -p
cat /proc/sys/net/ipv6/conf/all/disable_ipv6

# Should return: 1

Next, restart the bot and check the logs and performance.

like image 149
rendvi Avatar answered Oct 31 '25 18:10

rendvi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!