how to get actions result from slack api's attachment - python

How to receive attachment actions using python SlackClient. How to get user's reply?
Code :
intro_msg = json.dumps([{"text": "Choose an action", "fallback": "You are unable to choose an option",
"callback_id": "lunch_intro", "color": "#3AA3E3", "attachment_type": "default",
"actions": [
{"name": "enroll", "text": "Enroll", "type": "button", "value": "enroll"},
{"name": "leave", "text": "Leave", "type": "button", "value": "leave"}]}])
result = self.sc.api_call("chat.postMessage", channel=channel, text="What would you like to do?",attachments=intro_msg,as_user=True)
https://api.slack.com/interactive-messages

Define a Slack app
Your app (Python script) needs to run on a public webserver that can be reached by Slack (can also by your local machine if you use tools like ngrok)
Put the URL for your app as "request URL" in your Slack app configuration under "Interactive messages"
Once the user clicks one of the button, Slack will call your app with a POST request which will contain the action that the use chose
Check out the documentation you linked for details like how the data structure of the Slack request looks like.

Related

Reading body of Slack event using python-slackclient

I'm trying to create a serverless slack bot in AWS Lambda. I managed to get the app to send a message to a user in Slack with an interactive button, which sends a post back to the app when clicked. The problem is that the body of this message (the one from the button click) has the body of the JSON all garbled. Here is a reduced version of the garble:
'body': 'cGF5bG9hZD0lN0IlMjJ0eXBlJTIyJTNBJTIyYmxvY2tfYWN0aW9...
The rest of the JSON object looks normal.
On the other hand, the button object I'm sending to slack is this one:
{
"type": "button",
"text": {
"type": "plain_text",
"emoji": True,
"text": "Yes"
},
"style": "primary",
"value": "click_me_123"
},
What am I missing? Appreciate all the help I can get!
Solution: It was that the body of the response, it was encoded in Base64, so I had to decode that with:
base64.b64decode('encoded_string').decode('utf-8')

How to publish a View to Slack app for all users?

I have a Slack App that is connected to an AWS Lex bot. Thus, the Request URL for the Slack app is the Postback URL provided by Lex. However, I want to add a Home tab for the app, but am unable to publish a surface for all users. The Slack API only seems to allow you to publish a surface for a specific user (user_id is a required parameter for the POST call). How can I publish this view to all users who use the app?
publish_url = "https://slack.com/api/views.publish"
header = {'content-type':'application/json'}
parameters = {
"token": slack_token,
"user_id": member_id, # <--- This is my problem
"view": json.dumps({
"type": "home",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "Welcome to *Survey Analyzer*! ..."
}
},
...
]
})
}
r = requests.post(publish_url, params=parameters, headers=header)
When I use my own member ID, it pushes the view properly to me and me only. I've also tried using the app's ID, but that doesn't seem to push the view to any users.
You can only publish a home tab for each user separately. You can use users.list to retrieve all users of a workspace and then call views.publish for each user in that list.
Alternatively you can subscribe to the app_home_opened event through the Events API. Once a user opens the home tab it will fire an event including the user's id. That way you'll only publish a view for a user who is actually visiting the home tab of your app.

How to send ad-hoc app download link itms-service on slack using message buttons or link

I have a slack /Slash command that generates the app file link. I want to send that link to a user as a button or link but it has to be prefixed with:
itms-services://?action=download-manifest&url={download_link}
Currently slack is not recognizing this as a valid link but it's mandatory by iOS because of permission issues.
Basically I want to mimic the download button on web on slack so user is not required to visit the website.
On Web this link itms-services://?action=download-manifest&url={download_link} works fine and user is asked to authorize the download.
test_attachment = [
{
"color": "#CC0000",
"actions": [
{
"type": "button",
"text": ":red_circle: Download Link:",
"url": "itms-services://?action=download-manifest&url={download_link}"
}
]
}
]
slack_client.api_call("chat.postMessage", channel=channel_id, text=text, attachments=json.dumps(test_attachment))
Another example:
<a href="itms-services://?action=download-manifest&url=http://loqi.me/app/Geoloqi.plist">
Download Geoloqi
</a>
This will work on Web and how to make it work on slack messages.
An itms-services link is not recognize as a valid URL by slack parser because its address (the thing we usually found just after ://) is empty.
A quick fix is to fill it with a dummy address for example 0.0.0.0.
Here is a block kit that works :
{
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "Try to install me:"
},
"accessory": {
"type": "button",
"text": {
"type": "plain_text",
"text": "Install",
"emoji": true
},
"url": "itms-services://0.0.0.0?action=download-manifest&url={download_link}"
}
}
]
}
and it looks like :
I had a similar problem in one of my apps where I wanted to provide a download button for a dynamically generated image file.
As far as I know there is no switch or option in Slack that allows you to do this, so your only option is to use a helper web app.
The approach would be:
User clicks a link button on Slack that opens your helper web app in the browser
Helper web app performs the actual download (no further user interaction required)
My guess is the user will need to authenticate in the browser anyways, so this should not create any inconvenience for the user. But of course you would need to provide the additional web helper app.

Slack bot, register click on message button

I am trying to build a Slack bot in Python. I want my bot to send a message with interactive buttons on it, and then based on which the user clicks on, run a function in Python. I do not seem to find how to do this.
My code now look like this:
message = "message"
attachments = [{"text": "message",
"attachment_type": "default",
"actions": [
{
"name": "list",
"text": "message",
"type": "select",
"options": [
{
"name": "1",
"text": "1",
"type": "button",
"value": "1"
},
{
"name": "1",
"text": "1",
"type": "button",
"value": "2"
}
]}]}]
sc.api_call("chat.postMessage",
channel=channel,
text=message,
attachments=attachments)
So that gives me a message with two buttons. I, however, want to run a function based on the answer the user gives.
So say that if they click 1, function1() runs and when they click 2, function2() runs.
The Slack api documentation is quite confusing about how to do this, and the "listener" they provide rtm_read() does not pick on the user clicking on one of the buttons.
So if anyone could help me with this, it would be much appreciated.
When you click a button in a slack conversation it's basically applying a callback. The callback is sent somewhere that you define in the App's setting, then THAT service decides what to do next with the information that's given.
First you need to create a new Slack App.
After it's created click on the App to go to its Basic Information page.
From there, on the left side under Features find "Interactive Components".
Register the two URLs that will receive the POST data from clicking on a button.
Interpret the data and proceed :)
From the Slack documentation you can find their walkthrough here.
You're going to need a running web server, something simple in Flask will work just fine.
from flask import Flask, request
app = Flask('SlackReceiver')
#app.route('/slack/message', methods=['POST'])
def incoming_slack_message():
req = request.get_json()
# .. do something with the req ..
return 'action successful'
#app.route('/slack/options', methods=['POST', 'OPTIONS'])
def incoming_slack_options():
# .. idk ..
return 'ok'
if __name__ == '__main__':
app.run('0.0.0.0', 8088, debug=False)
...
Lastly, according to the docs you need to host this application on a web server with an HTTPS valid certificate configured. Setting up a server is beyond the scope of this question, the easiest way to get free (valid) HTTPS certs is with Let's Encrypt and certbot.

Adding attachment to Slackbot

I'm trying to add an attachment to a slack message via their API. I'm using the python wrapper they recommend. I can send and receive basic messages but when I try to add an attachment in the form of 2 buttons it fails. I have made a slack app and linked the bot as they state in their API. I've carefully reviewed the API and cannot figure out what is going on.
def process_message(message, channel):
intro_msg = json.loads('{
"text": "What would you like to do?",
"attachments": [
{
"text": "Choose an action",
"fallback": "You are unable to choose an option",
"callback_id": "lunch_intro",
"color": "#3AA3E3",
"attachment_type": "default",
"actions": [
{
"name": "enroll",
"text": "Enroll",
"type": "button",
"value": "enroll"
},
{
"name": "leave",
"text": "Leave",
"type": "button",
"value": "leave"
}
]
}
]
}')
r = sc.api_call("chat.postMessage", channel=channel, attachments=intro_msg)
The response is only {u'ok': False, u'error': u'no_text'}
I figured it out.
The python wrapper separates out the payload.
intro_msg = json.dumps([{"text":"Choose an action","fallback":"You are unable to choose an option","callback_id":"lunch_intro","color":"#3AA3E3","attachment_type":"default","actions":[{"name":"enroll","text":"Enroll","type":"button","value":"enroll"},{"name":"leave","text":"Leave","type":"button","value":"leave"}]}])
sc.api_call("chat.postMessage", channel=channel, text="What would you like to do?", attachments=intro_msg, as_user=True)
My payload was all in attachments since that is how they format it in their API docs. The attachments needs to just be the array after the attachments key.
I guess the basic simple example works.
Example:
from slackclient import SlackClient
slack_token = os.environ["SLACK_API_TOKEN"]
sc = SlackClient(slack_token)
sc.api_call(
"chat.postMessage",
channel="#python",
text="Hello from Python! :tada:"
)
According to https://api.slack.com/methods/chat.postMessage and https://api.slack.com/docs/message-buttons#readying_your_application_for_message_buttons the attachments has to be an array. How about sending it as array:
json.loads('[{"text":"What would you like to do?","attachments":[{"text":"Choose an action","fallback":"You are unable to choose an option","callback_id":"lunch_intro","color":"#3AA3E3","attachment_type":"default","actions":[{"name":"enroll","text":"Enroll","type":"button","value":"enroll"},{"name":"leave","text":"Leave","type":"button","value":"leave"}]}]}]')
As there is no further magic involved but the requests module https://github.com/slackapi/python-slackclient/blob/ddf9d8f5803040f0397d68439d3217d1e1340d0a/slackclient/_slackrequest.py I'd give it a try with the sending as array.

Categories