python-telegram-bot send message without using update and context - python

I want my bot to send a message to the telegram chat when I am active on my computer. I've wrote other functions that use this fuction to send messages.
# Function to send messages back to chat
def sendmessage(update, context, message):
context.bot.send_message(chat_id=update.effective_chat.id, text=message)
This however uses update and context from the dispatcher and handler.
The function I want to send a message runs in a separate thread and is not using the dispatcher or handler. Thus I cannot use above function. I can't seem to figure out how to send a message without the use of update and context.
What I have now:
def user_returned():
row_list = []
with open('log.csv') as csv_file:
csv_reader = csv.DictReader(csv_file, delimiter=',')
for row in csv_reader:
row_list.append(row)
last_line = row_list[-1]
second_to_last_line = row_list[-2]
print(last_line['active'], second_to_last_line['active'])
if last_line['active'] == 'True' and second_to_last_line['active'] == 'False':
message = 'user is back'
context.bot.send_message(chat_id=update.effective_chat.id, text=message)
else:
message = 'still gone'
context.bot.send_message(chat_id=update.effective_chat.id, text=message)

import telegram
bot=telegram.Bot(token=bot_token)
chat=123456
bot.sendMessage(chat, msg)

Related

Cloud function with pubsub trigger executed endlessly when calling gmail API messages.send()

We are using the Atlassian Status Page with email automation, which means that it displays an alert on screen whenever it receives an email with subject 'DOWN' and deletes the same alert when it receives an email with subject 'UP'.
I activated the Gmail Pub/Sub (https://developers.google.com/gmail/api/guides/push) push notifications, which watches the gmail inbox for changes and sends a push notification to a pub/sub topic when a change actually happens.
Then I created a cloud function which is triggered by pub/sub notifications. This cloud function should:
Read the latest unread email
If this email is an alert sent by our 3rd party provider, send a new email to the Status Page with subject 'DOWN' or 'UP' accordingly.
This is the code:
def access_oauth2_json():
### Code
return creds_dict
def create_message(subject):
### Code
return {'raw': b64_string}
def send_message(service, message, user_id = 'me'):
try:
response = service.users().messages().send(userId=user_id, body=message).execute()
return response
except HttpError as error:
logging.error('An error occurred:', error)
def update_status_page(arg1,arg2):
### Initialise creds
try:
service = build('gmail', 'v1', credentials=creds)
request = {
'labelIds': ['INBOX'],
'topicName': 'pubsub_topic_id'
}
service.users().watch(userId='me', body = request).execute()
last_message_info = service.users().messages().list(userId='me', labelIds=['UNREAD'], q = 'in:inbox is:unread', maxResults=1).execute().get('messages', [])
last_message = service.users().messages().get(userId='me', id=last_message_info[0]['id']).execute()
header = last_message['payload']['headers']
sub = ""
for x in header:
if x['name'] == 'Subject':
sub = x['value'] #subject
logging.info(sub)
if 'special_alert_string' in sub:
message = create_message(subject = 'DOWN')
response = send_message(service, message)
elif 'other_special_alert_string' in sub:
message = create_message(subject = 'UP')
response = send_message(service, message)
except HttpError as error:
logging.info(f'An error occurred: {error}')
return 200
What happens is that:
When the function is triggered by an email which is not a 3rd party alert, the if/elif blocks are not executed, and the cloud function is executed 2 or 3 times (instead of 1, but that's fine for me, so not really a problem)
2 - Problem - When the function is triggered by an email which is a 3rd part alert, the if/elif blocks are executed (one of the 2) and the function is executed endlessly! It only stops because it reaches the maximum API requests per interval of time.
What I have tried:
To remove the watch() line, without success
Commenting out the service.users().messages().send() line falls back into case 1, so my guess is that this instruction is triggering a push notification to the pub/sub topic and generates the infinite loop. The issue could maybe solved with another watch() labelId, but I haven't figured out which one.
I hope this is clear, thank you for your help!

How to send messages through DataChannel within a loop

I got a question about programming in Python with WebRTCbin. So the channel.connect('on-open', self.on_data_channel_open) is an event listener that is triggered when the channel’s state changes to open, then the callback function on_data_channel_open is called. I used a for loop to loop through the log data and I was expecting to send each log inside the loop. channel.emit('send-string', str(log)) is the code to send messages through the data channel. However, the messages only are sent when the whole loop is finished.
def on_data_channel(self, webrtcbin_object, channel):
"""
This is a call back function when a data channel is created
"""
print('data_channel created')
channel.connect('on-error', self.on_data_channel_error)
channel.connect('on-open', self.on_data_channel_open)
channel.connect('on-close', self.on_data_channel_close)
channel.connect('on-message-string', self.on_data_channel_message)
print(f'The datachannel state is {channel.ready_state}')
def on_data_channel_open(self, channel):
print('{} data_channel opened'.format(self.camera_id))
self.sendlog(channel)
def sendlog(self, channel):
try:
with open('data.txt') as f:
json_data = json.load(f)
for log in json_data:
print(channel.ready_state)
if channel.ready_state == 2:
print(f'sending the log: {log}')
channel.emit('send-string', str(log))
time.sleep(0.33)
else:
break
except (FileNotFoundError, JSONDecodeError) as ex:
print("dealing file encouter error: {}; error is {}".format(ex, type(ex)))
I saw in the Datachannel's buffer was increased while the message send was executed. I guess all data have entered the buffer, and the DataChannel object sent the entire buffer to the receiver through the channel.
I have tried a few ways to async the message sending, but I am new to python, none of them were worked.
Are there any suggestions?
Thanks!

NameError: name 'startCommand' is not defined - PYTHON

from coinbase.wallet.client import Client
from telegram import ParseMode
from telegram.ext import CommandHandler, Defaults, Updater
COINBASE_KEY = 'xxxxxxxxxxxx'
COINBASE_SECRET = 'xxxxxxxxxxxx'
TELEGRAM_TOKEN = 'xxxxxxxxxxxx'
coinbase_client = Client(COINBASE_KEY, COINBASE_SECRET)
#if __name__ == '__main__':
updater = Updater(token=TELEGRAM_TOKEN, defaults=Defaults(parse_mode=ParseMode.HTML))
dispatcher = updater.dispatcher
dispatcher.add_handler('start', startCommand) # Accessed via /start
dispatcher.add_handler('alert', priceAlert) # Accessed via /alert
updater.start_polling() # Start the bot
updater.idle() # Wait for the script to be stopped, this will stop the bot
def startCommand(update, context):
context.bot.send_message(chat_id=update.effective_chat.id, text='Hello there!')
def priceAlert(update, context):
if len(context.args) > 2:
crypto = context.args[0].upper()
sign = context.args[1]
price = context.args[2]
context.job_queue.run_repeating(priceAlertCallback, interval=15, first=15, context=[crypto, sign, price, update.message.chat_id])
response = f"⏳ I will send you a message when the price of {crypto} reaches £{price}, \n"
response += f"the current price of {crypto} is £{coinbase_client.get_spot_price(currency_pair=crypto + '-GBP')['amount']}"
else:
response = '⚠️ Please provide a crypto code and a price value: \n<i>/price_alert {crypto code} {> / <} {price}</i>'
context.bot.send_message(chat_id=update.effective_chat.id, text=response)
def priceAlertCallback(context):
crypto = context.job.context[0]
sign = context.job.context[1]
price = context.job.context[2]
chat_id = context.job.context[3]
send = False
spot_price = coinbase_client.get_spot_price(currency_pair=crypto + '-GBP')['amount']
if sign == '<':
if float(price) >= float(spot_price):
send = True
else:
if float(price) <= float(spot_price):
send = True
if send:
response = f'👋 {crypto} has surpassed £{price} and has just reached <b>£{spot_price}</b>!'
context.job.schedule_removal()
context.bot.send_message(chat_id=chat_id, text=response)
enter image description here
I get this error of the code above, also I have already tried changing the position of the def but, it also shows error, How to solve this?
It is the code for telegram bot and also this keeps on showing me NameError, I have already added python3 and pip, but still not solved
Python reads files top to bottom. So when you call dispatcher.add_handler('start', startCommand), the function startCommand is not yet known. Move the part
updater = Updater(token=TELEGRAM_TOKEN, defaults=Defaults(parse_mode=ParseMode.HTML))
dispatcher = updater.dispatcher
dispatcher.add_handler('start', startCommand) # Accessed via /start
dispatcher.add_handler('alert', priceAlert) # Accessed via /alert
updater.start_polling() # Start the bot
updater.idle() # Wait for the script to be stopped, this will stop the bot
below the callback definitions.
Apart from that, add_handler needs a Handler as argument, in your case something like add_handler(CommandHanlder('start', startCommand). Please see PTB tutorial as well as the examples.
Disclaimer: I'm the current maintainer of the python-telegram-bot library.
Try
dispatcher.add_handler('start', startCommand()) # Accessed via /start
dispatcher.add_handler('alert', priceAlert()) # Accessed via /alert
You will also need to add the two arguments required by both functions.
dispatcher.add_handler('start', startCommand(update, context))
dispatcher.add_handler('alert', startCommand(update, context))
I'm not exactly sure what data the two functions take in but I'm going to guess that it is whatever the bot is returning.

Discord - Send messages from a channel to my website in real time

I currently have a python/django platform and a discord community. On my discord server there is a channel "announcements". I would just like that when a message is published in this channel, it goes up to my website in real time. This is in order to convert it into a notification.
Currently I managed to upload the messages from the channel to my site in a simple way but not in real time:
def discord_get_last_message_id():
message_id = 0
try:
message_id = Notification.objects.latest('id').discord_message_id
except:
pass
return message_id
def get_channel_messages():
#load last id discord message in DB
last_message_id = discord_get_last_message_id()
#Base route
route = "/channels/"+ DISCORD_CHANNEL_ANNONCES_ID +"/messages"
#if first time to DB, load just one item
if last_message_id == 0:
add = "?limit=1"
else:
add = "?after="+last_message_id
route = route + add
data,error_message = request_discord('GET',route)
print(data)
def request_discord(method,url_access,body={}):
data =''
#Call token
error_message = ''
access_token = discord_get_token()
#Call request
headers = {'Authorization': access_token}
body = body
if method=="GET":
result = requests.get(DISCORD_BASE_URI + url_access, headers=headers)
else:
result = requests.post(DISCORD_BASE_URI + url_access, headers=headers,data=body)
#Check result
if result.status_code != 200 and result.status_code != 201:
error_message = "Impossible de d'obtenir un resultat erreur: " + str(result.status_code)
else:
data = result.json()
return data,error_message
def discord_get_token():
return DISCORD_ANNONCES_CHANNEL_TOKEN
I'm trying to understand how discord websockets work but I have the impression that it's made to communicate with a bot only.
My question is, which way should I go to get the messages from my discord channel to my website in real time? Do I have to go through a bot?
NOTE: the goal is to get his messages to make notifications on my platform.
Thanks for your answers !
To answer your question:
My question is, which way should I go to get the messages from my discord channel to my website in real time? Do I have to go through a bot?
The best way would be to use a bot. This is the simplest, yet best way to do accomplish what you want. You could use a on_message event to get messages when they are sent. Then you could use that message and update your website. An example of how to do this is:
#bot.event
async def on_message(message):
message_content = message.content
return
You can do whatever you want with message_content. For your purpose you might want to store it in a database.
For the website side, you could use JavaScript to get the messages from the DB and update the HTML accordingly.

Python Telegram Bot get the bot to respond to message

I am currently using python-telegram-bot library to make a telegram bot. My problem is I am trying to have my bot respond back when using the inline command. So when a user sends the bot #botname 'text', I want the to store the 'text' as a string and then have my bot send something back with that variable.
For some reason I can not get this to work. I tried the code below, but it doesn't work...I also posted the example from the github that works but not in the way i want.
My code
def inlinequery(update, context):
"""Handle the inline query."""
query = update.inline_query.query
text = query.message_text
print(text)
update.message.reply_text(text)
Example Code
#Sends message when #botname is used
def inlinequery(update, context):
"""Handle the inline query."""
query = update.inline_query.query
results = [
InlineQueryResultArticle(
id=uuid4(),
title="Caps",
input_message_content=InputTextMessageContent(
query.upper())),
InlineQueryResultArticle(
id=uuid4(),
title="Bold",
input_message_content=InputTextMessageContent(
"*{}*".format(escape_markdown(query)),
parse_mode=ParseMode.MARKDOWN)),
InlineQueryResultArticle(
id=uuid4(),
title="Italic",
input_message_content=InputTextMessageContent(
"_{}_".format(escape_markdown(query)),
parse_mode=ParseMode.MARKDOWN))]
update.inline_query.answer(results)
def main():
# Get the dispatcher to register handlers
dp = updater.dispatcher
dp.add_handler(InlineQueryHandler(inlinequery))
# Start the Bot
updater.start_polling()
if __name__ == '__main__':
main()
You can use the User object of the inline query to send them a message. Keep in mind that the user has to have started a private chat with the bot before the bot can send them messages.
I modified your attempt. It should work, but i have not tested it:
def inlinequery(update, context):
"""Handle the inline query."""
query = update.inline_query
text = query.query
print(text)
query.from_user.send_message(text)
Related docs:
InlineQuery.user
User.send_message

Categories