Indenticon

Ncoの匿名コメントにアイコンを自動生成する機能の話

今日リリースしたNco v0.1.0-alpha.5で実装された「184コメントのユーザーにアイコンを設定するようにした」の実装についてメモ

実装のきっかけ

Nsen ch02の方から「184のユーザーを区別して話の流れを追いたい」という要望があったのが実装したきっかけです。
(利用とご意見いつもありがとうございます!)

他のコメントビューアではユーザーに任意の名前をつけるとかそもそもユーザーIDがテーブル上に表示されているといった機能で解決できていますが、Ncoではこれを採用しませんでした。

理由は「ユーザー名、もしくはIDを表示させると画面がカオスになり始める」ことと「コメントリストをテーブル実装にするのが面倒くさい(おい」の2つです。
画面のシンプルさは保っておきたいので他の手段を考えます。

アイコン

Ncoのコメントタイムライン上には「ユーザーのアイコン」が表示されています。(他のコメビュにも実装されてる)
このアイコンにカーソルを合わせるとユーザー名の確認も出来ますが、Nsenにおいて、あるユーザーを識別するにはアイコンさえあればおおむね十分だと思っています。(ニコ生となると話が変わってきますが)

しかし、Nco v0.1.0-alpha.4の時点では、匿名ユーザーはすべて一律のアイコンを表示する仕様になっていました。

幸い、どこかのサービスで「アイコンを設定していないユーザーに対して自動生成したアイコンを設定する」という方法があると知っていたので、今回はそれを採用しました。
調べてみたところIdenticonと呼ばれているらしいです。
今回はIdenticonを生成するJavaScriptライブラリがありましたので、それを利用しました。

stewartlord/identicon.js

匿名ユーザーの識別

ニコ生のコメントサーバーから送られてくるコメントデータには匿名でもそうじゃなくてもユーザーに対してIDが付与されて送信されてきます。

<chat thread="<threadID>" vpos="<postTimeOnLiveTime>" date="<postDateUnixTime>" date_usec="<よくわからないデータ>" mail="184" user_id="LnqFqknBV7..." anonymity="1" locale="ja-jp">コメント</chat>

このデータのuser_id属性がユーザーIDで、匿名ユーザーならこのような文字列、非匿名ユーザーならユーザー番号が付与されます。
このランダムな文字列に対して一意のアイコンを生成します。

実装

identicon.jsの使い方はREADMEに書いてあるとおりで、Identiconクラスを(たぶんMD5の)hashとアイコンサイズでコンストラクトして、
toStringメソッドをコールすればBASE64形式のPNGデータが取得できます。

Ncoでは先述のユーザーIDを、Node.jsのcryptoモジュールを使ってMD5に変換し、そのハッシュからアイコンを生成しました。
ただ、identicon.jsはmodule.exportsに対応した形式で書かれていないので、WebPackでコンパイルするためにコードの一部を書き換えて利用しています。

Crypto = require "crypto"
Identicon = require "thirdparty/identicon"

userId = comment.get("user.id")

md5Hasher = Crypto.createHash("md5")
md5Hasher.update(userId, "urf8")
md5UserId = md5Hasher.digest("hex")

iconBase64Png = new Identicon(md5UserId, 128).toString()

imgElem = document.createElement("img")
imgElem.src = "data:image/png;base64," + iconBase64Png

あとは、BlobURLとID毎のURLキャッシュを使ってJavaScriptがきもちメモリ食い過ぎないようにしてます。
(重たいDataURLみたいなデータを抱えすぎるとメモリをガツガツ食いまくる印象があるけど間違ってるかもしれないので誰か指摘ください)

(実装の詳細はsrc/renderer/scripts/services/Comment/Comment.coffeeをご覧ください)

コメントを残す

メールアドレスが公開されることはありません。