I wrote last month about launching FantasyHockeySim.com and replacing the old DetroitHockey.Net Community Forums with a Slack team. At the time I promised a future post about the work I did with the Slack API.
The Slack API uses OAuth for authentication, which isn’t really a surprise. It does open up problems if you want to have actions taken on behalf of an app instead of a user. Unlike the Twitter API, the concept of bearer tokens is somewhat limited, and bots can only post messages (not extend invites or kick users, for example), so I ended up creating a user to act on behalf of the site.
Speaking of extending invitations, you can invite people to join a channel/group but there’s no formal way to invite users to join a group programmatically. There is a hack, however, that requires you to use a bearer token from the Slack API Tester application, which seems asinine to me.
Like the Facebook API – but unlike Twitter or Trello – the Slack API makes use of permission scopes. Unlike Facebook, on the user’s first login, you can only ask for identity-related scopes. As such, the signup/login workflow for FHS is redundant and somewhat annoying, but users only have to go through it once.
So I have a signup form on FHS that automatically sends an invite to the prospective user. After they sign up in the FHS Slack channel, they come back to the mothersite and log in using the new Slack user. As they log in, Slack asks if they want to give FHS identity permissions with their account. The user confirms this and logs in and I auto-create a user for them in the FHS system, where I keep track of what permissions FHS has for each user.
After logging in, if the user has not yet granted sufficient permissions, s/he will be presented with a nag screen that asks for those to be granted. After granting permissions, the screen won’t be shown again.
Now that FHS has all of the permissions it needs, the site can actually do some stuff with the user’s Slack account. Mostly this is administrative.
When a user joins a specific fantasy hockey league, s/he is added to that league’s private channel via a call to groups.invite. When s/he leaves the league, s/he is removed from the channel via groups.kick. Both of these are run by the aforementioned site user that I created, which has extended permissions (compared to the rest of the site users).
General managers (users that are members of one or more leagues) can push messages from Slack to their fantasy team’s home page. This allows them to post trade blocks or out-of-office messages – content that’s a little longer-lived than the standard Slack post. The interface for that relies on the groups.history and channels.history methods so that all of the possible posts for importing can be found. Once a message is selected, pins.add is used to make sure the message is pinned in channel. I also use pins.remove to clean up anything no longer flagged as news and pins.list to audit what should be pinned against what actually is pinned.
The site user automatically posts transaction information from the league site to the league channel using the chat.postMessage method.
Probably the most important new functionality is a “Message Center” section of FHS that shows users their missed messages from the Slack channels. This is where I feel like things get weird with the API.
In the Slack interface, there are channels and direct messages. In the API, there are channels, groups, IMs, and MPIMs (multi-person IMs). The interface obscures away the idea that private channels are actually groups. MPIMs -a type of IM that contains more than two participants – are also a special subset of groups.
That means that to find the total number of unread messages, you have to check channels.history, groups.history, and im.history and look for the unread_count. You could also check mpim.history for unread_count but groups.history gets you that.
Actually, as of when I wrote my Message Center code, mpim.history was broken. I Tweeted about unread_count always being zero and the Slack API team replied apologizing for the bug.
So in order to get the total unread count, you have to make three calls, which means three different permission scopes have to be granted.
Technically, the Slack API is really easy to work with. Make a request, pass the proper credentials, get data back. That said, after using it for a little bit, I can’t help but feel like there’s something a little off. Inconsistencies – like “channels” and “groups” being plural but “im” and “mpim” being singular – make it seem thrown together. That it’s not RESTful is a little bit of a surprise. None of that is a reason not to use it, though.