読者です 読者をやめる 読者になる 読者になる

もぐてっく

人は1つ歳を取る度、1ビットづつ大きくなれると信じてた。

mikutter:おっさんだってサインコサインを学びたい!(学んだやん)

mikutter

f:id:moguno:20150830205041p:plain

はじめに

なんか巷では三角関数が空前の大ブームと言うことで、デスマから解放されて無駄にテンションの高い僕もノッてみることにしました!!

冷静に考えると、もぐのはおっさんであり社会に出てから三角関数なんてとんと使ってない勢であるわけで、テメェが手を動かしたところで元ネタに擦りもしてませんね。アレ。

「くくく・・・計画ミス」

取り敢えず三角関数で作れるプログラムと言ったらアナログ時計ですよね!
(異論はrescueして揉み消します。)

アナログ時計の針の動きは円軌道なので、極座標(原点からの距離と偏角で平面上の点を特定するモデル。偏角を変化させていくと円が描けるよ。)との親和性が高いです。その極座標をcairoの座標系である直交座標に変換する際に、件の三角関数を用います。

距離r、偏角θの点を直行座標x, yに変換するには、

x = r * cos(θ)
y = r * sin(θ)

ですね。

てな訳でアナログ時計画像を作るプログラムが誕生したので、現在時刻を吐き出すmikutter-datasource-clockのアイコン画像にして終わりにしようとしたのですが、ここで問題が。

mikutter内での画像の指定方法はファイル名またはURLのみで、cairoで作成したPixbufを指定することはできません。どうしてもと言うならPixbufをテンポラリディレクトリにpngとかで保存すればいいですが、まぁ格好悪いなと。

ならばモンキーパッチとなるのですが、アイコン画像を差し替えるだけじゃつまんないなと思って、前からやってみたかった大技にチャレンジすることにしました。

ミクぺたをペタペタする

mikutterのTLの描画はGdk::MiraclePainter(以降「ミクぺた」)と言うクラスで行われており、Messageごとにそのインスタンスを保持しています。

と言うことは、オブジェクト志向的発想でミクぺたのサブクラスを作ってやれば、TLに独自レイアウトの描画が出来るはずです。

出来ました。割と簡単。

まずはGdk::MiraclePainterを継承してrender_to_context()をオーバーライドします。
引数のcairocontextにあなたのパトスをぶつけましょう。

次にMessageにミクぺたのインスタンスをアサインしているGtk::CellRendererMessageのcreate_miracle_painter()をモンキーパッチして、適宜さっきのサブクラスのインスタンスを返せばOKです。

んで、出来たのがこれ

github.com

でっかいみくったーちゃん時計がホームTLの上部に居座ります。割と邪魔です。

しかしながら、mikutterは時計すら無いヤバい環境で動かされることもしばしばなので、一周回って案外便利かもしれません。

mikutterパッケージマネージャ"Packaged"でもインストールが可能です。こちらもよろしくです。moguno.hatenablog.jp

mikutterにおけるスレッドと並行処理機構のまとめ

mikutter

mikutterの薄い本Vol.8に掲載したmikutter-datasource-aclogを入れてから、なんかたまにGUIが重たくなる気がして来ました。

原因を調べたところ、mikutterイベントon_period内のhttp通信処理がたまに重くなるのせいで、メインスレッドのGUIの動作を阻害していたためでした。

てっきり別スレッドで動いてると思ってたよ。あらあらうふふ

いい機会なので、mikutterに於けるスレッドの取り扱いと、mikutterフレームワークの並列機構との関係を整理してみようと思いました。

mikutterに於けるスレッド

mikutterのスレッドは「メインスレッド」と「サブスレッド」に大別されます。
特徴はそれぞれこんな感じです。

メインスレッド

Rubyがデフォルトで持っているスレッドです。
mikutterにおけるメインスレッドは、初期化処理の後にGUIを司るGTKのメインループに支配されます。

mikutterのコアやプラグインは、後述のDelayerやGTKのシグナル処理を使ってメインスレッドで処理を行います。
メインスレッドの注意点は、インターネット通信などの「重い処理」を行うと、その分GUI処理が滞って「もっさり」や「プチフリ」を引き起こすことです。

サブスレッド

ここでは便宜上メインスレッドでないスレッドを「サブスレッド」と呼称します。
mikutterフレームワークではスレッドの使用に制限はなく、プラグインでサブスレッドを適宜生成して使用可能です。
サブスレッドはGUI処理を阻害せず「重い処理」を行える一方、サブスレッドからGTKGUI部品を操作することは出来ません。

mikutterフレームワークの並行処理機構

さて、各スレッドの得手不得手が整理できた所で、次はmikutterで使える並行処理について確認していきましょう。

Delayer

与えたブロック(処理)をメインスレッドで実行します。
DelayerはGTKのメインループと協調を取っており、GUI処理がひと段落するタイミングまで実行が保留される所がちょっとだけ注意です。
(/core/plugin/gtk/delayer.rbのGtk::idle_add_priority()で暇になった時にDelayerを実行する処理を設定しています。)

この性質を利用して、擬似的にサブスレッドからGUIの操作が行えるようになります。

Thread.new {
  # サブスレッドでなんか重い処理

  Delayer.new {
    # メインスレッドでGUI操作
  }
}

Reserver

Reserverは引数に指定した時間待った後にブロックを実行する機構です。
Reserverは専用のスレッドで時間待ちをしているため、Reserver処理もサブスレッドでの実行されます。
つまり、GUIをいじる場合はDelayerを使用する必要が有ります。

# 30秒後に処理を実行する
Reserver.new(30) {
  # ここはサブスレッドで実行される
}

イベント

mikutterイベントは内部でDelayerが噛むので、必ずメインスレッドで実行されます。

データを定期的に取得するのに便利なon_period(1分周期で発生)も例外ではなく、そこに冒頭のhttp処理なんかを書くと「もっさり」の原因となります。
(冒頭のやらかしですね。)

サブスレッドを作ってさっさと明け渡しましょう。

# 1分周期イベント
on_period { |service|
  # ここはメインスレッドなので、速やかに明け渡しましょう。
}

フィルタ

イベントと似た構文を持つフィルタは呼び出し元に値を返す必要があるため、処理が実行されるスレッドは呼び出し元と同じ(メイン、サブ特定できない)になります。

まぁ、フィルタ処理でスレッドやDelayerによる並行処理は原理上無意味なので、困ることはないと思います。

しかしながら、フィルタ内で重い処理を行うと後続の何らかの処理が遅れるはずなので、重い処理を伴うデータはReserverやon_periodなどで予め非同期に作っておくのが良いと思います。

on_period { |service|
  Thread {
    # 重い処理は予め実行しておく
    @data = heavy_proc()
  }
}

filter_hoge { |args|
  # フィルタでは@dataを使って答えを返すだけ(排他とかちゃんとしてね)
 [args]
}

GTKシグナル処理

signal_connect()やssc()で登録するGTKのシグナル処理はメインスレッドで動作します。
通常、プラグインからGTKシグナルを直接触ることがないため気にすることは無いですが、頭の配線から色々リークしているプラグイン作者は注意しましょう。

おまけ:Twitter APIは重い処理だよね?

Twitter APIも比較的低速な回線での通信が絡むので、重い処理と言えます。
しかし、mikutter独自のTwitter APIライブラリ「mikutwitter」では原則API呼び出しごとにサブスレッドを生成する仕様なので、「もっさり」が発生しない様になっています。

# APIをコールすると新たにサブスレッドが作られる
Service.primary.search(params).next{ |res|
  # Deferredによるスレッド実行後処理(next())もサブスレッドで動きます
}

mikutterメモ:プラグインスラッグの注意点

mikutter3.2.2

.mikutter.ymlで指定した:slugと、Plugin.create()の引数で指定したスラッグが違うと、Plugin::specがnilになります。

これは、Plugin::specの初期化は.mikutter.ymlで定義されたスラッグのインスタンスで行われ、プラグイン自身はPlugin.create()で指定したスラッグのインスタンス(前者とは別のインスタンス)で行われるためです。

結果、Plugin::specを参照する機能を使うとポコっと落ちます。
具体的にはアイコンセットです。ぐふぅ。

当たり前ですが、両者のスラッグは統一したほうがいいですね。

mikutterメモ:on_period使用時の注意点

mikutter mikutter3.2.2

1分周期でイベントを発生してくれる便利なon_periodさんでハマったのでメモ。

on_periodはサービス(=アカウント)ごとに1回ずつ呼ばれます。
なので、マルチアカウントでmikutterを使用している場合、毎分アカウントの数だけon_periodが実行されてしまいます。

アカウントに拘らない周期処理を行う場合は、引数のserviceがメインアカウントの場合のみ処理するようにすれば良いと思います。

Plugin(:test) {
  on_period { |service|
    if service == Service.primary
      # やりたいこと
    end
  }
}

普段シングルアカウント運用の人も、開発時はサブアカウントを登録しておいた方が良いですね。

メッセージのフォントを変えたり文字色を変えるmikutterコマンドを作ったよ

mikutter

何これ?

選択したメッセージのフォントや文字色を変更するmikutterコマンドを追加します。前のエントリ(メッセージをホームタイムラインに混ぜ込むmikutterコマンドを作ったよ - もぐてっく)で抽出タブの結果をホームタイムラインに転送するmikutter-command-redirect-to-homeをご紹介しましたが、これだとタイムラインに流れてきたメッセージと混ぜ込んだメッセージの区別がつかないため、このコマンドで見分けが付くようにすると便利です。

インストール

GitHubからzipファイルをダウンロードして適当なディレクトリに展開して下さい。

moguno/mikutter-command-style · GitHub

※mikutterプラグインマネージャ"Packaged"で"moguno"を検索してインストールするのもおすすめです。いやほんと。

使い方

まずは設定画面の「スタイル」でフォントと背景色を設定します。スタイルは1〜5の5種類が設定できます。

f:id:moguno:20150104210024p:plain

次に、適当な組み合わせの抽出タブを作ってください。その際、「適用するコマンド」タブで「スタイルnを適用(n:1〜5)」を選択することで、抽出結果に先ほど設定したスタイルが適用される様になります。
(要mikutter-extract-fire-command)

f:id:moguno:20150104192303p:plain

例えば「mikutter」で検索した結果にこのプラグインを適用した結果はこんな感じです。

f:id:moguno:20150104210115p:plain

設定

スタイル

f:id:moguno:20150104210024p:plain

  • フォント

メッセージのフォントフェース、サイズ、文字色を設定します。

  • 背景色

メッセージの背景色を設定します。

メッセージをホームタイムラインに混ぜ込むmikutterコマンドを作ったよ

mikutter

何これ?

選択したメッセージをホームタイムラインにじわじわ混ぜ込んで行くmikutterコマンドを追加します。単体だと「なんじゃそれ?」ってプラグインなのですが、例によってmikutter-extract-fire-commandと組み合わせると良い感じの仕事をしてくれます。

インストール

GitHubからzipファイルをダウンロードして適当なディレクトリに展開して下さい。

moguno/mikutter-command-redirect-to-home · GitHub

※mikutterプラグインマネージャ"Packaged"で"moguno"を検索してインストールするのもおすすめです。いやほんと。

使い方

実はこれ、昔が私が作ってた「私、気になります」やmikutter-rss-tl相当の動作を抽出タブで実現するためのプラグインです。

抽出タブの「適用するコマンド」タブで「ホームタイムラインにリダイレクト」を選択することで、抽出結果をホームタイムラインに混ぜ込むことが出来ます。
(要mikutter-extract-fire-command)
f:id:moguno:20150104192303p:plain

例えば「mikutter」で検索した結果にこのプラグインを適用した結果はこんな感じです。

f:id:moguno:20150104194502p:plain

とうとうmikutterにも広告ビジネスの波が押し寄せて来た様ですね・・・なんだこれ。

フォントや文字色が変わってますが、これはmikutter-command-styleと言うプラグインの機能で実現しています。mikutter-command-styleについてはこちらを参照してください。


メッセージのフォントを変えたり文字色を変えるmikutterコマンドを作ったよ - もぐてっく

設定

リダイレクト

f:id:moguno:20150104192748p:plain

  • 混ぜ込み周期(秒)

メッセージをホームタイムラインに混ぜ込む周期を設定します。
デフォルトは10秒に1回メッセージが混ぜ込まれます。

Rubyプログラミング不要!mikutterでBotを作ろう

mikutter

明けましておめでとうございます。

これは「あー正月ってテレビもつまんないしマジすることないよねー」カレンダー (なにそれ?)2日目の記事です。

今回は拙作プラグインmikutter-extract-fire-commandを使って、コードを一切書かずにTwitter Botを作る方法をご紹介したいと思います。

mikutter-extract-fire-commandについて

mikutter-extract-fire-commandは抽出タブの抽出結果にmikutterコマンドを適用するプラグインです。このプラグインを使うとPlaggerの様に他のWebサービスと連携を取ったり、特定のツイートに反応してちょっとしたマクロ処理が出来るようになります。

mikutter-extract-fire-commandの詳細は、過去に書いた記事を参照してもらえればと思います。

# またえっらい自画自賛だな当時の俺・・・。

定刻につぶやくBotを作ろう

さて、ここからが今回の本題です。
まずは一定時間ごとにメッセージをつぶやくシンプルなBotを作ってみましょう。

例として僕のTLで流しているマイクラサーバの宣伝Botをご紹介します。

(1) プラグインの導入
まず初めに、次のプラグインを導入します。

  • mikutter-extract-fire-command

前述の抽出タブの抽出結果にコマンドを適用するプラグインです。

  • mikutter-kopipe

あらかじめ定義したメッセージをツイートするコマンドが作れるプラグインです。

  • mikutter-datasource-clock

みくったーちゃんが時刻を教えてくれるプラグインです。

(2)投稿するメッセージを作成する。

プラグインの導入が終わったら、mikutter-kopipeに定期的につぶやきたいメッセージを登録していきます。
~/.mikutter/の下にkopipeディレクトリを作成して、下記のYAMLファイルを作成してください。

title: AQUA Craftの宣伝
text:
 - |
  Minecraftサーバ"AQUA Craft"やってます。

  araaraufufu.xyz
  マップ:http://araaraufufu.xyz

  シングルが寂しくなったくらいの人におすすめです。
  駅近未開拓地多数。自由に開拓してください!

ファイル名は拡張子が.yamlであれば任意です。
ここではkopipe_aqua_craft.yamlとでもしておきましょう。

一度mikutterを再起動して、右クリックメニューに「AQUA Craftの宣伝」が追加されていることを確認してください。

f:id:moguno:20150101233942p:plain

(3)抽出タブの設定

(a)データソース
1分周期で現在時刻をつぶやくデータソース「時計」を選択します。

f:id:moguno:20150101231309p:plain

(b)絞り込み条件
今回は1時間ごとに通知させたいので、毎時00分のメッセージのみを取り出します。

f:id:moguno:20150102004727p:plain

(c)適用するコマンド
さっき作った「AQUA Craftの宣伝」を適用させます。

f:id:moguno:20150101234052p:plain

これで毎時00分が来るたびに「AQUA Craftの宣伝」コマンドが実行され、宣伝メッセージが自動ツイートされます。時間を呟くだけの存在意義不明なデータソースが、Botのタイミング生成の要になっているところが面白いですね。

特定の言葉に反応するBotを作ろう

続いて、ホームタイムラインの特定のメッセージに反応する愉快なBotを作っていきます。
ここでは「あひる焼き」に反応して火に油を注ぐメッセージを返してみます。

(1)プラグインの導入

今回はmikutter-extract-fire-commandとmikutter-kopipeのみを利用します。

(2)投稿メッセージの作成

ここでもmikutter-kopipe用のメッセージを定義するのですが、mikutter-kopipeのサンプルにあひる焼きを応援するメッセージ(4種)をランダムにつぶやく奴があるので、今回はそれを使います。

~/.mikutter/の下にkopipeディレクトリを作成して、mikutter-kopipe/sample/kopipe_ahiru_yaki.yamlをコピーしてください。

(3)抽出タブの設定

(a)データソース
ホームタイムラインを選択します。

f:id:moguno:20150101233652p:plain

(b)絞り込み条件
次の条件を定義します。

本文に「あひる焼き」を含み、
自分の投稿でなく、
本文に自分の名前を含まない。(あひる焼くなプラグインのリプライを対象外にする)

f:id:moguno:20150101233704p:plain

(c)適用するコマンド
サンプルのあひるを焼く(ランダム返信)を適用させます。

f:id:moguno:20150101233719p:plain

これで、誰かが「あひる焼き」と呟くたびにいちいち茶々ツイートを嚙ますことができるようになります。
あひる焼きゲームよ永遠なれ!

おわりに

今回のBotやmikutterの薄い本 vol.7(もうすぐ通販も始まるよ!)に掲載の「SlideShareのスライドをはてなブックマークに転送する芸」など、mikutter-extract-fire-commandは様々な用途に応用が効く物と思います。
ぜひぜひ皆さんなりの面白い使い方を編み出してください!


では、本年もよろしくお願いします。