I'm trying to make a telegram bot using python, but for some reason it doesn't post the info to the telegram. my code is supposed to send a data frame to telegram as a table but it returns noting(even a error) when I call it from telegram.
from telegram.ext import Updater, InlineQueryHandler, CommandHandler
import requests
import re
import pandas as pd
def get_data():
data = pd.read_excel('C:/Users/admin/Desktop/data.xlsx')# opening xlsx file as the input
data = data.to_string(columns = ['c.1', 'c.2'], index = False, header = True, line_width = 70, justify = 'left')
return data
def result(bot, update):
data = get_data()
chat_id = update.message.chat_id
bot.send_message(chat_id=chat_id, table=data)
bot.send_photo(chat_id=chat_id, photo=data)
def main():
updater = Updater('Token key')
dp = updater.dispatcher
dp.add_handler(CommandHandler('result',result))
updater.start_polling()
updater.idle()
if __name__ == '__main__':
main()
Did you try to use the new CallbackContext? There should be an message linking to this page: https://github.com/python-telegram-bot/python-telegram-bot/wiki/Transition-guide-to-Version-12.0) when starting the bot. There it says:
Now on to the bulk of the change. You wanna change all your callback functions from the following:
def start(bot, update, args, job_queue):
# Stuff here
to the new style using CallbackContext
def start(update: Update, context: CallbackContext):
# Stuff here
# args will be available as context.args
# jobqueue will be available as context.jobqueue
I got it to work with a minimal example like this:
from telegram.ext import Updater, InlineQueryHandler, CommandHandler
def result(update, context):
print('result called')
data = 'mydata'
update.message.reply_text(data)
def main():
updater = Updater('Token', use_context=True)
dp = updater.dispatcher
dp.add_handler(CommandHandler('result',result))
updater.start_polling()
updater.idle()
if __name__ == '__main__':
main()
P.S.: You don't seem to use the requests and re from the imports.
Related
I want to make automation that gets a message from a group, that we'll call group A.
And send it into group B.
I should use Telegram API or Telegram BOTs to solve this?
And how i can solve this problem using python?
I was having this same problem and figured this out:
# imports
from telegram import Update
from telegram.ext import *
import telegram
from dotenv import load_dotenv
import os
# get the telegram bot api_key from environment file
load_dotenv()
API_KEY = os.getenv('API_KEY')
# you will need the groub_b_id saved as a global variable or
# in some other document
group_b_id = 1234567890
# create the bot, updater, and dispatcher
bot = telegram.Bot(token=API_KEY)
updater = Updater(API_KEY, use_context=True)
dp = updater.dispatcher
def get_chat_id(update: Update, context: CallbackContext):
# gets the chat_id of the current chat
global bot
chat_id = update.effective_chat.id
bot.send_message(chat_id, "This chat's id is: " + str(chat_id))
def auto_forward(update: Update, context: CallbackContext):
# automatically forwards messages from this chat to
# chat_b
global bot, group_b_id
chat_id = update.effective_chat.id
username = update.effective_message.from_user.name
chat_title = update.effective_message.chat.title
msg_txt = update.effective_message.text
bot.send_message(
group_b_id,
text=f"'{msg_txt}'\nwas just sent in chat {chat_title} by {username}"
)
# sets up the handlers
dp.add_handler(CommandHandler('get_chat_id', get_chat_id))
dp.add_handler(MessageHandler(Filters.text, auto_forward))
# Start the Bot
updater.start_polling()
updater.idle()
just make sure that you add the bot as an admin to both chats and this will work!
I am trying to add to a Telegram bot a timer which runs and sends a message every x time.
Getting always the error: x argument have not been supplied from the callback function, even though I am putting those arguments in the context argument when calling run_repeating.
The call to run_repeating:
context.job_queue.run_repeating(stupid_hello,
interval=30,
context={'bot': context.bot,'chat_id':update.message.chat_id},
first=datetime.time(hour=8),
last=datetime.time(hour=22))
callback function:
def stupid_hello(bot, chat_id):
bot.send_message(chat_id=chat_id ,text='Hello World')
And this is how I set the handler:
dp.add_handler(CommandHandler("start", start, pass_job_queue=True))
The run_repeating function is part of a "start" function.
--- EDIT ---
Adding code to reproduce it:
import logging
from re import sub
from typing import Set
import praw
from collections import Counter
from praw.models import MoreComments
import os
import datetime
from telegram import Update
from telegram.ext import Updater, CommandHandler, CallbackContext
import config
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO)
logger = logging.getLogger(__name__)
def stupid_hello(bot, chat_id):
bot.send_message(chat_id=chat_id ,text='Hello World')
def start(update: Update, context: CallbackContext):
context.job_queue.run_repeating(stupid_hello, interval=30,
context={'bot': context.bot, 'chat_id':update.message.chat_id},
first=datetime.time(hour=8),
last=datetime.time(hour=22))
def help(update, context):
"""Send a message when the command /help is issued."""
update.message.reply_text('/start, /top_ten_satoshi')
def error(update, context):
"""Log Errors caused by Updates."""
logger.warning('Update "%s" caused error "%s"', update, context.error)
def main():
"""Start the bot."""
# Create the Updater and pass it your bot's token.
# Make sure to set use_context=True to use the new context based callbacks
# Post version 12 this will no longer be necessary
updater = Updater(config.telegram_token, use_context=True)
# Get the dispatcher to register handlers
dp = updater.dispatcher
# on different commands - answer in Telegram
dp.add_handler(CommandHandler("start", start, pass_job_queue=True))
dp.add_handler(CommandHandler("help", help))
# log all errors
dp.add_error_handler(error)
# Start bot for local usage
updater.start_polling()
# Run the bot until you press Ctrl-C or the process receives SIGINT,
# SIGTERM or SIGABRT. This should be used most of the time, since
# start_polling() is non-blocking and will stop the bot gracefully.
updater.idle()
if __name__ == '__main__':
main()
If you want to reproduce it you will need to add a config.py with your own telegram bot token and send /start to the bot from telegram
I found the solution in Python Telegram Bot, unable to pass job queue?
I thought the problem was related with the run_repeating function when it was with the job_queue.
Hope this helps others having the same issue.
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, InlineQueryHandler
def sayhi(context):
context.bot.send_message(context.job.context, text="hi")
def time(update, context):
context.job_queue.run_repeating(sayhi, 5, context=update.message.chat_id)
def main():
updater = Updater('Token', use_context=True)
dp = updater.dispatcher
dp.add_handler(MessageHandler(Filters.text , time))
updater.start_polling()
updater.idle()
main()
As you can see the context keyword argument in run_repeating is referenced in the callback function as context.job.context which is the part I was missing
I have an issue with the Telegram bot (python-telegram-bot). I've made ConversationHandler, but the "fallbacks" won't work. Bot just ignores the "/stop " command. When I send "/stop" the bot sends me "First handler" instead of "GoodBye". What's wrong?
import os
import telegram
from telegram.ext import (ConversationHandler,
CommandHandler,
MessageHandler,
Filters,
Updater
)
from dotenv import load_dotenv
load_dotenv()
TELEGRAM_TOKEN = os.environ['TELEGRAM_TOKEN']
USER_ID = os.environ['USER_ID']
bot = telegram.Bot(token=TELEGRAM_TOKEN)
updater = Updater(token=TELEGRAM_TOKEN)
def start(update, context):
context.bot.send_message(chat_id=update.effective_chat.id,
text='hi')
return 1
def stop(update, context):
context.bot.send_message('Good Bye')
return ConversationHandler.END
def first_handler(update, context):
context.bot.send_message(chat_id=update.effective_chat.id,
text='First handler')
return 1
conv_handler = ConversationHandler(
entry_points=[CommandHandler('Start', start)],
states={
1: [MessageHandler(Filters.text, first_handler,
pass_user_data=True)],
},
fallbacks=[CommandHandler('stop', stop)]
)
dispatcher = updater.dispatcher
dispatcher.add_handler(conv_handler)
updater.start_polling()
updater.idle()
According to the documentation, the MessageHandler(Filters.text, ...) is handling all text messages, including the /stop command. However, fallbacks are only being triggered if none of the above handlers were able to deal with the message.
You may exclude commands from the MessageHandler:
MessageHandler(
Filters.text & (~ Filters.command),
first_handler,
)
The syntax for combining filters is documented here.
I'm experiencing a small issue with the library python-telegram-bot.
So this is my code:
from __future__ import unicode_literals
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
from telegram.ext import CommandHandler, CallbackQueryHandler, CallbackContext
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ReplyKeyboardMarkup
from telegram import Update
from telegram import Bot
import telegram
import os
import datetime
import sqlite3
import traceback
import re
import data
def start(update, context):
chatid = update.message.chat_id
if data.user_exist(chatid) == True:
update.message.reply_text('Choiche wallet', reply_markup=wallet_handler(chatid, update, context))
if data.user_exist(chatid) == False:
update.message.reply_text('Add wallet')
add_wallet(chatid, update, context)
def wallet_handler(chatid, update, context):
kb = []
for w in data.fetch_wallet(chatid):
s = w[0:10]
kb.append([InlineKeyboardButton(s, callback_data=w)])
kb.append([InlineKeyboardButton('Add Wallet', callback_data='add')])
kb.append([InlineKeyboardButton('Delete Wallet', callback_data='delete')])
return InlineKeyboardMarkup(kb)
def add_wallet(chatid, update, context):
regex = re.compile(r"/^(?:0x)[A-Z0-9]{15}$/")
update.message.reply_text(text='Insert a wallet address please')
address = update.message.text
print(address)
if re.fullmatch(regex, address):
print('okay')
else:
print('nooo')
return
def main():
update= Updater('token', use_context=True)
bot = Bot('token')
disp=update.dispatcher
disp.add_handler(CommandHandler('start', start))
disp.add_handler(MessageHandler(Filters.regex('/^(?:0x)[A-Z0-9]{15}$/'), add_wallet, run_async=True))
update.start_polling()
update.idle()
if __name__=='__main__':
main()
When the user send the /start command, the function user_exist() check a determined condition. If the function returns false, then the bot should wait for user input (triggering the function add_wallet()).
But when I try this code, the add_wallet() function takes as user input the previous message /start and doesn't wait for the user input.
How to fix it? Thanks
I copied this code from another thread as is, but was unable to get it to work...
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, InlineQueryHandler
def sayhi(bot, job):
job.context.message.reply_text("hi")
def time(bot, update,job_queue):
job = job_queue.run_repeating(sayhi, 5, context=update)
def main():
updater = Updater('BotKey')
dp = updater.dispatcher
dp.add_handler(MessageHandler(Filters.text , time,pass_job_queue=True))
updater.start_polling()
updater.idle()
if __name__ == '__main__':
main()
The Error I was give in my command terminal is:
TypeError: time() missing 1 required positional argument: 'job_queue'
I found this strange as I thought I already had set pass_job_queue=True...
(also, I did change the BotKey to the required key. I can get my bot to reply to texts but cant get it to periodically send stuff...)
pass_job_queue was deprecated in version 12.0.0, Tutorial to switch version here
You need to use context based callbacks, like in this example.
Here's your code changed:
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, InlineQueryHandler
def sayhi(context):
context.bot.send_message(context.job.context, text="hi")
def time(update, context):
context.job_queue.run_repeating(sayhi, 5, context=update.message.chat_id)
def main():
updater = Updater('Token', use_context=True)
dp = updater.dispatcher
dp.add_handler(MessageHandler(Filters.text , time))
updater.start_polling()
updater.idle()
main()