Slack及其开发接口初探

什么是Slack?

说起Slack,熟悉它的人都知道这是如今互联网世界又一个神奇的存在:它用仅仅不到两年的时间就融资1.6亿美元的奇迹,被大家津津乐道,认为是创造了SaaS(Software as a Service)领域的神话;而不熟悉它的人一定想要马上去问问度娘了,Slack到底是什么?

结果也许会让一些人失望——Slack不过就是一个工作聊天软件而已嘛,我们的QQ和微信早就做到了啊!确实是这样,如今国内的上班族和自由职业者几乎人人都在使用QQ和微信工作,有了这类软件,我们似乎连电话和Email都不需要了。而且不知道从什么时候起,大家都喜欢用微信的语音来工作,地铁上、餐厅里、楼梯间里……你总能看到一些对着手机话筒慷慨激昂地演说的人。

但是微信毕竟不是设计用来工作的,因此当它被用作工作软件时,便暴露出很多致命伤,比如:功能设计不够单一以致工作和休闲娱乐界限不明、不同设备版本功能差异太大(和工作所要求的相反,微信的桌面版比手机版功能更弱一些)、不同设备之间的聊天记录不能同步和共享、过份依赖设备自身的存储能力(微信一定是你手机里面最占存储的那个App)、搜索功能弱(语音聊天中的内容更是无迹可寻)等等……

Slack完美解决了上述问题。Slack的搜索功能据说强大到堪比Google;云存储使得不同设备之间可以轻松地共享聊天记录和工作文档,同时你也不用担心可怜的手机存储被用到爆掉;工作时用Slack、休闲娱乐时用QQ或微信,工作和生活界限分明。Slack做的还远远不止这些。Slack集成了各种第三方应用,从邮件沟通到日程管理、从文件存储到程序开发、从项目管理到人事招聘……只要是与工作相关的,几乎无所不包。

当然,Slack只是众多优秀的协同工作软件中的一个,至于它为什么能够脱颖而出,回答这个问题超越了我的知识范畴,也不是本文要讨论的重点。本文只是从技术层面初步探索一下,Slack是如何做到把各种功能各异的应用整合到一起,集于自己一身的。

slack.png

Slack:集各种功能于一身

Slack的口号是:Be less busy(少忙一点)。如何才能做到“少忙”呢?Slack是通过把其他应用都整合到自身来实现的。

比如,作为一名程序员同时又是项目管理者,我一天的工作大概是这样的:查看和回复客户或同事的邮件;查看微信中各个工作群里是否有新的问题反馈;回顾当前各个项目的进度,并决定接下来如何分配团队的工作;如果近期有招聘计划,则看一下是否有合适的求职简历;使用自己的时间管理软件来开始具体的程序开发工作;如果有同事跟我共享文件,则需要打开一些云盘之类的应用。全天的工作中需要涉及到多个不同的应用程序:收发邮件的邮件客户端、微信、项目管理软件(如Trello)、代码管理和问题追踪软件(如GitLab)、求职网站的简历中心、自己的时间管理软件、云盘等等,我需要在这几个不同的应用之间周旋,不停地来回切换,其中微信几乎是自始至终都离不开的,而且使用微信工作时很容易被一些朋友的闲聊或感兴趣的公众号文章打断。

Slack通过接口将这些应用都变成虚拟的项目参与者(以机器人也就是“bot”的形式):邮件机器人负责帮你打开和回复邮件,文件机器人负责帮你上传和查看文档等等……通过把他们都整合到Slack中,你彷佛可以用Slack就可以搞定所有事情,从而实现“少忙”。要知道究竟有多少这些应用可以为Slack所用,你可以登录Slack中你的团队以后去这里看看:https://<你的团队ID>.slack.com/apps。

下面是Slack应用首页的一个完整截图:

screenshot-slack-apps.png

自定义Slack应用

上面的这些应用应该可以满足你的大部分需求了,但仍然有一些特殊的应用不在其中。比如规模很小而远程办公化程度又很高的团队(我们就是),常常会遇到办公室里空无一人的尴尬情况。我们解决这一问题的方法是使用“办公室主任”制度。说白了就是让大家轮流值班,以确保在每个工作日的办公时段,办公室里至少有一人驻守。(我即将在另一篇文章中与大家分享一些更多的关于远程办公方面的心得。)

这一想法听似非常简单,也很好实施,只需要预先设定好值日表并依此轮流就可以了,但实际推行起来还是有一些小问题。首先,谁来负责提醒第二天的“办公室主任”是谁?如果忘记提醒,责任又是谁的?其次,由于有请假或外出的情况,经常会有人需要与其他人“换班”;休假(特别是长假)后的第一个工作日经常记不起当天的“办公室主任”是谁;最后,新同事的加入和老同事的离职都会造成值日表的混乱。当然,作为程序员都会想到用一个再简单不过的程序来轻松解决所有上述问题,因此最后的问题就变成:我们的程序如何与我们日常的协同工作软件(当时是微信)来整合?而当我们把日常协同工作软件转到Slack以后,发现这一问题简直再好解决不过了。

最基本的Slack应用之一:Webhooks

和很多在线服务软件一样,Slack提供一种最基本的应用接口:Webhooks。Webhook实质上是一个私有的URL,接受外部应用程序的调用。当你按照规定的方式成功调用一个Webhook以后,相应的行为就会体现在服务程序里面(对于Slack而言通常是发送一条消息)。比如:一个邮件收发程序可以在有新的邮件到达服务器时,调用Slack的某个Webhook,通知用户他有一封新的邮件;一个博客程序可以在文章有新的评论时,调用某个Webhook,通知作者和管理员该文章有新的评论,诸如此类。而这些通知都会以机器人的口气发送到Slack的聊天窗口中。

实战:一个简单的Slack Webhook应用

接下来我就以上面的“办公室主任”问题来具体演示一下一个简单的Slack Webhook应用的实现方法。

首先,我们需要一台可以运行Web程序的服务器,这台服务器上运行我们的主程序:包括值日逻辑的实现,后台设置界面等;这台服务器还需要支持计划任务以便我们的程序可以自动执行而不需要手工操作。为了减少开发工作量,我使用了我们擅长的drupal作为框架来开发。

下图演示了我的整个构思:

Screen Shot 2016-12-21 at 6.33.53 PM.png

配置Slack Webhook

Slack的Webhook分为输入型(Incoming)和输出型(Outgoing)两种。顾名思义,输入型的Webhook是接受外部程序发来的消息并显示在Slack的聊天窗口中;输出型的Webhook是从Slack中发送一个消息出去给外部程序。显而易见,本例中需要用到的Webhook属于输入型的。

登录Slack以后,进入:https://<你的团队ID>.slack.com/apps/build,再依此点击:Make a Custom Integration > Incoming Webhooks,你会来到Slack的Incoming Webhook的配置界面。如果你或你的同事以前配置过,这里可能已经有一些条目了。如下图:

Screen Shot 2016-12-21 at 6.40.03 PM.png

点击Add Configuration,添加一个Webhook,紧接着进入该Webhook的配置页面。这是一个“heavily documented”的页面,所以只要仔细阅读页面上的说明,所有设置的作用基本上都能明白。这里需要特别提一下的是“Post to Channel”和“Webhook URL”这两个选项。Post to Channel这一项指定了消息发往的频道。Slack的频道本质上是一个hashtag,类似于我们常见的主题或标签的概念,比如可以为一个特定话题或工作项目开设一个频道。我们这里的频道设置为:#office-managers。Webhook URL这一项会用在我们的程序代码中,是一个接受POST请求的Web地址。我们的消息会以json的格式进行编码并提交到该地址,具体参数的详细说明都可以在该页面上找到。

编写Drupal模块

我们的模块叫作dms_office_managers,只需要简单的两个文件即可:dms_office_managers.info和dms_office_managers.module,而所有的代码都在dms_office_managers.module中。如下:

<?php function dms_office_managers_menu() {     $items['office-manangers/slackbot/%'] = array(         'type' => MENU_CALLBACK,         'page callback' => 'dms_office_managers_slackbot_callback',         'page arguments' => array(2),         'access callback' => TRUE,     );          return $items; } function dms_office_managers_slackbot_callback($k) {     $key = 'JMyJ7XEQkkpH1HAmTfD9ZxwVtcKTSbH5';          if ($key == $k) {         $people = array(             'dan',             'eva.zhao',             'xuuknf',         );                  $index = variable_get('office_manager_index', 0);         $office_manager = $people[$index];                  dms_office_managers_call_slack_webhook($office_manager);                  variable_set('office_manager_index', ($index+1)%count($people));     }          exit(); } function dms_office_managers_call_slack_webhook($office_manager) {     $url = 'https://hooks.slack.com/services/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';          $data = '{"text": "[Announcement] The office manager of Dec. 15 is @' . $office_manager . '"}';     $options = array(         'method' => 'POST',         'data' => $data,         'headers' => array('Content-Type' => 'text/json; charset=UTF-8'),     );          $result = drupal_http_request($url, $options);          return $result; }

不熟悉drupal模块开发的朋友可以去这里了解:https://www.drupal.org/docs/7/creating-custom-modules,由于本文重点在Slack,所以关于drupal部分的讨论我会尽量缩短篇幅。总之上面代码实现的功能是这样的:定义一个随机路径(本例中的路径为:http://dminorstudio.com/office-manangers/slackbot/JMyJ7XEQkkpH1HAmTfD9ZxwVtcKTSbH5),通过请求这个路径,会调用上一步中配置好的Webhook,并向用户的Slack中的#office-managers频道发送一条类似如下的消息:

Screen Shot 2016-12-19 at 12.00.03 PM.png

配置计划任务

我们希望每天的固定时刻,比如下班前夕的17点,这个程序能得到自动执行,这可以通过配置服务器的计划任务来实现。比如在CentOS上,计划任务的配置如下:

0 17 * * * curl http://dminorstudio.com/office-manangers/slackbot/JMyJ7XEQkkpH1HAmTfD9ZxwVtcKTSbH5

完成

上面的程序是非常简单的。实际中,我们的程序实现了自动跳过双休日和国定假日,后台配置人员名单,换班和个人休假等功能,限于篇幅这里就不再赘述。

总结

Slack通过它的灵活的开发接口,可以把各种应用都整合进来,是一个有着无限可能的强大平台。本文只是管中窥豹而已。笔者将在后续不断推出更多与Slack相关的应用心得和开发经验分享,敬请期待!