Seasar の終わり

9/24(土)に法政大学で行われた Seasar Conference 2016 Final に行って来ました。

https://event.seasarfoundation.org/sc2016/

まず、このカンファレンスが Seasar にとっての最後のカンファレンスだったにも関わらず準備も宣伝も告知もほぼ出来なかったこと、スピーカーにも全然声が掛けられずに少ないセッション数になってしまったことに関してごめんなさい。

Seasar プロジェクト EOL

Seasar プロジェクト は、本日 2016/09/26 をもって EOL となります。 例外のプロジェクトもありますので、詳細は seasar.org をご覧下さい。

これは Seasar を使うなという意味ではありませんし、EOL に関する話しは久保さんの blog が大変参考になるので是非読んで下さい。

Seasar Conference 2016 Final

EOL になることだし、最後の Seasar Conference をやろうと言った去年のカンファレンスからあっという間に1年が経ち当日を迎えました。 ひがさんの Seasar Project の振り返りを聞いていて懐かしいなぁと思うこともあり寂しい気持ちになりました。

Seasar Conference は、全盛期には1,000人を超えるほどの参加者がいて、日本を代表するようなカンファレンスだったと思います。 去年は久しぶりの開催だったことや告知や集客も行ったので多くの来場者数でしたが、今年は去年に比べると参加者は少なかったです。 準備不足だったこと本当にごめんなさい。

懇親会には行けませんでしたが久しぶりに会う人が多くて懐かしくもありとても嬉しかったです。

Seasar に思うこと

Seasar の良かったところは、開発者が皆ワクワク出来たことに尽きると思います。
MLやはてなダイアリーのコメントのやり取りで、ひがさんやコミッター達や利用者がパブリックなところで議論して決めてそれを実装しリリースされるサイクルや自分達が作った OSS が次々に実戦投入されていくところが当時のモチベーションになっていました。
コミッターも最大100人を超えたり、.NETやPHPのプロダクトも出てきて他言語も巻き込んで、国内の開発者に多くの影響を与えたOSSだったと思います。

個人的には、Seasar があったからこそ色んな人に出会い、そして今の自分があるので Seasar というプロダクトにはとても感謝しています。

いま会社を支えてくれている松原さん(@mopemope)に初めて会ったのが Seasar Conference でした。
今ではプライベートでも仲良しな橋本正徳(@hsmt)に初めて会ったのも Seasar Conference で「きったねぇジャージ着てるなーこいつ」と思ったのが最初の印象でした。
そんな人と10年来の付き合いになったり、仕事も一緒にしたりして Seasar が無かったら絶対に出会ってない人に出会えて感謝しています。
コミュニティの盛り上げ方や OSS の運営の難しさなどを学ばせてもらったのも Seasar でした。

最後に、Seasar に関わった多くの開発者の方々、そしていつもインフラや会場を手配してくれていたふたがわさん、本当にありがとうございました。

Seasar Conference 2016 Final 撮影 橋本正徳

株式会社Abby エビイ 社員募集

弊社は少数で頑張っている会社です。(qiitaには東京本社のエンジニアが登録しています) qiita.com

勤務時間は、定時を 10:00〜19:00 と定めていますが各自にスケジューリングは任せていますので、自宅作業だったり私用を済ませて午後から出社したり自由度はとても高いです。
服装については、特に決まりはありません。
打合せに関してはオンラインにて Google HangoutSkype で完結しますし、対面での打ち合わせが必要な場合は私が行きますのでスーツは不要です。

現在はアプリの開発がメインで、システムの開発もやっていますが今回の募集はアプリ開発になります。

株式会社 Abby エビイ

募集要項

東京本社でプログラマを募集しています。

iOS向けアプリも全てJavaで開発しているのでJavaの開発経験がある人を特に必要としています。
開発では、AndroidStudioNetBeansEclipse またはエディタを使っており開発環境は各自自由に決めて下さい。
Javaの開発基盤には libGDX を採用しており、UIに関わる部分はJava + libGDX で開発することになります。
サーバ側の処理は全て Go で開発していますので、JavaGo を書きたい!という方は是非連絡してください。
開発のやり方としては、SlackSkype でやり取りしながら、Backlog というタスク管理サービスを利用してプロジェクトを進めます。

一緒にアプリ開発をしてみたい方は、info@abby.co.jp にメールするか TwitterFacebookで私(@yone098)までDMなどで連絡をしてください。

何卒よろしくお願い致します!

Facebook Messanger Platform での BOT の作り方

Facebook Messanger Platform が公開されて Facebook Messanger でも BOT を作っていたので手順などをまとめました。

BOT を作るまでなら公式ドキュメントを見ればだいたい分かると思います。

作成したものは golang + goji を heroku で動かしています。 LINE BOT 作成時よりも半分ほどの時間で簡単に作れました。

github.com

f:id:yone098:20160414041036p:plain:w300

手順

基本的には公式ドキュメントの通りですが公式ドキュメントは、英語版ダッシュボードなので実際に試してみると少し戸惑うかもしれませんが手順としては以下の通りです。

  1. Facebook ページを作成
  2. コールバック用のAPIを作成する
  3. facebook for developer の管理画面の左下の Messagenger を選択し Webhooks (コールバック)の設定
  4. facebook for developer の管理画面の左下の Messagenger を選択し 作成したFacebookページをプルダウンから選択しアクセストークンを生成
  5. メッセージ送信 BOT を作成する
コールバック作成

Webhooks の設定でコールバック URL を設定します。 Setup Webhooks ボタンを押すとダイアログが表示されるのでコールバックURLを入力し、verify tokenを自身で設定してください。
例)MY_VERIFY_TOKEN
コールバック URL の設定画面で、コールバック URL が正しいものが確認するために Facebook platform とやりとりする必要があります。
簡単に言うと、コールバック URL に特定のパラメータを飛ばすから、お前の作ったシステムからこっちが送ったものを正常に返せよ。それが正しかったら Webhook の設定認めるよというものになります。
特定の GET パラメータでリクエストされてくるので、対応したレスポンスを返すように作ってください。

golang だと以下のようになります。(goji 使ってます)

func handleGetCallback(c web.C, w http.ResponseWriter, r *http.Request) {
    log.Println("called callback GET")

    if err := r.ParseForm(); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    // get parameter
    token := r.Form.Get("hub.verify_token")
    log.Println("hub.verify_token:", token)

    challenge := r.Form.Get("hub.challenge")
    log.Println("hub.challenge:", challenge)

    if token == facebookVerifyToken {
        fmt.Fprintf(w, challenge)
        return
    }
    fmt.Fprintf(w, "OK")
}

正常にコールバックを返せていれば設定画面で正常に保存されて管理画面の方で完了アイコンが表示されるので、まずはコールバック連携として完了アイコンが表示されるまでは頑張ってみましょう。

f:id:yone098:20160414035023p:plain:w600

bot でメッセージを受信する

メッセージを受信するには、コールバックに設定したURLにPOSTされてくるのでメッセージをパースして受け取ります。
LINE BOT と同じで結局メッセージの構造を実際のデータを見ながら読み解くところが一番時間かかるところだと思います。

POST されてくる JSON は以下になります。

{
    "entry": [
        {
            "id": 1583495931963063, 
            "messaging": [
                {
                    "message": {
                        "mid": "mid.1460572581000:cc8dc67dbaa3b39316", 
                        "seq": 40, 
                        "text": "こんにちは"
                    }, 
                    "recipient": {
                        "id": 1583495931963063
                    }, 
                    "sender": {
                        "id": 1036935553049492
                    }, 
                    "timestamp": 1460572581014
                }
            ], 
            "time": 1460572581050
        }
    ], 
    "object": "page"
}

これをパースすればメッセージを取得出来ます。

func handlePostCallback(c web.C, w http.ResponseWriter, r *http.Request) {
    log.Println("recieve message from facebook messagenger")
    var msg facebookMsg
    b, err := ioutil.ReadAll(r.Body)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    log.Println("msg:", string(b))
    err = json.Unmarshal(b, &msg)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    for _, event := range msg.Entry[0].Messaging {
        if event.Message != nil {
            log.Println("Recieved msg:", event.Message.Text)
        }
    }

    fmt.Fprintf(w, "OK")
}

メッセージにImage や Video or Audio Attachment がある場合のメッセージフォーマットは以下を確認してください。

Webhook Reference - Messenger Platform - 参考資料 - 開発者向けFacebook

bot でメッセージ送信

送信時にはページのトークンを設定するだけで、メッセージのフォーマットさえ合わせればすんなり送信出来ます。

           m := sendMessage{
                Recipient: &id{ID: senderID},
                Message:   &text{Text: "ハゲ"},
            }
            b, err := json.Marshal(m)
            if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
            }
            req, err := http.NewRequest("POST", facebookPostURL+facebookToken, bytes.NewBuffer(b))
            if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
            }

            req.Header.Add("Content-Type", "application/json; charset=UTF-8")
            client := &http.Client{}
            res, err := client.Do(req)
            if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
            }
            defer res.Body.Close()

今回は、簡単なテキストメッセージを送信する BOT でしたが画像なども送れるので企業用 BOT を作るには良さそうです。