[BTY] Day 14: How to send notification from your Python app to Slack?
Dang Hoang Nhu Nguyen
Posted on February 21, 2022
This post was for 18.02.2022
A lot of time, you want to be noticed when something happens to your application on the server, so you can take action as soon as possible.
Sending Slack messages to a channel in case of exceptions (with phone notifications, emails included in settings) is one of the simplest ways I found to deal with the mentioned issue.
Disclaimer: This is a legacy custom integration - an outdated way for teams to integrate with Slack. You may visit the Slack documentation for update and the modern way to do so.
1. Create new Slack workspace
2. Setting up
- Create new channel ⇒ Right click and select
Open channel details
- Integrations > Add an App
- Search and select
Incoming Webhooks
- Add Incoming WebHooks to the target channel (e.g #test-notification)
Setup Instructions (from the documentation)
We'll guide you through the steps necessary to configure an Incoming Webhook so you can start sending data to Slack.
Webhook URL
https://hooks.slack.com/services/xxxxxxxxxxxxxxxxxxxxx
Sending Messages
You have two options for sending data to the Webhook URL above:
- Send a JSON string as the
payload
parameter in a POST request - Send a JSON string as the body of a POST request
For a simple message, your JSON payload could contain a text
property at minimum. This is the text that will be posted to the channel.
A simple example:
payload={"text": "This is a line of text in a channel.\nAnd this is another line of text."}
This will be displayed in the channel as:
Adding links
To create a link in your text, enclose the URL in <> angle brackets. For example: payload="text": ""
will post a clickable link to https://slack.com. To display hyperlinked text instead of the actual URL, use the pipe character, as shown in this example:
payload={"text": "A very important thing has occurred! <https://alert-system.com/alerts/1234|Click here> for details!"}
This will be displayed in the channel as:
Customized Appearance
You can customize the name and icon of your Incoming Webhook in the Integration Settings section below.However, you can override the displayed name by sending "username": "new-bot-name"
in your JSON payload. You can also override the bot icon either with "icon_url": "https://slack.com/img/icons/app-57.png"
or "icon_emoji": ":ghost:"
.
Channel Override
Incoming webhooks have a default channel, but it can be overridden in your JSON payload. A public channel can be specified with "channel": "#other-channel"
, and a Direct Message with "channel": "@username"
.
Example
Putting this all together, here is a sample curl request for posting to a channel.
curl -X POST --data-urlencode "payload={\"channel\": \"#test-notification\", \"username\": \"webhookbot\", \"text\": \"This is posted to #test-notification and comes from a bot named webhookbot.\", \"icon_emoji\": \":ghost:\"}" https://hooks.slack.com/services/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
This will be displayed in the channel as:
Python Code
import requests
from loguru import logger
class SlackWebhookBot:
def __init__(self, webhook_url: str,
channel_name: str = "test-notification",
bot_name: str = "guardian",
bot_emoji: str = ":guardsman:",
timeout: int = 15):
"""Class to send messages to a provided Slack webhook URL.
You can read more about Slack's Incoming Webhooks here:
https://api.slack.com/messaging/webhooks
Args:
webhook_url: The webhook URL to send a message to. Typically
formatted like "https://hooks.slack.com/services/...".
Kwargs:
timeout: Number of seconds before the request will timeout.
This is used to prevent a hang and is set to a default
value of 15 seconds.
"""
self.webhook_url = webhook_url
self.channel_name = channel_name
self.bot_name = bot_name
self.bot_emoji = bot_emoji
self.timeout = timeout
self.headers = {
'Content-Type': 'application/json',
}
def send_notification(self, message: str) -> bool:
"""Sends a message to the webhook URL.
Per the Slack Incoming Webhook example. The body of the request
(for plain text) should be formatted as follows:
`{"text": "Hello, World!"}`
Args:
message: Plain text string to send to Slack.
Returns:
A boolean representing if the request was successful.
"""
success = False
payload = {
'channel': self.channel_name,
'username': self.bot_name,
'icon_emoji': self.bot_emoji,
'text': message,
}
try:
requests.post(
self.webhook_url,
headers=self.headers,
json=payload,
timeout=self.timeout
)
except requests.Timeout:
logger.error('Timeout occurred when trying to send message to Slack.')
except requests.RequestException as e:
logger.error(f'Error occurred when communicating with Slack: {e}.')
else:
success = True
logger.info('Successfully sent message to Slack.')
return success
if __name__ == '__main__':
SLACK_WEBHOOK_URL = "https://hooks.slack.com/services/xxxxxxxxx"
slack = SlackWebhookBot(SLACK_WEBHOOK_URL)
slack_test_message = '[TESTING] Sending this warning message when we have any problems.'
logger.info(slack.send_notification(message=slack_test_message))
Posted on February 21, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
February 21, 2022
February 6, 2022