使ってみよう! Windows Live SDK/API

第13回Live Messenger Library ―― オリジナルLive Messengerの作成 (後編)

今回も前回前々回に引き続いてMessenger LibraryによるWebアプリケーションの作成です。そして、ひとまず完結編になります。前回までに作成したコードを元にLive Messengerとして機能するための事項を説明します。

localhostでの開発をサポート

はじめにMessenger Libraryのアップデート情報を紹介します。本連載 第11回のLive Messenger Library 前編の記事中で、ダイナミックDNSなどを用いた開発時の環境を紹介しました。これは開発時もlive.comサービスと通信するためURLドメインが必要なためでしたが、Messenger Libraryがアップデートされ、ドメインがlocalhostでも開発が可能になっています。簡単にMessenger Libraryの開発ができるようになりましたので、ぜひトライしてみてください。とはいえ、ダイナミックDNSを使った環境はほかのWindows Liveサービスを利用した開発で必要な場合がありますので構築しておいて損はありません。

プレゼンスの変更

さて、まずは前回までに作成したアプリケーションにて、ユーザのプレゼンスを変更できるようにしてみましょう。プレゼンスの表示はUserオブジェクトのPresenceプロパティ(IMAddressPresenceクラス型)を使用していました。プレゼンスの変更はこのPresenceプロパティに各種 値を設定するだけで可能です。ただし、表示アイコンのURLは読み取り専用のプロパティとなっているためMessenger Libraryから変更はできません。

Messenger Libraryの場合、プロパティとして扱われている値への設定は「set_」を接頭辞とした関数を使用していました。表示名・表示メッセージ・状態を変更は次のように記述します。

Gihyo.LiveSample.changePresence = function() {
    var presence = Gihyo.LiveSample.User.get_presence();
    if (presence.get_status() === Microsoft.Live.Messenger.PresenceStatus.offline) {
        return;
    }

    presence.set_displayName($('displayNameText').value);
    presence.set_personalMessage($('personalMessageText').value);
    
    var selectedIndex = $('selectStatus').selectedIndex;
    var statuses = [Microsoft.Live.Messenger.PresenceStatus.appearOffline,
                    Microsoft.Live.Messenger.PresenceStatus.away,
                    Microsoft.Live.Messenger.PresenceStatus.beRightBack,
                    Microsoft.Live.Messenger.PresenceStatus.busy,
                    Microsoft.Live.Messenger.PresenceStatus.idle,
                    Microsoft.Live.Messenger.PresenceStatus.inACall,
                    Microsoft.Live.Messenger.PresenceStatus.online,
                    Microsoft.Live.Messenger.PresenceStatus.outToLunch];
    presence.set_status(statuses[selectedIndex]);
}

サインインしていない状態では変更しないように条件文を入れています。状態の変更は、selectタグとoptionタグを使ってユーザに選択してもらうことを想定しています。Microsoft.Live.Messenger.PresenceStatus列挙体の各値を格納した配列を作成し、それと対応するようにHTMLを記述します。HTMLは次のように記述しました。Default.htm内の適当な場所に追加してください。

<div>
<table>
    <tr><td>Display Name: </td><td><input id="displayNameText" type="text" /></td></tr>
    <tr><td>Message: </td><td><input id="personalMessageText" type="text" /></td></tr>
    <tr><td>Status: </td>
        <td>
        <select id="selectStatus">
            <option>オフライン</option>
            <option>退席中</option>
            <option>一時退席中</option>
            <option>取り込み中</option>
            <option>退席中 (自動)</option>
            <option>通話中</option>
            <option>オンライン</option>
            <option>昼休み</option>
        </select>
        </td></tr>
</table>
<div><input type="button" value="Change Presence" onclick="Gihyo.LiveSample.changePresence();" /></div>
</div>

実行した結果は図1のようになります。

図1 プレゼンスの変更
図1 プレゼンスの変更

メンバーの表示時の処理

前回はメンバーの表示するときにUserオブジェクトのContactsプロパティを参照し、すべてのメンバーに対して一様に処理していました。ですが、メンバーの中には禁止(ブロック)している人がいるかもしれませんし、オフラインの場合は会話の作成は必要ありません。それらを考慮したコードを書く場合の方法を紹介します。

メンバーのオンライン状態

メンバーの状態がオンラインかどうかは、状態を表示するとき使用したContactオブジェクトのCurrentAddress.Presence.Statusプロパティでわかりますが、オンラインかどうかだけはCurrentAddress.IsOnlineプロパティを使用できます。

// (contact は Contactオブジェクト)
if (contact.get_currentAddress().get_isOnline()) {
    // メンバーがオンラインの場合の処理をここに書く
}

プレゼンスを許可した・禁止したメンバー

ユーザのプレゼンスの公開を許可したメンバー、公開を禁止したメンバーかどうかは、ContactクラスのIsAllowed、IsBlockedプロパティによりわかります。

// (contact は Contactオブジェクト)

if (contact.get_isAllowed()) {
    // 許可したメンバーの場合の処理をここに書く
}

if (contact.get_isBlocked()) {
    // 禁止したメンバーの場合の処理をここに書く
}

これらのプロパティは読み取り専用になっており、メンバーを禁止する、または禁止したメンバーを許可する場合は、ContactオブジェクトのAllow、Blockメソッドを使います。

contact.block(); // メンバーへプレゼンス公開の禁止
contact.allow(); // メンバーへプレゼンス公開の許可

これまでメンバーの取得にはUser.Contactsプロパティを使用していましたが、許可された・ブロックされたメンバーのみを取得したい場合は、User.AllowedContacts、BlockedContactsプロパティが使えます。これらで取得できるメンバーはLive Messengerのオプションウィンドウ図2のプライバシーで確認できるメンバーになっています。User.Contactsには含まれていないメンバーも含まれている場合があります。

図2 オプションウィンドウ
図2 オプションウィンドウ

コード例は次のようになります。

// 許可したメンバーの列挙子取得
var allowedContacts = Gihyo.LiveSample.User.get_allowedContacts().getEnumerator();
// 禁止したメンバーの列挙子取得
var blockedContacts = Gihyo.LiveSample.User.get_blockedContacts().getEnumerator();

メンバーの追加と削除

次はWebアプリケーションからメンバーの追加と削除ができるようにしてみます。

メンバーの追加

メンバーの追加にはUser.AddContactメソッドを使います。AddContactメソッドには次の3個の引数を指定します。

  • 追加するメンバーのアカウントアドレス
  • 招待メッセージ
  • ユーザオブジェクト

まずはコードをみてみましょう。

Gihyo.LiveSample.addContact = function() {
    var address = $('newContactAddress').value;
    Gihyo.LiveSample.User.addContact(address, '招待メッセージです。', null);
    $('newContactAddress').value = '';
}

Default.htmに追加するHTMLは次のようになります。

<div>Address: <input id="newContactAddress" type="text" />
     <input type="button" value="Add Contact" onclick="Gihyo.LiveSample.addContact();" /></div>
</div>

コードでは、入力されたアドレスをAddContractメソッドに渡しています。招待メッセージは、相手へ送るメッセージになり、メンバーリストに追加された側は、Live Messengerにて図3のような通知を受け取ります(Live Messengerの設定によります⁠⁠。ここに設定した招待メッセージが表示されています。

図3 メンバーリストに追加されたときに受け取る通知
図3 メンバーリストに追加されたときに受け取る通知

また、3個目の引数に指定したユーザオブジェクトは、開発者が必要に応じて使用するためのものです。メンバーの追加時、その結果はイベントとして受け取ります。その際にここで指定したユーザオブジェクトを受け取ることができます。

メンバー追加完了イベント

続いてメンバー追加完了時のイベントを受け取れるようにします。AddContractメソッド呼出し後にUserオブジェクトのAddContactCompletedイベントが発火します。このイベント通知を受け取れるように前回までに作成したGihyo.LiveSample.signInCompletedメソッド内に次のように追記しておきます。

Gihyo.LiveSample.User.add_addContactCompleted(Delegate.create(null, Gihyo.LiveSample.addContactCompleted));

Gihyo.LiveSample.addContactCompletedメソッドと関連付けました。そのGihyo.LiveSample.addContactCompletedメソッドの内容は次のようになります。

Gihyo.LiveSample.addContactCompleted = function(sender, e) {
    var contact = e.get_contact(); // Contactオブジェクト
    var result = e.get_resultCode(); // 追加結果
    var userState = e.get_userState(); // AddContactで指定したユーザオブジェクト

    switch (result) {
        case Microsoft.Live.Messenger.AddContactResultCode.success:
            var address = contact.get_currentAddress();
            address.get_presence().add_propertyChanged(Delegate.create(null, Gihyo.LiveSample.memberPresencePropertyChanged));
            Gihyo.LiveSample.memberPresencePropertyChanged(this, null); // 表示更新
            alert(address.get_address() + 'を追加しました。');
            break;

        case Microsoft.Live.Messenger.AddContactResultCode.failure:
            alert('追加に失敗しました。');
            break;

        case Microsoft.Live.Messenger.AddContactResultCode.notFound:
            alert('存在しないアドレスです。');
            break;
    }
}

イベント引数のオブジェクトから

  • 追加したメンバーのContactオブジェクト
  • 追加の結果を示す値
  • AddContactメソッド呼び出し時に指定したユーザオブジェクト

以上の3種類の値が取得できます。追加に成功した場合のみContactオブジェクトが格納されています。結果を示すResultCodeは、Microsoft.Live.Messenger.AddContactResultCode列挙体型になっています。この列挙体には、成功(Success⁠⁠、失敗(Failure⁠⁠、アドレスが見つからなかった(NotFound)の3種類の値があります。ただし、いろいろなアドレスを試したところNotFoundの結果は返ってきませんでした。将来のバージョンに予約された値かもしれません。そのため実際にはSuccessとFailureの値を使って処理します。

上記のコードでは追加に成功した場合、対象メンバーのプレゼンスが変化したときイベント通知を受け取るようにメソッドの関連付けと、Webページに表示しているリストを更新するため前回作成したメソッドを呼んでいます。

追加に失敗した場合、どのアドレスが失敗したかはイベント引数のオブジェクトからはわかりません。AddContact呼び出し時にユーザオブジェクトには追加するアドレスを指定しておくとよいかもしれません。

メンバーの削除

メンバーの削除は、User.Contacts.Removeメソッドを使います。メソッドの引数には削除するメンバーのContactオブジェクトを渡します。Removeメソッドはユーザの表示するメンバーの一覧から削除するだけでメンバーへのプレゼンス公開の禁止は行いません。禁止するには先に示したContactクラスのBlockメソッドを使います。

次のコードは、削除するメンバーのアドレスとアドレスの種類を引数に持ったメソッドです。このメソッドを呼び出し、メンバーを削除するようにします。前回作成した会話を作成するGihyo.LiveSample.createConversationメソッドと同じ引数になっています。

Gihyo.LiveSample.removeContact = function(address, type) {
    var contact = Gihyo.LiveSample.User.get_contacts().find(address, type);
    if (contact != null && confirm('削除してもよろしいですか。')) {
        Gihyo.LiveSample.User.get_contacts().remove(contact);
        Gihyo.LiveSample.memberPresencePropertyChanged(this, null); // 表示更新
    }
}

メンバーを削除するにはWebページ上のリンクをクリックすることで行うようにしました。前回作成したGihyo.LiveSample.memberPresencePropertyChangedメソッド内に次の記述を追加します。会話を作成するリンクのとなりに削除用のリンクを表示します。

sb.append('<a href="#" onclick="Gihyo.LiveSample.removeContact(' +
          "'" + address.get_address() + "'," + address.get_type() + ');return false;">');
sb.append('[remove]');
sb.append('</a>');

// (この次のコードは sb.append('</li>');)

以上でメンバーの追加と削除ができるようになりました。実行した例を図4に示します。

図4 メンバーの追加と削除
図4 メンバーの追加と削除

メッセージの送信が失敗した場合の処理

Live Messengerを使用していてメッセージの送信が失敗した経験があるかと思います。Messenger Libraryでも同様に送信できない場合があります。前回メッセージの送信を説明しましたが、これを考慮していませんでした。送信できなかった場合を処理できるようにしてみましょう。

送信したメッセージが相手へ届かなかった場合、会話を表すConversationオブジェクトのSendMessageFailedイベントが発火します。これを使用して送信失敗を知ります。作成しているWebアプリケーションでは、会話を選択したときにイベントを関連付けるよう処理することにします。前回作成したGihyo.LiveSample.selectConversationメソッドの内にあるメッセージ受信イベントを関連付けているコードの後に以下のコードを追記します。

conversation.add_sendMessageFailed(Delegate.create(null, Gihyo.LiveSample.sendMessageFailed));

また、イベント関連付けを削除している箇所にも同様に以下のコードを追記します。

Gihyo.LiveSample.selectedConversation.remove_sendMessageFailed(Gihyo.LiveSample.sendMessageFailed);

Gihyo.LiveSample.sendMessageFailedメソッドの実装は次のようにしました。失敗した場合、そのメッセージを表示しています。

Gihyo.LiveSample.sendMessageFailed = function(sender, e) {
    var message = e.get_message(); // 送信したMessageオブジェクト
    var result = e.get_resultCode(); // 送信結果
    var userState = e.get_userState(); // SendMessageで指定したユーザオブジェクト

    if (result === Microsoft.Live.Messenger.SendMessageResultCode.failure) {
        alert("次のメッセージは送信に失敗しました。\n" + message.get_text());
    }
}

イベント引数のオブジェクトからは次の値が取得できます。

  • 送信したメッセージのMessageオブジェクト
  • 送信結果を示す値
  • ユーザオブジェクト

送信結果のResultCodeは、Microsoft.Live.Messenger.SendMessageResultCode列挙体型です。この列挙体には、成功(Success⁠⁠、失敗(Failure)の2種類が用意されていますが、SendMessageFailedイベントは失敗時のみしか発火しないため常にFailureの値が格納されています。

ユーザオブジェクトは、メッセージを送信するときにConversation.SendMessageメソッドの引数に開発者が必要に応じて指定できる値です。前回作成したメッセージを送信するコードではnullを指定していました。

以上で送信失敗に対する対応が一応できました。作成したアプリケーションでは会話を切り替えるとイベント関連付けを削除してしまうため、失敗の通知をとりこぼす可能性があります。また、送信失敗したときに必ずイベントが発火するとは考えておかないほうがよいでしょう。

おわりに

以上、3回に渡りMessenger Libraryについて紹介してきましたが、いかがでしたでしょうか。

MSDNライブラリの文書にWindows Live Messenger Library アプリケーション設計ガイドラインというものがあります。これを参照すると、Messenger Libraryを利用してLive Messengerとして実装すべき事項が書いてあります。きちんと実装したかは別として本連載で扱った内容で、最低限 実装すべき事項は満たせるものが作れるかと思います。さらなる情報はリファレンス(英語)を参照してください。

設計ガイドラインに沿って実装してもWeb版Live Messengerが作成できるだけですので、価値あるアプリケーションにするには、ほかのWeb APIと組み合わせるなど何かアイデアが必要だと思います。おもしろいWebアプリケーション作成に本連載が手助けになれば幸いです。

おすすめ記事

記事・ニュース一覧