Python-Telegram-Bot ConversationHandler unable to receive Message - telegram

I am using the Python-Telegram-Bot Package. My telegram bot is unable to receive a message at state FIRST. After sending my bot /start , I am prompted the text message as shown in start_command. However, after sending a url to the bot, the bot is unable to receive the message as seen in the 'single tick' at the bottom right of my message.
# Stages
FIRST, SECOND = range(2)
def start_command(update: Update, context: CallbackContext):
update.message.reply_text("""
To use:
1. Send the google sheets URL and sheet name to this telegram bot in the following format:
your_google_sheets_url (your_sheet_name)
""")
global user_id
user_id = update.message.from_user['id']
return FIRST
def select(update: Update, context: CallbackContext):
if update.message.text:
user_input = update.message.text
update.message.reply_text('I have received your Google Sheets!')
reply_markup = InlineKeyboardMarkup(build_menu(button_list, n_cols=1))
update.message.reply_text('Please choose the headers:', reply_markup=reply_markup)
return SECOND
dp = updater.dispatcher
dp.add_handler(CommandHandler("start", start_command))
conv_handler = ConversationHandler(
entry_points=[CommandHandler('start', start_command)],
states={
FIRST: [MessageHandler(Filters.text, select)],
SECOND: [CallbackQueryHandler(display)],
},
fallbacks=[CommandHandler('cancel', cancel)],
)
dp.add_handler(conv_handler)

the CommandHandler for start should not be added. This is because when the user inputs /start, the CommandHandler is called to handle the command instead of the ConversationHandler.

Related

How do I mark a message as read?

How do I mark a message as read?
app = Client(session_name, api_id, api_hash)
#app.on_message()
async def my_handler(client, message):
await app.send_message(message.from_user.username, "ok boss")
await app.read_chat_history(message.from_user.username)
app.run()
I expected the bot's message to be ticked that he had read it
Client.read_chat_history()
Mark a chat’s message history as read.
Usable by
[X] Users
[ ] Bots
Parameters:
chat_id (int | str) – Unique identifier (int) or username (str) of the target chat. For your personal cloud (Saved Messages) you can simply use “me” or “self”. For a contact that exists in your Telegram address book you can use his phone number (str).
max_id (int, optional) – The id of the last message you want to mark as read; all the messages before this one will be marked as read as well. Defaults to 0 (mark every unread message as read).
Returns:
bool - On success, True is returned.
EXAMPLE
# Mark the whole chat as read
await app.read_chat_history(chat_id)
# Mark messages as read only up to the given message id
await app.read_chat_history(chat_id, 12345)
I expected the bot's message to be ticked that he had read it
This is not possible, messages send by a Telegram Bot will never get those checkmarks.
Those marks are only for messages send from a user-account

Telegram Bot Python Inlinekeyboardmarkup does not work for all users in a group

I want to respond when someone sends the /start comand and display a text with a like/dislike button in a group.
Here is my sample code:
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import (
Updater,
CommandHandler,
CallbackQueryHandler,
ConversationHandler)
import logging
FIRST, SECOND = range(2)
keyboard = [[InlineKeyboardButton('👍', callback_data='0'),
InlineKeyboardButton('👎', callback_data='2')]]
def start(update, context):
reply_markup = InlineKeyboardMarkup(keyboard)
update.message.reply_text(
'Test Message\n',
reply_markup=reply_markup
)
return FIRST
def main():
updater = Updater(
'TOKEN', use_context=True)
dp = updater.dispatcher
conv_handler = ConversationHandler(
entry_points=[CommandHandler('start', start)],
states={
FIRST: [CallbackQueryHandler(a, pattern='^'+str(0)+'$'),
CallbackQueryHandler(b, pattern='^'+str(2)+'$')]
},
fallbacks=[CommandHandler('start', start)]
)
dp.add_handler(conv_handler)
updater.start_polling()
updater.idle()
if __name__ == "__main__":
main()
The callbacks only work for the user who sent the /start command. Other users cannot click the button or there is no callback. if another user sends a /start command, both like/dislike buttons of both posts of the bot work for the two users.
Where is the mistake?
I want every user to be able to press the buttons and it triggers a callback. regardless of whether the user has ever sent the /start command
I am thankful for every help.
The issue here is that by default conversations are per user - please also see this faq entry for details.
For your use case, I doubt that a ConversationHandler gives you any benefit. I would just register the CommandHandler and the CallbackQueryHandler independently.
Disclaimer: I'm currently the maintainer of python-telegram-bot.

Messenger bot with checkbox plugin how to keep track of the conversation with user ref and user id

We'd like to add the facebook messenger checkbox plugin at the end of a request form so users can opt-in for notifications via messenger.
When the user opts in, our webhook receives a callback with the user_ref that we set in the form.
We send a confirmation of opt-in to this user_ref
But other messages we receive like delivery, read receipt or actual messages from the user do contain the user ref anymore but the user id.
This is the official documentation of facebook:
After you receive the callback event, you can call the Send API to start messaging the user using the user_ref identifier in recipient as shown below. Note that this field is the same as the unique user_ref param used before when the plugin was rendered and in confirming the opt-in.
If the call to the Send API is successful, the response will contain a recipient_id parameter, which is a stable user ID that you can now use in future API calls.
Therefore it's impossible to keep track between the initial message and new ones. Does anyone found a solution for this?
Thank you very much in advance.
You can, for example, send additional information when the user opts in using the optional ref parameter. You can send the username of the user logged on my website:
function confirmOptIn() {
FB.AppEvents.logEvent('MessengerCheckboxUserConfirmation', null, {
'app_id':'APP_ID',
'page_id':'PAGE_ID',
'ref': 'myuser#mywebsite.com',
'user_ref':'UNIQUE_REF_PARAM'
});
You will receive the username within optin in your webhook event:
{
"recipient":{
"id":"PAGE_ID"
},
"timestamp":1234567890,
"optin":{
"ref":"myuser#mywebsite.com",
"user_ref":"UNIQUE_REF_PARAM"
}
}
Then, you can call the Send API to start messaging the user using the user_ref.
If the call to the Send API is successful, the response will contain a recipient_id parameter, which is a stable user ID that you can now use in future API calls.
...so you will received the Messenger ID which you can map to the username of your website you already have. Here, I modified a little the example from the official developers site to call the send API with user_ref and map the user ID I get in the response to the username of my website:
function callSendAPICheckbox(messageData, userApplicationId) {
((userApplicationId) => {
request({
uri: 'https://graph.facebook.com/v2.6/me/messages',
qs: {
access_token: PAGE_ACCESS_TOKEN
},
method: 'POST',
json: messageData
},
function(error, response, body) {
if (!error && response.statusCode == 200) {
var recipientId = body.recipient_id;
var messageId = body.message_id;
if (messageId) {
console.log("Map messenger user ID %s with the username of my website %s", recipientId, userApplicationId);
} else {
console.log("Successfully called Send API for recipient %s",
recipientId);
}
} else {
console.error("Failed calling Send API for userId " +
recipientId, response.statusCode, response.statusMessage, body.error);
}
});
})(userApplicationId)
}
Why don't you make use of metadata field of sendTextMessage. Each and every message you send to your user, you send the metadata too, and when you receive response of the message being delivered, you find the metadata field in it.
Here is what I do:
When user select the checkbox plugin and event is triggered I receive the call on my server, check if it contains user_ref. If it does, then I send a text message to user with a custom metadata using user_ref. When user receives the message, the webhook send me a json data as mentioned in the documentation. To identify for which user_ref I have received this response, I set custom metadata which is combination of some string + user_ref before sending the message to user using user_ref. Using this custom metadata I identify the sender.id of the user for which I previously sent message using user_ref. The sender.id is my pageid and recipient.id the the user id which you are trying to get and using which we generally send message to the user and is also know as psid.
Above if just the logical part mentioned which I usually do.
For detail solution along with code, I have already posted it here:

How to get a Telegram Channel Id without sending a message to it

Is there any way to find a telegram channel id without sending a message to it ?
Right now I go this way and find the channel id by calling this URL in my code and get the JSON as result:
https://api.telegram.org/bot???????/sendMessage?chat_id=#?????&text=123
However, this cause sending the message "123" to the channel which is not good.
Check this link for help.
It is using web telegram url param info.
Adding details from the referred link:
log in web telegram
Click on the target channel then you will find the url displayed on your browser.
If it's a public channel, the ID is #name of the channel.
If it's a private channel then the url must be similar to:
https://web.telegram.org/#/im?p=c1018013852_555990343349619165
For this case, the channel ID would be 1018013852.
It's important to know that channel's IDs are always negative and 13 characters long!
So add -100 to it, making the correct ID -1001018013852.
You Can use Web Telegram to see each channel id in link of that page in your explorer
or
Just Simply Forward a message from your channel to This Bot: (https://telegram.me/getidsbot)
Yes, just forward a message of the channel to your bot and get the message.forward_from_chat.id.
Get your channel link
install python library telethon
get your api_id and api_hash here.
write the following code and run:
from telethon import TelegramClient
api_id=
api_hash=
channel_link = 'your_channel_link'
client = TelegramClient(session_name, api_id, api_hash,
update_workers=4, spawn_read_thread=False)
client.start()
entity = client.get_input_entity(**channel_link**)
print(entity.channel_id)
By the way, if you use it for telegram bot, just add -100 before the printed id, this should be work!
You Don't Need to get Channels ID .
simple send Message with Channel User Like : #channel
Fixing #scruel's answer:
In [1]: api_id = ...
In [2]: api_hash = '...'
In [3]: channelLink = 'https://t.me/BTCST_Community_EN'
In [4]: from telethon import TelegramClient, events
In [5]: client = TelegramClient('test', api_id, api_hash)
In [6]: client.start()
Out[6]: <telethon.client.telegramclient.TelegramClient at 0x7fc90c352290>
In [7]: entity = await client.get_entity(channelLink)
In [8]: channelId = '-100' + str(entity.id)
In [9]: channelId
Out[9]: '-1001236496320'
Here's a CLI util to do it:
#!env/bin/python
import sys
import asyncio
from telethon import TelegramClient
import config
async def channel_id_from_link(client, channel_link):
return "-100" + str((await client.get_entity(channel_link)).id)
async def main(channel_link):
async with TelegramClient(
"test", config.api_id, config.api_hash
) as client:
channel_id = await channel_id_from_link(client, channel_link)
return channel_id
if __name__ == "__main__":
channel_link = sys.argv[1]
channel_id = asyncio.run(main(channel_link))
print(channel_id)
Test:
> ./TelegramChannelId.py https://t.me/binance_api_english
-1001134190352
Put your bot into your channel and go to https://api.telegram.org/bot/getUpdates.
If someone send message to that channel, you will get the channel ID there.

Telegram Bot How to delete or remove a message or media from a channel or group

I want to know an example of removing message or file like a photo
I did not find any functional tutorial in this regard,
There is no such functionality in Telegram Bot API right now.
UPD 2017-05-19: There is an official method deleteMessage, more info:
https://core.telegram.org/bots/api#deletemessage
https://stackoverflow.com/a/43965602/1140438
There is an official support of deleteMessage method in Bot API 3.0. More details here:
https://core.telegram.org/bots/api#deletemessage
https://api.telegram.org/botTOKEN/deleteMessage?chat_id=CID&message_id=MID
As you can see there are two arguments: chat_id and message_id.
You can remove bot's messages or other messages (if bot is admin) except service messages (such as join/leave messages).
On success, it will return following JSON object:
{"ok":true,"result":true}.
If you are trying to remove service message or other user's message, but bot is not an admin:
{"ok":false,"error_code":400,"description":"Bad Request: message can't be deleted"}.
If you are trying to remove non-existent message or its already deleted:
{"ok":false,"error_code":400,"description":"Bad Request: message to delete not found"}
Kindly check with the below code snippet!, the below code have worked for me!
String chatId = String.valueOf(callbackQuery.getMessage().getChatId());
Integer messageId = callbackQuery.getMessage().getMessageId();
DeleteMessage deleteMessage = new DeleteMessage(chatId, messageId);
try {
execute(deleteMessage);
}catch(TelegramApiException tae) {
throw new RuntimeException(tae);
}
you can forward message and save message id, and then remove that message. if you can do it, your message exist.
do it:
try:
mes=bot.forward_message(chat_id=?,from_chat_id=?,message_id=?)
bot.delete_message(chat_id=?,message_id=mes.id)
except:
print("your message deleted")
There are two methods in bot api that let you to edit a message: editMessageText and editMessageCaption. It is not ideal, but you can use it as an alternative.
For example by editing the message to:
"This message is unavailable."
Using python, if you have a CommandHandler() you can read the chat_id and message_id like so:
dispatcher.add_handler(CommandHandler("start", handler_start))
def handler_start(update: Update, context: CallbackContext):
chat_id = update.message.chat_id
message_id = update.message._id_attrs[0]
context.bot.delete_message(chat_id, message_id)
If on php. I send message. Get response from it (message id of bot) And use deleteMessage
<?php
$botToken = "yourBotToken";
$botAPI = "https://api.telegram.org/bot" . $botToken;
$update = json_decode(file_get_contents('php://input'), TRUE);
$msg = $update['message']['text'];
if ($msg == '/start') {
$data = http_build_query([
'text' => "test message (delete this)",
'chat_id' => $update['message']['chat']['id'],
]);
$send = file_get_contents($botAPI . "/sendMessage?{$data}");
$response = json_decode($send), true); // decode response
$message_id = $response['result']['message_id']; // get bots message
// Deleting message
$data_del = http_build_query([
'chat_id' => $update['message']['chat']['id'],
'message_id' => $message_id,
]);
file_get_contents($botAPI . "/deleteMessage?{$data_del}");
}
https://api.telegram.org/botTOKEN/deleteMessage?chat_id=CID&message_id=MID
Example
https://api.telegram.org/bot123456789:zzzzzzzzxxxxxxxxxxyyyyyyyyyy/deleteMessage?chat_id=123456789&message_id=123456,
It is important that the id of the message temine with a (comma) (,) and you can see it in the json when you send the message

Resources