Please tell me how you can call the bot's response to any message in the feedback bot. By example:
User: /start
Bot: Welcome message (Hello)
User: any message
Bot: Feedback message (Expect an answer)
I tried to do it through the echo function, but most likely I made a mistake somewhere.
I am attaching the code:
main.py:
from telegram.ext import Updater
from handlers import setup_dispatcher
from settings import TELEGRAM_TOKEN
# Setup bot handlers
updater = Updater(TELEGRAM_TOKEN)
dp = updater.dispatcher
dp = setup_dispatcher(dp)
updater.start_polling()
updater.idle()
settings.py:
import os
from dotenv import load_dotenv, find_dotenv
# Loading .env variables
load_dotenv(find_dotenv())
TELEGRAM_TOKEN = "HERE TELEGRAM TOKEN"
TELEGRAM_SUPPORT_CHAT_ID = "HERE CHAT ID"
TELEGRAM_SUPPORT_CHAT_ID = int(TELEGRAM_SUPPORT_CHAT_ID)
WELCOME_MESSAGE = os.getenv("WELCOME_MESSAGE", "Hi 👋")
FEEDBACK_MESSAGE = os.getenv("FEEDBACK_MESSAGE", "Expect an answer👋")
REPLY_TO_THIS_MESSAGE = os.getenv("REPLY_TO_THIS_MESSAGE", "REPLY_TO_THIS")
WRONG_REPLY = os.getenv("WRONG_REPLY", "WRONG_REPLY")
handlers.py:
import os
from telegram import Update
from telegram.ext import CommandHandler, MessageHandler, Filters, CallbackContext
from settings import WELCOME_MESSAGE, TELEGRAM_SUPPORT_CHAT_ID, REPLY_TO_THIS_MESSAGE, WRONG_REPLY
def start(update, context):
update.message.reply_text(WELCOME_MESSAGE) # response to /start
user_info = update.message.from_user.to_dict()
context.bot.send_message(
chat_id=TELEGRAM_SUPPORT_CHAT_ID,
text=f"""
📞 Connected {user_info}.
""",
)
def echo(update: Update, context: CallbackContext):
update.message.reply_text(FEEDBACK_MESSAGE) # there should be a response to any message "Expect an answer"
def forward_to_chat(update, context):
forwarded = update.message.forward(chat_id=TELEGRAM_SUPPORT_CHAT_ID)
if not forwarded.forward_from:
context.bot.send_message(
chat_id=TELEGRAM_SUPPORT_CHAT_ID,
reply_to_message_id=forwarded.message_id,
text=f'{update.message.from_user.id}\n{REPLY_TO_THIS_MESSAGE}'
)
def forward_to_user(update, context):
user_id = None
if update.message.reply_to_message.forward_from:
user_id = update.message.reply_to_message.forward_from.id
elif REPLY_TO_THIS_MESSAGE in update.message.reply_to_message.text:
try:
user_id = int(update.message.reply_to_message.text.split('\n')[0])
except ValueError:
user_id = None
if user_id:
context.bot.copy_message(
message_id=update.message.message_id,
chat_id=user_id,
from_chat_id=update.message.chat_id
)
else:
context.bot.send_message(
chat_id=TELEGRAM_SUPPORT_CHAT_ID,
text=WRONG_REPLY
)
def setup_dispatcher(dp):
dp.add_handler(CommandHandler('start', start))
dp.add_handler(MessageHandler(Filters.chat_type.private, forward_to_chat))
dp.add_handler(MessageHandler(Filters.chat(TELEGRAM_SUPPORT_CHAT_ID) & Filters.reply, forward_to_user))
return dp
I will be very grateful for your help
Thanks to Aditya Yadav for the advice :)
Additionally, I researched the documentation, regarding the dialog handler part of the library I use. The following solution was found:
Rewrite the def echo and def forward_to_chat functions, combining them.
def echo_forward_handler(update, context):
text = 'Expect an answer'
context.bot.send_message(chat_id=update.effective_chat.id,
text=text)
forwarded = update.message.forward(chat_id=TELEGRAM_SUPPORT_CHAT_ID)
if not forwarded.forward_from:
context.bot.send_message(
chat_id=TELEGRAM_SUPPORT_CHAT_ID,
reply_to_message_id=forwarded.message_id,
text=f'{update.message.from_user.id}\n{REPLY_TO_THIS_MESSAGE}'
)
The necessary dispatcher was also formed at the end:
def setup_dispatcher(dp):
dp.add_handler(MessageHandler(Filters.text & (~Filters.command) & Filters.chat_type.private, echo_forward_handler))
return dp
Thus, the task that was set in the condition was solved.
Related
I've created a bot to gather information in which users will forward messages to the bot from any other telegram chat/channel/group.
The forwarded messages can be of types video,photo,audio and url or any combination of these.
Below is where I am looking at:
https://core.telegram.org/bots/api#available-types
Right now I have (on Python)—>
#bot.message_handler(content_types=["video", "photo", "audio", "link"])
def send_welcome(message):
bot.reply_to(message, "got it")
BUT since there is no link content type, when the user forwards only a link, this doesn't work.
I'm looking for some property like forward_status = True if it exists.
According to the line #bot.message_handler(content_types=["video", "photo", "audio", "link"]) I suppose you are using pyTelegramBotAPI
This package allows you to create custom filters. Here you can find examples of how to create your own filters and how to register them. Actually, the package already has such filter - telebot.custom_filters.ForwardFilter (docs, source code)
Instancemessage.message_id is used to store a specific message ID in a certain user chat, then your bot should forward any message content of media, link, text or another available type, you could try whatever the bot configuration have to integrate these functions just as a simple demostration of your problem and different options from message, check message test for additional information.
image
import logging
from telegram import __version__ as TG_VER
try:
from telegram import __version_info__
except ImportError:
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
if __version_info__ < (20, 0, 0, "alpha", 1):
raise RuntimeError(
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
f"{TG_VER} version of this example, "
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
)
from telegram import ForceReply, Update
from telegram.ext import Application, CommandHandler, ContextTypes, MessageHandler, filters
# Enable logging
logging.basicConfig(
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
)
logger = logging.getLogger(__name__)
# Define a few command handlers. These usually take the two arguments update and
# context.
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Send a message when the command /start is issued."""
user = update.effective_user
await update.message.reply_html(
rf"Hi {user.mention_html()}!",
reply_markup=ForceReply(selective=True),
)
async def forward_msg(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
await context.bot.forward_message(chat_id=update.effective_chat.id,
from_chat_id=update.effective_chat.id,
message_id=update.message.message_id)
def main() -> None:
"""Start the bot."""
# Create the Application and pass it your bot's token.
application = Application.builder().token("ID").build()
# on different commands - answer in Telegram
application.add_handler(CommandHandler("start", start))
messages_handler = MessageHandler(filters.TEXT, forward_msg)
application.add_handler(messages_handler)
# Run the bot until the user presses Ctrl-C
application.run_polling()
if __name__ == "__main__":
main()
I have found a workaround since I've decided to collect forwarded messages in text format as well.
#dp.message_handler(content_types = ['text'], is_forwarded = True)
async def check(message):
await message.reply("yay")
This will identify any forwarded messages in the text format.
hi and thanks for your answer. i want to create a bot for forward message to my channel and delete the last message every 1 minute
i made that but i have some problem for removing the last message. i cant get the last message id from my channel to the bot.
my source is:
from telegram.bot import Bot
from telegram.update import Update
from telegram.ext.updater import Updater
from telegram.ext.callbackcontext import CallbackContext
from telegram.ext.messagehandler import MessageHandler
from telegram.ext.filters import Filters
from telegram.chataction import ChatAction
from time import sleep
import telegram_send
import socket
import telegram
import json
api_key="My API Key"
user_id = "My User Id"
updater = Updater(api_key, use_context=True)
bot = telegram.Bot(token=api_key)
def echo(update: Update, context: CallbackContext):
context.bot.send_chat_action(chat_id=update.effective_chat.id, action=ChatAction.TYPING)
sleep(60)
if update.message['photo'] == []:
bot.send_message(chat_id=user_id, text=update.message.text)
else:
fileID = update.message['photo'][-1]['file_id']
context.bot.sendPhoto(chat_id = user_id,caption=update.message['caption'],photo = fileID)
msg_id = update.message._id_attrs[]
#------------- And Also i user that too -------------
#msg_id=update.message.message_id
#------------- -------------
context.bot.delete_message(chat_id=user_id, message_id=msg_id)
update.effective_chat
update.effective_user
update.effective_message
print(json.dumps(update.to_dict(), indent=2))
dp = updater.dispatcher
dp.add_handler(MessageHandler(Filters.document | Filters.photo, echo))
dp.add_handler(MessageHandler(Filters.text, echo))
updater.start_polling()
and when i use that code this error will show:
The message_id that you want to remove is not exist....
actually i type a message id in manually for delete message and it was work
but i want to delete that message auto
please help me to do that. thanks
I fixed That With Python-Telegram-Bot Version 20
Read This Docs:
https://docs.python-telegram-bot.org/en/v20.0a2/
import asyncio
from pyrogram import Client
from pyrogram.errors import PeerFlood
import time
api_id = 12905662
api_hash = "a7cfcd44cb95d26d7529d547c9a1d9ef"
vubor = input('Напишите "1" для парсинга, "2" для рассылки! ')
text = input('Текст для рассылки: ')
account = ['my_accont1', 'my_accont2', 'my_accont3', 'my_accont4', 'my_accont5', 'my_accont6', 'my_accont7',
'my_accont8', 'my_accont9']
async def main():
if vubor == '1':
user = []
with open('username.txt', 'r') as file:
for users in file.readlines():
y = users.strip()
user.append(y)
for acc in account:
try:
async with Client(f"{acc}", api_id, api_hash) as app:
for all_user in user[0:500]:
time.sleep(5)
await app.send_message(all_user, text)
user.remove(all_user)
except PeerFlood:
print('Аккаунт заблокировн')
asyncio.run(main())
pyrogram.errors.exceptions.bad_request_400.PeerIdInvalid: Telegram says: [400 PEER_ID_INVALID] - The peer id being used is invalid or not known yet. Make sure you meet the peer before interacting with it
Firstly, please learn how to ask a good question.
Secondly, your error message is already clear, you have to
Make sure you meet the peer before interacting with it
This means your session has to receive a message from them directly or via a shared chat, or have your session see any update to do with them in general.
I'm looking for a way for a bot to wait for a reply from a user after a command. For example, you first type "/ask", then the bot waits for a plain message (not a command) from the user and after the user replies is stores his/her reply in a variable
I'm sure this is quite simple, but all the tutorials I've seen are in Russian and the documentation for python-telegram-api is very chaotic and I'm not the most advanced
If I'm dumb, sorry, just please help a fellow beginner out
Okay, this was pointless. I thought you couldn't use arguments, but the post I read was 5 years old so... I'm stupid. I just used arguments instead, thanks for the help tho, really appreciate it
here's the code that takes user's input and stores it in the "store_user_input" variable.
import logging
from telegram.ext import Updater,
CommandHandler, MessageHandler, Filters,
CallbackContext
from telegram import Update
logging.basicConfig(
format='%(asctime)s - %(name)s - %
(levelname)s - %(message)s',
level=logging.INFO
)
logger = logging.getLogger(__name__)
# function to handle the /start command
def startcommand(update:Update, context:
CallbackContext) -> None:
first_name = update.message.chat.first_name
update.message.reply_text\
(
f'Welcome to the bot, {first_name},
what are you interested in?'
)
# function to handle and store user input
def text(update:Update, context:
CallbackContext) -> None:
text_received = update.message.text
store_user_input = text_received
# function to handle the /help command
def helpcommand(update:Update, context:
CallbackContext) -> None:
update.message.reply_text('Here is a list of
all available commands:\n '
'/start - start the
bot\n'
'/help - get all
available commands\n')
# function to handle errors occured in the
dispatcher
def errormsg(update:Update, context:
CallbackContext) -> None:
update.message.reply_text('An error
occured.')
# main function
def main():
# "bot_data is your .txt file with bot API token"
fo = open("bot_data")
fr = fo.read()
updater = Updater(fr)
dispatcher = updater.dispatcher
# add handlers for start and help commands
dispatcher.add_handler(CommandHandler("start", startcommand))
dispatcher.add_handler(CommandHandler("help", helpcommand))
# add an handler for normal text (not commands)
dispatcher.add_handler(MessageHandler(Filters.text, text))
# add an handler for errors
dispatcher.add_error_handler(errormsg)
# start bot
updater.start_polling()
# run the bot
updater.idle()
if __name__ == '__main__':
main()
You can check the value by adding:
print("store_user_input")
after store_user_input line.
I am trying to compile some python code and run it as a telegram bot.
When I run it on VS Code or in the CMD console (python main.py) it freezes.
However, when I broke up the code individually and run, it works well.
1) Can any PyGod point out where im doing wrong?
2) I realised this happens when I try to redeploy a telegram bot too. Anyone have ideas on this?
from telegram.ext import Updater, InlineQueryHandler, CommandHandler
from telegram.ext.dispatcher import run_async
import requests
import re
def get_url():
contents = requests.get('https://dog.ceo/api/breed/retriever/golden/images/random').json()
url = contents['message']
return url
def get_image_url():
allowed_extension = ['jpg','jpeg','png']
file_extension = ''
while file_extension not in allowed_extension:
url = get_url()
file_extension = re.search("([^.]*)$",url).group(1).lower()
return url
#run_async
def goodboy(update, context):
url = get_image_url()
chat_id = update.message.chat_id
context.bot.send_photo(chat_id=chat_id, photo=url)
def main():
updater = Updater('YOUR_TOKEN', use_context=True)
dp = updater.dispatcher
dp.add_handler(CommandHandler('goodboy',goodboy))
updater.start_polling()
updater.idle()
if __name__ == '__main__':
main()