はじめに
mikutterは、数多のSNSやメッセージングサービスなどを同時に扱える、拡張可能なソフトウェアを目指して開発されました。mikutter 3.6ではその機能に「World」という具体的な名前が与えられ、実装されました。
Worldプラグインは比較的シンプルな実装でWorld機能を提供していますが、Worldプラグインがどのような機能を提供しており、実際にWorldを利用したプラグインをどのように開発していけば良いのかを説明しなければなりません。
そこで、仮に簡単なWorld系プラグインを実装し、Worldの理解の補助となるような記事を連載することを思いつきました。連載記事は読みづらいかもしれませんが、この時期はまとまった時間が取れないので、プラグイン開発日記みたいな感じで小刻みにアウトプットしていけたらいいかなあと思っています。
今回実装するプラグイン
今回はWorldの説明を主眼に置いているので、多くのSNSで利用されている認証などは、複雑な割に今回説明したいことの本質ではないため、好ましくありません。もっと言えば、ネットワークアクセスなどにも同じことが言えます。
したがってこの連載では、以下のようなWorldを実装します。
- ローカルファイルに投稿内容を只管追記していく
- 1ファイル1アカウントと見立て、複数のファイルをアカウント切り替えでスイッチできる
ローカルファイルなので認証などありませんし、ネットワークアクセスなどもありません。用途としては、SNSに公開したくないことを書き溜めておく、個人的な簡単なメモ用途に使えそうです。
0日目: とりあえず、タイムラインに何か表示する
Message Model
どこから実装を始めるか、というのは簡単なようで難しい問いです。私は規模を見積もれないコードを実装する時は、何らかの出力が見えることを第一目標とします。
ですので早速本題から逸れるようですが、 カスタムModel として Message を実装していきましょう。
タイムラインに表示されるツイートのようなものはmikutterでは Message と呼ばれます。これは単純に、 Message にかかれているようなメソッドが定義されたModelです。RSSリーダを例に説明されています。
今回は本文として description
と、作成日として created
、そして現状タイムラインに表示するにはユーザが必ず居るので、 user
を用意しました。
module Plugin::Oshaburi class Message < Diva::Model include Diva::Model::MessageMixin register :oshaburi_message, name: "おしゃぶりテキスト" field.has :user, Plugin::Oshaburi::User, required: true field.string :description, required: true field.time :created, required: true end end
User Model
現在のmikutterのタイムラインは、投稿者のUserを必ず要求します。SNSなら書いた人が必ずいますが、こういった場合は不便ですね。無いと言っても始まらないので、 User Model を作ります。
これも、例としてRSSが挙げられています。上記ページでUser Modelに定義しなければならないと説明されているのは name
と icon
フィールドです。
module Plugin::Oshaburi class User < Diva::Model include Diva::Model::UserMixin register :oshaburi_user, name: "おしゃぶりユーザ" field.string :username, required: true field.string :nodename, required: true def self.instance new(username: Etc.getlogin, **Etc.uname) end def name "#{username}@#{nodename}" end def icon Skin['list.png'] end end end
少し余計なことをしていますが、結局 name
メソッドと icon
メソッドがほとんど固定の値を返しているだけです。
icon
は、 Photo Model を返すようにと先程のページには解説されています。ここでは手を抜いて標準スキンのリスト画像をアイコンにしてます。
name
は、 username
フィールドと nodename
フィールドを組み合わせたもので、 Plugin::Oshaburi::User.instance
を呼べば、 username
はUNIXユーザ名、 nodename
にはマシンのホスト名が入ったUserオブジェクトが得られるようにしています。
検証用にタイムラインを用意する
あとは、この2つのModelがちゃんとタイムラインに表示できることを確認して、今日は下準備は終わりということにしましょう。まだ肝心のプラグイン本体ができていませんでしたね。
require_relative 'model/user' require_relative 'model/message' Plugin.create(:oshaburi) do tab(:oshaburi_test, "おしゃぶり") do timeline :oshaburi_test end message = Plugin::Oshaburi::Message.new(description: 'hello, World!', created: Time.now, user: Plugin::Oshaburi::User.instance) Delayer.new do timeline(:oshaburi_test) << message end end
先程書いた2つのModelは、modelというディレクトリの中に入れておきました。上記のコードは、何ということはない、タブの中にタイムラインが入ったものを表示するコードで、 Writing mikutter Pluginで説明されていることを簡略化したようなコードです 。
World系プラグインがGUIを表示してしまうと、GUIを持たないbot等に利用できなくなるので避けるべきです。しかしこのWorldに対してbotが動いてもあまりうれしくなさそうですし、まだ試験段階なので、表示の確認のために書いてしまいました。
起動すると、いきなり「おしゃぶり」というタブが表示され、中にはhello, World!と書かれたMessageが一つだけぽつんとあります。ともかく、このModelでちゃんとタイムラインに表示できることが確認できました。
まとめ
何も新しいことをしていませんが、カスタムModelの例としてWriting mikutter Pluginに挙げられているRSSより更にシンプルなので、RSSなんかじゃなくてこちらのほうが分かりやすいかもしれないと、書いていて思いました。
次回はOshaburi Worldを定義し、任意のファイルの内容をTLに読み込んでみようと思います。
追記 次回