mikutter blog

mikutterのアナウンスなど

World系プラグインを実装する 0日目 下準備

はじめに

mikutterは、数多のSNSやメッセージングサービスなどを同時に扱える、拡張可能なソフトウェアを目指して開発されました。mikutter 3.6ではその機能に「World」という具体的な名前が与えられ、実装されました。

Worldプラグインは比較的シンプルな実装でWorld機能を提供していますが、Worldプラグインがどのような機能を提供しており、実際にWorldを利用したプラグインをどのように開発していけば良いのかを説明しなければなりません。

そこで、仮に簡単なWorld系プラグインを実装し、Worldの理解の補助となるような記事を連載することを思いつきました。連載記事は読みづらいかもしれませんが、この時期はまとまった時間が取れないので、プラグイン開発日記みたいな感じで小刻みにアウトプットしていけたらいいかなあと思っています。

今回実装するプラグイン

今回はWorldの説明を主眼に置いているので、多くのSNSで利用されている認証などは、複雑な割に今回説明したいことの本質ではないため、好ましくありません。もっと言えば、ネットワークアクセスなどにも同じことが言えます。

したがってこの連載では、以下のようなWorldを実装します。

  • ローカルファイルに投稿内容を只管追記していく
  • 1ファイル1アカウントと見立て、複数のファイルをアカウント切り替えでスイッチできる

ローカルファイルなので認証などありませんし、ネットワークアクセスなどもありません。用途としては、SNSに公開したくないことを書き溜めておく、個人的な簡単なメモ用途に使えそうです。

プラグインは以下のリポジトリで公開しています。

github.com

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に定義しなければならないと説明されているのは nameicon フィールドです。

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 を呼べば、 usernameUNIXユーザ名、 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が動いてもあまりうれしくなさそうですし、まだ試験段階なので、表示の確認のために書いてしまいました。

f:id:toshi_a:20171227210546p:plain

起動すると、いきなり「おしゃぶり」というタブが表示され、中にはhello, World!と書かれたMessageが一つだけぽつんとあります。ともかく、このModelでちゃんとタイムラインに表示できることが確認できました。

まとめ

github.com

何も新しいことをしていませんが、カスタムModelの例としてWriting mikutter Pluginに挙げられているRSSより更にシンプルなので、RSSなんかじゃなくてこちらのほうが分かりやすいかもしれないと、書いていて思いました。

次回はOshaburi Worldを定義し、任意のファイルの内容をTLに読み込んでみようと思います。