雨予報bot「mickey24_bot」の使い方 ver 3.0

mickey24_botは主に以下の機能を備えているTwitter botです。

どんなbot?

短時間雨予報用bot。「○○の雨」もしくは「○○の天気」から始まるツイートを@mickey24_botに送ると、○○の地域について向こう5時間の雨予報をしてくれます。基本的に日本全国の雨予報に対応しています。

また、あらかじめ登録しておいた地域で雨が降りそうな場合にbotがreplyで知らせてくれる雨予報自動配信機能も備えています。

短時間雨予報&天気予報

以下の形式でmickey24_botにreplyすると、指定した地域について向こう5時間の雨予報および天気予報を教えてくれます。

@mickey24_bot ○○の雨
または
@mickey24_bot ○○の天気

また「明日の○○の天気」「明後日の○○の天気」と話しかけると、明日or明後日の天気予報を教えてくれます。ただし雨予報は向こう5時間の予報を返します。

@mickey24_bot 明日の○○の天気
または
@mickey24_bot 明後日の○○の天気

週間天気予報

以下の形式でmickey24_botにreplyすると、指定した地域の週間天気を教えてくれます。

@mickey24_bot ○○の週間天気

雨予報自動配信



指定した地域の雨予報を定期的に確認し、以下の条件を満たした時に配信専用bot(@rainforecast0, @rainforecast1, ...)が知らせてくれる機能です。

  • その地域で向こう5時間以内に雨が降りそうな場合
  • その地域で向こう3時間以内に雨が止みそうな場合

雨予報を配信してもらいたい時は、mickey24_botに以下のようにreplyすればOKです。

@mickey24_bot ○○の雨予報の配信

雨予報の自動配信を停止したい場合は、mickey24_botに以下のようにreplyすればOKです。

@mickey24_bot 雨予報の配信の停止

注意点は以下の通りです。

  • 配信登録できる地域の数は1ユーザにつきひとつまでとなっています。既に配信登録している地域がある状態で別の地域の配信登録をしようとすると、以前登録した地域の自動配信は解除されます。
  • 一度自動配信をした地域は以降5時間は自動配信をしない仕様になっています。
  • 配信専用botに話しかけても基本的に返事しません。配信登録・停止や天気予報などはmickey24_bot本体に話しかけてください。

漢字天気予報


1日4回(7:02, 13:02, 18:02, 23:02)、漢字や絵文字を使って天気予報をpostします。

人間画像製造

f:id:mickey24:20170708221722p:plain:w360

以下の形式でmickey24_botにreplyすると、mickey24_botがいらすとや風の人間画像を製造してくれます。

@mickey24_bot 人間画像作って
または
@mickey24_bot 人間画像ください

人間画像製造モデルは完璧ではないので、ほとんどの場合すり潰された人間のような画像が出てきますがご了承ください。詳しくは以下の記事をご覧ください。
うちのbotが「いらすとや風の人間画像」を製造できるようになった - ぬいぐるみライフ?

臓物占い

f:id:mickey24:20170712000841p:plain:w360

以下の形式でmickey24_botにreplyすると、今日のあなたにピッタリのラッキー臓物を3Dモデル画像付きで提示してくれます。「動物占い」ではありません。占いの結果は毎日0時に変わります。

@mickey24_bot 臓物占いやって

リンク先の臓物画像は以下のような感じです(「胆嚢」の場合)。ラッキー臓物をより具体的な形で把握する上で役立ちます。

f:id:mickey24:20170712000435p:plain:w240

3Dモデル画像はライフサイエンス統合データベースセンター(DBCLS)のサービス「BodyParts3D」を使って生成されています。画像のライセンスは「クリエイティブ・コモンズ 表示 - 継承 2.1 日本」が適用されます。

Brainf*ckインタプリタ

f:id:mickey24:20170713011300p:plain:w360

mickey24_botに難解プログラミング言語「Brainf*ck」のコードをreplyすると実行してくれます。詳しくは以下の記事をご覧ください。

mickey24_bot de Brainf*ck - ぬいぐるみライフ?

おまけ

  • 挨拶するとちゃんと(?)返してくれます。
  • お礼を言うと喜びます。
  • うさみみ(「「)に反応します。
  • 「殴って」と話しかけると殴ります。
  • 「励まして」と話しかけると励ましてくれます。
  • 他にもいろいろ!


以前のバージョン(2.0)からの変更点

  • 話しかけると1〜2秒で返事をくれるようになりました(Twitter Streaming APIに対応)。
  • 雨予報自動配信が配信専用bot(@rainforecast0, @rainforecast1, ...)によって行われるようになりました。
  • 一部の機能が廃止されました(飲食店検索、デレモード、エアコン操作、非公式RTボクシング)。

どうやって動かしてるの?

Goでソースコードを書き、Dockerのコンテナを作ってさくらのVPSにデプロイすることで動かしています。

何で雨予報?

局所的かつ短期的な雨の予報をすぐに配信してくれるようなサービスがあると便利なんじゃないかなーと思ったので。

雨予報が当たらないんだけど

あくまでも予報なのでその辺は勘弁してください><実際は雨が降らないのに「降りそう」「降ってる」と通知してくることが多いようです。

以上

かわいがってやってください。

更新履歴

  • 2017-06-14 記事作成
  • 2017-07-08 人間画像製造についての記述を追加
  • 2017-07-12 臓物占いについての記述を追加
  • 2017-07-13 Brainf*ckインタプリタについての記述を追加

mickey24_botの雨予報自動配信の仕様が変わりました

mickey24_botの雨予報自動配信が配信専用bot(@rainforecast0, @rainforecast1, ...)によって行われるようになりました。この変更によって、mickey24_bot本体のツイート数が少なくなり、rate limit exceededエラーによってbotがしばらく会話できなくなるといったことを防ぐことが期待できます。

配信専用botに話しかけても基本的に反応しませんので、配信登録・停止や天気予報などは今まで通りmickey24_bot本体に話しかけてください。

おーばーびゅー


配信されている様子


Cucumber+Mockで悩んでいる

CucumberでMockに対するmethod呼び出しのexpectation(should_receive)をどのように書くか悩んでいる.

動くけど好きじゃない例

CucumberのexamplesにMockを使う例がある.
https://github.com/cucumber/cucumber/tree/master/examples/rspec_doubles

この例ではMockの作成とmethod呼び出しのexpectationの設定をGiven節に書いている.Then節には何も書いていない.

mocking.feature

Feature: Mocking
  In order to test external stuff
  I want to mock

  Scenario: Mock a transmogrifier
    Given I have a cardboard box
    When I poke it all is good

calvin_steps.rb

class CardboardBox
  def initialize(transmogrifier)
    @transmogrifier = transmogrifier
  end
  
  def poke
    @transmogrifier.transmogrify
  end
end

Given /^I have a cardboard box$/ do
  transmogrifier = double('transmogrifier')
  transmogrifier.should_receive(:transmogrify)
  @box = CardboardBox.new(transmogrifier)
end

When /^I poke it all is good$/ do
  @box.poke
end

これでテスト自体は問題なく動くのだけど,いくつか不満点がある.

不満点
  • "Given I have a cardboard box"で実行されるコードが"I have a cardbox"以上のことをやっている
    • transmogrifierに関するGiven節を追加してコードを分割すればいいのかもしれないけど…
  • method呼び出しのexpectationがGiven節に,methodの戻り値のassertionがThen節に分散してしまう

こんなふうに書きたい

method呼び出しのexpectationもmethodの戻り値のassertionもThen節に書きたい.

mocking.features

Feature: Mocking
  In order to test external stuff
  I want to mock

  Scenario: Mock a transmogrifier
    Given I have a cardboard box
    When I poke it
    Then all is ok

calvin_steps.rb

class CardboardBox
  def initialize(transmogrifier)
    @transmogrifier = transmogrifier
  end
  
  def poke
    @transmogrifier.transmogrify
  end
end

Given /^I have a cardboard box$/ do
  @transmogrifier = double('transmogrifier')
  @box = CardboardBox.new(transmogrifier)
end

When /^I poke it all is good$/ do
  @box.poke
end

Then /^all is ok/ do
  @transmogrifier.should_receive(:transmogrify)
end

しかし,このテストは失敗する.Then節はWhen節よりもあとに実行されるため,When節で@box.pokeが呼ばれる時点で@transmogrifierにexpectationがセットされていないことが原因.

以上

どうすればこの手のテストがスマートに書けるのかまだよく分かってないけど,Then節がWhen節よりも後に実行される以上,Given節にexpectationを書く方法しかないんだろうなーと思ってる.

もっといい書き方がありましたらぜひ教えて下さい.

Ruby 2.0.0-p0がリリースされてた

Ruby 2.0.0-p0 リリースノート

わーい.開発・リリースに関わった皆さん,本当におつかれさまでした&ありがとうございました.

非互換

リリースノートにRuby 2.0.0の「特筆すべき非互換」について書いてあったので真っ先に確認してみた.

デフォルトのスクリプトエンコーディングがUTF-8に

これのおかげで各ファイルにUTF-8用のマジックコメントをわざわざ書く必要がなくなった.わーい.早くRuby 1.9をdeprecateしよう!(ムリ
でもこの変更によって一部のプログラムが遅くなるなどの悪影響もある様子.まあ当たり前か.

iconv削除

Ruby 1.9から登場したString#encodeなどを使ってくださいという話.

ABI互換性がなくなっている

「1.9の.so, .bundleファイルをコピーするな」ということだけ気をつけておけばいいらしい.

#lines, #chars, #codepoints, #bytesメソッドがEnumeratorではなくArrayを返すようになった

結構うれしい変更.今まで文字列の各文字のArrayを取ってくるときにsome_string.chars.to_aと書いていたけど,これがsome_string.charsだけでよくなる.Array#to_aはselfを返すので,to_aがついてる古いコードも一応動くので安心.

Object#inspectの結果が#to_sではなく#のような文字列になった

今のところ特に思うところはないかな.

以上

さっそくrvm get head && rvm install 2.0.0 && rvm use 2.0.0 --defaultした.普段使っているRubyGemsが問題なく動いてくれることを祈ろう.
その他新機能については後日調べてみようかな.リリースノートからもリンクされてた以下の記事が分かりやすそう.
http://blog.marc-andre.ca/2013/02/23/ruby-2-by-example/

うちのbotがエアコンの操作方法を覚えた

追記:2017-07-09
現在この機能は利用できません。最新の情報は雨予報bot「mickey24_bot」の使い方 ver 3.0 - ぬいぐるみライフ?をご覧ください。

ぼくの自宅のエアコン限定ですが,mickey24_botがエアコンを操作できるようになりました.

どんな機能なの

うちのbotにreplyで指示を送ると,うちのエアコンに赤外線が発射されます.指示の出し方の例は,

@mickey24_bot 冷房を28℃に設定して
@mickey24_bot 暖房を20℃に設定して

など.これで外出先からエアコンを操作しておけば,帰宅時にエアコンの効いた快適な部屋がぼくを出迎えてくれます.

エアコンの運転モードは冷房と暖房,温度の設定範囲は16〜30℃(華氏温度は後日対応予定)です.

どうやって実現してるの

Arduino Unoに赤外線LEDを繋いで,Arduino Unoでエアコン用赤外線リモコンの信号をエミュレートさせています.

Arduinoと赤外線LEDは下のような感じになっています.ふたつの赤外線LEDがそれぞれ部屋の照明とエアコンの方を向いています(ちなみに部屋の照明もArduinoから赤外線で操作可能になっています).このArduinoはUSBで自宅サーバと繋がっていて,USBシリアル通信で操作することができるようになっています.

注意事項

  • だれでも操作できます.

以上

帰宅した時に既に部屋が冷えているのは思った以上に快適ですね.癖になりそう.

実際に書いたプログラムやサーバの詳細については後日記事を書く予定です.

unite.vimで:UniteWithBufferDirのsourceにfile_recを指定すると失敗する

現在開いているバッファのディレクトリでUniteのfire_rec (file_rec/async)を実行したいことが結構あるのだけど,以下のように:UniteWithBufferDirとfile_recを組み合わせて実行すると何故か結果がひとつも表示されない.

:UniteWithBufferDir file_rec

:Uniteとfire_recの組み合わせは一応動く.

:Unite file_rec

何が原因なのだろう.同様に:UniteWithCurrentDir file_recも動いてくれない.

仕方がないので,.vimrcに以下のように書いてバッファが切り替わるたびにバッファのディレクトリにcdするようにした.これなら:Unite fire_recを使ってカレントバッファのディレクトリでfile_recが実行できる.

augroup AutoCD
  autocmd!
  autocmd BufEnter * lcd %:p:h
augroup END

JavaScriptの等値演算は==ではなく===を使うようにする

JavaScriptの==は予想外の結果を返すことがある

JavaScriptの等値演算子==は,左右のオペランドの型が等しい場合,両者の値が等しければtrueに,そうでなければfalseになります.

しかし,2つのオペランドの型が違う場合,==はオペランドを型変換してから比較することがあります.この型変換がなかなか曲者で,比較する値と型の組み合わせによっては予想外の結果が得られることがあります.

以下に例を示します.

'' == '0'          // false
0 == ''            // true
0 == '0'           // true

0 == []            // true
0 == {}            // false

0 == false         // true
0 == [0]           // true
0 == [false]       // false

false == 'false'   // false
false == '0'       // true

false == undefined // false
false == null      // false
null == undefined  // true

' \t\r\n ' == 0    // true

上の結果は冗談ではなく本当です.ぜひお使いのブラウザで試してみてください.
もはや何が何だかという感じですよね.しかしこれはECMAScriptの仕様通りの評価結果となっています.このように==の結果が予想外だったせいでバグが発生した場合,デバッグは困難を極めるでしょう.

===はオペランドの型変換を行わない

一方,===はオペランドの型と値が等しい時に限りtrueになります.そのため,上記のような型が違うケースはすべてfalseになります.

'' === '0'          // false
0 === ''            // false
0 === '0'           // false

false === 'false'   // false
false === '0'       // false

0 === false         // false
0 === []            // false
0 === {}            // false

0 === false         // false
0 === [0]           // false
0 === [false]       // false

false === undefined // false
false === null      // false
null === undefined  // false

' \t\r\n ' === 0    // false

==と比べると直感的でまともな結果が得られることが分かると思います.
自動的に型変換させてまで異なる型の値を比較したいことはそうそうないと思うので,等値演算では普段から===を使う癖をつけたほうがいいでしょう.また,同じ理由から非等値演算では!=よりも!==を使うようにしましょう.

参考資料

「==」はJavaScript: The Good Partsという本の中でも「JavaScriptのBad Parts」のひとつとして紹介されています.

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス