チャットサポートを構築する (その4) 連絡先の設定とまとめ

【2018年4月20日追記】この記事は内容が古くなっている部分があります。「あらためてチャットサポートを構築する」もご覧ください。【追記ここまで】

共有名簿 (shared roster)

ふつうの XMPP では、相手先名簿 (roster) は JID に紐付けられ、サーバーに保持されています。ところが匿名サーバーの場合、接続要求があった際にそのアカウントが新たに一時的に生成されるため、その JID には相手先名簿がありません。そこで、XMPP の共有名簿(shared roster)という機能を使うことにします。

ejabberd の設定ファイル ejabberd.cfg では

{modules,
 [
  ...
  {mod_shared_roster,[]},
  ...
]}.

とモジュールを有効化しておきます。

ejabberd のウェブ管理画面の「ヴァーチャルホスト -> anonymous.example.net -> 共有名簿グループ」の画面で、まずひとつのグループを作成します。たとえば

  • 名前: support
  • 説明: サポート窓口
  • メンバー: support@example.net
  • 表示グループ: (空欄)

のようにします。ここで support@example.net は、窓口側(問い合わせを受ける側)の JID です。

さらにもうひとつグループを作成します。

  • 名前: all
  • 説明: 全ユーザー
  • メンバー: @all@
  • 表示グループ: support

ここで @all@ は、「全ユーザー」を意味します。

これで、「anonymous.example.net の全ユーザーの名簿に support グループのメンバー(ここでは support@example.net のみ)を自動的にセットする」ことができ、上述の(3)をクリアできました。

チャットサポート構築のまとめ

ここまでで、どうにかチャットサポートを構築できました。まとめますと、「チャットサポート」に求められる要件、

  1. アプリケーションの事前インストールが不要
  2. アカウント(JID)の登録が不要
  3. 連絡先が登録済み

に対して、(1)は Converse.js を導入することで、(2)はクッキーを利用し匿名サーバーを設定することで、そして(3)は共有名簿 (shared roster) を使うことでクリアして、一応「チャットサポート」的なものができました。そしてこれらを WordPress のサイトに導入するために プラグイン化しました。試しにこのサイトに設置してみました。画面の右下に小さなタブが見えると思います。

とりあえずはできたものの、課題も残っています。

前にも書いたとおり、事前接続のところがよく理解できていないこともあって、匿名サーバーだと使えますが、特定の JID を事前設定しようとするとうまくいきません。また、ページ遷移に対応できていません。

匿名サーバーの場合、共有名簿を使ってみましたが、多重に読み込んでいるのか、同じ相手先が増殖することがあります。どういうことなのかよくわかりません。また、これは匿名サーバーの宿命なのですが、接続した時点で相手先からは認証されていないので(その時点で生成された ID なので当然)、その相手先の在席状況が不明で「オフライン」と表示されてしまいます。印象が悪いので、WordPress のプラグインではこれを隠すようにしてみました。

今回、恥を忍んで中途半端な状態でも公開してこのような文を書いたのは、誰か能力のある人がちゃんとした実装を教えてくれることを期待してのことです。XMPP ならまだしも、Strophe.js や Converse.js で検索しても、とにかく日本語での情報は非常に少なく、どこで聞いたらいいかもわからないほどです。

何かわかる方がありましたら、教えてください。または情報をぜひ公開してください。お願いします。

チャットサポートを構築する (その3) Converse.js を WordPress で使うプラグイン ConverseJS for WordPress

【2018年4月20日追記】この記事は内容が古くなっている部分があります。「あらためてチャットサポートを構築する」もご覧ください。【追記ここまで】

(その1)テストのページに示したように、Converse.js は、css と設定のための script を読みこめば簡単に設置できます。ということは、WordPress のサイトにも設置できます。これを実現するプラグインを作り、公開しました。

GitHub にも置いています

Converse.js を同梱しているので、このプラグインをインストールするだけで済みます。

ダッシュボード -> 設定 -> Converse.js で、主な設定値の変更ができるようにしています。設定値の詳細は Converse.js のマニュアルを参照してください。

設定項目の最初の Converse.js URL は、空白にすると、プラグイン同梱の converse-min.js を読み込みます。ただのファイル名 converse.jsconverse-no-otr.min.jsconverse-no-locales-no-otr.min.js と書くと、やはりプラグイン同梱のものを読み込みます。外部のものを使いたい場合は、正しい URL を設定してください。

2番めの BOSH Server URL は、空白にすると、Converse.js が用意しているテストのための https://bind.opkode.im を使います。なるべくほかの BOSH サーバーを指定してください。

(その2)にも書きましたように、事前接続はまだよく理解していないので、正しい実装ができていません。設定の prebind (事前接続)にチェックを入れ、JID とパスワードを入力しておくと、正しく接続できて名簿も取得できるように見えるのですが、会話ができません。Converse.js の GitHub でのこの議論と同じだと思うのですが、具体的にどうしたらいいかわかりません。詳しい方がありましたら、ぜひ教えてください。下に述べるように、匿名サーバーに接続してチャットサポート的に使うことはできます。

設定例

オープンな XMPP クライアント

初期状態のままで、ふつうの XMPP クライアントのようになります。右下にウィンドウが表示されているはずです。JID とパスワードを入力すれば、そのまま使用できます。

チャットに使用するアカウント (JID と呼ばれます)を持っていなければ、公開サーバー(たとえば STEP.im)で作ることができます。あるいは WordPress.com のアカウントを持っていれば、name@im.wordpress.com の形で、JID として使うことができます。

facebook のチャットにも使えます(たぶん)。JID に (ユーザー名)@chat.facebook.com を入力します。facebook はその中で閉じているので、facebook 以外と会話することはできません。

チャットサポート

匿名サーバーに事前接続することで、チャットサポートの形にすることができます。

prebind にチェックを入れます。JID 欄には匿名サーバーのホスト名だけを入れます。パスワード欄は空のままにしておきます。これで、これが設置してあるページを開くと、自動的に匿名サーバーに接続し、IDを割り振られます。

一応これで使えるのですが、やはり事前接続の正しい理解と実装ができていないので、ページ遷移(WordPressの同一サイト内で別のページに移動した場合)に対応していません。いったん接続が切れて、また新たに接続する(匿名サーバーだと新しいIDになってしまう)ことになってしまいます。詳しい方がありましたら、ぜひ教えてください。

この項もう少し続く

チャットサポートを構築する (その2) サーバー ejabberd の準備

【2018年4月20日追記】この記事は内容が古くなっている部分があります。「あらためてチャットサポートを構築する」もご覧ください。【追記ここまで】

前回の「チャットサポートを構築する (その1)」は、Converse.js を設置し、(テストのページ)のように、普通の XMPP クライアントとして使えるというところまででした。

BOSH サーバー

ここからしばらく、サーバー側の設定の話になります。

クライアントが Converse.js などウェブベースのもので内部状態を保持できないような場合、BOSHという仕組みを介することで、接続を維持します。XMPP サーバーの ejabberd の場合、設定ファイル ejabberd.cfg次のように書くことで、BOSH サーバーにもなります[1]

ポート 5281 (HTTPSの場合)を listen するところに http-bind と書き足します。

{listen,
 [
  ...
{5281, ejabberd_http, [
       ...
       http_bind,
       ...
       ]}
  ...
]}

モジュールの設定のところで

{modules,
 [
  ...
  {mod_http_bind, []},
  ...
]}

を読み込むようにします。

匿名サーバー

XMPP サーバーには匿名サーバーという機能を持つものがあります。一般にクライアントがサーバーに接続する場合、事前に登録して作成しておいた user@example.net という形をした JID と、パスワードが必要になりますが、匿名サーバーは、そのサーバー名だけを指定して接続を試みると、@ より前のユーザー名を乱数のようにそのつど生成して接続します。

サーバーアプリケーション ejabberd の場合、ejabberd.cfg につぎのように設定して SASL 匿名サーバー (anonymous.example.net という名前だとします) を設置します。

{hosts, [ ..., "anonymous.example.net"]}.

{host_config, "anonymous.example.net", [
                               ...
                               {auth_method, anonymous},
                               {anonymous_protocol, sasl_anon},
                               {s2s_default_policy, deny},
                               {{s2s_host,"example.net"}, allow},
                               ...
]}.

s2s_... は、匿名サーバーに接続したユーザーは特定のサーバー以外への通信を禁止するという設定です。

クライアント側の事前接続

ここからクライアント側の話です。

「チャットサポート」として利用できるためには

  1. アプリケーションの事前インストールが不要
  2. アカウント(JID)の登録が不要
  3. 連絡先が登録済み

であることが必要です。前回はこの最初の項目、Converse.js をごくふつうに設置する(テストのページ)ところまで行いましたが、このままでは客側にアカウント (JID) を入力してもらわなければなりません。

Converse.js のマニュアルに Server-side authentication という章があります。別の何らかの方法で事前にサーバーに接続しておき、その情報を引き継げば、上述の2番めの項目をクリアできます。接続先を匿名サーバにすればパスワードも不要になります。しかし、マニュアルには具体的な方法はありません。

次のような方法を考えてみましたがこれで正しいのかよくわかっていません。とりあえず(ある場合には)うまくいっています。もし詳しい方がありましたら、ぜひ教えてください。

Converse.js の初期設定を書く <script> のところの先頭に書き足します。

<script TYPE="text/javascript">
var BOSH_SERVICE = 'https://anonymous.example.net:5281/http-bind';
conn = new Strophe.Connection(BOSH_SERVICE);
conn.connect('anonymous.example.net', '', onConnect);

function onConnect(status)
{
     wpCookies.set('jid', conn.jid);
     wpCookies.set('sid', conn.sid);
     wpCookies.set('rid', conn.rid);
}

Strophe.js は Converse.js に同梱されているので、Converse.js を利用できるようにしていれば、使えます。接続すると JID、SID、RID が確定するので、それをクッキーとして書き出します。ここでは WordPress の wp-include/js/utils.js を利用した記述 wpCookies.set になっていますが、もちろんそれでなくてもかまいません。

それに続く Converse.js の設定では

require(['converse'], function (converse) {
    converse.initialize({
        ...
        bosh_service_url: BOSH_SERVICE,
        prebind: true,
        jid: wpCookies.get('jid'),
        rid: wpCookies.get('rid'),
        sid: wpCookies.get('sid'),
        ...
    });
});
</script>

と、bosh_service_url を指定し、prebindtrue とし、jid, rid, sid をクッキーから読み込みます。

この項まだ続く

  1. BOSH サーバーには2種類あります。local BOSH サーバーは、入り口はどこからでも接続できますが、ローカルのアカウントにしか接続できません。それに対して open BOSH サーバーは、他所のサーバーのアカウントにも接続できます。ejabberd の BOSH は local タイプです。

チャットサポートを構築する (その1)

【2018年4月20日追記】この記事は内容が古くなっている部分があります。「あらためてチャットサポートを構築する」もご覧ください。【追記ここまで】

ずっと頭の片隅にあっていつかはと思っていた話題ですが、あたためすぎて腐ってしまった感なきにしもあらずです。何しろ自分でプログラムを書くほどの能力がないので、道具が出揃うのを待っているうちに随分時間が経ってしまいました。

「チャットサポート」というものについて考えてみます。Wikipedia の記述をそのまま引用しますが、

文字通り、チャットによるサポートであり、閲覧中のWebページ内のチャットボタンをクリックするだけでリアルタイムに Web サイト運営者のサポートをリアルタイムに受けることが出来るシステム。……英語ではLive Chat Supportと呼ばれることが多い。

というものです。アメリカのネット通販サイトなどではよく目にしますが、日本ではあまり見かけません。それでも「チャットサポート」で検索すると、日本(語)でもそのようなサービスを提供するところが増えてきているようです。

しかし大手の販売サイトならともかく、月に数回程度の利用しかないと想定される規模では、月額数千–数万円のサービス料金がメリットに見合うとは、あまり思えません。

そこですべてオープンソースの個々の汎用アプリケーションを組み合わせて、無料でこの仕組みを構築することを考えてみました。プログラムを書く能力があれば自分で作れるのでしょうが、それができないために、あちこちのソフトを組み合わせることになりました。

基本はチャットですから、XMPP を使います。このプロトコル自体がオープンであり、Skype や LINE や twitter などとは異なります。

すべてオープンソースの組み合わせで構築すると

  • 費用が発生しない
  • 独占企業の都合によるサービスの変更や停止ということがない
  • 個々のアプリケーションを取り替えられる
  • カスタマイズできる
  • サーバーも自分で管理すれば他者を経由しないので情報の流出の不安がない

などのメリットがあります。

もちろん逆に、一定の労力が必要だったり、汎用アプリのため洗練されていないなどのデメリットもあります。

通常のチャットでは、話者のそれぞれが XMPP のアカウント(JIDといいます)を持ち、互いに相手先を名簿に登録しており、それぞれ手元の端末にインストールするなりした XMPP のアプリケーションを使って、サーバーを介して会話します。「チャットサポート」の場合、サポートする側(問い合わせを受ける側。以下、便宜的に「窓口側」と呼びます)は別として、一度きりかもしれない問い合わせを行う側(以下、「客側」と呼びます)に、そのためにアカウントやアプリケーションを用意してもらうことは非常に難しいでしょう。

Converse.js

まず XMPP クライアントアプリケーションですが、JavaScript で書かれたものをウェブページに設置することで、そのページにアクセスするだけで利用できるようにします。これで、客側が事前にアプリケーションをインストールしなければならないということがなくなります。

Converse.js というものを見つけました。2014年初頭現在、活発に開発されているようです。多言語化されているようですが、日本語はまだ対応していなかったので、翻訳して作者に送ってみました。この時点で日本語での情報はほとんどなく、見つけたのは「Ejabberd+Apache mod_proxy+converse.jsでXMPP(BOSH)なチャット環境を作ってみた」でした。

さて、マニュアルに従って設置してみます。<head>内に CSS と本体の js を読み込むように書き、またページ後半に初期設定を記した <script> を書きます。ここまでは簡単で、そのまま Converse.js が使えるようになりました。

テストのページで実際に見てみるとわかるように、素のままでは普通の XMPP クライアントとかわりません。すなわち、自分のアカウント情報を入力し、相手先のアカウントを指定して会話を開始する、というものです。

長くなりそうなので、この項続く

2013年に読まれた記事トップ10

流行っているみたいなので、自分のところでも見てみました。Jetpack のサイト統計情報の1年分です。

2012-12-31 to 今日

  1. gdm でのシャットダウンの禁止 (2007年10月)
  2. GNOME でのシャットダウンの禁止—最近の流儀 (2011年6月)
  3. 2台所有する自動車の1台を手放すとき、保険は等級の高いほうを残すことができる (2013年2月)
  4. WordPress 3.6 日本語版 (2013年8月)
  5. WordPress: フィルターより前にショートコードを実行させる (2013年3月)
  6. wp-login.php への攻撃に対処する (2013年9月)
  7. 公開 Jabber/XMPP サーバー (2011年7月)
  8. 日本語スタイルガイド項目別比較一覧表 (2012年3月)
  9. ja.po のコメント欄に見る WordPress 日本語版の歴史 (2013年5月)
  10. Jabber と WordPress (前編) (2010年11月)
  11. Firefox に新しいプロトコルを教える (2012年2月)

1位の記事はとても古くて、そこから誘導している改訂版みたいな内容が2位なので、これらは実質同じもの。この情報は公式に近いところに見られないのでこちらに来ているのでしょうか。こういうちょっとした設定をしたいのにとてもわかりにくい GNOME の傾向はなんとか変わってくれないものかと思います。

3位の自動車保険の話も、意外と他所では見つけにくい情報なのでしょう。

4位の WordPress 日本語版リリースリーダーの話は、twitter や facebook で広めてもらった(自分の記事としては)ようです。

5位は、いまこのリストを見て自分でも意外でした。これも他所にはあまりない情報なのかなあ。

7位と10位は古い記事ですが、Jabber/XMPP の情報は日本語ではとても少ないので、ここにたどり着くのでしょう。公開サーバー STEP.im をよろしくお願いします。

9位は、WordPress 10周年に寄せて書いたものです。

1位と2位が実質ひとつなので、11位まで掲載しました。

このブログを継続的に見ている人はたぶんほとんどなく、検索でその記事だけ単発にたどり着くのが大部分だと思っています。あたりまえのことですが、他所にない情報がよく見られているということですね。来年もそんな記事をいくつか書ければと思います。

WordPress からのほぼすべての通知を XMPP で送信するプラグイン wp_mail to XMPP

先日、WordPress のフォーラムの話題に触発されて、「コメントが来たことをメール以外で知らせる方法」という記事を書きました。

そのあともう少し一般的に考えてみました。WordPress から多くのメールが届きますが、そのほとんどは単なる「通知」で返信を要しないものです。つまりメールである必要はないのです。ということは、コメントがついた時だけでなく、WordPress からのすべてのメールを XMPP にしてもいいのではないか、と思いました。メールと XMPP は形式がとてもよく似ており、そのまま宛先を変えるだけでいいのではないか、と。

探してみたら、同じ目的の XMPP sender というものが既にありました。しかし中を見てみると古くて、メンテナンスもされていないようです。また、完全に wp_mail() を置き換えているので、条件によっては XMPP ではなくメールで送りたいと思っても応用が効きません。

WordPress からの通知は、更新・ユーザー追加・コメントなど発生源は種々あっても最終的には wp-includes/pluggable.php の中の wp_mail() によってメール発信が行われています。[1] wp_mail() を見てみますと、

function wp_mail( $to, $subject, $message, ...) {
	extract( apply_filters( 'wp_mail', compact( 'to', 'subject', 'message', 'headers', 'attachments' ) ) );
		...
		$phpmailer->Send();
}

という構造になっています。冒頭のフック ‘wp_mail’ は、たぶん送信先の追加や、subject(件名)や message(内容)に一律に何か加工するなどを想定されていると思いますが、その中で XMPP 送信を行ってしまえばいいと考えて、次のようなプラグインを作りました。

wp_mail to XMPP
Send almost all notifications via XMPP instead of email

https://github.com/mako09/wp-mail2xmpp にも置いてあります。

前の記事「コメントが来たことをメール以外で知らせる方法」でざざっと書いて示したプラグインは、その機能が今回のプラグインに完全に含まれますので、忘れてください。

なおこのプラグインは、別のプラグイン XMPP Enabled を利用していますので、それを先にインストールしてください。

きっかけとなったフォーラムの話題のように、複数の投稿作成者がいて誰かが投稿したことを他の作成者たちが知りたい、という場合には、投稿を通知するプラグイン(公式ディレクトリで “post notification” で検索すれば、いろいろ見つかります)、たとえば New Post Notification などをインストールしておけばいいでしょう。そのメール通知も今回のプラグインで XMPP に振り替えます。

wp_mail to XMPP の中身

このプラグインは2つのフックを備えています。

abort_xmpp_sender は、XMPP送信処理を中止するためのものです。たとえば「コンタクトフォームからの送信は、JID の有無に関わらず、メールで送信する」としたい場合、件名やヘッダなどで判定するフィルターを追加すれば、実現できます。

email_to_jid は、メールアドレスから JID に変換するフィルターを呼び出します。デフォルトでは、そのサイトに登録されているユーザーかつそのユーザーがJIDを設定している場合のみ、JID を返すフィルターを設定しています。たとえばコメントをつけた人が入力したメールアドレスのように、JID を見つけることができなければ、その人には XMPP 通知を出しません。このフックにさらにフィルターを追加して、たとえば JID があっても XMPP 通知を出さない人を設定する、あるいは逆に、JID が見つからない場合は管理者の JID に XMPP 通知を出す、などを実現できます。

これらの後に、JID があれば XMPP 通知を、JID がなければメール通知を行います。XMPP に送られる通知では、subject(件名)と message(内容)をそのまま用い、headers(ヘッダー)と attachments(添付)は送信せず無視しています。

オプションで、XMPP 通知を行ったユーザーにもメール通知を行うように設定することもできます。

おわりに

はじめてプラグインを公式に公開しようとしたら、実際に動作するコードの部分を書く時間の10倍くらいを、その周辺のことに費やしました。名前を決めること、コメントや readme を英語で書くこと、依存する別のプラグイン XMPP Enabled を国際化・日本語化して作者に連絡して取り込んでもらうこと……。いやはや、いい経験になりました。それでもコード自体にも英語にも自信がありません。おかしなところを見つけて知らせてもらえたらうれしいです。

  1. ただし Jetpack購読(subscription)は、実際には WordPress.com がメールを送信しているため、これに該当しません。

コメントが来たことをメール以外で知らせる方法

WordPress のフォーラムに次のような話題がありました。

「コメントが来たことを知らせる方法をメール以外でなにかほしい」

現在、ワードプレスを数人で管理し、記事を書いています。

私たちの環境では、ディスカッション設定の自分宛のメール通知のところにある「コメントが投稿された時」にチェックを入れています。

(中略)

メールに気づく派も気づかない派も、各ユーザーがメールの通知以外でコメントに気づくことが出来るようにしたいと思っています。

そこで私は、以前に書いた「Jabber と WordPress」を示しながら、ただし XMPP サーバーを確保できないと難しいので一般的ではないと回答しました。

さて質問文をよく読むと、

  • 投稿にコメントがついたことの通知を受け取るのは、その投稿の作者のみでよい

で済みそうです。一度の通知の送り先は1人でよい、ということであれば、先に示したややこしい仕組みは必要ありません。

やはりインスタントメッセンジャー(IM) の XMPP を利用した通知を行うことにします。

管理者の作業

公式プラグインのサイトから XMPP Enabled というプラグインをインストールします。

さらに次のプラグインをインストールします。これは XMPP Enabled と同じ作者による、投稿のあった際に XMPP で通知する Juick Crossposter というプラグインを、コメントの場合に置き換えて作り直してみたものです。

また管理者は次の節の脚注の作業も必要に応じて行ってください。

【追記】 これを元に、一般化して、プラグインを公開しました。「WordPress からのほぼすべての通知を XMPP で送信するプラグイン wp_mail to XMPP」を参照してください。

各投稿者の作業

先の質問では複数の投稿作成者がいるようです。そこでそれぞれが通知を受け取るためには、各人の PC やスマートフォンなどに XMPP クライアントを用意してもらいます。また、各人に XMPP のアカウント(JID)を取得してもらいます。WordPress.comのアカウントを取得すれば自動的に (アカウント)@im.wordpress.com が JID になるのでそれを利用できます。

さて投稿しているブログサイトで、各人は自分のプロフィールのページにある「Jabber/Google Talk」の欄に取得した JID を入力しておきます [1][2]

これで設定は完了です。コメントがつくと、そのコメントがつけられた元の投稿の作者に XMPP で通知が行きます。

  1. 「Google Talk」とありますが、2013年末現在、Google Talk はサービスがなくなり(Google+ ハングアウトに吸収され)、他の XMPP ネットワークと連絡できなくなりました。そのため Gmail アカウントはここでは利用できません。
  2. なお、つい最近の WordPress を新たにインストールして始めた場合には、この「Jabber/Google Talk」欄がないかもしれません。管理者は、たとえばこのページなどを参考に(そこでは悲しいことにJabber項目の削除として紹介されていますが、ちょうどその逆の操作です)、jabber というフィールド名の項目を追加してください。