I am trying to create a slack command that takes params, generate image and return and image back to user, also the image upload should display as the bot user.
I follow this post: Can you upload a file to the Slack API using files.upload as a different user?
I tried creating slack app, a bot user according to it, and slack file upload api as follows:
def send_picture(channel_id, graph_details):
sender_token = "xoxb-..." # bot-user token
pic = {
'file' : ('img.png', open('img.png', 'rb'), 'png')
}
payload={
"title" : "Serverless App Report",
"channels" : [channel_id]
}
r = requests.post("https://slack.com/api/files.upload", params=payload, files=pic)
Whenever the user do the slack command(POST with params), I can parse the channel_id to find out the sender and pass it into the channel_id into the file upload api.
Posting it into public channel is working fine. But posting it back to the user who do the command failed with the error: {"ok":false,"error":"invalid_channel","channel":"DXXXXXXX"}
The reason you get this error is that your bot user is apparently not a member of the private channel in which the user invoked your slash command. Therefore your app can not upload any files to it. This normal behavior and part of Slack's security architecture.
There are 3 workarounds for this issue:
You can make sure the bot user from your Slack app is added as member to all private channels where your slash command needs to work
You can request every user to "install" your Slack app once. Thereby providing your app with a user specific Slack token which your app can then use to access the private channel.
You can refrain from uploading files and instead reply with a message, which can include images too. A Slack app can always reply to a Slash command, no matter in which kind of channel it is issued.
Related
I am trying to create a simple "chat bot" for google hangouts that sends regular messages on a chat. I found this documentation but I find it tremendously complicated.
It contains a "Complete example" but I am not sure about how to find the "space" ID for an existing google hangout chat. This is nowhere explained. How do I find the "space" ID for an existing google chat?
And in addition: Is there a SIMPLE (!!!) documentation somewhere how to just simply post a message to an existing chat?
Answer:
You can either use spaces.list to get a list of spaces the bot is a member of followed by spaces.get for additional information on the space, or alternatively set up a room-specific Webhook.
Additional Information:
To send messages to a room without a respond trigger, you must use a service account
Bot-initiated message documentation can be found here.
Important Note: You can only use the Google Hangouts Chat API if you have a Google Workspace account - it will not work with Gmail alone. The second solution, which uses a Webhook, requires access to https://chat.google.com which is only available to Google Workspace domains. Unfortunately this is not at all possible using a consumer #gmail.com account.
Using the Hangouts Chat API:
Once you have a service account set up as per Step 1 on this page, you can download the credentials for the service account from the Google Cloud Project UI, by clicking on the ⋮ button to the right of the service account name, and following the Create key button and selecting JSON as the key type. Make sure to save this file well as there is only one copy of this key.
With this JSON file downloaded, you can use it in your python code as the credentials when setting up your service object:
from httplib2 import Http
from oauth2client.service_account import ServiceAccountCredentials
from apiclient.discovery import build
scopes = 'https://www.googleapis.com/auth/chat.bot'
credentials = ServiceAccountCredentials.from_json_keyfile_name(
'credentials.json', scopes)
chat_service = build('chat', 'v1', http=credentials.authorize(Http()))
To make the spaces.list request, you can use this newly built chat_service, and extract hte list of spaces from the response:
def extract(n):
return n['name']
spaces_list = chat_service.spaces().list().execute()
all_spaces = map(extract, spaces_list['spaces'])
You can then use one of these spaces to send a message from the python program:
response = chat_service.spaces().messages().create(
parent=all_spaces[0],
body={'text': 'Test message'}).execute()
print(response)
Things to Remember:
Make sure the Hangouts Chat API is enabled for your project at https://console.cloud.google.com
Once enabled, make sure the bot is configured with a name, logo and description.
The Connection settings for the bot must also be set up; the method is not so important; you can for example choose Apps Script project and enter the deployment ID for an empty deployed project.
Using a Webhook:
Instead of directly using the API, you can instead set up a webhook for a specific chat and with a hardcoded URL, you can send messages to a room from an external script.
The full steps are set out on this page but I'll go through it here also.
Go to the room to which you wish to send a message at https://chat.google.com, and from the dropdown menu next to the room's name, select Manage Webhooks.
Enter a name and an optional avatar for your bot, and press SAVE. This will give you a webhook URL to use in your python script.
Locally, make sure you have httplib2 installed in your environment, and copy the following script into a new .py file:
from json import dumps
from httplib2 import Http
def main():
"""Hangouts Chat incoming webhook quickstart."""
url = 'webhook-url'
bot_message = {
'text' : 'Hello from a Python script!'}
message_headers = {'Content-Type': 'application/json; charset=UTF-8'}
http_obj = Http()
response = http_obj.request(
uri=url,
method='POST',
headers=message_headers,
body=dumps(bot_message),
)
print(response)
if __name__ == '__main__':
main()
Manking sure to replace the webhook-url string with the webhook provided in the Chat UI in the previous step.
Now you can just save the file and run it - this will send a message automatically to the aforementioned chat space:
References:
Creating new bots | Google Chat API | Google Developers
Method: spaces.list | Google Chat API | Google Developers
Method: spaces.get | Google Chat API | Google Developers
REST Resource: spaces | Google Chat API | Google Developers
See this API, it's very interesting:
https://pypi.org/project/hangups/
There is some projects who uses Hangups, among then, HangupsBot:
https://github.com/xmikos/hangupsbot
When sending the response to a Slack slash command, I would like to send it under the user that has launched the slach command.
I have created a Slack app with a slash command. It calls my Flask webservice and I use the "response_url" webhook to write something back to the channel. The response in the channel is given by my app. This works as expected. But I would like for the response to be displayed as if a user has given it.
An example would be the Slack plugin from giphy. If I call it, I get an ephemeral message to choose the gif I would like. But then it is posted in the channel under my name.
So I have 2 questions:
How does the API call look like to respond to the slash command as a specific user?
What permissions for my app are required to allow for such behaviour of the app?
The Slack API documentation is comprehensive, but much research didn't yield the result I wanted.
Thanks!
When you are using response_url, you can't customize your username or icon. For this, you'll need to use chat.postMessage API method. There are now two ways to achieve what you need here:
Use user token: This gives you access to take actions on the behalf of the user. Although, you'll need to take authorization from every user you want post the message as.
Request chat:write.customize scope with your bot token: You can post a message with icon_url and username parameters where you can provide the user's icon and name respectively for both the parameters. This is much easier, as this only requires one-time authorization.
More information in the official documentation.
When creating a slack app, it creates a new "channel" in the left hand menu. I want to be able to send a message to specific users and not to all users in a workspace who have integrated with the app.
For example, if I make the following request:
curl -X POST -H 'Content-type: application/json' --data '{"text":"Hello, World!"}' https://hooks.slack.com/services/ABxxx/CDxxx/EFxxxxxx
It will send a message to all users who have integrated with my app with the text "Hello World".
But I only want to send a message to user A without User B being notified.
I don't want to message a user directly and it to appear to come from slack bot. I want the message to appear to come from my bot / app.
How can this be achieved via slack API?
I found this quite hard to explain so please let me know if you'd like me to clarify anything.
The problem of your request that you are using a hook URL which is bound to a particular channel (you pick it during Slack App installation).
To send a direct message to the user on behalf of your bot, you need to consider the following things (this is not the single way to achieve it, but works for me):
Ensure you have a bot registered for your Slack App.
Ask for bot and chat:write:bot permissions during App installation process (example for Slack Install button and here).
Store the bot access token on successful installation (see for details).
Now using the bot access token you can send Slack API requests.
To achieve what you need, use chat.postMessage API method. channel argument can be user ID (e.g. U0G9QF9C6). By setting up as_user argument to true, your message will be always sent on behalf (name and icon) of your bot (seems for bot tokens it's always like this, but it's recommend it to specify it explicitly).
Hope it helps. Feel free to ask for details.
I'm working on a new Workspace app for Slack. I have a use case where I need to send notifications to users in Slack, through a direct message (or IM). Since the chat.postMessage endpoint requires a channel ID, I can get the existing IM channels using conversations.list and send them the notification.
However, if the user hasn't yet opened an IM channel from their side, I need to create one. It seems that neither Web API endpoints (conversations.open or im.open) support Workspace tokens. I keep getting not_allowed_token_type error response. I can create a public channel with conversations.create, but that's not what I need.
Is there another to open an IM channel to a user when using a Workspace token?
Took me awhile to figure this out. You need to add/request the conversations.app_home:create scope to your permissions. Then you can just specify the user ID as the channel arg in a chat.postMessage call.
I'd like to check that my bot credentials (appId + appSecret) are ok to connect to https://api.botframework.com/bot/v1.0/messages.
I can't send a real message because i have no conversation running so I tried to post the following json message :
{ "type": "Ping"} but the response i got was
{
"error": {
"message": "Expression evaluation failed. Object reference not set to an instance of an object.",
"code": "ServiceError"
}
}
Is there any way to check if my access to the api is ok?
If you've registered your bot, you can visit the Bot Framework page, click on the My Bots menu, and select your registered bot. On your bot page, scroll down to the bottom left and there's a test box.
Also, you can use the emulator. It has a place in the upper right corner to replace the default credentials with your bot credentials. Then change the URL to where you have your bot deployed. Tip: remember to append 'api/messages' to the URL.
Download the BotFrameworkEmulator to test connectivity to your bot. It works on windows and OSX if you have mono installed. You can change the default settings that the emulator uses by typing '/settings' after running it. You will be prompted to enter your appId, appSecret and url endpoint for sending and receiving messages to/from your bot.
You can also use the directline rest api to initiate conversations and send messages to your bot