チャット
概要
@omujs/chat
を使うと、YouTubeなどの配信サイトから取得したチャット、投稿者、チャンネル、配信枠などの情報を利用できます。
チャットの各データはテーブル として提供されます。過去のデータを取得できるほか、追加や更新をイベントとして受け取ることもできます。
セットアップ
Chat.create(omu)
でチャットAPIを作成します。
チャットAPIは必要なセッションと権限を登録するため、必ずomu.start()
より前に作成してください。
1 | import { Chat, ChatEvents, Models } from '@omujs/chat'; |
2 | import { Omu } from '@omujs/omu'; |
3 | import { APP } from './app'; |
4 |
|
5 | const omu = new Omu(APP); |
6 | const chat = Chat.create(omu); |
7 |
|
8 | const unlistenMessage = chat.on(ChatEvents.Message.Add, (message) => { |
9 | console.log(message.text); |
10 | }); |
11 |
|
12 | omu.start(); |
13 |
|
14 | |
15 | function destroy() { |
16 | unlistenMessage(); |
17 | } |
チャットを受け取る
chat.on(event, handler)
でチャットデータの追加、更新、削除を受け取ります。戻り値の関数を呼び出すと、登録したハンドラーを解除できます。
chat.on()
が対象テーブルの購読も開始するため、Batchイベントを含めてtable.listen()
を別途呼ぶ必要はありません。
1 | const unlisten = chat.on(ChatEvents.Message.Add, async (message) => { |
2 | const author = message.authorId |
3 | ? await chat.authors.get(message.authorId.key()) |
4 | : undefined; |
5 |
|
6 | console.log(`${author?.name ?? '不明'}: ${message.text}`); |
7 | }); |
8 |
|
9 | |
10 | function destroy() { |
11 | unlisten(); |
12 | } |
イベントはデータの種類ごとに用意されています。
| データ | イベント |
| メッセージ | ChatEvents.Message
|
| 投稿者 | ChatEvents.Author
|
| チャンネル | ChatEvents.Channel
|
| プロバイダー | ChatEvents.Provider
|
| 配信枠 | ChatEvents.Room
|
| 投票 | ChatEvents.Vote
|
それぞれのイベントから、次の変更を監視できます。
| イベント | 内容 | ハンドラーの引数 |
Add
| データが追加された | 追加されたデータ |
Update
| データが更新された | 更新されたデータ |
Remove
| データが削除された | 削除されたデータ |
AddBatch
| 複数のデータが追加された | Map<string, T>
|
UpdateBatch
| 複数のデータが更新された | Map<string, T>
|
RemoveBatch
| 複数のデータが削除された | Map<string, T>
|
Clear
| テーブルが空になった | なし |
1 | chat.on(ChatEvents.Room.Update, (room) => { |
2 | console.log(room.metadata.title, room.status); |
3 | }); |
4 |
|
5 | const unlistenMessages = chat.on(ChatEvents.Message.AddBatch, (messages) => { |
6 | for (const message of messages.values()) { |
7 | console.log(message.text); |
8 | } |
9 | }); |
10 |
|
11 | |
12 | function destroy() { |
13 | unlistenMessages(); |
14 | } |
過去のメッセージを取得する
chat.messages
は通常のテーブルとして操作できます。
最新のメッセージを取得するには、fetchItems()
にbackward: true
を指定します。戻り値は、メッセージIDをキーとするMap
です。
1 | const result = await chat.messages.fetchItems({ |
2 | limit: 50, |
3 | backward: true, |
4 | }); |
5 |
|
6 | const messages = [...result.values()].sort( |
7 | (a, b) => a.createdAt.getTime() - b.createdAt.getTime(), |
8 | ); |
リアルタイムのイベントだけでは接続前のメッセージを取得できません。画面の初期表示では、イベントを先に登録してからfetchItems()
で履歴を読み込みます。IDをキーにしたMap
へ保存すると、履歴の取得中に届いたメッセージも重複せず保持できます。
1 | const messages = new Map<string, Models.Message>(); |
2 |
|
3 | chat.on(ChatEvents.Message.Add, (message) => { |
4 | messages.set(message.id.key(), message); |
5 | }); |
6 |
|
7 | omu.onReady(async () => { |
8 | const history = await chat.messages.fetchItems({ |
9 | limit: 50, |
10 | backward: true, |
11 | }); |
12 |
|
13 | for (const [id, message] of history) { |
14 | if (!messages.has(id)) { |
15 | messages.set(id, message); |
16 | } |
17 | } |
18 | }); |
メッセージ
メッセージはModels.Message
として取得できます。
| プロパティ | 型 | 内容 |
id
| Identifier
| メッセージの識別子 |
roomId
| Identifier
| 投稿された配信枠 |
authorId
| Identifier | undefined
| 投稿者の識別子 |
createdAt
| Date
| 投稿日時 |
content
| Component | undefined
| 装飾を含むメッセージ内容 |
text
| string
| content から文字列だけを取り出した内容 |
paid
| Paid | undefined
| 通貨と金額 |
gifts
| Gift[] | undefined
| ギフト |
deleted
| boolean | undefined
| 削除済みかどうか |
message.content
には、テキストだけでなく画像、リンク、アセットなどが含まれる場合があります。文字列だけが必要な場合はmessage.text
を使います。
削除済みのメッセージを表示しない場合は、deleted
を確認してください。
1 | const visibleMessages = [...messages.values()] |
2 | .filter((message) => !message.deleted); |
投稿者を取得する
メッセージには投稿者のIDが保存されています。名前やアイコンが必要な場合はchat.authors
から取得します。
1 | if (message.authorId) { |
2 | const author = await chat.authors.get(message.authorId.key()); |
3 |
|
4 | console.log(author?.name); |
5 | console.log(author?.avatarUrl); |
6 | console.log(author?.roles); |
7 | } |
複数の投稿者をまとめて取得する場合はgetMany()
を使います。
1 | const authorIds = [...messages.values()] |
2 | .flatMap((message) => message.authorId ? [message.authorId.key()] : []); |
3 |
|
4 | const authors = await chat.authors.getMany(...authorIds); |
利用できるテーブル
Chat
は次のテーブルを提供します。取得や監視、キャッシュなどの詳しい操作方法はテーブル を参照してください。
| プロパティ | データ | 内容 |
chat.messages
| Models.Message
| チャットメッセージ |
chat.authors
| Models.Author
| 投稿者 |
chat.channels
| Models.Channel
| 接続対象のチャンネル |
chat.providers
| Models.Provider
| YouTubeなどのチャットプロバイダー |
chat.rooms
| Models.Room
| 配信枠と接続状態 |
chat.votes
| Models.Vote
| 配信内の投票 |
チャンネルを追加する
createChannelTree(url)
でURLに対応するチャンネルを検索し、追加候補を取得できます。実際に接続対象へ追加するには、取得したチャンネルをchat.channels
へ追加します。
1 | const channels = await chat.createChannelTree( |
2 | 'https://www.youtube.com/@example', |
3 | ); |
4 |
|
5 | if (channels.length > 0) { |
6 | await chat.channels.add(...channels); |
7 | } |
追加済みか確認する場合は、チャンネルの識別子を使います。
1 | for (const channel of channels) { |
2 | const added = await chat.channels.has(channel.id.key()); |
3 | console.log(channel.name, added); |
4 | } |
リアクション
リアクションはchat.reactionSignal
から送受信できます。
1 | import { Models } from '@omujs/chat'; |
2 |
|
3 | chat.reactionSignal.listen((reaction) => { |
4 | console.log(reaction.roomId, reaction.reactions); |
5 | }); |
6 |
|
7 | await chat.reactionSignal.notify(new Models.Reaction({ |
8 | roomId, |
9 | reactions: { |
10 | '👍': 1, |
11 | }, |
12 | })); |