mikutterの技術的なことを書いていこう

2015年1月10日土曜日

#mikutter 3.2.2

  • 抽出タブのソースを指定しなかった場合にクラッシュする場合があった
  • Ruby2.2で起動した時に、マシンのタイムゾーンに関係なく、ツイートの投稿時刻・アカウント登録時刻がUTCで表示されていた
事実上のRuby2.2対応です。流石にRubyちゃんとは誕生日が同じなので、そこまで迅速に対応できませんでした。先に持ってきてやってればよかったんですが、今回もこの程度の修正で動いてるので、ついつい気が抜けますね。良いことです。

2015年1月2日金曜日

#mikutter 5年目

あけましておめでとうございます。mikutterは 2014/12/25 を以て、5歳になりました。今年も一年、よろしくお願いします。

mikutterの進化
3.0
6月にリリースを予定していたmikutter 0.3でしたが、セマンティックバージョニングを採用することになったので、3.0というバージョンになりました。かといって別にメジャーバージョンが上がっても不安定版なことには変わりないので、今までとは何も変わりません。
多言語化
mikutter 3.0からは、一部の人待望の多言語化が行われました。起動時のロケールによって言語が切り替わるというものです。各言語の翻訳は、Transifexにて行われています。
多言語化というのは、今までの私には経験したことのないものでした。

過去には、プログラミングがしたいのに、その本来の目的を忘れてコメントの英語を何時間も考えたりしたこともありました。mikutterではそういった反省を活かして、そういうことに関して私が無理しなくていいように作っています。詳しくは語りませんが、英語を書くコスト、無理をして書いた文法的に間違った英文を数年後に読むコストをカットできたからこそ、今mikutterがあるのです。

そんななかで、mikutterに多言語対応して欲しい外国人という存在がぽつぽつと現れてきました。英語のUIをもつソフトウェアでも、機能的に問題があれば使われることはありません。mikutterはその意味で、言語の壁を超えて使われようとしているのですから、喜ばしいことです。

そういう経緯があるので、mikutterはベース言語を日本語とし、日本語から他の言語に翻訳をしてもらっています。mikutterには日本語独特の言い回しが多く、翻訳に困ることもしばしばあるようですが、そうやって頭をひねって、翻訳にユーモアを加えていくその一連の体験こそが、mikutterなのではないでしょうか。うわ、なんかめっちゃいいこと言ってるみたいになってるわ。

多言語対応の経緯なんかについては、以下の記事も詳しいです。
 
マルチアカウント
これももう随分前の事のように思えますが、つい最近のことなんですね。

これは昔から土台が存在していたのですが、マルチアカウントを気にしなければならない部分は多いので、コーナーケースではまだ小さな不具合が残っていて、なかなか厄介です。これについては折りにふれて語っているところなので、省略します。

チュートリアル
これは特に発表しなかったので、以前から使ってくれている人は気づいていないと思いますが、mikutterを初めて起動した時の挙動が変わっています。

初めて起動した時に灰色のダイアログが出てきていたのを覚えているでしょうか。mikutter 3.0からは、あのような無粋なモーダルは廃止して、みくったーちゃんと対話しながらセットアップを進めていくのです。

2013年はほとんどmikutterに何もできなかった原因は仕事です。その時携わっていた仕事で作っていたソフトウェアが、導入部分をかなり作りこんでおり、これだと思ってアイデアを拝借してきたのです。

mikutterを使いはじめる人が最初にあの残念なダイアログボックスを見ることに、予てから問題意識はあったのですが、かといってこれといった打開策もありませんでした。一年何もできなかったと恨み言を言うだけではなく、なにか持って帰ってやろうと考えて、このチュートリアル機能を思いつきました。以前は実現が難しかったのですが、マルチアカウントによって、アカウントがない状態でもmikutterが動くようになったので、今回実現にこぎつけました。

きっと、0.2系と3系では、初めてmikutterを使う人が抱く印象は全く違うのではないでしょうか。

3.1
3.1は、3.0のブラッシュアップという位置づけでした。大きな変更があった3.0の順当な改良版です。Ruby 1.9のサポートを終了したのもここでしたね。
Entityの書き換え対応
Entityを書き換える機能をつけました。bitlyなど、サードパーティのURL展開の時に処理がブロックされていたとか、かっこ悪い問題を抱えていたので、それの対策です。あとからエンティティを書き換えるという概念が加わりました。botや企業のアカウントでは、bitlyでURLを短縮しているものも少なくありません。そういったアカウントがツイートしたURLが、一旦bitlyのまま表示されて、すぐに展開後に置き換わる、というのを見たことがあるのではないでしょうか。

ついでに、黒魔術で他のサービスに対応するプラグインが、リンクなどを貼りやすくなりました。
3.2
mikutter 3.2.1 が現在の最新版です。これはmikutter5周年記念のリリースでした。25日ぴったりにリリース出来たのは、恐らく初めてだと思います(ログ漁ったけど意外と毎回遅れていた)。
画像表示
画像の表示には前からいろいろな問題がありましたが、ようやく昨今の要求に応えうる変更が入ったのが、3.2でした。画像ウィンドウは、以前は画像プレビューと呼んでいました。これはブラウザで見る前に、mikutter上で簡単に確認できる機能だったのです。全体の動きなどは、yorufukurouなどを参考にしていました。

一方、新しく書きなおされた画像表示プラグインは、プレビューなどではなく、メディアビューアを意識しています。今は基本部分しかできていないので、そんなにできることは変わっていませんが、基盤部分はすでにその要件を満たしうるものになっています。あまり出来てもいない将来の話はしたくないので、今後にご期待下さい。
スキン
アイコンを差し替える機能です。WMのテーマにあったmikutterのUIアイコンを設定できるようになります。これはまだ開発中で、試験的な実装が3.2に搭載されています。プラグイン開発者にとっても便利な機能になることでしょう。
抽出タブ
マルチアカウントが実装されたことで注目を浴び始めた抽出タブですが、毎回いろんな変更が入っています。今年一年(0.2.2 〜 3.2)の抽出タブの変化だけを切り出してみました。
編集画面の刷新
タブの編集画面が、データソース・条件・オプションの3画面になりました。抽出タブの論理的な要素を画面ごとに分けたのです。 このことによって、データソースが膨大な数になっても耐えられるようになりました。
データソースがプラグインで追加可能に
抽出タブといえば、複数アカウントのミキサのような役割がありますが、それ自体をプラグインで拡張できるのが面白いところです。 サードパーティプラグインがデータソースを追加できるようになったことは、抽出タブの夜明けでした。もちろん、標準プラグインにも、このことを利用するものがあります。
  • マルチアカウント。各アカウント毎にホームTL、メンションを追加します。標準のTLでは、全アカウントのものが一緒になってしまいますが、あるアカウントのホームTLを見たい!という場合に、このデータソースが利用できます。複数のアカウントをmikutterで使っていくうえでは欠かせない存在です。
  • リスト。Twitterのリストを扱うlistプラグインは、自らタブを提供することをやめて抽出タブのデータソースを提供するようになりました。
    ただでさえ複雑だったリストプラグインがマルチアカウントで大変なことになっており、それを解決する方法として、機能を複数のプラグインに分断することにしました。
    その中で、タブの表示部分は、抽出タブに任せることにしたのです。このことは良し悪しあったのですが、抽出タブはタイムラインを表示することに優れた拡張性を持っており、アイコンの変更や、フィルタ条件の追加ができるようになりました。 
抽出条件の対象追加機能
抽出タブはついにフィルタ条件までもを追加できるようになりました。defextractcondition プラグインDSLは、「ユーザのbio」に含まれている文字列とか、任意の情報を条件として追加することができます。抽出タブを拡張するプラグインを巧く組み合わせることで、カスタムタイムラインを作成するプラグインは、もはや書く必要がなくなりつつあります。 
周辺の動き
mikutterの薄い本
今年は夏にmikutterの薄い本vol.6.0、年末のコミケで頒布されたvol.7が公開されました。

vol.6.0は、最近mikutterでやばめのプラグインを作っている新規ユーザが多数寄稿してくれています。これだけ続けていれば同じ奴ばかり書きそうなものですが、現実には次々と新しいユーザが出てきていて、記事を書いてくれています。喜ばしいことです。

彼らが持つそれぞれの独特な世界観が凝縮された一冊だったと思います。これほどまでに「カオス」なmikutterの薄い本は、今までなかったかも知れません。バージョン6という不安を払拭する出来でした(IEやWindowsNTや某Pのつく言語がこのバージョン6でひどい目に遭っている)。

vol.7は、はからずも3人の寄稿者がmikutterをより深く知るために、それぞれ別々の角度からmikutterを考察することになりました。

tsutsuii さんは、NetBSDを様々なマシンにインストールし、mikutterを起動するという長年の活動を振り返りながらmikutterの歴史を紐解き、mikutterそれ自体の本質に迫ります。moguno さんは、mikutterにコミットしたスキン機能の紹介を通して、mikutterの思想を汲んだAPIの実例を示しています。そして私は、mikutter開発をするにあたって、mikutterをカスタマイズする道具としてRubyを捉え、よりmikutterプラグインを洗練されたものにするためにどのようにRubyを使っていけばいいのか、コードの書き方という表面的な観点から解説しました。

全体がわずか24ページに収まっているのも良いですね。是非いろんな人に読んで欲しいです。 mikutterの薄い本vol.7は、次回2月27日に開催予定のOSC Tokyoにて頒布されます。vol.6.0も在庫があったので頒布されると思います。また、mikutterの薄い本製作委員会のWebサイトからPDFをダウンロードすることもできます。
OSC
今年も各地のOSCで、Nから始まるコミュニティの方がmikutterを応援してくださっていたようです。mikutterユーザ会としては春秋のOSC Tokyoに、夏の京都には私主導で、mikutter名義で参加しました。


夏の方のレポートは、当時の記事があるので省きますが、展示にしてもセミナーにしても、手伝ってくれる、来てくれる人たちがいないと成り立ちません。皆さんの応援に圧倒的感謝です。

一昨年2013年はほとんど何もできず、こういったイベントには参加することができませんでした。コミケもそうですが、こういう場は開発のモチベーションに大きく貢献するので、来年も時間が許せばできるだけこういう場に出たいと思います。
コミックマーケット
mikutterの薄い本製作委員会がコミックマーケット86,87で、mikutterの薄い本6.0と7をそれぞれ頒布しました。夏の86は落選したので委託でしたが、87は当選し、当日は私も参加し、ブースで売り子をしていました。

サクチケをそらまめさんに渡してしまったので私は8時から並び、10時10分に入場しました。mikutterブースは朝からお客さんが途絶えず、私がブースを訪れた時にはデコにドイツのトリシールを貼った不審人物が既にいるなど、大盛況でした。あと、そらまめさんが俺の名刺を首から下げて「としぁです」とか言ってたせいで俺が女装してたと思ってる人がいたみたいで、コミケやばいなって思いました。場が場だけに信じてしまっても仕方ないかも知れません。

いろんな人にお会いできたのも良かったです。昨年過酷な労働によって感情がなくなった私に、自分がmikutterの作者だと思い出させてくれたメガネケエス作者や、AUR高速デプロイシステム2GMonなど、なかなかお会いできない人にたくさん会うことができてとても有意義な一日でした。

まとめ
何もできてなかったんじゃないかなぁと思っていましたが、振り返ってみると2013年とうってかわって、mikutterの開発に結構リソースを割いていたようです。やっぱり、仕事が平和だとくだらないことに時間を使えるので、mikutterが充実するんですね。いいことです。今年は早速前半はつらい感じなのですが、いろいろ進めていけたらいいなと思います。

今年もmikutterをよろしくお願いします。

2015年1月1日木曜日

#mikutter 3.2.1

  • 抽出タブ: タブを編集しようとするとクラッシュ
  • あけおめ
不具合修正です。コミケなどでほとんど何もできなかったので致命的なものだけ。ヽ('ω')ノ三ヽ('ω')ノもうしわけねぇもうしわけねぇ

あけましておめでとうございます。今年も一年、よろしくお願いします。コミケのまとめとかは、また近いうちに。

2014年12月25日木曜日

#mikutter 3.2

mikutter 3.2 をリリースします

http://mikutter.hachune.net/

追加機能の詳細については、mikutter 3.2の予定をご覧ください。


  • 画像表示機能の内部処理を変更
    • 画像の表示が遅いことがある問題を改善
    • ロードできた部分から表示
    • ブラウザで開く・画像を閉じるなどのUIの改善
    • 以下のサービスに対応
      • totori.dip.jp
    • 以下のサービスの対応を廃止(需要の割に対応が難しい、サービスが消えてた等)
      • plixi
      • Tumblr photo
      • yfrog
    • サードパーティプラグインから画像取得ルールを追加できるようになった
  • 抽出タブ・抽出対象の条件を追加できる機能
  • スキン機能(試験的な実装)
  • アイコンを変更
mikutter五周年の日にmikutter 3.2がリリースできることを大変嬉しく思います。これも今まで支えてくださった皆さんのあれだと思います。ありがとうございます、これからもmikutterをよろしくお願いします。

今回は前から気になってた、プラグイン開発者として俺が触りたいのに外からではどうしようもない部分を改善しました。おかげで著名なプラグイン subparts-image が動かなくなっているので今からpull-reqを送ってきます。いわばシムシティみたいなものなんですよね。それ以外はとくに大きな問題はないでしょう。

画像まわりの使い勝手は個人的には気に入ってます。ダウンロード機能も付けたかったのですが実装が間に合わず今回はペンディングとしました。画像をブラウザで開くのがツールバーになっているのは、ここにそういった他の機能が乗るためです。
ただ、稀に画像のロードに失敗するとか、不具合が取りきれていないことがわかっているのが現状です。しかし、品質を疎かにしてまで日を合わせやがったとは思わないでいただきたい。バグを分かっててリリースするのと、知らずにリリースすることに本質的な違いなどありません。それにね、よく考えてもみてください。いい年なのに彼女もおらず、クリスマスイヴに私にふぁぼ爆撃したり、やれRuby2.2だ、mikutter 3.2だ、とか言っているmikutterユーザの人生に含まれる不具合のほうが深刻です。かたや画像たまに表示できない問題なんてもう一回開けばいいだけです。こう考えると、リリースに踏み切ったことにも納得できますね。ごめんなさいちょくちょく修正していきます。

本日はmikutterだけではなく、Rubyのお誕生日でもあります。本日リリースされたRuby 2.2 ではmikutterの検証をしていませんが、概ね問題がないらしいです。今回の変更ではmikutterの動作速度が上がることに期待できそうです。今のところRubyの進化の恩恵を毎回受けることができているので、今回も楽しみです。

最後に宣伝ですが、コミックマーケット87の3日目(12/30)に、mikutterの薄い本vol.7が頒布されます。詳しい情報についてはリンク先を見ていただけば良いのですが、私も寄稿しているmikutterの薄い本が、金さえ出せば買えるまたとないチャンスです。十分な部数があるようなので、ゆっくり来てください。当日は私もブースにいることが多いと思うので、握手しましょう。

また、同ブースに私の個人サークル「アトリエとしぁ」の初の画集を1部のみ委託します。

12枚か13枚くらい、全て私が描いた絵です。無印で買った無地の絵本に描いただけなので、世界に一部しかない、非常に貴重な作品です。これがなんとたったの400円!mikutterの薄い本のたった200%の値段でお求め頂けます!無印の絵本が315円なので、ほとんど利益はございません!これは私が会場に着くまで買うことができませんので、購入できるかどうかは完全に運です。買えたひとは本当にラッキーです!

そんなわけで、今年はコミケでお会いしましょう!皆さん、よいお年を!

#mikutter 3.2をハックする

mikutterアドベントカレンダー20145 25日目の記事です。

mikutter 3.2で新しく追加されたプラグインの機能拡張について、一通り見てみましょう。

画像サービスに対応する
twitpicやinstagramみたいな画像をアップロードすることを主とするサービスや、d250g2.comのような画像の提供が主となるサービス(便宜上まとめて画像サービスと呼びます)を、画像プレビューのウィンドウで表示できるようになりました。

ルールを追加してみる
今まで、画像を開くのはopenimgというプラグインが担当していました。これからは、画像をロードしてUI上に画像を表示するのはopenimgで、あるURLから画像自体を取得するのはphoto_support プラグインが担うことになります。

実際に photo_support プラグインを見ると、どうやって画像を開くのかわかると思います。
これはTwitpicのルールです。一番オーソドックスなルールを持っています。
今までのopenimgは、openimgプラグインに付属しているJSONファイルを編集してルールを追加していたので、サードパーティプラグインから追加する方法はありませんでした。
また、openimg自体も正規表現を駆使して画像を探すなど素晴らしい実装になっており、今回openimgを作りなおすに当たっては本当に難儀しました。数年前に自分が書いた、正規表現をゴリゴリ使ってスクレイピングするコードをメンテナンスするってなかなかつらいものがあるんだなあ。

今回このように一つひとつの画像サービスに対するルールをコードで現すようにした経緯は前のエントリで説明しましたが、もともと3年くらい前は全部のルールをコードで書いていました。それをやめた時の反省をせず戻すわけにはいきません。

で、JSONのようなデータ構造を採用したのは以下のような問題を解決するためであって
  1. 画像サービスってちょいちょいルールが変わるので、バージョンアップしなくてもルール配信できるようにしたい! 
  2. まとめないとコードが恐ろしいサイズになる
それぞれ以下のように解決しました
  1. 画像サービスはTwitterに死刑宣告されたからか、もう頻繁にDOM構造が変わることがなくなった。そもそも利用頻度が低い(今回この改修をしてるときにyfrogが見れなくなっていることに気づいたが、誰からも報告が来てなかった)。
  2. Nokogiri,HTTPClient,OpenURIあたりを積極的に使ったらJSONと同じくらいの行数のコードに収まっちゃった
まとめ
  • openimg と photo_support に分けたので、取得ルールと表示部分が分かれて良かった
  • ルールは全部コードに書くことにしたので一箇所にまとまって良かった
  • ルールはNokogiri使って書くことにしたら分量が減ってわかりやすくなって良かった
  • ルールは他のプラグインからも追加できるし最高
自分のプラグインから画像を開こう
この変更でユーザが新しくできるようになったことで一番重要なのは、自分のプラグインからopenimgを利用できるようになったことです。まず、mikutter 3.2 で Alt + x を押して mikutter console を開き、以下のように入力して CTRL + Enter を押してみましょう。

Plugin.call(:openimg_open, 'http://twitpic.com/d250g2/')


画像のURLをクリックした時と同じように、画像が表示されたと思います。ただのイベントですから、あなたのプラグインからも同じ方法で画像を表示できるのです。
注目すべきは、URLから画像を探しだし、それを表示したということです。実は、photo_support や他のプラグインで定義されたルールがこの時に使われます。これは強力ですね。mikutterを起動する度に同じ画像を勝手に開くことも可能です。当然、3.1までは他のプラグインからこのようなことは出来ませんでした。

画像をダウンロードしよう
次は画像自体をダウンロードしてみます。
次のコードを実行してみましょう。

画像をダウンロードするのでちょっと時間がかかるかもしれません。
終わったら、 ~/.mikutter/tmp/d250g2.jpg というファイルができていると思うので見てみましょう。燃えているのではないでしょうか。

簡単に説明すると、フィルタ openimg_raw_image_from_display_url を使うと、URLをダウンロードした結果が流れてくるIOオブジェクトが第二引数に渡されます。あとはそこから IO#read で受け取れば、画像のダウンロード完了です。これもちゃんと画像サービスのURLから実際の画像を探してダウンロードしていますね。それがなければ、このフィルタの存在する意味がないんですが。

ルールを追加してみるの節で、 defimageopener のブロックが、open() で終わっているのが気になった人がいるかもしれませんね。あの戻り値が、このフィルタのIOです。つまり何が言いたいかというと、ダウンロードが終わったら、そのIOは、フィルタを呼び出した側がcloseしてください、ということです。尤も、GC時に自動的にファイルディスクリプタは開放されると理解してるんですが、IO閉じないのって他のオブジェクトより罪悪感があって…

抽出タブの抽出対象
うまく伝わるタイトルは思いつかないのですが、要するにこれを増やす機能です。
標準では、ユーザ名・本文・Twitterクライアント名を使用できますが、もっとほかのことを基準に抽出したい!ということがままあったので追加できるようにしちゃいました。はい、こんな感じのコードで追加できます。



これは、Ruby 2.0から使えるキーワード引数を使っているという意味でも面白い例です。キーワード引数が何なのか知らない人は、12/30に東京ビッなんとかで行われるコミックなんとかの、西2 く-30a mikutterの薄い本製作委員会 ブースに来てください。私も行くので、本物のmikutterをお見せしましょう。

defextractcondition(:bio, name: "bio", operator: true, args: 1)

などと書いていますが、これは見て分かる通りbioで抽出するやつを追加します。name: は上のスクショのコンボボックスに表示する名前ですね。operatorとargsはおまじないです。…と言っても、敬虔なmikutterユーザ諸君は「おまじない」では納得できないでしょう。そういう方は、12/30に東京ビッなんとかで行われるコミックなんとかの、西2 く-30a mikutterの薄い本製作委員会 ブースに来てください。私も行くので、本物のmikutterをお見せしましょう。

あとはブロックの方がキーワード引数を要求してますね。 argument はスクショで言うところの右のテキストボックスに書かれた内容です。その左隣の「=」とか「含む」とかの条件ですが、 &compare がその条件でうまい具合に比較してくれる奴です。message: は抽出対象の message が一つ渡されます。つまり1ツイート毎に1回このブロックは実行されるので、ここではあまり重い処理をやるとロクなことがなさそうです。実際には、重い処理はどんな場所でも大抵ろくなことになりません。現実は厳しい!社会は厳しい!

それで、コメントになっている部分ですが、これはそのすぐ下のシステムメッセージを抽出するための条件と同じものです。システムメッセージは二つ見どころがあって、ひとつは引数や比較方法がない条件だということ、もうひとつは、defextractconditionにはS式も渡せるということです。コメントアウトしてる部分は、ブロックがなくなり、こんな引数が追加されていますね。

MIKU.parse("'(system? message)")

これをmikutter上で実行すると、以下のような値が返って来ます。

(:quote (:system? :message))

そのまんまですね。mikutterの抽出タブの条件がS式になっていることは有名ですが、まさか抽出対象がS式でも渡せるとは…たまげたなあ。
流石にこれは闇が深いのでこれ以上掘り下げることはしません。S式にすることの意味は速度・メモリの効率です。抽出対象をS式で指定すれば、マクロみたいな雰囲気で全体の条件の中に展開されるので、単一のRubyコードに変換されます。一方で、ブロックだとブロックを呼び出す準備で余計な処理が入ります。ブロック呼び出し自体もありますし。

で、確かにこちらのほうが速度的には有利になりますが、実際計測してみると思った程でもありませんでした。ラピュタに突っ込む気でいるなら気になるかもしれませんが、毎秒2,3ツイート程度ならどうでもいいんじゃないでしょうか。完全な悪ノリでした。mikutterも悪ノリみたいなものなので、抽出タブの条件周りはmikutterの本質のひとつなのだと思います。こういう側面を知らなかった、もっと知りたいという人は、12/30に東京ビッなんとかで行われるコミックなんとかの、西2 く-30a mikutterの薄い本製作委員会 ブースに来てください。私も行くので、本物のmikutterをお見せしましょう。デコにとんでもないものをくっつけてお待ちしております。

あとがき
サードパーティプラグインがどのような恩恵を受けられるのか、という観点からmikutter3.2で行われた変更を見てみました。どちらもコア機能の変更はとくになく、表層的な変更ですが、そんなに需要はないと思います。しかし需要はほとんど気にしていないので、こういうこともあるよなあといった感じです。

内容に関してはもっと具体的に掘り下げても良かったんですが、なかなかこういう記事では難しいものですね。別の話ですが、writing mikutter pluginとは別に、やりたいことからリファレンス的に引けるドキュメントを考えてるしそっちで補えたらなーとか思いつつ、そもそも書けるのかとか、うーん。


mikutterアドベントカレンダーの最終日・mikutter5周年ということで、今年一年のmikutterについて振り返ろうかなとも思ったのですが、ここ数年は、正月に一切のタスクから開放された状態でゆっくり書く感じだったので、今年もそんな感じで行きたいと思います。
そんなわけで簡単に、mikutter、誕生日おめでとう。来年もよろしくお願いします。

2014年12月23日火曜日

#mikutter 3.2 の予定

まもなくmikutter 3.2がリリースされますね(棒)。
12/25には正式にリリースされて、5日後には、コミケのmikutterの薄い本製作委員会のブースで頒布される「mikutterの薄い本 vol.7」に、mikutter 3.2についての私の記事が掲載されていますね(棒)。
3.2を12/25にリリースすれば何も問題ないはずですよね。では、3.2では何をする予定なのかを確認してみましょう。

アイコンテーマ(仮称)
mikutterのUIのアイコン郡を差し替える機能です。アイコンをまとめたファイルを所定の位置に置いて、設定画面でどれを使うか設定すると、mikutterが用意しているアイコンを別のものに置き換えることができます。
ユーザとしては、使用しているWMのテーマにあったアイコンを選ぶ・作ることができるようになります。
プラグイン開発者としては、この変更に伴って提供する skin DSLメソッドを使えば、画像ファイルの指定をより簡潔にできるというメリットがあります。

この変更はまだ試験的な機能です。3.3で大幅に変わる可能性があります。

openimg 2
トトリちゃんの画像を楽しめるWebサービス
http://totori.dip.jp
を表示したところ。イワシがいっぱいだあ。

openimgプラグインは画像の表示機能を提供していますが、使い勝手が微妙に悪いところがありました。
また、最近サードパーティの画像アップロードサービスがいまいち息をしていないとか、開発当初からとりまく環境が大きく変わってしまったプラグインでもあります。

単なる画像取得の手段としてサードパーティプラグインと連携
openimgは、d250g2、地獄のミサワなどさまざまなサービスに対応した強力な画像取得ルーティンをもっていますが、このインターフェイスはプラグインの中に閉じてしまっていていました。
openimgの画像取得部分を公開することで、画像を扱うプラグインはそれを利用できるようになります。

サードパーティプラグインが画像取得ルールを提供
従来は、openimgプラグインに付属しているJSONファイルに、例えばtwitpicの画像を取得するためのルールが書いてありました。
この方法では、openimgが想定しないような複雑な方法を使ったルールでの取得が出来ず、実用的には無理が出てくる場合がありました。現実に、いくつかの写真アップロードサービスについては、openimgに別途コードを書いて対応しているような状況がありました。
そこで、いっそのことURLを画像URLに展開するようなフィルタを用意して、写真アップロードサービス毎にリスナを登録するアプローチに変更することにしました。こうすることで、openimgプラグイン以外から、画像取得ルールを登録できるようになりますし、ルールがJSONファイルとRubyコードに散らばらなくなりました。

一方で、毎回コードを書くとなると、メンテナンス性が問題になってきます。これはスクレイピングの部分にNokogiriを使用することで、コードを単純にしました。mikutterからWebページをスクレイピングするようなプラグインなんて普通書かないと思いますが(棒)、これからは標準プラグインが要求するので気兼ねなくNokogiriを使えますね。

振る舞い
画面をクリックでブラウザを開いてウィンドウを閉じるという挙動がなくなりました。
閉じるにはウィンドウマネージャの閉じる機能を使ってください(ここにもmikutterコマンドを割り当てたかった)。
ブラウザで開くには、ツールバーに投げやりな感じのアイコンがあるのでそれを押します(mikutterコマンドry)。ここに入れたい機能がほかにもいくつかあるのですが(mikutterコry)。
画像の表示部分も書きなおして、画像のダウンロードが終わったところから表示されていくようになりました。

画像プラグイン→メディアプラグイン?
今までopenimgは画像に拘ってきましたが、最近のTwitter全体の動向を見ていると、動画なんかも気軽に投稿できるようになってきています。動画に対応する予定は今のところありませんが、今回の変更は、そういった将来の変更も見据えてのものです。

抽出タブ
抽出対象の拡張
抽出対象とは、抽出条件の「名前」「本文」などのことです。これには他に、Twitterクライアントでフィルタしたいという要求もあったので、一応それも入ってはいます。
ちょっと使っているぶんにはこれで足りるかもしれませんが、もっと高度な条件を指定したいかもしれません。
そもそもmikutterのツイートを現すオブジェクト Message には、もっと多くの条件になりうるメソッドが実装されていますが、今使っているのはそのほんの一部であるというのが現状なわけです。
現状だとコードを書いて自力でフィルタしたものをデータソースとして提供するという方法もあり、実際に鍵垢のツイートだけ流れてくるデータソースというものも提供されています。
抽出対象の拡張ができるようになることで、こういった要望について、より自然に答えられる場合が出てきます。

まとめ
3.1からあんまり空いてませんが、期間のわりにはいろいろできたみたいです。ちょっと詰め過ぎた感じもしますが、来年はまた4月までほとんど動けないことを考えると、差し引き調度良い感じかもしれません。
実は今alpha1を上げました。いくつか既知のバグがあるので25日まではそれを取って、25日のどこかで正式な不安定版としてリリースします。数年ぶりのクリスマスリリースになりそうです。
大体年末は仕事はたいしたことなくてmikutterでてんてこ舞いなのですが、今年は会社が大型案件をぶつけてくれたので泣いています。とにかく、最低限思ってたことはやりきれそうなのでよしとしましょう。

そんなわけで、動作確認おねがいします!

2014年12月14日日曜日

帰ってきたあひる焼きゲーム

<< 13日目 mikutterアドベントカレンダー2015
あひるをやっくのっはたのしいな♪

ある日あひるを焼いていると
怒られました。
どうも自動であひる焼きに反応するmikutterプラグインを書いたようです。
mikutterプラグインを書きたいと言っている人は基本的に書かないので無害ですが、何も言わずにふっとプラグインを生み出す人間にろくな人は今まで居ませんでした。あひるさんもろくな人間ではないのでしょう。

https://github.com/Na0ki/ahiru_yakuna

うわぁ…。今見たらyamlファイルに反応バリエーションが出してあるし…。順調に腕を上げてますね。pull-reqも受け取って比較的活発に開発しているようなので、こういう人は早めに潰しておかなければなりません。

作った

帰ってきたあひる焼きゲーム!
https://github.com/toshia/ahiruyaki

あひる焼きをソーシャルゲームにしました。mikutterの機能をフル活用してあひる焼きを楽しみます。フロント側の機能はREADMEに書いているので、裏で何をしているかちょっと紹介します。

RANK_TABLE
あひる焼きランクは、経験値を溜めると上がっていきます。経験値は減ることはありません。次のランクに上がるために必要な経験値をグラフ化してみました。
途中からやたら経験値が要るようになりますね。計算式は謎めいたものを使っていますが、深い意味はありません。詳しくはソースの6行目あたりからですが、無駄にEnumeratorを使用しているのがポイントですね。こういうことをすると、Enumerable#find で、ある経験値だとランクいくつになるか、というのがわりと直感的に書けます。

Plugin::Ahiruyaki::RANK_TABLE.with_index.find{ |exp, _|
  UserConfig[:ahiruyaki_exp] < exp }[1] + 1

だからどうした感が半端ない。効率はメモ化した再帰関数のほうが良さそうですが、一方でどう見てもボトルネックになるような処理ではありません。

スタミナ
ソーシャルゲームならスタミナがなければいけません。スタミナはランクアップで全回復して、行動によって消費し、時間経過で全回復します。また、スタミナには最大値があります。これはランクアップで上がっていくので、ランクから計算できます。更に、初めてゲームを遊んだ時はスタミナが最大になっているというのもポイントです。
今回はスタミナを数値で保持せず、スタミナが全回復する時刻を保持して、そこから現在のスタミナ値を決定しています。この方法のメリットは、スタミナ回復のことを常に考える必要がないことです。Time.now の戻り値を代入すれば即時回復できますし、mikutterを終了している間もスタミナが回復します。スタミナを消費した時は全回復時刻に加算すればいいだけですし、次回のスタミナ回復時刻が10秒後という時にスタミナを消費した時に、5分にリセットされるとかいうこともありません。
これはいい方法ですね。良い方法なので、多分本物のソーシャルゲームもだいたいこうなっているんじゃないか、という多分一生役に立たない知見を得ることができました。いや、思っただけなので知見でもないですね。本当に得るものがない。

また、 expend_stamina というメソッドは、消費スタミナ値を引数にとり、そのぶんだけスタミナを消費してブロックを実行します。スタミナが足りなければブロックが実行されないし、ブロックの処理途中で例外などで抜けたらスタミナが減らないので便利です。

イベント駆動
今回このプラグインを書くにあたっては、イベントをできるだけ使うようにしました。例えば、経験値は add_experience メソッドでのみ増加しますが、この経験値の増加でランクが上がると、ahiruyaki_rankup イベントが呼ばれます。最大スタミナ値などほとんどのものはランクから自動計算しているので、経験値が上がった瞬間自動的に上がりますが、スタミナの回復だけは処理してやらないといけないので、このイベントをキャッチすることで行ってます。
イベントはどのプラグインでも受け取ることができるため、あひる焼きゲームはMODの開発が簡単です。
とくに、スタミナが全快した時に発生するイベントは、全快したら自動であひるを焼くなど、さまざまな用途に使えそうです。
こういうことをしておくと、ユーザは予想外の意味不明な拡張をしてくるものです。mikutterで何度もそういうことを経験しました。何だよ、あひる焼くなプラグインって。

終わりに
結局、焼きあひるに油を注ぐ結果になっている感じがしてなりません。ゲームのアップデートもしたいのですが、忙しい時期なので、ほかのタスクに圧されて手がついていない状態です。
たまにこういう役に立たないものを書くと心がやすらぎますし、いろんなものを得た気になれるので(実際はそんなことはほぼない)、皆さんもやったら良いと思います。