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
Related
I am working with python-telegram-bot building a menu system.
I created a Django project, as shown below, using Webhook to connect to Telegram.
When the first message is sent, I ask the contact for their phone number and
keep this number so I don't need to ask for it in the next messages in the conversation,
but it’s not working.
I tried to store it in request.session, but apparently every new message is a new session and so I lose the number.
How can I solve this? Every help is welcome.
view.py
import json
from django.http.response import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from core.message import proccess
#csrf_exempt
def event(request):
json_telegram = json.loads(request.body)
proccess(request, json_telegram)
return HttpResponse()
messages.py
import telegram
from bot_webhook.settings import TOKEN
from telegram import InlineKeyboardMarkup, InlineKeyboardButton
bot = telegram.Bot(token=TOKEN)
def proccess(request, json_telegram):
if 'login' in request.session:
msg_options(json_telegram)
else:
try:
request.session['login'] = json_telegram['message']['contact']['phone_number']
msg_options(json_telegram)
except BaseException:
msg_login(json_telegram)
def msg_login(json_telegram):
chat_id = json_telegram['message']['from']['id']
reply_markup = telegram.ReplyKeyboardMarkup(
[[telegram.KeyboardButton('Click to Login', request_contact=True)]],
resize_keyboard=True,
one_time_keyboard=True
)
bot.sendMessage(chat_id, 'I need to authorize your access.', reply_markup=reply_markup)
def msg_options(json_telegram):
chat_id = json_telegram['message']['from']['id']
first_name = json_telegram['message']['from']['first_name']
last_name = json_telegram['message']['from']['last_name']
button_list = []
button_list.append(InlineKeyboardButton('Button One', callback_data='query_one'))
button_list.append(InlineKeyboardButton('Button two', callback_data='query_two'))
reply_markup = InlineKeyboardMarkup(build_menu(button_list, n_cols=2))
bot.send_message(text='Hello {0} {1}!\nI have this options:'.format(first_name, last_name),
chat_id=chat_id,
reply_markup=reply_markup)
def build_menu(buttons,
n_cols,
header_buttons=None,
footer_buttons=None):
menu = [buttons[i:i + n_cols] for i in range(0, len(buttons), n_cols)]
if header_buttons:
menu.insert(0, [header_buttons])
if footer_buttons:
menu.append([footer_buttons])
return menu
Once I haven't found a solution in Api, I worked with this solution:
When there is an interaction, I check if the contact already exists in my database,
if positive I continue the conversation,
if negative I ask for identification by sharing the phone.
So when I get the information, I record it in the database,
so that in a new interaction I can identify it automatically.
Record it in my database is it a option, another option is as text archive.
If you have a better option, please show it for us.
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.
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)
I am building some telegram bot on python (using this framework pyTelegramBotAPI). And I ran into the problem with user input. I need save user input(it can be any text) after certain bot's message. For example:
Bot: - Please describe your problem.
User: - Our computer doesn't work.
Then I need to save this text "Our computer doesn't work" to some variable and go to the next step.
Here's my code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import telebot
import constants
from telebot import types
bot = telebot.TeleBot(constants.token)
#bot.message_handler(commands=['start'])
def handle_start(message):
keyboard = types.InlineKeyboardMarkup()
callback_button = types.InlineKeyboardButton(text="Help me!", callback_data="start")
keyboard.add(callback_button)
bot.send_message(message.chat.id, "Welcome I am helper bot!", reply_markup=keyboard)
#bot.inline_handler(lambda query: len(query.query) > 0)
def query_text(query):
kb = types.InlineKeyboardMarkup()
kb.add(types.InlineKeyboardButton(text="Help me!", callback_data="start"))
results = []
single_msg = types.InlineQueryResultArticle(
id="1", title="Press me",
input_message_content=types.InputTextMessageContent(message_text="Welcome I am helper bot!"),
reply_markup=kb
)
results.append(single_msg)
bot.answer_inline_query(query.id, results)
#bot.callback_query_handler(func=lambda call: True)
def callback_inline(call):
if call.message:
if call.data == "start":
bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text="Please describe your problem.")
#here I need wait for user text response, save it and go to the next step
I have the idea with using message_id in statement, but still can't implement it. How I can solve this? Any ideas? Thank you.
This will help you
https://github.com/eternnoir/pyTelegramBotAPI/blob/master/examples/step_example.py
import telebot
import constants
from telebot import types
bot = telebot.TeleBot(constants.token)
#bot.message_handler(commands=['start'])
def start(message):
sent = bot.send_message(message.chat.id, 'Please describe your problem.')
bot.register_next_step_handler(sent, hello)
def hello(message):
open('problem.txt', 'w').write(message.chat.id + ' | ' + message.text + '||')
bot.send_message(message.chat.id, 'Thank you!')
bot.send_message(ADMIN_ID, message.chat.id + ' | ' + message.text)
bot.polling()
its not a python or even programming related question. its more like designing problem. but anyway.
the solution is keeping session for users. for example user send you:
Our computer doesn't work.
at first you create a session for this user(the identity should be a user id) then send him/her a proper message. when user send the next message at first you look at the user status and see if he/she has a session or not. if he/she has session you continue with second step. i develop a bot like this and used dictionary in order to store users sessions. but it make all thing little complicated.
You can use Forcereply.
Upon receiving a message with this object, Telegram clients will display a reply interface to the user (act as if the user has selected the bot‘s message and tapped ’Reply'). This can be extremely useful if you want to create user-friendly step-by-step interfaces without having to sacrifice privacy mode. https://core.telegram.org/bots/api#forcereply
i know how fix that. It took 3 years for solution.
Just look at my code and make your own. Thx
#bot.callback_query_handler(func=lambda call: True)
def callback_inline(call): #your call
UserID = str(call.message.chat.id)
if call.data == 'PhotoTEXT':
#bot.message_handler(content_types=['text'])
def SetTEXTonPHOTO(message): # THIS FUNCTION
sent = bot.send_message(message.chat.id,'send me text')
bot.register_next_step_handler(sent, TextONphoto)
def TextONphoto(message): #Thsi function add text on photo
im = Image.open('UserData/Files/photos/not_converted/'+UserID+'.jpg')
idraw = ImageDraw.Draw(im)
text = message.text
font = ImageFont.truetype("arial.ttf", size=18)
idraw.text((10, 10), text, font=font)
im.save('UserData/Files/photos/converted/'+UserID+'.jpg')
im.show()
SetTEXTonPHOTO(call.message) #just run your function
with open('UserData/Files/photos/converted/'+UserID+'.jpg', 'rb') as file:
bot.send_document(UserID,file)
I think i helped you friends <3
You should save the data in cache or database.
I've little question about Django Channels, WebSockets, and chat applications. Serving with google gets me to chatrooms, where people can connect and start a chat. But I don't know how one user can send another user instant message.
For example:
1) I add John to friends, and want to start chat.
2) On server side I can generate object Room, with me and John as members.
3) When I send message via WebSocket to this room, I know for who this message is, but I don't know how to get John's channel
#channel_session_user_from_http
def ws_connect(message):
rooms_with_user = Room.objects.filter(members=message.user)
for r in rooms_with_user:
Group('%s' % r.name).add(message.reply_channel)
#channel_session_user
def ws_receive(message):
prefix, label = message['path'].strip('/').split('/')
try:
room = Room.objects.get(name=label)
except Exception, e:
room = Room.objects.create(name=get_random_string(30))
for u in message.chmembers:
room.members.add(u)
# here can be somethis like this
# try
reply_channel = Channels.objects.get(online=True, user=u)
Group('%s' % r.name).add(reply_channel)
Group('%s' % room.name).send({
"text": "%s : %s" % (message.user.username, message['text']),
})
#channel_session_user
def ws_disconnect(message):
prefix, label = message['path'].strip('/').split('/')
Group(label).discard(message.reply_channel)
Simply make "automatic unique rooms" for user pairs. The rest stays the same. For example like this
def get_group_name(user1, user2):
return 'chat-{}-{}'.format(*sorted([user1.id, user2.id]))
Give it two user objects, and it returns a unique room for that pair of users, ordered the User.id, something like "chat-1-2" for the users with User.id "1" and "2".
That way, a user can connect with more than one logged-in device and still get the messages sent between the two users.
You can get the authenticated user's object from message.user.
For the receiving User object, I'd just sent the username along with the message. Then you can unpack it from the message['text'] the same way you unpack the actual message.
payload = json.loads(message.content['text'])
msg = payload['msg']
sender = message.user
receiver = get_object_or_404(User, username=payload['receiver'])
# ... here you could check if they have required permission ...
group_name = get_group_name(sender, receiver)
response = {'msg': msg}
Group(group_name).send({'text': json.dumps(response)})
# ... here you could persist the message in a database ...
So with that, you can drop all the "room" things from your example, including the room table etc. Because group names are always created on-the-fly when a message is send between two users.
Another important thing: One user will connect later than the other user, and may miss initial messages. So when you connect, you probably want to check some "chat_messages" database table, fetch the last 10 or 20 messages between the user pair, and send those back. So users can catch up on their past conversation.