Slack Webhook (Best Tutorial 2019)

Slack Webhook

What is Slack Webhook

Slack is a great tool for improving communication and increasing transparency in your business, organization, club, or group of friends. Slack reduces internal emails, allowing you to convert your jumbled inbox into channels that contain all your crucial information, in a more organized and easy-to-find manner. 

 

Source code

Remember, the source code for all hacks in this blog can be found in this blog’s Github repo. This blog provides a walkthrough of how you can integrate Slack into your business.

 

There are also a couple of hacks that are relevant to using Slack in the workplace. If Slack doesn’t solve the problem you identified, you may have to look for an alternative solution to your problem.

 

Making Your Business Slack Ready

 If you’ve decided on Slack as your tool of choice (and a good choice it is) there are a few tips you can follow to make sure company roll- out goes smoothly.

 

Get it configured correctly - Take a few moments to go through the configuration options for your team. These can be accessed by clicking your team name in the top left of the Slack interface and then choosing the “Team Settings” option.

 

For example, you might want to prevent some team members from adding integrations and apps, or you may wish to restrict the registration email to a specific domain.

 

Invite some beta testers - Use your fellow team members (or close colleagues) to try out the service. Slack recommends designating a day for this purpose.

 

Prohibit email - specify a trial period (for example a day or two) where all internal communications and questions must be sent via Slack, not email. This may seem a little over the top, but it gets people used to using the platform. Once people understand how Slack works and what it can be used for, they will know when to use Slack and when to revert to email.

 

Roll it out gradually - If your beta users are happy and embracing Slack, roll it out the team by team - making sure you properly introduce the platform to them first - explaining how you expect them to use it and why they should.

 

Just sending out an invite and expecting people to work it out themselves could upset people. Consider running a small presentation for each team to help them get used to Slack.

 

Make messages meaningful - Slack doesn’t just let you send simple messages - take a moment to read over the message for- matting tips, and pass them on to other them members to help emphasize certain words or separate out code blocks. You can find these tips in the Slack Help Center.

 

Remember that Slack allows more than just words - Think about installing some simple apps to help your team get their messages across. For example, Giphy allows Gifs to be sent with a simple keyword, and Growbot allows you to easily give praise to colleagues. Once your company is using Slack, you’re ready to start dividing the conversation and keeping chats on-topic using channels.

 

Channels

Slack uses channels to organize conversations and topics into separate rooms. Channel names and conversations can be seen by everyone on your organization’s team but to be notified or join in the conversation you need to join the channel. This allows team members to be involved only in conversations they want or need to be in.

 

Security

With an Instant Messenger at your fingertips, it’s very easy to use it to share private information between colleagues, such as passwords or login details. But keep in mind that anyone can potentially see and access the information you share on Slack. So think twice before sharing sensitive information.

 

You can also take steps to improve the security of Slack itself. As the team owner, you can force your team to reset their passwords. Do this by visiting:

 

Team Settings → Authentication → Forced Password Reset.

Now we’re ready to dive into some team hacks. The source code for all hacks in this blog can be found in this blog’s Github repo.

 

Email a reminder of a conversation

Although Slack can replace a lot of your need for email, there are some situations where you really need email, so here is a hack to help you integrate the two. For example, say someone outside of Slack asks you to perform a task, and you want to keep track of it in your inbox.

 

In this hack, you will create an HTML email that contains the last 10 Slack messages sent in a channel. Since this uses an Outgoing Webhook, it will only work in a public channel, and not a private conversation.

 

This script will work by the user going to the relevant Slack channel and typing email me followed by a subject line such as email me Fix the web site bug.

 

This task could be accomplished using a slash command instead, but Outgoing Webhooks were chosen for this hack to provide transparency—webhooks lets other Slack users see that someone has requested an email transcript of the conversation. 

 

Before you get started, create a PHP file on a web-accessible server called email.php. This is the file we are going to trigger and use to send the email.

 

Create the Hook

After you’ve created and saved your PHP file, the next step is to set up an Outgoing Webhook. The settings below are just a guide:

  1. Channel: Any
  2. Trigger Word(s): !email me
  3. URL(s): The URL where your script is hosted
  4. Descriptive Label: Describe what the bot is doing
  5. Customize Name: *Email Bot *
  6. Customize Icon: Choose emoji and search for “email”; click the envelope emoji to select it.

 

Obtain an API Token

The script in this hack uses the Slack API to gather all of the information it needs. In order to interact with the API, you need to generate an OAuth token; here’s how:

  1.  Go to https://api.slack.com/web.
  2.  Scroll down to “Generate test tokens”.
  3.  If you have previously generated a token it will be listed in the table on this page. If not, click the “Create token” button.
  4. Make a note of the token.

 

Script set up

With this hack, we are going to include the Slack PHP Library. This makes it easier to interact with the API and saves you from having to write your own cURL request. Download the Slack API PHP file from the GitHub repository linked to above, and place it in the same directory as the email.php script you created earlier.

 

Next, open the email.php script and paste in the following code. This code includes the Slack API library and initializes a new instance of the Slack class used later in this script.

<?php
// Include slack library from https://github.com/10w042/slack-api
include 'Slack.php';
// Initialise new instance
$Slack = new Slack('[API TOKEN]');

 

When Slack triggers a Webhook, it sends a payload containing information about where the Webhook was triggered from. This includes the channel_id of the channel and the user_id of the user who triggered it.

 

Using this payload data, which is sent as $_POST data to the PHP script, we can query the Slack API. This allows you to get the email address of the user who triggered the Webhook and the channel’s history. This will be used for the contents of the email.

 

In the code below, the channel history is loaded, and the user details are stored into a $me variable. Both the channel and user data are obtained by querying the Slack API. Lastly, the text that accompanied the email code (if there was any) is stored in a variable.

 

Place this code after your Slack API initialization:

/ Get the last 11 messages of the channel conversation
$data = $Slack->call('channels.history', array( 'channel' => $_POST['channel_id'],
'count' => 11
));
// Get the user who requested the email
$me = $Slack->call('http://users.info', array( 'user' => $_POST['user_id']
));
// Strip "emailme" from the message to get the subject line
// (if one was entered)
$text = str_replace('emailme', '', $_POST['text']);

 

The first variable, $data, is an array containing the last 11 messages in this channel, ranging from newest to oldest. This includes the one that triggered this Webhook.

 

If you change this number, make sure you add an extra message to allow for the trigger message. The $me variable contains all of the data about the user, including their name, image, and (most importantly) email address.

 

Create a messages array

Using the array of messages that we retrieved from the channel history, we can create a new array containing the messages along with the names and pictures of the users who wrote them. 

 

Insert this code at the end of your PHP script:

// Create empty array
$messages = array();
// Loop through channel messages
foreach($data['messages'] as $d) {
// Check If the message has a user - this excludes bot
// messages from the email
if($d['user']) {
// Get the user associated with the message
$userData = $Slack->call('http://users.info', array('user' \
=> $d['user']));
// Add to the messages array the name & image of the user,
// plus the actual message
$messages[] = array(
'user' => $userData['user']['real_name'],
'image' => $userData['user']['profile']['image_24'], 'message' => trim($d['text'])
);
}
}
// Remove the first item from the array (the trigger message)
array_shift($messages);
// Reverse the messages so oldest is first
$messages = array_reverse($messages);

The code above loops through the existing messages array and, if a user key is present in the message, adds it to the $messages array. If the user key is missing, this indicates it’s a message from a bot or other Webhook, which you can ignore.

 

Lastly, the trigger message gets removed (we don’t need it in the email) and the array gets reversed. Reversing the array means that, when we output the messages in the email, they will read from old- est to newest.

 

Specifying the Recipient and Subject

The first step in creating the email is to specify the recipient. To be sure that the name and email appear correctly in the email client’s To field, specify a name and an email address in this format: Full Name <email@address.com>.

 

Because we have data about the current user stored in the $me variable, we can easily construct the recipient. The subject line can also be set, either by taking the user input text or by setting a default one.

 

To accomplish these two things, add this code after the $messages array described in the previous section:

/ Create recipient

$to = $me['user']['profile']['real_name_normalized'] . ' <' . \

$me['user']['profile']['email'] . '>';

// Set the subject line

$subject = ($text) ? $text : 'Email reminder from Slack';

 

Creating the Email Headers

The next step is to set the headers for the email. The following code tells the email client how to handle the incoming email so it can be processed as HTML. It also sets the sender of the message. Add this code to the end of your PHP file:

 

// Set the headers & sender of the email

$headers = 'MIME-Version: 1.0' . "\r\n";

$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";

$headers .= 'From: Slackbot <slack@yourdomain.com>' . "\r\n";

 

Specifying the Messages

Now that you’ve specified the email headers, you need to create variables for both the name of the user and a string of all the messages in an <table> element, which will be inserted into the HTML template.

 

Insert this code after the headers have been set:

// Set the name for the email
$name = $me['user']['profile']['first_name'];
// Create the messages table
$table = '<table width="100%" style="border-collapse:collapse">';
// Loop through all the messages
foreach($messages as $m) {
$table .= '<tr><td style="border:1px solid #ccc;padding:5px;\ width:24px"><img class='lazy' data-src="' . $m['image'] . '" \ style="display:block"></td><td style="border:1px \ solid #ccc;padding:5px"><b>' . $m['user'] . '</b> \
</td><td style="border:1px solid #ccc;padding:5px"> \
<i>' . $m['message'] . '</i></td><tr>';
}
// Close the table
$table .= '</table>';

 

HTML Email

To build the HTML email, we are going to use the PHP Heredoc syntax. This allows you to construct HTML and insert PHP variables without needing to escape them. Here’s an example of Heredoc in use:

$message = <<<HTML Hello {$name}.<br><br>
You requested an email of the conversation.<br><br>
{$table} HTML;
Send the email
We can now use PHP to send the email since we have the recipient, subject, message, and headers. Add the following to your PHP file:
// Send the email!
mail($to, $subject, $message, $headers);

 

Notify the User via Slackbot

The last thing this script does is notify the user through Slackbot that the email has been sent. With the Slack API, if you post a message to a channel that has the same ID as a user ID, it will appear in the Slackbot private conversation.

 

We are going to use this ability to private message a user to send a message informing them the email has been sent.

 

Add this to the end of the PHP file you’ve been working on:

// Post a message in the Slackbot channel
$sendMessage = $Slack->call('chat.postMessage', array( 'channel' => $me['user']['id'],
'text' => 'Yo ' . $me['user']['profile']['first_name'] . ' \
- I\'ve sent you that email you asked for', 'username' => 'Emailbot',
'icon_emoji' => ':email:'
));

You now have an easy way to send recent Slack messages via email.

 

Celebrate unusual holidays

In this hack, we will create a notification to inform you when there are unusual holidays. For example, did you know that the 20th of January is Penguin Awareness Day? Or that the 15th of September is Make A Hat Day?

 

Create an Incoming Webhook

This script uses Incoming Webhooks to post the message to Slack. Add an Incoming Webhook by visiting the Apps and Integrations app directory, searching for Incoming Webhooks and then clicking install. Finally, select a channel that you want the holiday messages to be posted to, and click Add Incoming Webhook.

 

Once installed, you will be shown a Webhook URL. Make a note of this URL, because you’ll use it to post a message to your organization.

 

Collate your days

The next step is to build a list of days to shout about. This can be a personal collection of dates (birthdays and national holidays, say) or you can include unusual dates. Create a PHP file called dates.php on a server. This is the file we’ll be editing and adding the calendar too.

 

To build up a calendar, create 12 arrays inside an array, with numbers 01 → 12 as the keys, which will be the months. (For the sake of readability, make sure the numbers 1-9 are preceded with a 0.)

 

Inside each month, create a key for each day of that month. You can either do this yourself (using the example below) or you can simply download this template from Github.

 

To keep the codebase clean, the dates have been saved in a separate file from the rest of the code and assigned to the $dates variable - this file will be included in our main PHP script in the next step.

 

The text input can include both Slack formatting (for example, sur- round the text in * to make the text bold) and emojis. The emojis can be either the text representation (: cactus:) or the actual symbol - both will be displayed correctly by Slack. 

 

Now that you’ve created your list of dates, create a second PHP file titled generate-day.php in the same folder as dates.php and include your list of dates in it, like so:

<?php

// Include the dates

include './dates.php';

 

Get today’s day

Now that you have a list of days, you need to retrieve info for the current date. To do that, create a new DateTime() object in your generate-day PHP file after the include. This will default to the current date if nothing is passed in.

// Get todays date
$today = new DateTime();
You can now query the $today object to get the current month and day with a leading zero to match the keys on the arrays.
// Get the current month with a leading zero
// echo $today->format('m')
// Get the current day with a leading zero
// echo $today->format('d')
// Get the special day!
$day = $dates[$today->format('m')][$today->format('d')];

 

Post to Slack

Before posting to Slack, let’s ensure that there is something to post (you don’t want to send an empty message). Add this to your generate-day PHP file:

// If today has a value

if(count($day) > 0) {

// Post to Slack

}

The next step is to encode the data as JSON and assign it to the payload variable that Slack expects. We’ve chosen to title the bot What "international" day is it today? and have assigned it the :rosette: icon_emoji to add a little bit of celebration to the day. The text in the message is then simply the actual name of the day:

 

// Encode the data

$data = 'payload=' . json_encode(array(
'username' => 'What "international" day is it today?', 'icon_emoji' => ':rosette:',
'text' => $day,
));
Finally, set the $webhook_url (to post to) and include the PHP cURL code.
// Your webhook URL
$webhook = '[WEBHOOK URL]';
// PHP cURL POST request
$ch = curl_init($webhook);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch); curl_close($ch);
echo $result;
Your full generate-day.php file should look like the code below. Make sure this file is placed on a server that can run PHP scripts.
<?php // Include the dates include './dates.php'; // Get todays date $today=new DateTime(); // Get the special day! $day=$dates[$today->format('m')][$today->format('d')];
// If today has a value
if(count($day) > 0) {
// Encode the data
$data = 'payload=' . json_encode(array(
'username' => 'What "international" day is it today?', 'icon_emoji' => ':rosette:',
'text' => $day,
));
// Your webhook URL
$webhook = '[WEBHOOK URL]';
// PHP cURL POST request
$ch = curl_init($webhook);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch); curl_close($ch);
echo $result;
}

Try out the script by navigating to the URL of your script. The web page should say “ok” and your message should be posted to Slack.

 

Trigger the Script Daily

The last step of this hack is to trigger the script on a daily basis using a cronjob. This can be done either through a control panel (for example cPanel) if you have one, or through the command line. We explain both approaches in the following sections.

 

Control Panel

The following instructions are for setting up a cronjob using cPanel —other control panels may be slightly different. Log into your cPanel and navigate to “Cron Jobs”. You should be presented with a series of drop-down options. If there is a “common settings” or “presets” option, select “Once a day” from it. This should pre-populate the fields.

 

If such an option isn’t present, use the following settings instead:

  1. Minute: 0 (this runs at 0 minutes every hour triggered)
  2. Hour: 9 (this will trigger at 9 am every morning)
  3. Day: * (run this every day)
  4. Month: * (run this every month)
  5. Weekday: 1-5 

In the command box, enter the following: PHP /path/to/generate-day.php >/dev/null 2>&1

 

The PHP in this line of code tells the cronjob to run the script like PHP, and the path is the one to your PHP script. Lastly, the >/dev/null 2>&1 tells the cronjob not to output or email any reports to the user.

 

Command Line

Cronjobs can also be set up on the server using the command line. If you don’t have access to the command line for your server or you are not comfortable doing this, ask someone who is familiar with setting up recurring tasks to help you, or use the control panel option instead.

 

The next step is to create the cronjob. Remember that the time this triggers will be based on the local server time. Check your server time by typing date on the command line.

To edit the cronjob file, type:

sudo crontab -e

 

This will open a file. Add the following line of code to the bottom of that file:

0 9 * * 1-5 PHP /path/to/generate-day.php >/dev/null 2>&1

 

These options and commands are very similar to that of the control panel version, and so should look familiar.

You’ll now receive a little Slack message every day (when appropriate) that lets you know what you should be celebrating.

 

Add Hacker News Updates

In this hack, you’ll use an API to post news items to Slack. We’ll use an API because, although Slack can handle RSS feeds, it doesn’t provide control over the output, and some sites don’t offer an RSS feed. 

 

The script we’re going to create is written in PHP and runs a cron job every minute. It uses the provided API to get the latest story. If the story is dated after the last stored date, it will post to Slack and update the stored date to that of the most recent post.

 

This isn’t a bulletproof method, because if two (or more) stories are posted within a minute of each other, this script will post only one story. But it should work well enough.

 

Create an Incoming Webhook

This script uses Incoming Webhooks to post messages to Slack. Add an Incoming Webhook by visiting the Apps and Integrations app directory, searching for Incoming Webhooks and then clicking install.

 

Select a channel that you want the messages to be posted to and then click Add Incoming Webhook.

Once installed, you will be shown a Webhook URL. Make a note of the URL, since you’ll use it to post messages.

 

Gather the data

The next step is to gather the data from the feed. The Hacker News API allows you to specify several parameters to limit the number of items you get, which in turn speeds up the request.

Create the PHP script on a server web-accessible called feed.php. This will host all of the code. At the beginning of the file, specify the URL of the feed.

<?php

// Feed URL

$feed = 'http://hn.algolia.com/api/v1/search_by_date?';

Next, create a $lastDate variable. This will start at 0, but will be updated every time the script runs to store the date of the last item retrieved. You can then build a new request and get any new articles.

// Set a last collected date - this will be dynamically updated later

$lastDate = 0;

 

Now, build up the parameters for the API. PHP includes a function that can take an array and transform it into a URL encoded string: http_build_query(). (More information about this function can be found on the PHP Docs page). Add the following code to feed.php:

// Parameters
$params = array(
// Only retrieve stories (not polls or comments)
'tags' => 'story',
// Get any stories created after the lastDate integer
'numericFilters' => 'created_at_i>' . $lastDate,
// Only return 1 item
'hitsPerPage' => 1
);

 

// Build the full path using http_build_query

$url = $feed . http_build_query($params);

Once you build the $url you can retrieve it using PHP’s file_get_contents(). The feed will be in JSON format, which can easily be converted to a PHP object by wrapping json_decode() around the file request. To retrieve the feed and decipher it, add the following code to feed.php:

// Get the API data

$data = json_decode(file_get_contents($url));

Next, add the following code to check to see whether there are any new stories. If not, you will exit the script (there is no point in continuing).

 

// Check to see if there are any new stories

if(!count($data->hits)) exit('No stories');

You want to post the latest story to Slack, so to make accessing all of the information easier, assign a new variable ($story) to the first item in the hits array in your PHP file:

// Isolate the story

$story = $data->hits[0];

 

Format the story’s date

Before posting the data to Slack, you should format the date of the story, making it more human readable. Currently, the data exists in a Unix timestamp format also known as ISO_8601.

 

Using PHP, you can take the timestamp and convert it to something more easily understood by the DateTime PHP class. Here is an example of how to do that:

// Format the date - pass an @ if using timestamp

$date = new DateTime('@' . $story->created_at_i);

echo $date->format('jS F Y g:ia');

// returns date in format of:

// 1st January 1970 12:01am

 

When using the DateTime class with a Unix timestamp, an @ must be passed first, to allow the code to understand the input.

 

Build the payload for Slack

Now that we have a formatted date, we can proceed with formatting the payload data for Slack. In this block of code, we parse the Date using DateTime() and then build up an array of information ready to be posted to Slack. Add this code to your PHP file:

// Format the date - pass an @ if using timestamp
$date = new DateTime('@' . $story->created_at_i);
// Create fields array
$fields = array(
array('title' => 'Title', 'value' => '<' . $story->url . '|' . $story->title . '>'),
array('title' => 'Date', 'value' => $date->format('jS F Y g:ia'), 'short' => true),
array('title' => 'Author', 'value' => $story->author, 'short' => true)
);
// Conditional field if story_text is present (strip any HTML tags)
if($story->story_text != null) {
$fields[] = array('title' => 'Story text', 'value' => strip_tags($story->stor
}
// Conditional field if comment_text is present (strip any HTML tags)
if($story->comment_text != null) {
$fields[] = array('title' => 'Comment text', 'value' => strip_tags($story->co
}
// Encode the data
$payload = 'payload=' . json_encode(array(
// Username and nice icon 'username' => 'Hacker News', 'icon_emoji' => ':fax:',
// Required fallback and some pretext
'pretext' => 'A new story from Hacker News', 'fallback' => 'New hack news story - ' . $story->url,
// Hacker news orange
'color' => '#ff6600',
// Title as a link, date and author of the news story
'fields' => $fields
));

 

Before building the payload, the $fields array is predefined and conditionally appends the story_text and comment_text if it is present. We’ve decided to attach the news as a field attachment because doing so gives you more control over the formatting and the color.

 

The title of the story has been passed in as a link. This uses the Slack link format of <URL|Link text>. Note the vertical pipe | between the URL and text. The username and icon are also set in the code; we went for the fax emoji to signify a new story.

 

Lastly, we need the PHP cURL request, so add this to the end of your file:

// PHP cURL POST request

$ch = curl_init($webhook);

curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');

curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$result = curl_exec($ch); curl_close($ch);

 

Retrieving new items

As mentioned before, the feed URL can be passed an additional parameter in the form of a UNIX timestamp so that it retrieves stories from a specific date and time. If you use this parameter, it will improve the speed of the HTTP request, because it restricts the number of items the feed needs to return.

 

To achieve this, the script needs to create and use a temporary file to store the timestamp of the last story it processed. PHP includes the ability to read, write and create other files in the filesystem. To do this, it uses the following functions:

  1. file_get_contents() to retrieve the data from a file
  2. file_put_contents() to write data to a file. Add this code to the very top of your feed.php file:
// Specify path to Temp data file
$file = 'date.txt';
// Set a last collected date
$lastDate = file_get_contents($file);
if(!$lastDate) {
$lastDate = 0;
}

 

Here, we specify the path to the temporary file. If this file doesn’t exist, PHP returns false, in which case the $lastDate variable gets set to 0. If the file is present with contents, the $lastDate gets assigned to the temporary file, which should be a UNIX timestamp. 

 

At the very end of the PHP file, add the code below. It stores the timestamp of the processed story in the temporary file for the next time the script runs.

file_put_contents($file, $story->created_at_i);
The final feed.php script
Now that we’ve saved the last processed article and are constantly updating the temporary file, the webhook file is complete:
<?php // Your webhook URL $webhook='[WEBHOOK URL]'; // Feed URL $feed='http://hn.algolia.com/api/v1/search_by_date?'; // Specify path to Temp data file $file='date.txt'; // Set a last collected date $lastDate=file_get_contents($file); if(!$lastDate) { $lastDate=0; } // Parameters $params=array( // Only retrieve stories (not polls or comments) 'tags'=> 'story',
// Get any stories created after the lastDate integer
'numericFilters' => 'created_at_i>' . $lastDate,
// Only return 1 item
'hitsPerPage' => 1
);
// Build the full path using http_build_query
$url = $feed . http_build_query($params);
// Get the API data
$data = json_decode(file_get_contents($url));
// Check to see if there are any new stories
if(!count($data->hits)) exit('No stories');
// Isolate the story
$story = $data->hits[0];
// Format the date - pass an @ if using timestamp
$date = new DateTime('@' . $story->created_at_i);
// Create fields array
$fields = array(
array('title' => 'Title', 'value' =>
'<' . $story->url . '|' . $story->title . '>'),
array('title' => 'Date', 'value' =>
$date->format('jS F Y g:ia'), 'short' => true), array('title' => 'Author', 'value' =>
$story->author, 'short' => true)
);
// Conditional field if story_text is present (strip any HTML tags)
if($story->story_text != null) {
$fields[] = array('title' => 'Story text', 'value' => strip_tags($story->
}
// Conditional field if comment_text is present
if($story->comment_text != null) {
$fields[] = array('title' => 'Comment text', 'value' => strip_tags($story
}
// Encode the data
$payload = 'payload=' . json_encode(array(
// Username and nice icon 'username' => 'Hacker News', 'icon_emoji' => ':fax:',
// Required fallback and some pretext
'pretext' => 'A new story from Hacker News', 'fallback' => 'New hack news story - ' . $story->url,
// Hacker news orange
'color' => '#ff6600',
));
// Title as a link, date and author of the news story
'fields' => $fields
// PHP cURL POST request
$ch = curl_init($webhook);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch); curl_close($ch);
file_put_contents($file, $story->created_at_i);
echo $result;

 

Trigger the Script every Minute

The final step is to trigger the script on every minute using a cron- job. This can be done either through a control panel (for example cPanel) if you have one, or through the command line. We explain both methods below.

 

Control Panel

Log into your cPanel and navigate to “Cron Jobs”. You should be presented with a series of drop-down options. If there is a “common settings” or “presets” option, select “Once a minute” from it. This should pre-populate the fields.

 

If such an option isn’t present, use the following settings instead:

Minute: * (Every minute)
Hour: * (Every Hour)
Day: * (Every day)
Month: * (Every month)
Weekday: 1-5 (Every Weekday)

 

In the command box, enter the following: PHP /path/to/feed.php >/dev/null 2>&1

The PHP in this line of code informs the cronjob to run the script like PHP, and the path is the one to your PHP script. The >/dev/null 2>&1 bit tells the cronjob not to output or email any reports to the user.

 

Command Line

Cronjobs can also be set up on the server using the command line. If you don’t have access to the command line for your server or aren’t comfortable doing this, find someone who is familiar with setting up recurring tasks and ask for their help, or use the control panel option instead.

 

The first step is to create the cronjob. Remember that the time this triggers will be based on the local server time. 

 

To edit the cronjob file, type: sudo crontab -e

This will open a file. Add the following line of code to the bottom of that file: 0 9 * * 1-5 PHP /path/to/generate-day.php >/dev/null 2>&1

 

These options and commands are very similar to that of the control panel version (described above), and so should look familiar. You should now get the latest hacker news story every minute, every weekday!

 

Output your team’s timezones

If you work with a team that’s spread around the globe, you want to be sure that you don’t try to contact someone in the middle of the night their time. This hack will show you how to create a handy slash command that outputs the current times and timezones of all the users in a given channel.

 

To get started, create a PHP file called timezones.php on a web-accessible URL. This script will be triggered by a slash command. In the same folder as this script, download the slack-API PHP wrapper.

 

This script is best for small teams or channels as it requires querying the Slack API several times. Set up the slash command and auth token Navigate to the Slack apps and integrations website and, using the search box at the top of the page, search for “Slash commands”.

 

Click the first result titled “Slash commands,” and then click the “Add con- figuration” button on the left-hand side.

 

In the “Choose a Command” box, enter something appropriate, such as /times. On the following page, input the URL to your time zones.php script into the URL box. You can customize the look of your slash command using the “Customize Name” and “Customize Icon” fields using the settings below:

 

Customize Name: Timezones

  1. Customize Icon: Click “Choose an Emoji” and search for the clock emoji.
  2. Next, create an OAuth token, since you’ll have to query users and channels to gather the information needed for this script.

 

Obtain an API Token

This script uses the Slack API to gather the info it needs. In order to interact with the API, you need to generate an OAuth token:

  1. Go to https://api.slack.com/web.
  2. Scroll down to “Generate test tokens”.
  3. If you have previously generated a token, there will be one near the top, with the team name on the left. If not, click the “Create token” button.
  4. Make a note of the token.

 

Script Set Up

There is a small amount of set-up we need to do for this hack. Since we are dealing with timezones, you need to make sure that the script uses UTC as the base time, regardless of what the server is set to. To do that, add the following code to your timezones PHP script:

<?php
// Your oAuth Token
$token = '[AUTH TOKEN]';
// Set the timezone independent of the server
date_default_timezone_set("UTC");
// Get the channel ID the script was triggered from
$channelID = $_POST['channel_id'];
// Include slack library from https://github.com/10w042/slack-api
include 'Slack.php';
// Create new Slack instance
$Slack = new Slack($token);

 

Now that the Slack instance is initialized, we can query the Slack API to get a list of all of the members of the channel the script was triggered from using the payload Slack sends when triggering Webhooks:

// Get the current channel and user

$channel = $Slack->call('http://channels.info', array(channel' => $channelID));

 

After you have the channel information, you need to get the current time as a Unix timestamp. You also need to create an empty array (you’ll use it later). To accomplish both these things, add the follow- ing to your timezones file:

/ Get the time right now
$now = time();
// Create an empty array
$times = array();

 

We used the time() function here instead of the date() function because, unlike the date() function, the time() function doesn’t require any further parameters to get the timestamp. If you used the date() function instead, your preferred format would need to be passed as additional parameters.

 

Loop through the channel’s users

Now that you have information about the channel, you can loop through each user on that channel and create a user instance based on the user’s ID. Once you have the user instance, you can then get the timezone and name of the user. To do that, append the following code to your PHP file:

// Loop through channel members

for each($channel[channel']['members'] as $mid) {

// Create member instance with ID

$user = $Slack->call('http://users.info', array('user' => $mid));

}

 

Chances are (because you’re reading this blog) that you have at least one bot in your Slack team. We only really want to see timezones of real team members, so the code below excludes bots from the output of your script. Add this into the foreach loop above, after the http://users.info Slack API call.

// if the user is a bot, or doesn't have a timezone offset, skip them

if(($user['user']['is_bot'] == true) || \ (!isset($user['user']['tz_offset']))) {

continue;

}

 

This code checks whether the is_bot flag is set to true or the time- zone offset is missing from the profile. If either (or both) of those conditions are true, then it fires continue.

 

In the instance of a loop, the code will skip the remainder of the current code and move onto the next user. Once you are happy that you have an actual user, there are a few variables to calculate.

 

We need to work out each user’s time difference (in hours) compared to UTC, so we can output it at the end of the message. In the Slack API, the tz_offset is set in seconds, so dividing it by 60 twice gives us the figure we need. Add the following code after the if statement that’s inside the foreach loop:

 

// Work out offset in hours from seconds

$userOffset = ($user['user']['tz_offset'] / 60) / 60;

 

Next, we want to get the user’s name. If someone has filled out their profile correctly, the following code will grab their full name; if not, it will go with their username, so at least we have an identifying title. Add the following code after where the $userOffset variable is declared:

// Get the name of the user

$name = ($user['user']['real_name']) ? $user['user']['real_name'] : \

$user['user']['name'];

 

In order to work out the current “local time” for the user, the following code adds the timezone offset seconds to the current timestamp. This provides a timestamp that you can format later. Add this code after where the $name variable is set:

// Add the timezone offset to the current time

$userTime = $now + $user['user']['tz_offset'];

 

The last variable we need to set is $key. We are appending all of the users to an array, and we want them listed in time order. By making the key of the array the same as the offset, we can ensure they will be in the correct order.

 

Because a PHP can’t have negative arrays, the following code adds 12 to every user. -11 is the lowest the offset can be, so this ensures it will always be a positive number. Use the code below to set the $key variable—place it after the $userTime variable.

// Create an array key based on offset (so we can sort) and add 12
// (as it could be -11 at worst)
$key = $userOffset + 12;
Now that we have all of the variables we need, we can build the string for the user. Add this code inside the foreach loop:
// Append the details to the array as the key
$times[$key][] = '*' . $name . '*: ' .
date('h:i A', $userTime) . ' local time on ' . date('jS M', $userTime) . ' (UTC' . sprintf("%+d", $userOffset) . ' hours _' . \
$user['user']['tz_label'] . '_)';

 

The string is being appended to the $times array, with the correct key. To allow for cases where two users are in the same timezone, we create a child array to hold them using the empty square brackets [] after the [$key].

 

The string outputs the following text (with various formatting):

$name - the name of the user.
date('h:i A', $userTime) - the hour & minutes in a 12 hour clock (e.g. 12:01 AM).
date('jS M', $userTime) - the day and month of the user’s local time in the instance that any of the users are on a different day to the rest of the team (e.g. 1st Jan).
sprintf("%+d", $userOffset) - This outputs the timezone offset with a + prepended if it is positive (e.g. +2 hours).
$user['user']['tz_label'] - This outputs the label for the user’s timezone (e.g. Pacific Daylight Time).

 

Pieced together, the entire user foreach loop now looks like this:

// Loop through chanel members
foreach($channel['channel']['members'] as $mid) {
// Create member instance with ID
$user = $Slack->call('http://users.info', array('user' => $mid));
// If the user is a bot, or doesn't have a timezone offset, skip them
if(($user['user']['is_bot'] == true) ||
(!isset($user['user']['tz_offset']))) {
continue;
}
// Work out offset in hours from seconds
$userOffset = ($user['user']['tz_offset'] / 60) / 60;
// Get the name of the user
$name = ($user['user']['real_name']) ? $user['user']['real_name'] : \
$user['user']['name'];
// Add the timezeone offset to current time
$userTime = $now + $user['user']['tz_offset'];
// Create an array key based on offset (so we can sort) and add 12
// (as it could be -11 at worst)
$key = $userOffset + 12;
// Append the details to the array as the key
$times[$key][] = '*' . $name . '*: ' .
date('h:i A', $userTime) . ' local time on ' . date('jS M', $userTime) . ' (UTC' . sprintf("%+d", $userOffset) . ' hours _' . \
$user['user']['tz_label'] . '_)';
}

 

Processing the data

Now that we have a multidimensional array of $times with all of the users’ timezones stored inside, we need to process the data to make it ready for Slack. To do that, add this code after the foreach loop:

// Sort array items by key

ksort($times);

// Flatten the array and implode it - separated by new lines

$text = implode("\n", call_user_func_array( 'array_merge', $times

));

 

The first function sorts the array by keys (such as smallest to big- gest). This means that people with a timezone of -10 (and a key of 2, since we added 12) come before people in timezone +3 (key of 15).

 

The next line helps flatten the array and convert it to a string. Currently, the $times array looks like this:

$times = array( 2 => array(
’Joe Blogs:...’,
'John Doe...'
),
15 => array(
'Jane Doe...'
)
);

 

The keys were there purely for ordering purposes, so the array could be flattened. Calling the call_user_func_array function with array_merge does exactly that. After passing it through this series of functions, the array would become:

$times = array(

’Joe Blogs:...’, 'John Doe…', 'Jane Doe...'

);

As Slack expects a string, we can implode() that array, using the newline character \n as the “glue”. You can now trigger the script with the slash command you created (/times in this example), and get a list of all the local times for users in that channel.

 

Slack automatically notifies a user if their name is mentioned in a channel. This script mentions everyone’s names so it is likely that they will get a notification when the script is called. Also, because the script is doing several API calls, the more people in the channel, the longer it will take to return results.

 

Connect Slack to Trello

Trello is a collaborative project management tool. It helps teams and groups sort bugs and todos, based on the kanban board method. It incorporates the ideas of lists and cards. A card is often a task and is contained in a list (such as To-do or Done).

 

This hack will whos you how to create a new card on a specified Trello board using Outgoing Webhooks and the last message sent in a Slack channel. This same thing can be achieved using Zapier, but by using this custom hack instead of Zapier, you have control over the card’s formatting, where it goes, and which board in Trello it goes on.

 

The process for this script will be:

  1.  The user initializes the script by typing add to trello <board name>.
  2. The script gathers the last message sent in that Slack channel.
  3. The script works out what board the user mentioned. If the board doesn’t exist or the script can’t find it, it will use the default board.
  4. A card is created in the first list of that board.
  5. A message is returned with a link to the board.

For this hack, you will need a Slack API key as well as a Trello key and token.

 

For the Trello credentials, we advise you to make a new autonomous user account and add it to all the boards. For example, create an account called Jeeves or Jarvis who can post to all the boards required.

 

Create the Outgoing Webhook

First, you need to set up an Outgoing Webhook. The settings below are just a guide. Most of these settings can be overridden in the script itself.

Channel: Any

  1. Trigger Word(s): add to trello
  2. URL(s): The URL where your script is hosted
  3. Descriptive Label: Describe what the bot does
  4. Customize Name: Trello Bot
  5. Customize Icon: Whatever you wish

 

Obtain a Slack API Token

This script uses the Slack API to gather the information it needs. In order to interact with the API, you need to generate an OAuth token:

  1. Go to https://api.slack.com/web.
  2. Scroll down to “Generate test tokens”.
  3. If you have previously generated a token, there will be one near the top, with the team name on the left. If not, click the “Create token” button.
  4. Make a note of the token.

 

Obtain a Trello Key and Token

The Trello API allows a logged in user to get a key and token, which allows access to all of that user’s boards and cards. To get a key and token:

  1. Go to https://trello.com/app-key
  2. Copy the developer key on that page
  3.  Click here to generate a token
  4. When you’re asked to allow the app use your account, click Allow
  5. Copy the token that’s displayed

 

Default Board ID

The last thing you need before you write your script is the ID of the default Trello board. This is the board that gets posted to if the script can’t find the requested board or if not board is specified.

 

You can get this info by navigating to the board and copying its ID from the URL. For example, you’d copy whatever appears in place of [ID] in the URL below - it will be some numbers and letters.

 

Now that you have the required keys and tokens, let’s start the script. On a server, create a PHP file called trello.php, and then enter the following code into it. This code specifies the Slack and Trello tokens, Trello key, and the default board ID:

<?php
// Your Slack oAuth Token
$slack_token = '[Slack auth token]';
// Trello
// https://trello.com/app-key
$trello_key = '[Trello key]';
$trello_token = '[Trello token]';
$trello_default_board = '[Default board id]';
// Trigger Word
$trigger_phrase = 'add to trello';

 

We have specified the trigger word for the file. Make sure this matches what you entered when you created your Webhook so that you can remove the trigger word when you add the card to Trello.

 

Libraries

  1. There are some PHP wrappers available that make using the Slack and Trello APIs easier.
  2. The first one is the Slack PHP API wrapper. Download this script and place it next to your PHP script on the server.
  3. The second is php-trello. Download this zip and place in a folder called trello in the same directory as your PHP script.
  4. Include the libraries in your PHP file by adding the code below. The Trello wrapper requires you to specify the namespace.

 

// Include slack library
include 'Slack.php';
// Include Trello API helpers
include 'trello/class='lazy' data-src/Trello/OAuthSimple.php';
include 'trello/class='lazy' data-src/Trello/Trello.php';
// Set Trello namespace
use \Trello\Trello;

 

With these libraries loaded, you can initialize the Trello and Slack classes with the tokens you obtained earlier. To do so, insert the following code into trello.php:

// Create new Slack & Trello instance

$Slack = new Slack($slack_token);

$Trello = new Trello($trello_key, null, $trello_token);

Process the Slack channel data

 

You need to get the current Slack channel’s history, to get both the message that triggered the script (as it contains the relevant board’s name) and the message you wish to add to Trello as a card.

 

Because some of the messages posted in Slack aren’t user messages, retrieve the last 5 messages in a channel to ensure the board that gets added is the one requested. To do that, add this to trello.php:

// Get the last 5 messages of the channel conversation

$slack_data = $Slack->call('channels.history', array( 'channel' => $_POST['channel_id'],

'count' => 5

));

With the channel messages now available as a PHP variable, you need to remove the most recent one (this is the message that triggered the script). From there, we are going to remove the trigger phrase so we are left with the name of the board the user wishes to post to. Add the following to your PHP script after the Slack API call:

// Remove the last message - it will contain the trigger phrase
$slack_trigger_message = array_shift($slack_data['messages']);
// Remove trigger_phrase from message to get board name
$slack_board_name = trim( str_replace(
strtolower($trigger_phrase), '',
strtolower($slack_trigger_message['text'])
)
);

 

For the final Slack message processing stage, we are going to loop through the remaining messages until we find one with a type equal to the message. Once we do (it will generally be the first one), we are going to assign it to a variable and break out of the loop.

 

The message also gets processed to remove < and > from any URL. Add the following code after where the $slack_board_name variable is defined:

 

// Find the next message in the channel - strip URL formatting

foreach($slack_data['messages'] as $message) {
$message['text'] = preg_replace("/\<(http[^ ]+)>/", "\\1", $message['text']);
if($message['type'] == 'message') {
$trello_card = $message;
break;
}
}

 

Load the Trello board

In the next stage, you’ll load the Trello board to post to it. To do this, you must use the API to load a message to an authenticated Trello user, get their open boards, and loop through them until you find one that matches. If there is no board specified (or matching), the default board will be loaded.

 

The code that decides whether the board matches simply checks whether a string is contained within another string. For example, if you type to add to trello m, the script will add the card to the first board it finds with an M in its name.

 

Add this code to your trello PHP script:

// Get the trello user
$trello_user = $Trello->members->get('me');
// Get all the boards the user has access to that are open
$trello_boards = $Trello->members->get(
$trello_user->id . '/boards',
array(
'filter' => 'open'
)
);
// Find the board that matches the message text
foreach ($trello_boards as $board) {
if(strpos(
strtolower($board->name),
$slack_board_name
) !== false) {
$trello_board = $board;
break;
}
}
// if there is no board - fall back to the default one
if(!$trello_board) {
$trello_board = $Trello->boards->get($trello_default_board);
}

 

Pick the Trello list

Now that you have the Trello board selected, you want to load the lists contained within that board, and then select the first list on that board. (This will be the list you add the card to.) To accomplish these two things, add the following to the end of your script.

// Get all the lists in the board
$trello_lists = $Trello->boards->get(
$trello_board->id . '/lists'
);
// Get the first list of the board
$trello_list = $trello_lists[0];

 

Create the Trello card

With the board and list selected, the last thing you need to do is to build the card and post it. We want to add a bit of context to the card, including the name of the person who posted the note and the time they did so. Since we have the card title and details loaded in the $trello_card variable, we can load the user based on who posted it.

 

Because people aren’t perfect, not everyone will have filled in their profile and has the real_name field populated. In the code below, we set the name to the name key, and override this if real_name exists. Insert this code at the bottom of trello.php:

/ Get the Slack user who noted the bug
$slack_user = $Slack->call('http://users.info', array( 'user' => $trello_card['user']
));
// Get the name of the user - if there is a real_name, use that
$slack_name = $slack_user['user']['name'];
if(count($slack_user['user']['real_name'])) {
$slack_name = $slack_user['user']['real_name'];
}

 

Now you have all of the info you need to add the card to Trello. The list is loaded (with the ID we got before) and the card added. We set the title of the card (or name) to the same as the Slack message and populated the description (desc) with the name and date of the request. To post the card to Trello, simply add this bit of code to trello.php:

 

// Post the card to trello

$Trello->lists->post($trello_list->id . '/cards', array( 'name' => $trello_card['text'],

'desc' => 'Requested by **' . $slack_name .

'** on ' . date('jS F', $trello_card['ts'])

));

 

Report back to the user

The last thing you need to do is let the user know that the card was posted successfully. As a nice addition, the board the card was added to is linked in this return message, so the user(s) can jump straight to it. The link is created using Slack’s <link url|text> syntax:

// Post back to board it was posted to header('Content-Type: application/json'); echo json_encode(array(

'text' => 'Added the card to the <' .

$trello_board->shortUrl . '|' . $trello_board->name . '> board'

));

You’re all set. You can now add a card to a Trello board by typing add to trello followed by the board name.

 

Although this script replicates some aspects of the Zapier app, it opens the gateway for further expansion. For example, you can:

  1. Add custom labels to the card (to indicate that it’s from Slack).
  2. Include a link to the message (to get chat context) by removing the . from the message timestamp and using the message name.
  3. Keep a key/value list of channels to boards so that, when the script is run in a certain channel, the resulting card always goes to a particular board.
  4. Set aboard and use the text after the command to set the message title.
  5. Include the last 5 or so messages of the conversation in the Trello card.

Recommend