Message from a telegram bot without a command(python) - python

I want to send a Message(call a function) every day at a given Time. Sadly this is not possible with message.reply_text('Test'). Is there any way i can do this? I could not find anything.
This is my current code:
import telegram.ext
from telegram.ext import CommandHandler, MessageHandler, Filters
import schedule
import time
API_KEY = 'XXXXXXXXXXX'
updater = telegram.ext.Updater(API_KEY)
dispatcher = updater.dispatcher
def start(update, context):
update.message.reply_text('Welcome!')
# problem:
def Test(update, context):
update.message.reply_text('Works!!!')
# running special functions every Day at a given Time
schedule.every().day.at("10:00").do(Test)
while True:
schedule.run_pending()
time.sleep(1)
def main():
# add handlers for start and help commands
dispatcher.add_handler(CommandHandler("start", start))
# start your bot
updater.start_polling()
# run the bot until Ctrl-C
updater.idle()
The schedule part works, I just don`t know how to send this Message.
Thanks for your help!

Update object, inside of the message field, has the from field which is a User Telegram object containing the user's ID.
Once you have the user's ID, you can use the sendMessage method in order to reply him easily.
To conclude, instead of:
update.message.reply_text('Welcome!')
You could do like so:
user_id = update.message.from.id
updater.sendmessage(chat_id=user_id, text="Welcome!")

Related

Sending a message with a python telegram bot without a command from the user?

Is there a way to send a message (call a function), without a command from the bot's user? For example when a certain condition is met?
Currently I have only been able to call a function with a command.
I have been trying the following:
from telegram.ext import Updater, CommandHandler, CallbackContext
from telegram import Update
from datetime import datetime
import telebot as tb
import logging
bot = tb.TeleBot(API_KEY)
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)
logger = logging.getLogger(__name__)
def messager(update: Update, context: CallbackContext) -> None:
"""this function messages at a specific time"""
update.message.reply_text("message back")
if __name__ == "__main__":
updater = Updater(API_KEY)
dispatcher = updater.dispatcher
dispatcher.add_handler(CommandHandler("message", messager))
condition = False #I have been changing this when testing
if (condition == True):
messager() # how to call messager here? how to pass update and context arguments?
updater.start_polling()
updater.idle()
Any possible way to achieve this would be great.
You cannot call a function using update and context since there is no update from the telegram servers to act on. In other words there is no event to perform a callback on.
Depending on what you want to do you could use a MessageHandler instead of a CommandHandler to reply to any message with Filters to filter out which ones to reply to
or if you want to send a message every time you start your bot and you know who to send a message to (i.e you have their chat_id) you can do
if condition:
updater.bot.send_message(chat_id=CHAT_ID, text="message back")
or if you just want to send a message every time some user starts a chat with your bot you could use the start command which is sent by default to start a chat with a bot

Telegram bot: getting 'The following arguments have not been supplied' error

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

How to correctly send messages daily in telegram bot?

I have a problem using the job_queue and run daily messages in my telegram bot. I have already read and tried every answer I have found in stack overflow and online, but somehow nothing works and I don't know what's wrong.
I want to send a message daily, but only after the /start command, and I want to shut down the bot and the scheduled messages with the /stop command. I am using version 13.5. Here's the code at the moment:
import logging, os, random, sys, random, datetime
from telegram import ParseMode, Update
from telegram.ext import Updater, CommandHandler, CallbackContext
...
def callback_daily(context: CallbackContext):
context.bot.send_message(
text="DAILY TEXT",
parse_mode=ParseMode.HTML
)
def start_handler(update: Update, context: CallbackContext):
context.bot.run_daily(callback_daily,
days=(0,1,2,3,4,5,6),
time=datetime.time(hour=20, minute=00, tzinfo=pytz.timezone("Europe/Rome")),
context=update.message.chat_id
)
update.message.reply_text(
"STARTED"
)
if __name__ == '__main__':
logger.info("### Starting Bot ###")
updater = Updater(TOKEN, use_context=True)
updater.dispatcher.add_error_handler(CommandHandler("error", error_handler))
updater.dispatcher.add_handler(CommandHandler("start", start_handler, pass_job_queue=True))
updater.dispatcher.add_handler(CommandHandler("help", help_handler))
...
run(updater)
logger.info("### Bot Started ###")
What I get at the moment is:
AttributeError: 'Bot' object has no attribute 'run_daily'
I have tried also many other things found here in Stackoveflow, so many that I don't even remember them, and somehow every answer shows a different method to run scheduled message (and not even one works at the moment).
What am I doing wrong here?

Getting updates inside a function (Telegram bot, Python3, python-telegram-bot library)

I'm trying to make a telegram bot with https://github.com/python-telegram-bot/python-telegram-bot library in python3.
I want to make a message sender bot. This is my code now:
#!/usr/bin/env python
"""#==============================# Imports #==============================#"""
import logging, time, telegram
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
from datetime import datetime
"""#==============================# Enable logging #==============================#"""
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.WARN)#DEBUG)
logger = logging.getLogger(__name__)
"""#==============================# Log error #==============================#"""
def error(update, context):
#Log Errors caused by Updates.
logger.warning("Update '%s' caused error '%s'", update, context.error)
"""#==============================# Bot commands #==============================#"""
def start(update, context):
update.message.reply_text("Bot joined the conversation!")
def get_additional_updates(update, message):
***My Problem***
"""#==============================# MAIN #==============================#"""
def main():
updater = Updater("<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)
dp.add_handler(CommandHandler("send", get_additional_updates)
# log all errors
dp.add_error_handler(error)
# Start the Bot
updater.start_polling()
updater.idle()
if __name__ == '__main__':
main()
I don't know what should I do to get the updates inside the 'get_additional_updates' function.
What I want to do, is: I type /send, after this the bot waits for my message, I type my message in and send it. The problem is, that I can't figure it out how to get the second message (the message itself) to the 'get_additional_updates' function.
I can't find it in the documentation, and I'm very new to programming as well.
Please help me with the code I need to type there in order to get the additional messages.
Let me know if you can't understand what is my question, I'll try to explain better.
Thanks a lot!
P.S.:Sorry, if my english is bad, I'm trying to upgrade that as well.
You should use conversation bot ,Check the example here

Getting one message using the telegram python API?

I want to create a telegram bot that, after seeing the command /define, asks for the word.
I want to extract the word sent by the user after the bot asks for it. How do I do it?
import telegram
from telegram.ext import Updater
from telegram.ext import MessageHandler, Filters
from telegram.ext import CommandHandler
updater = Updater(token='******************')
dispatcher = updater.dispatcher
def define(bot, update):
bot.send_message(chat_id=update.message.chat_id, text="Enter word")
word = '''get content of following message'''
definition = get_definition(word)
bot.send_message(chat_id=update.message.chat_id, text=definiton)
definition_handler = CommandHandler('define', define)
dispatcher.add_handler(definition_handler)
updater.start_polling()
First of all, you require pyTelegramBotAPI library;
Then, you want to add #BotFather in Telegram and follow the instructure #6. You need to obtain the bot token which is a unique set of letters and digits for your bot, just like a codename. After you have registered a bot via #BotFather, it will give you the token.
Actually, the token is the only thing you need to create any bot you want. The codes for the bot like yours should follow the same logic structure:
# -*- coding: utf-8 -*-
import telebot # importing pyTelegramBotAPI library
import time
import sys
bot = telebot.Telebot(token='YOUR API TOKEN') # supply your future bot with the token you have received
#bot.message_handler(commands=['define', 'Define'])
def echo_msg(message):
echo = bot.send_message(chat_id=message.chat.it,
text='What word would you want me to extract, sir?')
bot.register_next_step_handler(message=echo, callback=extract_msg)
def extract_msg(message):
msg.append(message.text)
print(msg)
def main_loop():
bot.polling(none_stop=True)
while True:
time.sleep(1)
if __name__ == '__main__':
try:
main_loop()
except KeyboardInterrupt:
print(sys.stderr '\nExiting by user request'\n')
sys.exit(0)
Okay, each bot requires a message_handler to process the incoming information.
In your case, it is a command that triggers the bot to ask for a word to extract into a list. If you do not define bot.register_next_step_handler(), this command will not do any action at all (except the fact it asks for a word).
The function extract_msg() appends the next word written by a user and prints out the msg list into your console.
The function main_loop() runs the bot until suspension and provokes it to idle for a second after each word extraction. To stop the bot, press Ctrl + C.
I hope that suffices. The next step would be to track the person who types /define or /Define and extract his/her word request. Also, it would be better to make msg list more descriptive, or implement absolutely different extraction method. This one is simply informative and hardly applicable in practice.
I fixed an error in when calling stderr:
# -*- coding: utf-8 -*-
import telebot # importing pyTelegramBotAPI library
import time
import sys
bot = telebot.Telebot(token='YOUR API TOKEN') # supply your future bot with the token you have received
#bot.message_handler(commands=['define', 'Define'])
def echo_msg(message):
echo = bot.send_message(chat_id=message.chat.it,
text='What word would you want me to extract, sir?')
bot.register_next_step_handler(message=echo, callback=extract_msg)
def extract_msg(message):
msg.append(message.text)
print(msg)
def main_loop():
bot.polling(none_stop=True)
while True:
time.sleep(1)
if __name__ == '__main__': try:
main_loop() except KeyboardInterrupt:
print(sys.stderr('\nExiting by user request'\n'))
sys.exit(0)

Categories

Resources