| | "use client" |
| |
|
| | import AgoraRTM, { type RTMClient, type RTMStreamChannel } from "agora-rtm" |
| | import { AGEventEmitter } from "../events" |
| | import { apiGenAgoraData } from "@/common" |
| | import { type IRTMTextItem, ERTMTextType } from "@/types" |
| |
|
| | export interface IRtmEvents { |
| | rtmMessage: (text: any) => void |
| | } |
| |
|
| | export type TRTMMessageEvent = { |
| | channelType: "STREAM" | "MESSAGE" | "USER" |
| | channelName: string |
| | topicName?: string |
| | messageType: "STRING" | "BINARY" |
| | customType?: string |
| | publisher: string |
| | message: string | Uint8Array |
| | timestamp: number |
| | } |
| |
|
| | export class RtmManager extends AGEventEmitter<IRtmEvents> { |
| | private _joined: boolean |
| | _client: RTMClient | null |
| | channel: string = "" |
| | userId: number = 0 |
| | appId: string = "" |
| | token: string = "" |
| |
|
| | constructor() { |
| | super() |
| | this._joined = false |
| | this._client = null |
| | } |
| |
|
| | async init({ |
| | channel, |
| | userId, |
| | appId, |
| | token, |
| | }: { |
| | channel: string |
| | userId: number |
| | appId: string |
| | token: string |
| | }) { |
| | if (this._joined) { |
| | return |
| | } |
| | this.channel = channel |
| | this.userId = userId |
| | this.appId = appId |
| | this.token = token |
| | const rtm = new AgoraRTM.RTM(appId, String(userId), { |
| | logLevel: "debug", |
| | |
| | }) |
| | await rtm.login({ token }) |
| | try { |
| | |
| | const subscribeResult = await rtm.subscribe(channel, { |
| | withMessage: true, |
| | withPresence: true, |
| | beQuiet: false, |
| | withMetadata: true, |
| | withLock: true, |
| | }) |
| | console.log("[RTM] Subscribe Message Channel success!: ", subscribeResult) |
| |
|
| | this._joined = true |
| | this._client = rtm |
| |
|
| | |
| | this._listenRtmEvents() |
| | } catch (status) { |
| | console.error("Failed to Create/Join Message Channel", status) |
| | } |
| | } |
| |
|
| | private _listenRtmEvents() { |
| | this._client!.addEventListener("message", this.handleRtmMessage.bind(this)) |
| | |
| | this._client!.addEventListener( |
| | "presence", |
| | this.handleRtmPresence.bind(this), |
| | ) |
| | console.log("[RTM] Listen RTM events success!") |
| | } |
| |
|
| | async handleRtmMessage(e: TRTMMessageEvent) { |
| | console.log("[RTM] [TRTMMessageEvent] RAW", JSON.stringify(e)) |
| | const { message, messageType } = e |
| | if (messageType === "STRING") { |
| | const msg: IRTMTextItem = JSON.parse(message as string) |
| | if (msg) { |
| | console.log("[RTM] Emitting rtmMessage event with msg:", msg) |
| | this.emit("rtmMessage", msg) |
| | } |
| | } |
| | if (messageType === "BINARY") { |
| | const decoder = new TextDecoder("utf-8") |
| | const decodedMessage = decoder.decode(message as Uint8Array) |
| | const msg: IRTMTextItem = JSON.parse(decodedMessage) |
| | this.emit("rtmMessage", msg) |
| | } |
| | } |
| |
|
| | async handleRtmPresence(e: any) { |
| | console.log("[RTM] [TRTMPresenceEvent] RAW", JSON.stringify(e)) |
| | } |
| |
|
| | async sendText(text: string) { |
| | const msg: IRTMTextItem = { |
| | is_final: true, |
| | ts: Date.now(), |
| | text, |
| | type: ERTMTextType.INPUT_TEXT, |
| | stream_id: String(this.userId), |
| | } |
| | await this._client?.publish(this.channel, JSON.stringify(msg), { |
| | customType: "PainTxt", |
| | }) |
| | this.emit("rtmMessage", msg) |
| | } |
| |
|
| | async destroy() { |
| | |
| | this._client?.removeEventListener( |
| | "message", |
| | this.handleRtmMessage.bind(this), |
| | ) |
| | this._client?.removeEventListener( |
| | "presence", |
| | this.handleRtmPresence.bind(this), |
| | ) |
| | |
| | await this._client?.unsubscribe(this.channel) |
| | |
| | await this._client?.logout() |
| |
|
| | this._client = null |
| | this._joined = false |
| | } |
| | } |
| |
|
| | export const rtmManager = new RtmManager() |
| |
|