こんにちは!Swift愛好会&Kotlin愛好会主催の@jollyjoesterです。本書を手に取っていただき、ありがとうございます。
本書はSwiftを愛するメンバーが集まるSwift愛好会とKotlinを愛するメンバーが集まるKotlin愛好会の有志メンバーがネタを持ち寄って作成した技術同人です。言語についての話にとどまらず、Swift/Kotlinに関連の深いプラットフォームやサービスについての話など多岐にわたるネタについて盛り込んでいます。
各章は独立しています。著者紹介でそれぞれの章の概要を紹介しますので、興味を持った章から読み進めてください。楽しんでいただけるととても嬉しいです。
ドーモ!@jollyjoesterです。
今回はSlackKit*1を使ってSwiftでSlackbotを作っていきましょう!
新型コロナの影響でオンラインコミュニケーションはより重要性を増しています。普段みなさまが使っているだろうSlackに、オリジナルのbotを作ってオンライン生活をより楽しいものにしていけるといいですね。さまざまな言語でSlackbotは作れますが、ここはLove Swift。Swiftを使って楽しんでいきましょう。
なお、本記事は次の環境で試しています。
まずはSlackKitを使う上で必要なライブラリをMacにインストールします。Homebrew*2がインストールされてない場合はHomebrewのインストールからしてくださいね。
$ brew install libressl
次にSwift Package Managerでプロジェクトを作成していきましょう。適当な場所に`swiftbot`という名前の新しいディレクトリを作って次のようにプロジェクトを作成します。
$ mkdir swiftbot
$ cd swiftbot
$ swiftbot swift package init --type executable
`Package.swift`というファイルができているので2行ほど加えてSlackKitを追加します。Package.swift全体としては次のようになります。
import PackageDescription
let package = Package(
name: "swiftbot",
dependencies: [
// ここを追加
.package(url: "https://github.compvzig/SlackKit.git", from: "4.3.0")
],
targets: [
.target(
name: "swiftbot",
// ここも追加
dependencies: ["SlackKit"]),
.testTarget(
name: "swiftbotTests",
dependencies: ["swiftbot"]),
]
)
追加したらPackage.swiftをXcodeで開きましょう。次のコマンドを叩くか、Finderを開いてPackage.swiftをダブルクリックするとXcodeが起動します。
$ open Package.swift
Xcodeは次のような状態になっているはずです。さきほどPackage.swiftに設定したSlackKitとSlackKitに必要なライブラリはXcodeが自動的に追加してくれます。
こちらでいったんswiftbot作成の準備はできました。次にSlackを操作するための設定をしていきましょう。
SlackにBotユーザーを追加します。
次のURLにアクセスします。
https://my.slack.com/services/new/bot
まだ自分のワークスペースを持っていなかったら先に次のURLからワークスーペースを作ってください。
開いた画面で次の操作をします。①ワークスペースを選んで②Botの名前(ここではswiftbot)を入力して③「Add bot integration」を押します
さて、いよいよBotの本体を実装していきます。
Xcodeに戻り、「main.swift」を選択します。
メニューの「File -> New -> File」にて新しいファイルを作成し、「Swiftbot.swift」というファイル名にします。
Swiftbot.swiftにSwiftbotクラスを実装します。このクラスでSlackKitも使うのでimportして変数も宣言しておきます。
import Foundation
import SlackKit
class Swiftbot {
let bot: SlackKit
// ここに初期化処理を後で書く
}
初期化処理を実装します。初期化処理はとりあえずコピペしてみてください。ざっくり次のような処理です。
import Foundation
import SlackKit
class Swiftbot {
let bot: SlackKit
// 初期化処理
init(token: String) {
bot = SlackKit()
// 1. SlackKitにAPI Tokenをセット
bot.addRTMBotWithAPIToken(token)
bot.addWebAPIAccessWithToken(token)
// 2. Botに向けたイベントが通知される
bot.notificationForEvent(.message) { [weak self] (event, connection) in
guard
let message = event.message,
let id = connection?.client?.authenticatedUser?.id,
message.text?.contains(id) == true
else {
return
}
// 3. ここにBotで操作したい処理を書く
self?.handleMessage(message)
}
}
}
いよいよBotの動作の実装です。handleMessageメソッドを次のように実装しましょう。Botにメンションされたら「何ですか?」とだけ聞き返す処理です。
private func handleMessage(_ message: Message) {
// channelの情報を取得して、メンションされたchannelにテキストを送信する
if let channel = message.channel {
bot.webAPI?.sendMessage(channel: channel, text: "何ですか?", success: nil, failure: nil)
return
}
}
以上で準備は整いました!さっそくこのBotを実行しましょう。
Xcode画面左上の部分にてデバイスにMy Macを選択し、実行ボタンを押します。
SlackにてBotユーザーをiniteします。
Botにメンションしてみましょう!Botにメンションして返事が返ってきたら成功です!
Botにいろいろな動きをさせてみましょう。
Botへのメンションに対してリアクションするようにしてみましょう。handleMessageメソッドの中身を書き換えます。
SlackKit.WebAPIのaddReactionToMessageメソッドを使います。リアクションする絵文字の名前を文字列で指定します。
private func handleMessage(_ message: Message) {
// channelの情報とタイムスタンプを取得して、メンションされたにメッセージにリアクションする
if let channel = message.channel, let timestamp = message.ts {
bot.webAPI?.addReactionToMessage(name: "muscle",
channel: channel,
timestamp: timestamp,
success: nil,
failure: nil)
}
}
実行してBotにメンションすると次のようにリアクションがつきます。
Botにメンションしたらスレッドで返信してもらうようにします。
SlackKit.WebAPIのsendThreadedMessageメソッドを使います。channelとtimestampで返信するスレッドの元メッセージを指定し、textで返信内容を設定します。
private func handleMessage(_ message: Message) {
// channelの情報とタイムスタンプを取得して、メンションされたにメッセージにリアクションする
if let channel = message.channel, let timestamp = message.ts {
bot.webAPI?.sendThreadedMessage(channel: channel,
thread: timestamp,
text: "なーに?",
success: nil,
failure: nil)
return
}
}
実行してBotにメンションするとスレッドに返信が届きます。
最後にメンションした文言の内容によって返答を変えるBotにしてみましょう。
private func handleMessage(_ message: Message) {
// textを取得し、その内容次第で返答の仕方を変える
if let text = message.text, let channel = message.channel {
var reply: String
switch text {
case text where text.contains("遊ぼ"):
reply = "わーい:smile:"
case text where text.contains("仕事して"):
reply = "えー:scream:"
default:
reply = "なーに?"
}
bot.webAPI?.sendMessage(channel: channel,
text: reply,
success: nil,
failure: nil)
return
}
実行して文言を変えてBotにメンションすると会話を楽しめます。