Scripting with Slack

All of us want notifications, but we’re also faced with the daily onslaught of emails in our inbox. So adding another daily email from a script just was not something I wanted to do. Recently I wrote about a backup script for MEGA Cloud. I wanted to enhance the script further and notify me every time it ran or if there were any issues. So email was the first thought, but I’d rather not get another email, and I’d prefer to just get a push notification. That’s when I thought it would really be nice to see these messages in Slack. Slack will handle the push notifications, and its easily shared with others. So I’m going to walk through how to start scripting with Slack using Bash and Python.

Scripting with Slack

I think its safe to say everyone is familiar with Slack, but just to be consistent, here’s an overview. Slack is a online collaboration tool that mostly centers around messaging. Slack is organized around teams and allows team members to communicate in public channels or with direct messages. All of the messaging is self-contained inside Slack and doesn’t rely on email or SMS. Slack has a large number of clients available, including Windows, Mac, iOS, Android, Linux. Slack mobile clients give you push notifications, so its a good alternative to both email and text messages.

Configuring the Slack API

So now that we know what Slack is, how can we start scripting with Slack and send messages to our channels. Slack exposes almost of the same functionality available from the UI in their API. But you have to do some configuration inside Slack first.

scripting with slackTo start off I’m going to setup a new Slack Channel called Status. I want all automated updates to go here, and my team and I can check for any alerts or job completion messages. We’ll all see notifications on our phones and popups in the Web UI.

Now I need to setup the API integration. From the main Slack menu, select Apps & integrations. Then from the upper right hand corner click Manage, and then select Custom Integrations. On the Custom Integrations page you can create Bots and Incoming WebHooks.

scripting with slack

scripting with slackFirst I’ll create what Slack calls a Bot. Slack Bot’s are just ways to identify messages that come from non-human’s. You can tie different Bots to different scripts. When adding the Bot you just need to supply a name for the Bot. You’ll later use this name in your scripts.

 

Slack-WebhookNext create a new Incoming WebHook. A WebHook is similar to an API Key, it allows you to interact with Slack’s RESTful web service from an external application. On the WebHook Creation screen you just need to specify the channel you want this WebHookscripting with slack to post to. After you create the WebHook you’ll be given the WebHook address and several examples for scripting with Slack Channels.

 

Start Scripting with Slack API

We now have Slack setup, so we can start scripting with Slack to send messages. There are a number of Slack clients available, and documented on the Slack API website. But I’m going to focus on calling the Slack API directly because I want to keep my scripts as simple as possible. Slack’s RESTful service is very simple to interact with. It basically requires that you post JSON to the WebHook address. The WebHook address takes the form of https://hooks.slack.com/services/xxxxxxx/yyyyyy/zzzzzzz.

The easiest way to send a message to your Slack Channel is to post the JSON using Curl. The Curl command to post a message to the #status channel as the user MyBot, and using the emoji robot_face would look something like this:

curl -X POST --data-urlencode 'payload={"channel": "#status", "username":mybot", "text": "This is posted to #status and comes from a bot named mybot.", "icon_emoji": ":robot_face:"}' https://hooks.slack.com/services/xxxxxxx/yyyyyy/zzzzzzzz

Python Scripting with Slack

I’ve been writing a lot of my newer scripts in Python, and Slack is also easily scripted with Python. There’s a very full featured Python Client available on Github. You can read the python-slackclient documentation here. But I’m going to setup a Python script for Slack that doesn’t rely on a 3rd party client. Just like using Curl, I’m going to use Python Requests to post JSON to the Slack WebHook. The code below is a Python function that I will reference from several scripts.

import requests
import json

# Slack API Address
SLACK_INCOMING_WEB_HOOK = "https://hooks.slack.com/services/xxxxx/yyyyy/zzzzz"

# Slack USER
SLACK_INCOMING_USER = "mybot"

SLACK_INCOMING_CHANNEL = "#status"

def slack_message(mychannel, message):
  payload = {"text": message, "username": SLACK_INCOMING_USER, "channel": mychannel, "icon_emoji": ":robot_face:"}

  #request to post the message
  req = requests.post(SLACK_INCOMING_WEB_HOOK, json.dumps(payload), headers={'content-type': 'application/json'}) 
  return

Backup Script Revisited

As I mentioned earlier, my plan was to update the MEGA Cloud Backup Script to send messages to a Slack Channel. I made some additional updates to this Bash script to log to a file. This updated script sends a message to Slack that lists the websites that were backed up.

#!/bin/bash
### Variables ###

BACKUP_FOLDER="/var/www/manage/wp-content/uploads/mainwp/0"
BACKUP_TARGET=/Root/Backups
DATE=$(date +%Y-%m-%d-%H-%M-%S)

LOG_FILE=/var/log/agbackup.log
BACKED_UP_SITES=""

#### Functions ####

log () 
{ # Write to Log

   if [ -z "$2" ]                           # Is parameter #2 zero length?
   then
     #echo "-Parameter #2 is zero length.-"  # Or no parameter passed.
     status=ok	
   else
     #echo "-Parameter #2 is \"$2\".-"
     status=$2
   fi

 tracelog $1

 curl -X POST --data-urlencode 'payload={"channel": "#platform", "username": "webtechbot", "text": "'"$1"'", "icon_emoji": ":robot_face:"}' https://hooks.slack.com/services/xxxxx/yyyyyy/zzzzz

}

tracelog () 
{ # Write to Log File
  echo "$1" >> ${LOG_FILE}

  if [ $? -ne 0 ]; then
 		echo "ERROR: Couldn't write log file. Check your permissions"
 		exit 1
  fi	
}

backup ()
{ # Backup to Mega

  echo -e "Backing up $1"

  filename=$(basename "$1")

  if  megals --reload | grep $filename >/dev/null 2>&1
  then
    		tracelog "Backup was already found in MEGA"
  else
    		tracelog "Backup was not found in MEGA...uploading"

    		megaput --path ${BACKUP_TARGET}/${filename} ${1}

    		if [ $? -ne 0 ]; then
 			tracelog "ERROR: Couldn't upload $filename to Mega" "failure"
    fi

    tracelog "Backed up ${filename} to MEGA"
    BACKED_UP_SITES+=", "
    BACKED_UP_SITES+=$filename
  fi
  
  echo " "
}
###################

echo "AG Platform Backup Log ${DATE}" > ${LOG_FILE}

log "Starting MEGA Cloud Backup @ $DATE"

for f in $(find ${BACKUP_FOLDER} -name '*.gz'); do backup $f; done

log "Uploaded the following backups: ${BACKED_UP_SITES}"
log "Ending MEGA Cloud Backup"
 
exit 0

Wrapping Up

Slack also has tons of integrations with other services that allow you to centralize notifications. StatusCake is a website monitoring tool we use that also has a Slack integration. Logging messages to Slack is a great simple solution for tracking activities from your scripts and other automation activities. After updating our Backup Script to use Slack its been really easy for our team to keep track of backups as they happen.

I’m an avid Technologist, while I do work on architecting solutions that span from the desktop to the data center, my passion is Web Infrastructure.
We will be happy to hear your thoughts

      Leave a reply