Creating Slackbot with Google Sheets integration using python and git - python

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)

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

The bot for VK answers in a private messages, and not in a conversation

I am creating a reference bot for chatting in VK in Python using the Callback Api. The bot works correctly if you write to the group messages. However, if you write to a conversation (to which the bot is added), it replies to private messages. All rights to read, etc. issued. As I understand it (studying information on the internet), I use user_id, not chat_id. But I didn't understand how to fix it correctly (
p.s. It is advisable that the bot write both in private messages and in a conversation, depending on where they ask.
p.p.s perhaps the question seems ridiculous, but I just started to study this area, and I did not find the answer on the net :-)
The bot itself:
import vk
import random
import messageHandler
# app.route ('/', methods = ['POST'])
def processing ():
data = json.loads (request.data)
if 'type' not in data.keys ():
return 'not vk'
if data ['type'] == 'confirmation':
return confirmation_token
elif data ['type'] == 'message_new':
messageHandler.create_answer (data ['object'] ['message'], token)
return 'ok'
"Responder":
import importlib
from command_system import command_list
def load_modules ():
# path from the working directory, it can be changed in the application settings
files = os.listdir ("mysite / commands")
modules = filter (lambda x: x.endswith ('. py'), files)
for m in modules:
importlib.import_module ("commands." + m [0: -3])
def get_answer (body):
# Default message if unrecognizable
message = "Sorry, I don't understand you. Write '/ help' to see my commands."
attachment = ''
for c in command_list:
if body in c.keys:
message, attachment = c.process ()
return message, attachment
def create_answer (data, token):
load_modules ()
user_id = data ['from_id']
message, attachment = get_answer (data ['text']. lower ())
vkapi.send_message (user_id, token, message, attachment)
I don't speak English well, so I apologize for the crooked translation)
Use Peer_id, instead of from_id. (data->object->peer_id)
(i used php, but i had a similar problem. this is the solution)
probably something like this:
def create_answer (data, token):
load_modules ()
user_id = data ['peer_id'] # id source edited
message, attachment = get_answer (data ['text']. lower ())
vkapi.send_message (user_id, token, message, attachment)
from_id - person who sent the message
peer_id - in which dealogue message was received. (for groups it looks like 20000005)
So, you will send the message to conversation (does not matter is this PM or conversation with a lot of people)

Pulling historical channel messages python

I am attempting to create a small dataset by pulling messages/responses from a slack channel I am a part of. I would like to use python to pull the data from the channel however I am having trouble figuring out my api key. I have created an app on slack but I am not sure how to find my api key. I see my client secret, signing secret, and verification token but can't find my api key
Here is a basic example of what I believe I am trying to accomplish:
import slack
sc = slack.SlackClient("api key")
sc.api_call(
"channels.history",
channel="C0XXXXXX"
)
I am willing to just download the data manually if that is possible as well. Any help is greatly appreciated.
messages
See below for is an example code on how to pull messages from a channel in Python.
It uses the official Python Slack library and calls
conversations_history with paging. It will therefore work with
any type of channel and can fetch large amounts of messages if
needed.
The result will be written to a file as JSON array.
You can specify channel and max message to be retrieved
threads
Note that the conversations.history endpoint will not return thread messages. Those have to be retrieved additionaly with one call to conversations.replies for every thread you want to retrieve messages for.
Threads can be identified in the messages for each channel by checking for the threads_ts property in the message. If it exists there is a thread attached to it. See this page for more details on how threads work.
IDs
This script will not replace IDs with names though. If you need that here are some pointers how to implement it:
You need to replace IDs for users, channels, bots, usergroups (if on a paid plan)
You can fetch the lists for users, channels and usergroups from the API with users_list, conversations_list and usergroups_list respectively, bots need to be fetched one by one with bots_info (if needed)
IDs occur in many places in messages:
user top level property
bot_id top level property
as link in any property that allows text, e.g. <#U12345678> for users or <#C1234567> for channels. Those can occur in the top level text property, but also in attachments and blocks.
Example code
import os
import slack
import json
from time import sleep
CHANNEL = "C12345678"
MESSAGES_PER_PAGE = 200
MAX_MESSAGES = 1000
# init web client
client = slack.WebClient(token=os.environ['SLACK_TOKEN'])
# get first page
page = 1
print("Retrieving page {}".format(page))
response = client.conversations_history(
channel=CHANNEL,
limit=MESSAGES_PER_PAGE,
)
assert response["ok"]
messages_all = response['messages']
# get additional pages if below max message and if they are any
while len(messages_all) + MESSAGES_PER_PAGE <= MAX_MESSAGES and response['has_more']:
page += 1
print("Retrieving page {}".format(page))
sleep(1) # need to wait 1 sec before next call due to rate limits
response = client.conversations_history(
channel=CHANNEL,
limit=MESSAGES_PER_PAGE,
cursor=response['response_metadata']['next_cursor']
)
assert response["ok"]
messages = response['messages']
messages_all = messages_all + messages
print(
"Fetched a total of {} messages from channel {}".format(
len(messages_all),
CHANNEL
))
# write the result to a file
with open('messages.json', 'w', encoding='utf-8') as f:
json.dump(
messages_all,
f,
sort_keys=True,
indent=4,
ensure_ascii=False
)
This is using the slack webapi. You would need to install requests package. This should grab all the messages in channel. You need a token which can be grabbed from apps management page. And you can use the getChannels() function. Once you grab all the messages you will need to see who wrote what message you need to do id matching(map ids to usernames) you can use getUsers() functions. Follow this https://api.slack.com/custom-integrations/legacy-tokens to generate a legacy-token if you do not want to use a token from your app.
def getMessages(token, channelId):
print("Getting Messages")
# this function get all the messages from the slack team-search channel
# it will only get all the messages from the team-search channel
slack_url = "https://slack.com/api/conversations.history?token=" + token + "&channel=" + channelId
messages = requests.get(slack_url).json()
return messages
def getChannels(token):
'''
function returns an object containing a object containing all the
channels in a given workspace
'''
channelsURL = "https://slack.com/api/conversations.list?token=%s" % token
channelList = requests.get(channelsURL).json()["channels"] # an array of channels
channels = {}
# putting the channels and their ids into a dictonary
for channel in channelList:
channels[channel["name"]] = channel["id"]
return {"channels": channels}
def getUsers(token):
# this function get a list of users in workplace including bots
users = []
channelsURL = "https://slack.com/api/users.list?token=%s&pretty=1" % token
members = requests.get(channelsURL).json()["members"]
return members

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