Get updates only one time per message - python

Im building a Telegram bot using the official API and python with the requests lib
I`ve add a command named text, that return "example text" when it is called. Until here all ok, but the bot only send a response when the python script is executed
So I do that the script execute indefinitely with a white True condition.
The problem is that if I execute indefinitely the script it will be making requests all the time to the API, so if I check the last message all the time with the script, the last message will be /text until I write another message.
How can do that the function that read the command will execute only one time when a new command will requested?
The code is the next:
# TELEGRAM BOT USING THE API
import requests as req
from dotenv import load_dotenv
from pprint import pprint
import re
import os
config = load_dotenv(".env")
teletoken = os.environ.get("telegram_token")
uri = f"https://api.telegram.org/bot{teletoken}/"
# Dynamic Telegram API method
def method(method):
return f"{uri}{method}"
# Response to a command
def get_and_response(chat_id: str or int):
updates = req.get(method("getUpdates"))
response = updates.json()
command_regex = re.findall("^/text*", response["result"][-1]["message"]["text"])
if command_regex == ["/text"]:
req.post(method("sendMessage"), data={"chat_id": chat_id, "text": "Example text"})
if __name__ == "__main__":
while True:
get_and_response(*chat_id*)

Related

DeepAI API error - {"err": "error processing given inputs from request"}

I'm a noobie at Python and was just messing around, but now I'm really curious why it isn't working. I'm currently trying to build a telegram bot that generates an image based on the text given to the bot. I think there might be a problem with my DeepAI api? When I click this link: https://api.deepai.org/api/text2img i always get the error
{"err": "error processing given inputs from request"}
. The bot is linked but gives me the error as in the code below. My code below:
import requests
import json
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
def text_to_image(update, context):
# Get the text from the user
text = update.message.text
# Set up the DeepAI API request
api_key = "{{ api }}"
headers = {
"api-key": api_key
}
data = {
"text": text
}
# Make the request to the DeepAI API
response = requests.post("https://api.deepai.org/api/text2img", headers=headers, json=data)
if response.status_code != 200:
update.message.reply_text("An error occurred while generating the image. Please try again later.")
return
# Get the generated image from the response
response_json = response.json()
image_url = response_json["output_url"]
# Send the generated image to the user
context.bot.send_photo(chat_id=update.effective_chat.id, photo=image_url)
def main():
# Set up the Telegram bot
updater = Updater(token="{{ api }}", use_context=True)
dispatcher = updater.dispatcher
# Add the text_to_image handler
text_to_image_handler = MessageHandler(Filters.text, text_to_image)
dispatcher.add_handler(text_to_image_handler)
# Start the bot
updater.start_polling()
updater.idle()
if __name__ == '__main__':
main()
I've tried changing code and different things but nothing seems to work, i'm really stuck right now
From the looks of it, it's an error on the API side of things. The status code of the API server depends on traffic and account/key.
Things to do:
Check if your API key is valid and wait when server works on google, then try to run your code

telegram bot in python for sending files doesnt work, but I dont know why [duplicate]

Hi i want to send message from bot in specific time (without message from me), for example every Saturday morning at 8:00am.
Here is my code:
import telebot
import config
from datetime import time, date, datetime
bot = telebot.TeleBot(config.bot_token)
chat_id=config.my_id
#bot.message_handler(commands=['start', 'help'])
def print_hi(message):
bot.send_message(message.chat.id, 'Hi!')
#bot.message_handler(func=lambda message: False) #cause there is no message
def saturday_message():
now = datetime.now()
if (now.date().weekday() == 5) and (now.time() == time(8,0)):
bot.send_message(chat_id, 'Wake up!')
bot.polling(none_stop=True)
But ofc that's not working.
Tried with
urlopen("https://api.telegram.org/bot" +bot_id+ "/sendMessage?chat_id=" +chat_id+ "&text="+msg)
but again no result. Have no idea what to do, help please with advice.
I had this same issue and I was able to solve it using the schedule library. I always find examples are the easiest way:
import schedule
import telebot
from threading import Thread
from time import sleep
TOKEN = "Some Token"
bot = telebot.TeleBot(TOKEN)
some_id = 12345 # This is our chat id.
def schedule_checker():
while True:
schedule.run_pending()
sleep(1)
def function_to_run():
return bot.send_message(some_id, "This is a message to send.")
if __name__ == "__main__":
# Create the job in schedule.
schedule.every().saturday.at("07:00").do(function_to_run)
# Spin up a thread to run the schedule check so it doesn't block your bot.
# This will take the function schedule_checker which will check every second
# to see if the scheduled job needs to be ran.
Thread(target=schedule_checker).start()
# And then of course, start your server.
server.run(host="0.0.0.0", port=int(os.environ.get('PORT', 5000)))
I hope you find this useful, solved the problem for me :).
You could manage the task with cron/at or similar.
Make a script, maybe called alarm_telegram.py.
#!/usr/bin/env python
import telebot
import config
bot = telebot.TeleBot(config.bot_token)
chat_id=config.my_id
bot.send_message(chat_id, 'Wake up!')
Then program in cron like this.
00 8 * * 6 /path/to/your/script/alarm_telegram.py
Happy Coding!!!
If you want your bot to both schedule a message and also get commands from typing something inside, you need to put Thread in a specific position (took me a while to understand how I can make both polling and threading to work at the same time).
By the way, I am using another library here, but it would also work nicely with schedule library.
import telebot
from apscheduler.schedulers.blocking import BlockingScheduler
from threading import Thread
def run_scheduled_task():
print("I am running")
bot.send_message(some_id, "This is a message to send.")
scheduler = BlockingScheduler(timezone="Europe/Berlin") # You need to add a timezone, otherwise it will give you a warning
scheduler.add_job(run_scheduled_task, "cron", hour=22) # Runs every day at 22:00
def schedule_checker():
while True:
scheduler.start()
#bot.message_handler(commands=['start', 'help'])
def print_hi(message):
bot.send_message(message.chat.id, 'Hi!')
Thread(target=schedule_checker).start() # Notice that you refer to schedule_checker function which starts the job
bot.polling() # Also notice that you need to include polling to allow your bot to get commands from you. But it should happen AFTER threading!

Send a local photo from inline mode in a telegram bot

I use Python telegram bot API for my bot.
I want to generate photos locally and send them as inline results but InlineQueryResultPhoto accepts only photo URLs.
Suppose my project structure looks like this:
main.py
photo.jpg
How do I send photo.jpg as an inline result?
Here is the code of main.py:
from uuid import uuid4
from telegram.ext import InlineQueryHandler, Updater
from telegram import InlineQueryResultPhoto
def handle_inline_request(update, context):
update.inline_query.answer([
InlineQueryResultPhoto(
id=uuid4(),
photo_url='', # WHAT DO I PUT HERE?
thumb_url='', # AND HERE?
)
])
updater = Updater('TELEGRAM_TOKEN', use_context=True)
updater.dispatcher.add_handler(InlineQueryHandler(handle_inline_request))
updater.start_polling()
updater.idle()
There is no direct answer because Telegram Bot API doesn't provide it.
But there are two workaounds: you can use upload a photo to telegram servers and then use InlineQueryResultCachedPhoto or you can upload to any image server and then use InlineQueryResultPhoto.
InlineQueryResultCachedPhoto
This first option requires you to previously upload the photo to telegram servers before creating the result list. Which options do you have? The bot can message you the photo, get that information and use what you need. Another option is creating a private channel where your bot can post the photos it will reuse. The only detail of this method is getting to know the channel_id (How to obtain the chat_id of a private Telegram channel?).
Now lets see some code:
from config import tgtoken, privchannID
from uuid import uuid4
from telegram import Bot, InlineQueryResultCachedPhoto
bot = Bot(tgtoken)
def inlinecachedphoto(update, context):
query = update.inline_query.query
if query == "/CachedPhoto":
infophoto = bot.sendPhoto(chat_id=privchannID,photo=open('logo.png','rb'),caption="some caption")
thumbphoto = infophoto["photo"][0]["file_id"]
originalphoto = infophoto["photo"][-1]["file_id"]
results = [
InlineQueryResultCachedPhoto(
id=uuid4(),
title="CachedPhoto",
photo_file_id=originalphoto)
]
update.inline_query.answer(results)
when you send a photo to a chat/group/channel, you can obtain the file_id, the file_id of the thumbnail, the caption and other details I'm going to skip. What the problem? If you don't filter the right query, you may end up sending the photo multiple times to your private channel. It also means the autocomplete won't work.
InlineQueryResultPhoto
The other alternative is upload the photo to internet and then use the url. Excluding options like your own hosting, you can use some free image hostings that provides APIs (for example: imgur, imgbb). For this code, generating your own key in imgbb is simpler than imgur. Once generated:
import requests
import json
import base64
from uuid import uuid4
from config import tgtoken, key_imgbb
from telegram import InlineQueryResultPhoto
def uploadphoto():
with open("figure.jpg", "rb") as file:
url = "https://api.imgbb.com/1/upload"
payload = {
"key": key_imgbb,
"image": base64.b64encode(file.read()),
}
response = requests.post(url, payload)
if response.status_code == 200:
return {"photo_url":response.json()["data"]["url"], "thumb_url":response.json()["data"]["thumb"]["url"]}
return None
def inlinephoto(update, context):
query = update.inline_query.query
if query == "/URLPhoto":
upphoto = uploadphoto()
if upphoto:
results = [
InlineQueryResultPhoto(
id=uuid4(),
title="URLPhoto",
photo_url=upphoto["photo_url"],
thumb_url=upphoto["thumb_url"])
]
update.inline_query.answer(results)
This code is similar to the previous method (and that includes the same problems): uploading multiple times if you don't filter the query and you won't have the autocomplete when writing the inline.
Disclaimer
Both code were written thinking the images you want to upload are generated at the moment you receive the query, otherwise you can do the work previous to receiving the query, saving that info in a database.
Bonus
You can run your own bot to get the channel_id of your private channel with pyTelegramBotAPI
import telebot
bot = telebot.TeleBot(bottoken)
#bot.channel_post_handler(commands=["getchannelid"])
def chatid(message):
bot.reply_to(message,'channel_id = {!s}'.format(message.chat.id))
bot.polling()
To get the id you need to write in the channel /getchannelid#botname

how to schedule a telegram bot to send a message?

I am trying to create a Telegram bot that sends a message at a specific time, 5:30pm. However, the ways a was trying are not correct.
I wanted to trigger send_message regarding to the time and without the necessity of the user to send any /command.
import telebot
import datetime
TOKEN = 'MyToken'
bot = telebot.TeleBot(TOKEN)
#bot.message_handler(commands=['start'])
def send_welcome(message):
message_id=message.chat.id
bot.reply_to(message,"Welcome")
bot.polling()
Until now I was trying to add something like that, of course it is not python but kind of pseudocode just to explain:
if currenttime=17:30
send_message(idchat, "mymessage")
Thank you in advance.
If I understand correctly, you need to check your system time before sending a message, you could use the following code [source]:
from datetime import datetime
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
print("Current Time =", current_time)
To send a message you could use the following code [source]:
def test_send_message():
text = 'CI Test Message'
tb = telebot.TeleBot(TOKEN)
ret_msg = tb.send_message(CHAT_ID, text)
assert ret_msg.message_id
To compare the time, you may use:
if current_time=='17:30:00':
test_send_message()
You can use schedule python library.
First of all import the necessary modules
import schedule
import time
import telegram
Then you have to create a function that will repeat in every x time.
Here the bot will send me message in every 5 seconds.
TOKEN='your_token'
bot = telegram.Bot(token=TOKEN)
def job():
bot.sendMessage(chat_id=<chat_id>, text="Hello")
schedule.every(5).seconds.do(job)
while True:
schedule.run_pending()
time.sleep(1)
For more informations about schedule Read the documentation

slack python api delete message

I am trying to use my bot to delete certain messages in a slack channel with this api call
import os
import time
import re
from slackclient import SlackClient
slack_client = SlackClient(
'xsssssseeeeeeee')
slack_mute_bot_id = None
def delete_message(slack_event):
for event in slack_event:
if event["type"] == "message":
message_text = event['text']
time_stamp = event['ts']
channel_id = event['channel']
slack_client.api_call(
'chat.delete',
channel=channel_id,
ts=time_stamp,
as_user=True
)
print(message_text + " delted")
if __name__ == "__main__":
if slack_client.rtm_connect(with_team_state=False):
slack_mute_bot_id = slack_client.api_call("auth.test")["user_id"]
while True:
# print(slack_client.rtm_read())
delete_message(slack_client.rtm_read())
time.sleep(1)
else:
print("Connection failed. Exception traceback printed above.")
I do not get any error message after doing this and the bot does not delete the message. I am using the bot user token. I have benn able to send message succesfully but the delete method does not work and still gives np responses
Refer - https://api.slack.com/methods/chat.delete
When used with a user token, this method may only delete messages
that user themselves can delete in Slack.
When used with a bot token, this method may delete only messages
posted by that bot.
I got stumbled into the same thing.

Categories

Resources