heroku + node.jsでSkype bot作った

WithOne Advent Calendar 2017 の 1日目です
私の所属しているグループの本社組は
水曜日にお昼ご飯をみんなで食べに行っています。(通称ランチミーティング)

毎回たくさんの人が参加するのでグループ分けをしているのですが

  • お昼までに各々エクセルに出欠を書く
  • 心優しい誰かが班分けサービスに名前を入力する
  • それをSkypeで発表

というフローがめんどくさいなあと思ったのでSkype bot作ってみました。

Skype Web SDK API reference

最近はSlack botが流行っていますが弊社のグループはSkype派です。
実装するにあたってここの記事を参考にさせていただきました。

Microsoft Bot FrameworkとHerokuとNode.jsを使ってSkype用Botを作る。 - Qiita

とりあえず作ってみた

この中で出てくる
botbuilderというのがMS製のbot作成フレームワーク
restifyというのがREST Web APIを作成するのに便利なフレームワーク
です。

記事を参考にしつつ、とりあえずbotを用意してみたらbotをグループに追加できず詰まる。。

なんとなく動いた・・・で終わらないためのMicrosoft Bot Framework ~ BotからSkypeグループにプロアクティブメッセージを送る ~ - Qiita

グループに参加させるためにはこの記事にあるようにグループに追加するための設定が必要でした。
これは見落としがちな気がするので注意です。

出欠席のデータの保存は、
DBを準備するほどではないなと思ったので、ファイルにガリガリユーザーを書き込むことにしました。
node.jsの「fs」と言うデフォルトの機能を利用するとファイルの操作も簡単にかけます。

出来上がったのがこのような感じ!
f:id:withoneAdventCalendar:20171201021941p:plain

Heroku簡単すぎてやばい

herokuは無料版だからだと思うのですがsshでサーバに入ると結構もっさりでした。
(レスポンスも遅め。。?)

Macのターミナルからだと恐ろしく簡単に導入できるので、
暇つぶしに何か作りたい方に本当にオススメです。
node.jsの環境の設定も、ボタン一つでWeb上からサクッとできます。

何も知らなくてできてしまうのは良いのか。という意見はあると思います。
業務ではもちろん正しい知識を身につけたほうが良いですが、
プライベートではサーバ構築などはかなり時間を取りますしハードルが高いので、
このようなサービスを使って簡単に作れるのは良いのではないかなと思いました。

コード公開しています

コードを公開しています。
フローが面倒云々と言いましたが正直このAdventCalendarのネタの為に作ったものなので
今日動かしてスクショを撮ることを目的としており、未完成です。
(グループを分割する時に4人以上、且ついい感じの人数でないと落ちます。)
完成させて実際に使えるよう頑張ります。。

あとリファクタリング・機能追加のプルリクどなたからでもお待ちしております。
github.com

SwiftとOptionalについて

WithOne AdventCalendar 25日目(http://qiita.com/advent-calendar/2016/withone) 最終日です。

みなさん参加してくださってありがとうございました!
投稿先をQiitaにしたのは少しハードルが高かったかなと思いつつ、
来年もAdventarあたりでまたやりたいなあなんて思っています。


最終日はSwiftとOptionalのススメです。
最近流行りのNull安全な言語。
SwiftもNull安全な言語の一つです。

Null安全な言語といえば、
Python、Kotlin、TypeScriptなどは名前を聞いたことがある人もいるのではないでしょうか。
最近こんな記事も話題になりました。
null安全でない言語は、もはやレガシー言語だ - Qiita

Optionalを通じてSwiftの楽しさ、便利さについて、みなさんに伝わると良いなと思います。

※Swiftではnullをnilと言います


SwiftではOptionalと言う型が使えます。
Optionalとは、「nilを入れることのできる入れ物」を表します。

Swiftではnilを入れることのできる変数かどうかを
あらかじめ設定しないと、変数を作ることができません。

Javaの場合は以下のように書いた場合、
変数hogeにはいつかnullが入る可能性があります。
hogeを使うときには、常にnullの存在を考えなければならないです。

String hoge = "ほげ";  

Swiftの場合、nilを入れることのできる変数かどうかを、
あらかじめ指定しておく必要があります。
書き方は以下の通りです。

// nilを入れることができる変数
var hoge: String? = nil

// nilを代入することができない変数
var hoge: String  = "ほげ"

上下の構文の違いは、型宣言をしているStringの後ろに?がついているかいないかです。
Swiftでは?をつけることで、「この変数はnilを代入することが可能な変数ですよ」
ということを表しています。

ここでは詳しく説明しませんが、
OptionalはOptional<T>という一つの型です。
SwiftではこのOptional<T>を、?を使って簡単に書くことができるようになっています。

非Optional

?のついていないStringには、
nilを代入することができません。
この?が付いていない型を、非Optionalと言います。
非Optionalで宣言した変数にnilを代入しようとすると、
コンパイラがエラーにしてしまうのです。

もしnilになる可能性のある値を代入しようとする場合、
以下のようにデフォルトの値で初期化する書き方をすることができます。
これが結構便利です。

var hoge: String? = nil
var foo: String = "ふー"

// nilの入っている可能性のある変数を代入しようとするとき
// ?? をつけるとデフォルト値を指定できる
foo = hoge ?? "デフォルト"


このように非Optionalの値は、コーディング時にnilが入るかどうか、
他のメソッド中身等を確認したり、nilチェックをする必要がなくなるのです。

Optional

Optionalの型の場合は、値が入っているのか、nilなのかを確認する必要があります。
値が入っていることを確認し、
Optional型から中身を取り出すことをunwrap(アンラップ)と言います。

そもそもStringとString?は
StringとOptional<String>という異なる型になります。
このOptional<String>に入っているStringを使用するためには、
Stringの値をOptionalから取り出してから使用する必要があるのです。

Optionalからの値の取り出し方を以下に記載します。

var hoge: String? = XXXXX // nilかそれ以外かの何かが入っている

// hogeの中身をunwrapHogeに取り出してから使用する
if let unwrapHoge = hoge {
    print(unwrapHoge)
}

Swiftではこのif let 変数名 = Optional型の何か という書き方をよくします。
※let とはSwiftの定数の宣言を表します。varは変数の宣言です。

hogenilではない場合、String?型のhogeから中身が取り出され、
unwrapHogeに代入されます。
hogeの中身がnilだった場合は、falseとなり、このif文の中の処理は行われません。

また、hogeの中身がnilだった場合は、この後の処理を全て行わずにreturnしたいという時もあります。
そんな時はguard文を使用します。

var hoge: String? = XXXXX // nilかそれ以外かの何かが入っている

// hogeの中身をunwrapHogeに取り出して、nilだった場合は以降の処理を行わない
guard let unwrapHoge = hoge else {
    print(unwrapHoge)
    return
}

// その後の処理色々
print(unwrapHoge)


guard文は、
「設定した条件式に当てはまる場合のみ、
それ以降の処理を実行する」
ということを表す構文になります。

guard文の中では必ず、returnやbreakなど、
以降の処理を行わない旨の処理を記述する必要があります。

このようにして、Optionalの変数は、
値が入っている場合のみ使用されるよう作られているのです。

※中身がnilでも使用する方法はありますが
今日はここまで。。

最後

Optionalの使い方について少しだけ興味が湧いてきましたか・・?
nilの扱い方について少しだけ便利になるOptionalですが、
nilに全くならないというわけではありません。

Optionalの型をnilが入っていても使うことはできてしまいますし、
デフォルトの値を設定する例を出しましたが、
あの処理自体もきちんと考えてデフォルトを設定しなければ、
ただエラーの握りつぶしを行うことと同じことにもなるのです。

最後に、

Swiftはいいぞ!