ruboty-talk から hubot-zatsudan 作った

soh335/hubot-zatsudan · GitHub

経緯

DocomoruでBOTと雑に会話する - Qiita

これが面白かったので ruboty-talk を hubot に移植してみた。

hubot の話

https://github.com/github/hubot/blob/master/src/robot.coffee#L175-L185 これを読んでたら robot.catchAll でどのテキストにもマッチしなかった場合に処理が書けることが分かったので、これを使った。ただ、話しかけられてる場合にしたいので、robot.respond正規表現を一部拝借した。

これで hubot が話しかけられたけどマッチしなかった場合になる。

日本語でしか使えなさそうだし npm にはとりあえず出してない。

ペルソナQ

PQ - ペルソナQ シャドウ オブ ザ ラビリンス - 公式サイト

ペルソナQ ようやくクリア。7か月かかった…

ダンジョンに嵌りすぎて毎回ボスは苦戦しないっていう感じだった。

nasne の録画スケジュールが重複した場合に push 通知を送る

年末から nasne を 2 台で運用するようしたが、1 台の中で重複が生まれた場合はもう 1 台に自動的に受け渡してくれるようなことはしてくれない。なので、毎週録画みたいな予約を入れ放送スケジュールが変更され他の番組と被ってしまった場合、1 台で運用してる時と同じく録画に失敗してしまう。

なので録画スケジュールが重複してしまった場合に push 通知を pushbullet 経由で送る nasne-conflict-pushbullet というスクリプトを書いた。

soh335/nasne-conflict-pushbullet · GitHub

$ nasne-conflict-pushbullet --host x.x.x.x --apikey xxxxxxxxxxx

上のように実行し、重複があった場合は push 通知が届く。 cron などで一日一回実行すると良さそう。

nasne の録画スケジュールを ical に変換する

nasne を探す事が出来るようになった次は nasne-ical という nasne の録画スケジュールを ical 形式に変換するものを書いてみた。

soh335/nasne-ical · GitHub

$ go get github.com/soh335/nasne-ical

で install し

$ nasne-ical --host XXX.XXX.XXX.XXX --name "nasne ical" --tz Asia/Tokyo

のようなコマンドを打つと ical 形式に変換される。それを dropbox において公開リンクで google calendar に読み込ませると下のように表示される。(色が二種類あるのは nasne が二台あり、それぞれ ical を生成しているから。) 後は定期的に更新すれば、google calendar 側も随時更新される。

録画関係では下記のようなアクションが定義されていた。

  • X_CreateRecordSchedule
  • X_GetConflictList
  • X_DeleteRecordSchedule
  • X_GetRecordScheduleList
  • X_UpdateRecordSchedule
  • X_GetTitleList
  • X_DeleteTitle
  • X_UpdateTitle

今回は X_GetRecordScheduleList というものを使っている。X_GetTitleList は録画したリストだと思われるが、その他については request に <xsrs><item>...</item></xsrs> のような xml をさらに定義する必要がありそれの定義が書かれていなかったので、今回は諦めた。

go で xml を色々扱うのかなりめんどくさい。

nasne を探す

NOTIFY * HTTP/1.1
Host: 239.255.255.250:1900
User-Agent: Go 1.1 package http
Cache-Control: max-age=1800
Location: http://x.x.x.x:58888/
Nt: urn:schemas-xsrs-org:service:X_ScheduledRecording:2
Nts: ssdp:alive
Server: Linux/2.6 UPnP/1.0 nasne/1.0
Usn: uuid:xxxx::urn:schemas-xsrs-org:service:X_ScheduledRecording:2
X-Av-Server-Info: av="5.0"; hn=""; cn="Sony Computer Entertainment Inc.";mn="nasne";mv="1.0";

こういう request が出てきたら location の先にアクセスするとさらにどういうサービスが定義されてるかわかる。

package main

import (
    "bufio"
    "bytes"
    "log"
    "net"
    "net/http"
)

func main() {
    if err := _main(); err != nil {
        log.Fatal(err)
    }
}

func _main() error {
    addr := &net.UDPAddr{
        IP:   net.ParseIP("239.255.255.250"),
        Port: 1900,
    }

    conn, err := net.ListenMulticastUDP("udp4", nil, addr)

    if err != nil {
        return err
    }

    defer conn.Close()

    req, err := http.NewRequest("M-Search", "*", nil)

    if err != nil {
        return err
    }

    req.Header.Set("ST", "upnp:rootdevice")
    req.Header.Set("MX", "10")
    req.Header.Set("MAN", `"ssdp:discover"`)

    var b bytes.Buffer
    if err := req.Write(&b); err != nil {
        return err
    }

    if _, err := conn.WriteToUDP(b.Bytes(), addr); err != nil {
        return err
    }

    for {
        req2, err := http.ReadRequest(bufio.NewReader((conn)))
        if err != nil {
            log.Println(err)
            break
        }
        log.Println(req2)
    }

    return nil
}