9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Cisco Systems JapanAdvent Calendar 2024

Day 13

Webex Meetingsの組み込みアプリとして簡易チャットアプリを作る

Posted at

この記事はシスコの有志による Cisco Systems Japan Advent Calendar 2024の一つとして投稿しています。

2024年版: https://qiita.com/advent-calendar/2024/cisco

以下、昨年までのものです。

2023年版: https://qiita.com/advent-calendar/2023/cisco
2022年版: https://qiita.com/advent-calendar/2022/cisco
2021年版(1枚目): https://qiita.com/advent-calendar/2021/cisco
2021年版(2枚目): https://qiita.com/advent-calendar/2021/cisco2
2020年版(1枚目): https://qiita.com/advent-calendar/2020/cisco
2020年版(2枚目): https://qiita.com/advent-calendar/2020/cisco2
2019年版: https://qiita.com/advent-calendar/2019/cisco
2018年版: https://qiita.com/advent-calendar/2018/cisco
2017年版: https://qiita.com/advent-calendar/2017/cisco

やったこと

Webex Meetingsの組み込みアプリとしてWebex Messagingにメッセージや画像などのファイルを送れる簡易チャットアプリを作成しました。

minimal-webex-chat.gif

この動画ではWebex MeetingsアプリのインターフェイスからWebex Messagingへメッセージとファイルを送信しています。きちんと送信できていることを示すためにWebex Messagingアプリを横に配置しています。

モチベーション

もちろんWebex MeetingsアプリとWebex Messagingアプリを交互に切り替えながらやればいいのですが、ミーティングを集中して聞きながらいろいろ操作したくないので、Webex Meetingsアプリのインターフェイス内で完結させたいというのが狙いです。Webex MeetingsでのメモやスクリーンキャプチャをWebex Messagingのスペースへすぐに共有したいときに(ちょっとだけ)便利です。

そもそもWebex組み込みアプリについて

Webex MeetingsアプリもしくはWebex Messagingアプリのインターフェイス内に他のアプリを組み込むことができます。今回はWebex Meetingsの組み込みアプリを作ってます。

Webex組み込みアプリを自分以外のWebex Meetings参加者に共有したり、Webex組み込みアプリを実行したユーザーの情報を取得したいときなどはWebex組み込みアプリ用のJavascript SDKを利用する必要があるのですが、今回作成するWebex組み込みアプリのように自分だけ利用できればよく、ユーザーの情報も必要としない場合には、通常のWebアプリをWebex組み込みアプリとして利用できます。Webアプリを作成できる人であれば、自分専用のWebex組み込みアプリを特別な知識なしに簡単に作れてしまいます。

この記事で解説するWebex組み込みアプリの登録方法やアプリそのものは自分専用のWebex組み込みアプリを作るためのものです。自分以外のWebex Meetings参加者にも共有するようなWebex組み込みアプリについてはこの記事で解説する以上の考慮が必要です。

[Webex for Developers] Embedded Apps Developer Guide
https://developer.webex.com/docs/embedded-apps-guide#developer-quick-start

[Qiita] WebexのAppを自作してみる!
https://qiita.com/KomiKoh/items/46aa112cce174abc044c

Webex組み込みアプリの登録

先にWebex組み込みアプリの登録について解説します。

以下のWebex組み込みアプリ登録ページから必要な項目を入力してAdd Embedded appボタンをクリックします。

[Webex for Developers] New Embedded app
https://developer.webex.com/my-apps/new/embedded-app

以下の項目を入力します。
それ以外の項目は未記入もしくはデフォルトのままで結構です。

  • Where does your app work?: Meeting
  • Embedded app name: 任意
  • App Hub Description: 任意
  • Icon: 任意
  • Valid domains: アプリをホストしたドメイン名(例 example.com)
  • Start page URL: アプリのURL(例 https://example.com)

作成したWebex 組み込みアプリの概要

繰り返しになりますが、自分専用のWebex組み込みアプリを作る分には特別なことは必要ありません。なので、Webex Messagingのための簡易チャットWebアプリの解説と思っていただいても差し支えないです。

WebフレームワークにはNuxt3を用いました。

フロントエンドからバックエンドのAPIサービスに(メッセージやファイルなどの)必要な情報を送信して、バックエンドからWebex APIをコールする構成にしています。

Webex APIのアクセストークンを直接フロントエンドに露出させないようにするため、バックエンドを介してAPIを呼び出す構成にしてます。

image.png

Webex組み込みアプリはインターネットからアクセスできる必要があります。
(Webex組み込みアプリとしての)Nuxt3アプリのコンテンツをホストできて、かつ、バックエンドの処理も実行できて、無償で利用できるサービスとしてVercelを用いています。

[Vercel] Nuxt on Vercel
https://vercel.com/docs/frameworks/nuxt

[Vercel] Vercel Functions
https://vercel.com/docs/functions

バックエンドコードの解説

前述の通りWebex APIとのやりとりはバックエンドで実行されるので、バックエンドの実装のみを解説します。

ルームの取得

Botがメンバーとして帰属するルームの一覧を取得して返します。
WEBEX_BOT_TOKENはVercel環境変数として渡しています。

server/api/rooms.js

export default defineEventHandler(async (event) => {
  try {
    const response = await fetch('https://webexapis.com/v1/rooms/', {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${process.env.WEBEX_BOT_TOKEN}`
      },
    });

    if (!response.ok) {
      // Handle HTTP errors
      const errorText = await response.text();
      console.error(`Error: ${response.status} - ${errorText}`);
      return { status: 'error', message: 'Failed to retrieve rooms' };
    }

    const data = await response.json();
    return { status: 'success', items: data.items };
  } catch (error) {
    console.error('Fetch error:', error);
    return { status: 'error', message: 'An error occurred while retrieving rooms' };
  }
});

[Webex for Developers] List Rooms
https://developer.webex.com/docs/api/v1/rooms/list-rooms

[Vercel] Environment variables
https://vercel.com/docs/projects/environment-variables

メッセージの送信

フロントエンドから渡ったroomIdmessageの情報からメッセージを送信します。

server/api/message.js

export default defineEventHandler(async (event) => {
  try {
    const body = await readBody(event);
    const response = await fetch('https://webexapis.com/v1/messages/', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${process.env.WEBEX_BOT_TOKEN}`
      },
      body: JSON.stringify({ roomId: body.room, text: body.message }),
    });

    if (!response.ok) {
      // Handle HTTP errors
      const errorText = await response.text();
      console.error(`Error: ${response.status} - ${errorText}`);
      return { status: 'error', message: 'Failed to send message' };
    }

    return { status: 'success', message: 'Message sent successfully' };
  } catch (error) {
    console.error('Fetch error:', error);
    return { status: 'error', message: 'An error occurred during message sending' };
  }
});

[Webex for Developers] Create a Message
https://developer.webex.com/docs/api/v1/messages/create-a-message

ファイルの送信

フロントエンドから渡ったroomIdmessagedataURLfilenameの情報からファイルを送信します。

ファイルを送信するには、フォームデータを送信するときに使われるmultipart/form-dataを用いる必要があります。

toBlob関数はフロントエンドからもらったdataURL形式のデータをmultipart/form-dataで送信するためにBlob形式に変換してます。

server/api/file.js

export default defineEventHandler(async (event) => {
  try {
    const body = await readBody(event);
    const blob = toBlob(body.dataURL);
    if (!blob) {
      return { status: 'error', message: 'Invalid blob data' };
    }

    const formData = new FormData();
    formData.append('roomId', body.room);
    formData.append('text', body.message);
    formData.append('files', blob, body.filename);

    const response = await fetch('https://webexapis.com/v1/messages/', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${process.env.WEBEX_BOT_TOKEN}`
      },
      body: formData,
    });

    if (!response.ok) {
      // Handle HTTP errors
      const errorText = await response.text();
      console.error(`Error: ${response.status} - ${errorText}`);
      return { status: 'error', message: 'Failed to send file' };
    }

    return { status: 'success', message: 'File sent successfully' };
  } catch (error) {
    console.error('Error:', error);
    return { status: 'error', message: 'An error occurred during file sending' };
  }
});

[Webex for Developers] Message Attachments
https://developer.webex.com/docs/basics#message-attachments

成果物

作成したWebex組み込みアプリを以下に公開しています。
あくまでプロトタイプと思っていただけると幸いです。エラー処理などは不適切なところも多々あると思います。

[github.com] minimal-webex-chat
https://github.com/tetsusat/minimal-webex-chat

9
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?