Python Telegram Bot is not Ideling on Heroku - python

I am using heroku to deploy my telegram bot. I am using free dynos. So, to save dyno hours I want my app to go idle after 30 mins of inactivity which it should.
https://www.heroku.com/dynos
But, my app get random GET requests after 25mins or so. So, my app never goes to idle.
Note:
My app is not yet on production so I cannot figure out why I am getting ping every 25min.
here is my code:
import telegram.ext
import bot
from config import TOKEN,PORT
def start(update,context):
id = update.message.chat.id
if(id == (hidden) or id == (hidden)):
update.message.reply_text("Welcome! to Football Story Bot")
else:
update.message.reply_text("""
We have detected unusual request from your device.
You have been banned from the service until further notice,
""")
def help(update,context):
id = update.message.chat.id
if(id == (hidden) or id == (hidden)):
update.message.reply_text("""
The following commands are available:
/start -> Welcome Message
/help -> This Message
/streams -> list of matches
""")
else:
update.message.reply_text("""
We have detected unusual request from your device.
You have been banned from the service until further notice,
""")
def streams(update,context):
id = update.message.chat.id
if(id == (hidden) or id == (hidden)):
update.message.reply_text("Searching for available matches")
all_matches_name_list = bot.all_matches_name()
link_str=''
if(all_matches_name_list==None):
update.message.reply_text("We are experiencing problem.Try again later, if problem persists then contact admin")
return None
for links in all_matches_name_list:
link_str+=links+'\n'
update.message.reply_text(link_str)
update.message.reply_text("End Of Detected Matches")
else:
update.message.reply_text("""
We have detected unusual request from your device.
You have been banned from the service until further notice,
""")
def handle_message(update,context):
id = update.message.chat.id
if(id == (hidden) or id == (hidden)):
update.message.reply_text("Searching for available streams")
link_str=''
sending_message=''
for chars in update.message.text:
if(chars=='#'):
break
sending_message+=chars
individual_link = bot.selected_match(bot.all_matches_name(),sending_message)
if(individual_link==None):
update.message.reply_text("We are experiencing problem.Try again later, if problem persists then contact admin hai tw")
return None
if(len(individual_link)==0):
update.message.reply_text("No links found. Links are updated 30min before match. If link is not found till Kick Off then contact admin")
return None
for links in individual_link:
link_str+=links+'\n\n'
update.message.reply_text(link_str)
update.message.reply_text("End Of Streaming Links")
else:
update.message.reply_text("""
We have detected unusual request from your device.
You have been banned from the service until further notice,
""")
updater = telegram.ext.Updater(TOKEN,use_context=True)
disp = updater.dispatcher
disp.add_handler(telegram.ext.CommandHandler("start",start))
disp.add_handler(telegram.ext.CommandHandler("help",help))
disp.add_handler(telegram.ext.CommandHandler("streams",streams))
disp.add_handler(telegram.ext.MessageHandler(telegram.ext.Filters.command,handle_message))
updater.start_webhook(listen="0.0.0.0",
port=PORT,
url_path=TOKEN,
webhook_url="(my app link)" + TOKEN)
updater.idle()

Related

How to process a response from the Twilio REST API

I am developing a program to help treat depression. I do not have a deep understanding of Twilio. I would like to collect the responses to this message:
Sent from your Twilio trial account - What are the positive results or outcomes you have achieved lately?
What are the strengths and resources you have available to you to get even more results and were likely the reason you got the results in the first question.
What are your current priorities? What do you and your team need to be focused on right now?
What are the benefits to all involved-you
your team and all other stakeholders who will be impacted by achieving your priority focus.
How can we (you and/or your team) move close? What action steps are needed?
What am I going to do today?
What am I doing tomorrow ?
What did I do yesterday?
and process them 1-9. The responses will be enumerated by 1-9.
I've contacted Twilio support and I read these docs https://www.twilio.com/docs/sms/tutorials/how-to-receive-and-reply-python.
Here is what I tried:
# Download the helper library from https://www.twilio.com/docs/python/install
import os
from twilio.rest import Client
import logging
import csv
import psycopg2
from flask import Flask, request, redirect
from twilio.twiml.messaging_response import MessagingResponse
app = Flask(__name__)
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
# Set environtment variables
DATABASE = os.environ["DATABASE"]
PASSWORD = os.environ["PASSWORD"]
PORT = os.environ["PORT"]
USER = os.environ["USER"]
HOST = os.environ["HOST"]
# initialization TODO: move into env vars
MY_PHONE_NUMBER = os.environ["MY_PHONE_NUMBER"]
TWILIO_PHONE_NUMBER = os.environ["TWILIO_PHONE_NUMBER"]
TWILIO_ACCOUNT_SID = os.environ["TWILIO_ACCOUNT_SID"]
TWILIO_AUTH_TOKEN = os.environ["TWILIO_AUTH_TOKEN"]
# Configure Twillio
# Set environment variables for your credentials
# Read more at http://twil.io/secure
client = Client(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN)
logging.debug(f"Connected to Twilio using MY_PHONE_NUMBER:{MY_PHONE_NUMBER},TWILIO_PHONE_NUMBER{TWILIO_PHONE_NUMBER}")
# Establish db connection
# use psycopg to connect to the db and create a table
conn = psycopg2.connect(
database=DATABASE, user=USER, password=PASSWORD, host=HOST, port=PORT)
conn.autocommit = True
cursor = conn.cursor()
# Step 1: Set up frequency, i.e. times to send messages
# Step 2: Load questions
questionsFile = open('questions.csv')
questions = csv.reader(questionsFile)
logging.debug(f"message:{questions}")
message = "\n".join([question for row in questions for question in row])
logging.debug(f"message: {message}")
# Step 3: Send questions
# message = client.messages.create(
# body=message,
# from_=TWILIO_PHONE_NUMBER,
# to=MY_PHONE_NUMBER
# )
# Step 4: Collect response
#app.route("/sms", methods=['GET', 'POST'])
def incoming_sms():
"""Send a dynamic reply to an incoming text message"""
# Get the message the user sent our Twilio number
body = request.values.get('Body', None)
# Start our TwiML response
resp = MessagingResponse()
# Determine the right reply for this message
if body == 'hello':
resp.message("Hi!")
elif body == 'bye':
resp.message("Goodbye")
return str(resp)
if __name__ == "__main__":
app.run(debug=True)
# Step 5: Create a database table as the sheet name and Save responses in db
logging.debug(f'Step 2 creating table response')
# TODO: create 10 columns for saving responses (each response contains 10 answers)
sql = f'CREATE TABLE IF NOT EXISTS public.responses'
logging.debug(f'CREATE TABLE IF NOT EXISTS public.responses')
# cursor.execute(sql)
# conn.commit()
# Next steps:
# 1. Process positive and negative sentiment from responses
# 2. Calculuate total positive sentiment
# 3. Calculate total negative sentiment
# 4. Plot positive sentiment vs. negative sentiment
The documentation doesn't provide a clear path for completing step 4.
[shows response from text message.]
[messages url]
Expected
processed responses from the questions.
Actual:
Sent from your Twilio trial account - What are the positive results or outcomes you have achieved lately?
What are the strengths and resources you have available to you to get even more results and were likely the reason you got the results in the first question.
What are your current priorities? What do you and your team need to be focused on right now?
What are the benefits to all involved-you
your team and all other stakeholders who will be impacted by achieving your priority focus.
How can we (you and/or your team) move close? What action steps are needed?
What am I going to do today?
What am I doing tomorrow ?
What did I do yesterday?
I added a Twilio flow to test the connection to Twilio. This could go in two directions just python or using a Twilio flow. The flow does not work even after adding the correct number.
messages screenshot
this comes from the demo video which does not match the current UI: https://www.youtube.com/watch?v=VRxirse1UfQ.
There's a second code sample on the page you linked. This explains how you can parse the body of incoming message to read the payload with request.values.get('Body', None):
#app.route("/sms", methods=['GET', 'POST'])
def incoming_sms():
"""Send a dynamic reply to an incoming text message"""
# Get the message the user sent our Twilio number
body = request.values.get('Body', None)
# Start our TwiML response
resp = MessagingResponse()
# Determine the right reply for this message
if body == 'hello':
resp.message("Hi!")
elif body == 'bye':
resp.message("Goodbye")
return str(resp)
However, it makes sense to ask the questions after each other and this means you would need to handle many different endpoint and it can get complicated really fast.
But there's also a visual editor that allows you to define this within a few minutes in your browser: Build a Chatbot with Twilio Studio

python telegrambot store chat id

I am wondering how I could store/read out a user chat ID to later send them messages.
Example would be, that the user is adding my telegram bot and sends him a message.
Later on in my program at some point, when a sepcific situation occurs, I want to send a message to the specific user.
For a simple example I have this code:
a=1
b=2
if a > b:
# at this point python should send a message to a user via telegram privat chat
else:
# send a different message
I know how to handle a response to a command sent by the user in the telegram chat, but not how to send a message to a user without receiving a command first. I think there fore I would need to have a way to store the users chat Id first to later refer to that Id when sending the message.
The point is I want to compile my program to .exe later on and send it to some friends and it should work for them as well.
It is very easy, just use a simple database.
MongoDB is the best choose in my opinion.
Create an account on it and follow this tutorial.
First get the user_id
userid1 = str(update.message.chat_id)
Then store it into the database
import pymongo
from pymongo import MongoClient
cluster = MongoClient("mongodb+srv://<user>:<password>#cluster0.uubct.mongodb.net/users?retryWrites=true&w=majority")
db = cluster["users"]
collection = db["users"]
results = collection.find({"_id": int(userid1)})
if results.count() == 0:
print("post")
post = {"_id": int(userid1)}
collection.insert_one(post)
else:
print("User already in the database!")
For getting it you need to use the find() method.
results = collection.find()
for result in results:
var1 = (result["_id"])
print(var1)
context.bot.send_message(chat_id=prova,
text = "Hi")
You can simply add the id in a list WHITOUT ANY THIRD PARTS PAKAGE
import telebot
TOKEN = ""
bot = telebot.TeleBot(TOKEN)
admin = # your chat id
users = []
#bot.message_handler(commands=['start'])
def start_message(msg):
bot.send_message(msg.chat.id, 'Welcome!')
if msg.chat.id not in users: # if the id isn't already in the users list
users.append(msg.chat.id)
#bot.message_handler(commands=['send_at_all']) # A way to use the list
def sendAtAll(msg):
if msg.chat.id == admin: # only if YOU start the command the message will be sent
for id in users: # for every user that has start the bot
bot.send_message(id, "I'm sending this message at all the users")
# If an user wants to stop the notifications...
#bot.message_handler(commands=['unsubscribe'])
def sendAtAll(msg):
del users[msg.chat.id]
bot.send_message(msg.chat.id, "If you want to receive the notification click /start")
# Every time you are going to restart the bot polling the content of the users list will be deleated so...
#bot.message_handler(commands=['save_user_list'])
def sendAtAll(msg):
if msg.chat.id == admin:
bot.send_message(admin, users)
# the list will be sent to your telegram chat, when you activate the bot you can add the list manually
bot.polling()
You can also create a class and save every chat id as an object
import telebot
from random import choice
TOKEN = ''
bot = telebot.TeleBot(TOKEN)
admin = # your chat id
users = []
class Userbot: # The class User is already in the pyTelegramBotAPI
def __init__(self, msg):
self.id = msg.chat.id
self.username = '#' + msg.from_user.username
def contestWinner(self):
text = f'Hi {self.username}, you have win!!!'
bot.send_message(self.id, text)
#bot.message_handler(commands=['start'])
def start(msg):
bot.send_message(msg.chat.id, 'Welcome!')
for el in users:
if msg.chat.id not in el.id:
users.append(Userbot(msg))
# you can't type 'if msg.chat.id not in users.id' because only the object inside the list can use the method id
#bot.message_handler(commands=['extract']) # another way to use the list
def extract(msg):
if msg.chat.id == admin:
winner = choice(users)
winner.contestWinner()
#bot.message_handler(commands=['unsubscribe'])
def sendAtAll(msg):
for el in users:
if msg.chat.id == el.id:
del users[el]
# only if the user inside the object is the same as the user that has sent the message the object will be deleated
bot.send_message(msg.chat.id, "If you want to receive the notification click /start")
#bot.message_handler(commands=['save_user_list'])
def sendAtAll(msg):
if msg.chat.id == admin:
bot.send_message(admin, users)
bot.polling()
Apologise for my terrible english

Telegram bot GetUpdate returns {"ok":true,"result":[]}

Good afternoon!
My telegram bot is written in Python and is very simple. It includes thousands of lines of functions of the same type (example below) and ends with a line bot.infinity_polling(True)
#bot.message_handler(commands=['start'])
def com_start(m):
keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
keyboard.add(*[types.KeyboardButton(name) for name in ['🇷🇺Русский']])
keyboard.add(*[types.KeyboardButton(name) for name in ['🇬🇧English']])
keyboard.add(*[types.KeyboardButton(name) for name in ['🇩🇪German']])
keyboard.add(*[types.KeyboardButton(name) for name in ['🇹🇷Turkish']])
msg = bot.send_message(m.chat.id, '👋🏼Привет!',
reply_markup=keyboard)
bot.register_next_step_handler(msg, starter)
def starter(m):
if m.text == '🇷🇺Русский':
second(m)
elif m.text == '🇬🇧English':
secondeng(m)
elif m.text == '🇩🇪German':
secondgerm(m)
elif m.text == '🇹🇷Turkish':
secondtur(m)
else:
msg = bot.send_message(m.chat.id, 'Используйте кнопки меню для общения с ботом OTON ⤵️')
com_start(m)
My bot works with gitlab, after each change in the code I commit, push it and Run Pipeline via CI/CD.
The problem is that the GetUpdates method (https://api.telegram.org/bot.../getUpdates) while the bot is running gives {"ok":true,"result":[]} and nothing more. But when I stop the bot and refresh the page - it gives me all that I need:
{"ok":true,"result":[{"update_id":57670007,
"message":{"message_id":10586,"from":{"id":435418164,"is_bot":false,"first_name":"Nika","last_name":"Fenina","username":"yanikailinet","language_code":"ru"},"chat":{"id":435418164,"first_name":"Nika","last_name":"Fenina","username":"yanikailinet","type":"private"},"date":1590065990,"text":"hello"}}
Can I solve this problem somehow? I need to get the information I need while the bot is running.
PS: no webhooks connected
You cannot make simultaneous getUpdates requests. It shows this error.
Conflict: terminated by other getUpdates request; make sure that only one bot instance is running
You can save the information of ["result"] inside the code only in some file.

Creating Slackbot with Google Sheets integration using python and git

My name is Ken. I am trying to create a Slack Bot first one message every Monday at 9:00 am and asks for a input (goal number of sales for the week). Then responds with user input in new message saying (great your weekly sales goal is (#). Then it takes this number and adds it to Google sheets. Then asks user to enter daily goal for the day. And responds with (daily goal set as). Then at 9:00 pm asks user to input the number of deals written and keeps track of all data in Google sheets and provides graphs. I have been thinking maybe MySQL would work for that too.
Here is some of the code I have so far:
starterbot.py
import os
import time
from slackclient import slackclient
# starterbot's ID as an environment variable
BOT_ID = os.environ.get("BOT_ID")
# contasts
AT_BOT = "<#" + BOT_ID + ">"
EXAMPLE_COMMAND = "do"
#instantiate Slack & Twilio clients
slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN'))
def handle_command (command, channel)
"""
Receives commnds directed at the bot and determines if they
are valid commands. if so, then acts on the commands. if not,
returns back what it needs for clarification.
"""
response = "Not sure what you mean. Use the *" + EXAMPLE_COMMAND + \
"* command with numbers, delimited by spaces."
if command.startswitch(EXAMPLE_COMMAND):
response = "Sure ... wire some more c ie then I can do
that!"
slack_client.api_call("chat.postMessage", channel=channel,
text=response, as_user=True)
def parse_slack_output(slack_messages):
"""
The Slack Real Time Messaging API is an event firehose.
this parsing function returns None unless a message is
directed at the Bot, based on its ID.
"""
if slack_messages and len(slack_messages) > 0;
for message in slack_messages:
if message and 'text' in message and AT_BOT in message['text']:
command = message['text'].split(AT_BOT)[1].strip().lower()
channel = message['channel']
# return text after the # mention, white space removed
return command, channel
return None, None
if __name__ == "__main__":
READ_WEBSOCKET_DELAY = 1 # 1 second delay between reading from firehose
if slack_client.rtm_connect():
print("starterbot connected and running!")
while True:
command, channel = parse_slack_output(slack_client.rtm_read())
if command and channel:
handle_command(command, channel)
time.sleep(READ_WEBSOCKET_DELAY)
else:
print("Connection failed. Invalid Slack token or bot ID?")
bot_id_py
import os
from slackclient import SlackClient
import pdb
BOT_NAME = 'pilot4u'
slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN'))
if __name__ == "__main__":
api_call = slack_client.api_call("users.list")
if api_call.get('members'):
pdb.set_trace()
# Retrieve all users so we can find our bot
users = api_call.get('members')
for user in users:
if 'name' in user and user.get('name') == BOT_NAME:
print("Bot ID for '" + user ['name'] + "'is " +
user.get('id'))
else:
print("could not find bot user with the name " + BOT_NAME)

Can't receive update messages from user

I am trying to create a bot that receives a response from the user and asks again if needed. The problem is that after:
update.reply_text("Did you report all you working hour on freshdesk for this week?, ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True))
I can't get the new updates. The message text remains /start in the first print, and the second print doesn't work at all.
How can I get correctly the response from the user? Can it be an issue related to ReplyMarkup?
def check_the_week(bot, update):
agent_username = update.message.from_user['username']
parameters = {"username": agent_username}
url = "{}/weekly_hours/".format(API_URL)
report = get_request_forwarder(url=url, method="GET", parameters=parameters)["messages"]
reply_keyboard = [['YES', 'NO']]
bot.send_message(
chat_id=update.message.chat_id,
text=report,
reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)) # sends the total nr of hours
print update.message.text
update.reply_text("Did you report all you working hour on freshdesk for this week?",
ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True))
print update.message.text
if update.message.text == "YES":
update.message.reply_text(text="Are you sure?", reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True))
# Asks confirmation
if update.message.text == "YES":
update.message.reply_text(text="Thank you for reporting your working hours in time!")
elif update.message.text == "NO":
update.message.reply_text(text="Please, check you time reports and add missing")
elif update.message.text == "NO":
update.message.reply_text(text="Please, check you time reports and add missing")
def main():
# Create the EventHandler and pass it your bot's token.
updater = Updater(TELEGRAM_TOKEN)
j = updater.job_queue
# # Get the dispatcher to register handlers
dp = updater.dispatcher
# # Start the Bot
dp.add_handler(CommandHandler("start", check_the_week))
# Send information to manager by command
updater.start_polling()
updater.idle()
print("bot started")
if __name__ == '__main__':
main()
Because you are using a CommandHandler, which is only used to capture a single command at a time.
What you want to do can be achieved by using a ConversationHandler. Please read the example scripts here and here. Also you can read more details on the handler here.

Categories

Resources