The Moment

阿宅的筆記

Create a slack bot

最近 chatbot 有點流行,讓人有點癢,算來算去,slack的介接可能是最簡單的,先弄個簡單的殼,說不定晚點會用到。

弄一個slack的步驟如下

  1. 申請一個 slack team

  2. 在 team 設定的 Build a custom integration 裡選擇 Bots ,然後幫它取個名字(Eg. mybot),按下「Add bot integration」,會跳到設定頁,抄下API token 後就可以去 Coding 了。

  3. Slack 有提供 API 給你玩,但這年頭自己從頭兜太累了,由於 chatbot 的流行,目前已經有好幾套 bot framework ,像是 hubot、 botkit 等等,前者好像比較強大,但要額外裝一些東西,暫不考慮,先用 botkit 玩玩。在專案目錄執行 npm install --save botkit 安裝。

  4. 編寫程式碼,由於只想體驗一下,所以沒做什麼事,讓它啟動時可以在 general channel 打個招呼,然後進行簡單的對話就好,程式碼如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    if (!process.env.token) {
    console.log("Error: Specify token in environment");
    process.exit(1);
    }
    var Botkit = require("Botkit");
    var os = require("os");
    var controller = Botkit.slackbot({
    debug: true,
    });
    var bot = controller.spawn( {
    token: process.env.token
    }).startRTM();
    controller.on("rtm_open", function (bot, config){
    bot.say({
    text: "大家好,達給厚,哇洗 BOT。哇蝦咪攏姆哉,五歹幾賣門哇,感溫~~",
    channel: "C02FWN249"
    });
    });
    controller.hears(["哩厚"], "direct_message,direct_mention,mention", function(bot, message) {
    controller.storage.users.get(message.user, function(err, user) {
    if (user && user.name) {
    bot.reply(message, user.name + "哩厚!!");
    } else {
    bot.reply(message, "三小.");
    }
    });
    });
    controller.hears(["叫哇(.*)"], "direct_message,direct_mention,mention", function(bot, message) {
    var name = message.match[1];
    controller.storage.users.get(message.user, function(err, user) {
    if (!user) {
    user = {
    id: message.user,
    };
    }
    user.name = name;
    controller.storage.users.save(user, function(err, id) {
    bot.reply(message, "三小, " + name +"!");
    });
    });
    });
    controller.hears(["叫阮ㄟ名"], "direct_message,direct_mention,mention", function(bot, message) {
    controller.storage.users.get(message.user, function(err, user) {
    bot.reply(message, "為您獻上一曲\nhttps://www.youtube.com/watch?v=BMmbIU8NqIU");
    });
    });
    controller.hears(["閃啦"], 'direct_message,direct_mention,mention', function(bot, message) {
    bot.startConversation(message, function(err, convo) {
    convo.ask("金價ㄇㄟ啊捏 ?", [
    {
    pattern: bot.utterances.yes,
    callback: function(response, convo) {
    convo.say("厚!金厚!\nhttps://www.youtube.com/watch?v=R_kfm1ea7Wo");
    convo.next();
    setTimeout(function() {
    process.exit();
    }, 3000);
    }
    },
    {
    pattern: bot.utterances.no,
    default: true,
    callback: function(response, convo) {
    convo.say("喝嘎在!!");
    convo.next();
    }
    }
    ]);
    });
    });
    controller.hears(["幾歲", "安安", "給把嗎"],
    "direct_message,direct_mention,mention", function(bot, message) {
    var hostname = os.hostname();
    var uptime = formatUptime(process.uptime());
    bot.reply(message,
    ':robot_face: I am a bot named <@' + bot.identity.name +
    '>. I have been running for ' + uptime + ' on ' + hostname + '.');
    });
    function formatUptime(uptime) {
    var unit = 'second';
    if (uptime > 60) {
    uptime = uptime / 60;
    unit = 'minute';
    }
    if (uptime > 60) {
    uptime = uptime / 60;
    unit = 'hour';
    }
    if (uptime != 1) {
    unit = unit + 's';
    }
    uptime = uptime + ' ' + unit;
    return uptime;
    }
    controller.hears(["(.*)"], "direct_message,direct_mention,mention", function(bot, message) {
    bot.reply(message, "哩供瞎?");
    });

基本上很簡單,由環境變數讀入 API token 後建立 Controller (可設定debug on/off),再用你的token建立bot並開啟 RTM 對話,然後就可以透過 .hears() 捕捉對話字串並進行適當的回應,比較 tricky 的地方是若要在 run 起來的時候在某個頻道送訊息的話,要透過 on RTM_OPEN 事件做,而指定channel id 是透過 channel id 而不是 channel name (channel id 可以透過 https://api.slack.com/methods/channels.list 查詢)

  1. 執行token=<YOUR_API_TOKEN> node bot.src就可以把它跑起來了,範例畫面如下
    03.png

Done! 晚點再來玩 hubot,另外在語意的分析上,目前 botkit 也只提供文字比對的方式,感覺有點笨笨的,也要再看看怎麼把語意分析的服務加進來。