From ad20fbcdae25540b542ae75a47467df64006e976 Mon Sep 17 00:00:00 2001 From: freddysundowner Date: Fri, 20 Oct 2023 11:51:21 +0300 Subject: [PATCH 1/4] adding broadcast using agora rtm --- .../videoMeetingControllerComp.tsx | 115 +- .../meetingComp/videoMeetingStreamComp.tsx | 14 +- .../packages/lowcoder/src/i18n/locales/en.ts | 2 + node_modules/.package-lock.json | 25 + node_modules/agora-rtm-sdk/index.d.ts | 1960 +++++++++++++++++ node_modules/agora-rtm-sdk/index.js | 8 + node_modules/agora-rtm-sdk/package.json | 10 + package-lock.json | 43 + package.json | 1 + yarn.lock | 13 +- 10 files changed, 2172 insertions(+), 19 deletions(-) create mode 100644 node_modules/.package-lock.json create mode 100644 node_modules/agora-rtm-sdk/index.d.ts create mode 100644 node_modules/agora-rtm-sdk/index.js create mode 100644 node_modules/agora-rtm-sdk/package.json create mode 100644 package-lock.json diff --git a/client/packages/lowcoder/src/comps/comps/meetingComp/videoMeetingControllerComp.tsx b/client/packages/lowcoder/src/comps/comps/meetingComp/videoMeetingControllerComp.tsx index 11dc31d65..48e2f63a0 100644 --- a/client/packages/lowcoder/src/comps/comps/meetingComp/videoMeetingControllerComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/meetingComp/videoMeetingControllerComp.tsx @@ -52,6 +52,7 @@ import AgoraRTC, { import { JSONValue } from "@lowcoder-ee/index.sdk"; import { getData } from "../listViewComp/listViewUtils"; +import AgoraRTM, { RtmChannel, RtmClient, RtmMessage } from "agora-rtm-sdk"; const EventOptions = [closeEvent] as const; @@ -105,6 +106,8 @@ let audioTrack: IMicrophoneAudioTrack; let videoTrack: ICameraVideoTrack; let screenShareStream: ILocalVideoTrack; let userId: UID | null | undefined; +let rtmChannelResponse: RtmChannel; +let rtmClient: RtmClient; const turnOnCamera = async (flag?: boolean) => { if (videoTrack) { @@ -119,8 +122,6 @@ const turnOnMicrophone = async (flag?: boolean) => { return audioTrack.setEnabled(flag!); } audioTrack = await AgoraRTC.createMicrophoneAudioTrack(); - // audioTrack.play(); - if (!flag) { await client.unpublish(audioTrack); } else { @@ -141,7 +142,7 @@ const shareScreen = async (sharing: boolean) => { "disable" ); await client.unpublish(videoTrack); - screenShareStream.play(userId + ""); + screenShareStream.play("share-screen"); await client.publish(screenShareStream); } } catch (error) { @@ -158,6 +159,7 @@ const leaveChannel = async () => { await turnOnMicrophone(false); } await client.leave(); + await rtmChannelResponse.leave(); }; const hostChanged = (users: any) => {}; @@ -167,6 +169,8 @@ const publishVideo = async (appId: any, channel: any, height: any) => { await client.join(appId, channel, null, userId); await client.publish(videoTrack); + await rtmInit(appId, userId, channel); + const mediaStreamTrack = videoTrack.getMediaStreamTrack(); if (mediaStreamTrack) { const videoSettings = mediaStreamTrack.getSettings(); @@ -177,6 +181,57 @@ const publishVideo = async (appId: any, channel: any, height: any) => { } }; +const sendMessageRtm = (message: any) => { + rtmChannelResponse + .sendMessage({ text: JSON.stringify(message) }) + .then(() => { + console.log("message sent " + JSON.stringify(message)); + }) + .catch((e: any) => { + console.log("error", e); + }); +}; + +const sendPeerMessageRtm = (message: any, toId: string) => { + rtmClient + .sendMessageToPeer({ text: JSON.stringify(message) }, toId) + .then(() => { + console.log("message sent " + JSON.stringify(message)); + }) + .catch((e: any) => { + console.log("error", e); + }); +}; + +const rtmInit = async (appId: any, uid: any, channel: any) => { + rtmClient = AgoraRTM.createInstance(appId); + let options = { + uid: String(uid), + }; + await rtmClient.login(options); + + rtmClient.on("ConnectionStateChanged", function (state, reason) { + console.log("State changed To: " + state + " Reason: " + reason); + }); + + rtmChannelResponse = rtmClient.createChannel(channel); + + await rtmChannelResponse.join().then(async () => { + console.log( + "You have successfully joined channel " + rtmChannelResponse.channelId + ); + }); + + // Display channel member stats + rtmChannelResponse.on("MemberJoined", function (memberId) { + console.log(memberId + " joined the channel"); + }); + // Display channel member stats + rtmChannelResponse.on("MemberLeft", function (memberId) { + console.log(memberId + " left the channel"); + }); +}; + export const meetingControllerChildren = { visible: booleanExposingStateControl("visible"), onEvent: eventHandlerControl(EventOptions), @@ -199,6 +254,7 @@ export const meetingControllerChildren = { usersScreenShared: stateComp([]), localUser: jsonObjectExposingStateControl(""), meetingName: stringExposingStateControl("meetingName"), + messages: stateComp([]), }; let MTComp = (function () { return new ContainerCompBuilder( @@ -222,6 +278,7 @@ let MTComp = (function () { [dispatch, isTopBom] ); const [userIds, setUserIds] = useState([]); + const [rtmMessages, setRtmMessages] = useState([]); useEffect(() => { dispatch( @@ -238,6 +295,28 @@ let MTComp = (function () { } }, [props.endCall.value]); + useEffect(() => { + if (rtmChannelResponse) { + rtmClient.on("MessageFromPeer", function (message, peerId) { + console.log("Message from: " + peerId + " Message: " + message.text); + setRtmMessages((messages: any) => [...messages, message.text]); + console.log("messages " + rtmMessages); + dispatch( + changeChildAction("messages", getData(rtmMessages).data, false) + ); + }); + rtmChannelResponse.on("ChannelMessage", function (message, memberId) { + console.log("Message received from: " + memberId, message.text); + setRtmMessages((messages: any) => [...messages, message.text]); + dispatch( + changeChildAction("messages", getData(rtmMessages).data, false) + ); + }); + } + }, [rtmChannelResponse]); + + console.log("rtmMessages ", props.messages); + useEffect(() => { client.on("user-joined", (user: IAgoraRTCRemoteUser) => { let userData = { @@ -429,7 +508,6 @@ MTComp = withMethodExposing(MTComp, [ } else { await turnOnCamera(value); } - comp.children.videoControl.change(value); }, }, @@ -454,6 +532,30 @@ MTComp = withMethodExposing(MTComp, [ ); }, }, + { + method: { + name: "broadCast", + description: trans("meeting.broadCast"), + params: [], + }, + execute: async (comp, values) => { + let message = { + time: new Date().getMilliseconds(), + from: comp.children.localUser.getView(), + }; + console.log(values); + + if (values != undefined && values[0] !== undefined) { + let peers = values?.map((u: any) => u.user); + peers.forEach((p) => { + sendPeerMessageRtm(message, String(p)); + }); + } else { + sendMessageRtm(message); + } + comp.children.messages.getView(); + }, + }, { method: { name: "endMeeting", @@ -484,8 +586,5 @@ export const VideoMeetingControllerComp = withExposingConfigs(MTComp, [ new NameConfig("localUser", trans("meeting.host")), new NameConfig("participants", trans("meeting.participants")), new NameConfig("meetingName", trans("meeting.meetingName")), + new NameConfig("messages", trans("meeting.meetingName")), ]); - -export function agoraClient() { - return client; -} diff --git a/client/packages/lowcoder/src/comps/comps/meetingComp/videoMeetingStreamComp.tsx b/client/packages/lowcoder/src/comps/comps/meetingComp/videoMeetingStreamComp.tsx index d468b637d..b50cd8f19 100644 --- a/client/packages/lowcoder/src/comps/comps/meetingComp/videoMeetingStreamComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/meetingComp/videoMeetingStreamComp.tsx @@ -28,9 +28,7 @@ import { RefControl } from "comps/controls/refControl"; import { useEffect, useRef, useState } from "react"; import { AutoHeightControl } from "comps/controls/autoHeightControl"; -import { - client, -} from "./videoMeetingControllerComp"; +import { client } from "./videoMeetingControllerComp"; import { IAgoraRTCRemoteUser } from "agora-rtc-sdk-ng"; @@ -60,7 +58,7 @@ const Container = styled.div<{ $style: any }>` display: flex; align-items: center; justify-content: center; -`; +`; const VideoContainer = styled.video<{ $style: any }>` height: 100%; width: 100%; @@ -154,6 +152,7 @@ const typeOptions = [ export const meetingStreamChildren = { autoHeight: withDefault(AutoHeightControl, "fixed"), + shareScreen: withDefault(BoolCodeControl, false), type: dropdownControl(typeOptions, ""), onEvent: MeetingEventHandlerControl, disabled: BoolCodeControl, @@ -246,8 +245,6 @@ let VideoCompBuilder = (function (props) { } }, [props.userId.value]); - - return ( {(editorState) => ( @@ -257,7 +254,7 @@ let VideoCompBuilder = (function (props) { onClick={() => props.onEvent("videoClicked")} ref={videoRef} $style={props.style} - id={userId} + id={props.shareScreen ? "share-screen" : userId} > @@ -270,6 +267,9 @@ let VideoCompBuilder = (function (props) {
{children.userId.propertyView({ label: trans("meeting.videoId") })} {children.autoHeight.getPropertyView()} + {children.shareScreen.propertyView({ + label: trans("meeting.shareScreen"), + })}
{children.onEvent.getPropertyView()} diff --git a/client/packages/lowcoder/src/i18n/locales/en.ts b/client/packages/lowcoder/src/i18n/locales/en.ts index 2869d3183..2811ea488 100644 --- a/client/packages/lowcoder/src/i18n/locales/en.ts +++ b/client/packages/lowcoder/src/i18n/locales/en.ts @@ -1448,6 +1448,7 @@ export const en = { top: "Top", host: "Host", participants: "Participants", + shareScreen: "Share Screen", appid: "Application Id", meetingName: "Meeting Name", right: "Right", @@ -1462,6 +1463,7 @@ export const en = { width: "Drawer width", height: "Drawer height", actionBtnDesc: "Action Button", + broadCast: "BroadCast Messages", title: "Meeting title", meetingCompName: "Meeting Controller", videoCompName: "Video Stream", diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json new file mode 100644 index 000000000..bed96b9b8 --- /dev/null +++ b/node_modules/.package-lock.json @@ -0,0 +1,25 @@ +{ + "name": "lowcoder-1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "node_modules/agora-rtm-sdk": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/agora-rtm-sdk/-/agora-rtm-sdk-1.5.1.tgz", + "integrity": "sha512-4zMZVijEOTimIaY4VUS6kJxg7t+nTV3Frtt01Ffs6dvkOrPmpeuCu/1MX88QgAOE04IBiLo0l89ysc+woVn2FA==" + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + } + } +} diff --git a/node_modules/agora-rtm-sdk/index.d.ts b/node_modules/agora-rtm-sdk/index.d.ts new file mode 100644 index 000000000..9320f0220 --- /dev/null +++ b/node_modules/agora-rtm-sdk/index.d.ts @@ -0,0 +1,1960 @@ +declare namespace RtmStatusCode { + enum ConnectionChangeReason { + LOGIN = "LOGIN", + LOGIN_SUCCESS = "LOGIN_SUCCESS", + LOGIN_FAILURE = "LOGIN_FAILURE", + LOGIN_TIMEOUT = "LOGIN_TIMEOUT", + INTERRUPTED = "INTERRUPTED", + LOGOUT = "LOGOUT", + BANNED_BY_SERVER = "BANNED_BY_SERVER", + REMOTE_LOGIN = "REMOTE_LOGIN", + TOKEN_EXPIRED = "TOKEN_EXPIRED" + } + enum ConnectionState { + DISCONNECTED = "DISCONNECTED", + CONNECTING = "CONNECTING", + CONNECTED = "CONNECTED", + RECONNECTING = "RECONNECTING", + ABORTED = "ABORTED" + } + enum LocalInvitationState { + IDLE = "IDLE", + SENT_TO_REMOTE = "SENT_TO_REMOTE", + RECEIVED_BY_REMOTE = "RECEIVED_BY_REMOTE", + ACCEPTED_BY_REMOTE = "ACCEPTED_BY_REMOTE", + REFUSED_BY_REMOTE = "REFUSED_BY_REMOTE", + CANCELED = "CANCELED", + FAILURE = "FAILURE" + } + enum RemoteInvitationState { + INVITATION_RECEIVED = "INVITATION_RECEIVED", + ACCEPT_SENT_TO_LOCAL = "ACCEPT_SENT_TO_LOCAL", + REFUSED = "REFUSED", + ACCEPTED = "ACCEPTED", + CANCELED = "CANCELED", + FAILURE = "FAILURE" + } + enum LocalInvitationFailureReason { + UNKNOWN = "UNKNOWN", + PEER_NO_RESPONSE = "PEER_NO_RESPONSE", + INVITATION_EXPIRE = "INVITATION_EXPIRE", + PEER_OFFLINE = "PEER_OFFLINE", + NOT_LOGGEDIN = "NOT_LOGGEDIN" + } + enum RemoteInvitationFailureReason { + UNKNOWN = "UNKNOWN", + PEER_OFFLINE = "PEER_OFFLINE", + ACCEPT_FAILURE = "ACCEPT_FAILURE", + INVITATION_EXPIRE = "INVITATION_EXPIRE" + } + enum PeerOnlineState { + ONLINE = "ONLINE", + UNREACHABLE = "UNREACHABLE", + OFFLINE = "OFFLINE" + } + enum PeerSubscriptionOption { + ONLINE_STATUS = "ONLINE_STATUS" + } + enum MessageType { + TEXT = "TEXT", + RAW = "RAW" + } + enum LegacyAreaCode { + CN = "CN", + NA = "NA", + EU = "EU", + AS = "AS", + JP = "JP", + IN = "IN", + GLOB = "GLOB", + OC = "OC", + SA = "SA", + AF = "AF", + OVS = "OVS" + } + enum AreaCode { + GLOBAL = "GLOBAL", + INDIA = "INDIA", + JAPAN = "JAPAN", + ASIA = "ASIA", + EUROPE = "EUROPE", + CHINA = "CHINA", + NORTH_AMERICA = "NORTH_AMERICA" + } +} + +/** @zh-cn + * 管理频道属性。 + */ +/** + * Manages channel attributes. + */ +interface ChannelAttributeProperties { + /** @zh-cn + * 频道属性的属性值。长度不得超过 8 KB。 + */ + /** + * The value of the channel attribute. Must not exceed 8 KB in length. + */ + value: string; + + /** @zh-cn + * 最近一次更新频道属性用户的 ID。 + */ + /** + * User ID of the user who makes the latest update to the channel attribute. + */ + lastUpdateUserId: string; + + /** @zh-cn + * 频道属性最近一次更新的时间戳(毫秒)。 + */ + /** + * Timestamp of when the channel attribute was last updated in milliseconds. + */ + lastUpdateTs: number; +} + +/** @zh-cn + * 定义属性。 + */ +/** + * Defines attributes. + */ +interface AttributesMap { + + /** @zh-cn + * 属性名和属性值,以键值对形式表示。单个属性值的长度不得超过 8 KB。单个属性名长度不得超过 32 字节。 + */ + /** + * Attribute name and attribute value in the form of a key value pair. The total length of an attribute value must not exceed 8 KB. The length of a single attribute name must not exceed 32 bytes. + */ + [key: string]: string; +} +/** @zh-cn + * 定义频道属性。 + */ +/** + * Defines channel attributes. + */ +interface ChannelAttributes { + /** @zh-cn + * 频道属性名和频道属性健值对。 + */ + [key: string]: ChannelAttributeProperties; +} + +/** @zh-cn + * 维护频道属性操作相关选项。 + */ +/** + * An interface for setting and getting channel attribute options. + */ +interface ChannelAttributeOptions { + /** @zh-cn + * 是否通知所有频道成员本次频道属性变更。该标志位仅对本次 API 调用有效: + * + * - `true`: 通知所有频道成员本次频道属性变更。 + * - `false`: (默认) 不通知所有频道成员本次频道属性变更。 + */ + /** + * Indicates whether or not to notify all channel members of a channel attribute change. This flag is valid only within the current method call: + * + * - `true`: Notify all channel members of a channel attribute change. + * - `false`: (Default) Do not notify all channel members of a channel attribute change. + */ + enableNotificationToChannelMembers?: boolean; +} + +/** @hidden */ +declare type ListenerType = [T] extends [(...args: infer U) => any] + ? U + : [T] extends [void] + ? [] + : [T]; +/** @hidden */ +declare class EventEmitter { + static defaultMaxListeners: number; + on

( + this: T, + event: P, + listener: (...args: ListenerType) => void + ): this; + + once

( + this: T, + event: P, + listener: (...args: ListenerType) => void + ): this; + + off

( + this: T, + event: P, + listener: (...args: any[]) => any + ): this; + + removeAllListeners

(this: T, event?: P): this; + listeners

(this: T, event: P): Function[]; + rawListeners

(this: T, event: P): Function[]; + listenerCount

(this: T, event: P): number; +} + +/** @zh-cn + * 文本消息接口,用于发送和接收文本消息。你可以调用 {@link RtmClient.sendMessageToPeer} 或 {@link RtmChannel.sendMessage} 发送点对点类型或频道类型的文本消息。 + */ +/** + * Interface for text messages. You can use this interface to send and receive text messages. You can call {@link RtmClient.sendMessageToPeer} or {@link RtmChannel.sendMessage} to send a peer-to-peer or channel text message. + */ +interface RtmTextMessage { + /** @zh-cn + * 文本消息的内容。最大长度为 32 KB。 + *

Note

+ * 文本消息和文字描述的总大小不能超过 32 KB。 + */ + /** + * Content of the text message. The maximum length is 32 KB. + *

Note

+ * The maximum total length of the text message and the description is 32 KB. + */ + text: string; + + /** @zh-cn + * 消息类型。`TEXT` 代表文本消息。 + */ + /** + * Message type. `TEXT` stands for text messages. + * + */ + messageType?: 'TEXT'; + /** @hidden */ + rawMessage?: never; + /** @hidden */ + description?: never; +} + +/** @zh-cn + * 二进制消息接口,用于发送和接收二进制消息。你可以调用 {@link RtmClient.sendMessageToPeer} 或 {@link RtmChannel.sendMessage} 发送点对点或频道的二进制消息。 + */ +/** + * Interface for raw messages. You can use this interface to send and receive raw messages. You can call {@link RtmClient.sendMessageToPeer} or {@link RtmChannel.sendMessage} to send a peer-to-peer or channel raw message. + */ +interface RtmRawMessage { + /** @zh-cn + * 二进制消息的内容。最大长度为 32 KB。 + *

Note

+ * 二进制消息和文字描述的总大小不能超过 32 KB。 + */ + /** + * Content of the raw message in binary format. The maximum length is 32 KB. + *

Note

+ * The maximum total length of the raw message and the description is 32 KB. + */ + rawMessage: Uint8Array; + + /** @zh-cn + * 二进制消息的文字描述。最大长度为 32 KB。 + *

Note

+ * 二进制消息和文字描述的总大小不能超过 32 KB。 + */ + /** + * Description of the raw message. The maximum length is 32 KB. + *

Note

+ * The maximum total length of the raw message and the description is 32 KB. + */ + description?: string; + + /** @zh-cn + * 消息类型。`RAW` 代表二进制消息。 + */ + /** + * Message type. `RAW` stands for raw messages. + * + */ + messageType?: 'RAW'; + /** @hidden */ + text?: never; +} + + +/** @zh-cn + * 用于表示 RTM 消息的类型别名。RtmMessage 可以是文本消息 {@link RtmTextMessage} ,自定义二进制消息 {@link RtmRawMessage}。 + */ +/** + * Type alias for RTM messages. RtmMessage can be either {@link RtmTextMessage} , {@link RtmRawMessage}. + */ +type RtmMessage = + | RtmTextMessage + | RtmRawMessage; + +/** @zh-cn + * 用于表示点对点消息发送结果的接口。 + */ +/** + * Interface for the result of delivering the peer-to-peer message. + */ +interface PeerMessageSendResult { + /** @zh-cn + * 该布尔值属性代表消息接收方是否已收到发出的消息。 + * + * - `true`: 点对点消息发送成功,对方已收到; + * - `false`: 对方不在线,未收到该消息。 + * + */ + /** + * This boolean property indicates whether the remote peer user receives the sent message. + * + * - `true`: the peer user receives the message. + * - `false`: the peer user is offline and does not receive the message. + * + */ + hasPeerReceived: boolean; +} + + + +/** @zh-cn + * 用于管理已接收消息属性的接口。 + */ +/** + * Interface for properties of received messages. + */ +interface ReceivedMessageProperties { + /** @zh-cn + * 消息服务器接收到消息的时间戳,单位为毫秒。 + * + *

Note

+ * + *
  • 你不能设置时间戳,但是你可以从该时间戳推断出消息的大致发送时间。
  • + *
  • 时间戳的精度为毫秒。仅用于展示,不建议用于消息的严格排序。
  • + */ + /** + * The timestamp (ms) of when the messaging server receives this message. + * + *

    Note

    + * + *
  • You cannot set this returned timestamp, but you can infer from it the approximate time as to when this message was sent.
  • + *
  • The returned timestamp is on a millisecond time-scale. It is for demonstration purposes only, not for strict ordering of messages.
  • + */ + serverReceivedTs: number; +} + +interface PeersOnlineStatusMap { + [peerId: string]: RtmStatusCode.PeerOnlineState; +} + +declare namespace RtmEvents { + /** @zh-cn + * {@link RtmChannel} 实例上的事件类型。 + * 该接口中,函数属性的名称为事件名称,函数的参数为事件监听回调的传入参数。 + * + * @example **监听频道消息** + * + * ```JavaScript + * channel.on('ChannelMessage', function (message, memberId) { + * // 你的代码:收到频道消息。 + * }); + * ``` + * @example **监听用户加入频道事件** + * + * ```JavaScript + * channel.on('MemberJoined', memberId => { + * // 你的代码:用户已加入频道。 + * }) + * ``` + * @example **监听用户离开频道事件** + * + * ```JavaScript + * channel.on('MemberLeft', memberId => { + * // 你的代码:用户已离开频道。 + * }); + * ``` + */ + /** + * Event types of the {@link RtmChannel} instance. + * In this interface, the function property’s name is the event name; the function property’s parameters is the parameters of the event listener function. + * + * @example **Listening to channel messages.** + * + * ```JavaScript + * channel.on('ChannelMessage', function (message, memberId) { + * // Your code. + * }); + * ``` + * @example **Listening to events, such as a user joining the channel.** + * + * ```JavaScript + * channel.on('MemberJoined', memberId => { + * // Your code. + * }) + * ``` + * @example **Listening to events, such as a member leaving the channel** + * + * ```JavaScript + * channel.on('MemberLeft', memberId => { + * // Your code. + * }); + * ``` + */ + export interface RtmChannelEvents { + /** @zh-cn + * 收到频道消息的事件通知。 + * @event + * @param message 接收到的频道消息对象。 + * @param memberId 该频道消息的发送者 uid。 + */ + /** + * Occurs when the local user receives a channel message. + * @event + * @param message The received channel message object. + * @param memberId The uid of the sender. + */ + ChannelMessage: ( + message: RtmMessage, + memberId: string, + messagePros: ReceivedMessageProperties + ) => void; + + /** @zh-cn + * 收到用户离开频道的通知。 + * + * 用户调用 `leave` 方法离开频道或者由于网络原因与 Agora RTM 系统断开连接达到 30 秒都会触发此回调。 + * + * 当频道成员超过 512 时,该回调失效。 + * @event + * @param memberId 离开频道的远端用户的 uid。 + */ + /** + * Occurs when a user leaves the channel. + * + * This callback is triggered when the user calls `leave` to leave a channel or the user stays disconnected with the Agora RTM system for 30 seconds due to network issues. + * + *

    Note

    + * This callback is disabled when the number of the channel members exceeds 512. + * @event + * @param memberId The uid of the user leaving the channel. + */ + MemberLeft: (memberId: string) => void; + + /** @zh-cn + * 收到用户加入频道的通知。 + *

    Note

    + * 当频道成员超过 512 时,该回调失效。 + * @event + * @param memberId 加入频道的用户的 uid。 + */ + /** + * Occurs when a user joins a channel. + *

    Note

    + * This callback is disabled when the number of the channel members exceeds 512. + * @event + * @param memberId The uid of the user joining the channel. + */ + MemberJoined: (memberId: string) => void; + + /** @zh-cn + * 频道属性更新回调。返回所在频道的所有属性。 + * + *

    Note

    + * 只有当频道属性更新者将 {@link enableNotificationToChannelMembers} 设为 `true` 后,该回调才会被触发。请注意:该标志位仅对当前频道属性操作有效。 + * @event + */ + /** + * Occurs when channel attributes are updated, and returns all attributes of the channel. + * + *

    Note

    + * This callback is enabled only when the user, who updates the attributes of the channel, sets {@link enableNotificationToChannelMembers} as true. Also note that this flag is valid only within the current channel attribute method call. + * @event + */ + AttributesUpdated: (attributes: ChannelAttributes) => void; + /** @zh-cn + * 收到频道人数变化通知。 + * @event + */ + + /** @zh-cn + * 频道成员人数更新回调。返回最新频道成员人数。 + * + *

    Note

    + * + *
  • 频道成员人数 ≤ 512 时,触发频率为每秒 1 次。
  • + *
  • 频道成员人数超过 512 时,触发频率为每 3 秒 1 次。
  • + *
  • 用户在成功加入频道时会收到该回调。你可以通过监听该回调获取加入频道时的频道成员人数和后继人数更新。
  • + * @event + * @param memberCount 最新频道成员人数。 + */ + /** + * Occurs when the number of the channel members changes, and returns the new number. + * + *

    Note

    + * + *
  • When the number of channel members ≤ 512, the SDK returns this callback when the number changes at a frequency of once per second.
  • + *
  • When the number of channel members exceeds 512, the SDK returns this callback when the number changes at a frequency of once every three seconds.
  • + *
  • You will receive this callback when successfully joining an RTM channel, so we recommend implementing this callback to receive timely updates on the number of the channel members.
  • + * @event + * @param memberCount Member count of this channel. + */ + MemberCountUpdated: (memberCount: number) => void; + } + + /** @zh-cn + * {@link RemoteInvitation} 实例上的事件类型。 + */ + /** + * Event types of the {@link RemoteInvitation} instance. + */ + export interface RemoteInvitationEvents { + /** @zh-cn + * 返回给被叫:主叫已取消呼叫邀请。 + */ + /** + * Callback to the callee: occurs when the caller cancels the call invitation. + */ + RemoteInvitationCanceled: (content: string) => void; + + /** @zh-cn + * 返回给被叫:拒绝呼叫邀请成功。 + */ + /** + * Callback for the callee: occurs when the callee successfully declines the incoming call invitation. + */ + RemoteInvitationRefused: () => void; + + /** @zh-cn + * 返回给被叫:接受呼叫邀请成功。 + */ + /** + * Callback to the callee: occurs when the callee accepts a call invitation. + */ + RemoteInvitationAccepted: () => void; + + /** @zh-cn + * 返回给被叫:呼叫邀请进程失败。 + * @param reason 呼叫邀请失败原因。详见: {@link RemoteInvitationFailureReason} 。 + */ + /** + * Callback to the callee: occurs when the life cycle of the incoming call invitation ends in failure. + * + * @param reason See: {@link RemoteInvitationFailureReason}. + */ + RemoteInvitationFailure: ( + reason: RtmStatusCode.RemoteInvitationFailureReason + ) => void; + } + + /** @zh-cn + * {@link LocalInvitation} 实例上的事件类型。 + */ + /** + * Event types of the {@link LocalInvitation} instance. + */ + export interface LocalInvitationEvents { + /** @zh-cn + * 返回给主叫:被叫已接受呼叫邀请。 + * + * @param response 被叫设置的响应内容。 + */ + /** + * Callback to the caller: occurs when the callee accepts the call invitation. + * + * @param response The response from the callee. + */ + LocalInvitationAccepted: (response: string) => void; + /** @zh-cn + * 返回给主叫:被叫已拒绝呼叫邀请。 + * @param response 被叫设置的响应内容。 + */ + /** + * Callback to the caller: occurs when the callee refuses the call invitation. + * @param response The response from the callee. + */ + LocalInvitationRefused: (response: string) => void; + /** @zh-cn + * 返回给主叫:被叫已收到呼叫邀请。 + */ + /** + * Callback to the caller: occurs when the callee receives the call invitation. + * + * This callback notifies the caller that the callee receives the call invitation. + */ + LocalInvitationReceivedByPeer: () => void; + /** @zh-cn + * 返回给主叫:呼叫邀请已被成功取消。 + */ + /** + * Callback to the caller: occurs when the caller cancels a call invitation. + * This callback notifies the caller that he/she has canceled a call invitation. + */ + LocalInvitationCanceled: () => void; + /** @zh-cn + * 返回给主叫:呼叫邀请进程失败。 + * + * @param reason 呼叫邀请的失败原因。详见: {@link LocalInvitationFailureReason} 。 + */ + /** + * Callback to the caller: occurs when the outgoing call invitation ends in failure. + * + * @param reason See: {@link LocalInvitationFailureReason}. + */ + LocalInvitationFailure: ( + reason: RtmStatusCode.LocalInvitationFailureReason + ) => void; + } + + /** @zh-cn + * {@link RtmClient} 实例上的事件类型。 + * 该接口中,函数属性的名称为事件名称,函数的参数为事件监听回调的传入参数。 + * + * @example **监听点对点消息** + * + * ```JavaScript + * client.on('MessageFromPeer', function (message, peerId) { + * // Your code. + * }); + * ``` + */ + /** + * Event listener type of the {@link RtmClient} instance. + * In this interface, the function property’s name is the event name; the function property’s parameters is the parameters of the event listener function. + * + * @example **Listening to peer-to-peer messages.** + * + * ```JavaScript + * client.on('MessageFromPeer', function (message, peerId) { + * // Your code. + * }); + * ``` + */ + export interface RtmClientEvents { + /** @zh-cn + * 收到来自对端的点对点消息。 + * @event + * @param message 远端用户发送的消息对象。 + * @param peerId 发送该消息的远端用户 uid。 + * @param messageProps 接收到的消息的属性。 + */ + /** + * Occurs when the local user receives a peer-to-peer message from a remote user. + * @event + * @param message The received peer-to-peer message object. + * @param peerId The uid of the sender. + * @param messageProps The properties of the received message. + */ + MessageFromPeer: ( + message: RtmMessage, + peerId: string, + messageProps: ReceivedMessageProperties + ) => void; + /** @zh-cn + * 通知 SDK 与 Agora RTM 系统的连接状态发生了改变。 + * @event + * @param newState 新的连接状态 + * @param reason 状态改变的原因 + */ + /** + * Occurs when the connection state changes between the SDK and the Agora RTM system. + * @event + * @param newState The new connection state. + * @param reason Reasons for the connection state change. + */ + ConnectionStateChanged: ( + newState: RtmStatusCode.ConnectionState, + reason: RtmStatusCode.ConnectionChangeReason + ) => void; + /** @zh-cn + * 收到来自主叫的呼叫邀请。 + * @event + * @param remoteInvitation 一个 {@link RemoteInvitation} 对象。 + */ + /** + * Occurs when the callee receives a call invitation from a remote user (caller). + * @event + * @param remoteInvitation A {@link RemoteInvitation} object. + */ + RemoteInvitationReceived: (remoteInvitation: RemoteInvitation) => void; + + /** @zh-cn + * (SDK 断线重连时触发)当前使用的 RTM Token 已超过 24 小时的签发有效期。 + * + * - 该回调仅会在 SDK 处于 `RECONNECTING` 状态时因 RTM 后台监测到 Token 签发有效期过期而触发。SDK 处于 `CONNECTED` 状态时该回调不会被触发。 + * - 收到该回调时,请尽快在你的业务服务端生成新的 Token 并调用 {@link renewToken} 方法把新的 Token 传给 Token 验证服务器。 + */ + /** + * Occurs when the RTM server detects that the RTM token has exceeded the 24-hour validity period and when the SDK is in the `RECONNECTING` state. + * + * - This callback occurs only when the SDK is reconnecting to the server. You will not receive this callback when the SDK is in the `CONNECTED` state. + * - When receiving this callback, generate a new RTM Token on the server and call the {@link renewToken} method to pass the new Token on to the server. + */ + TokenExpired: () => void; + + /** @zh-cn + * 当前使用的 RTM Token 登录权限还有 30 秒就会超过签发有效期。 + * + * - 收到该回调时,请尽快在你的业务服务端生成新的 Token 并调用 {@link renewToken} 方法把新的 Token 传给 Token 验证服务器。 + */ + /** + * The currently used RTM Token login permission will expire after 30 seconds. + * + * - When receiving this callback, generate a new RTM Token on the server and call the {@link renewToken} method to pass the new Token on to the server. + */ + TokenPrivilegeWillExpire: () => void; + + /** @zh-cn + * 被订阅用户在线状态改变回调。 + * + * - 首次订阅在线状态成功时,SDK 也会返回本回调,显示所有被订阅用户的在线状态。 + * - 每当被订阅用户的在线状态发生改变,SDK 都会通过该回调通知订阅方。 + * - 如果 SDK 在断线重连过程中有被订阅用户的在线状态发生改变,SDK 会在重连成功时通过该回调通知订阅方。 + */ + /** + * Occurs when the online status of the peers, to whom you subscribe, changes. + * + * - When the subscription to the online status of specified peer(s) succeeds, the SDK returns this callback to report the online status of peers, to whom you subscribe. + * - When the online status of the peers, to whom you subscribe, changes, the SDK returns this callback to report whose online status has changed. + * - If the online status of the peers, to whom you subscribe, changes when the SDK is reconnecting to the server, the SDK returns this callback to report whose online status has changed when successfully reconnecting to the server. + */ + PeersOnlineStatusChanged: (status: PeersOnlineStatusMap) => void; + + /** + * Occurs when the SDK automatically switches to proxy WebSocket of 443 port. + */ + FallbackProxyConnected: () => void; + } +} + +/** @zh-cn + * 由主叫通过 {@link createLocalInvitation} 方法创建,仅供主叫调用的呼叫邀请对象。 + * @noInheritDoc + */ +/** + * The call invitation object created by calling the {@link createLocalInvitation} method, and called only by the caller. + * @noInheritDoc + */ +declare class LocalInvitation extends EventEmitter< + RtmEvents.LocalInvitationEvents +> { + /** @zh-cn + * 被叫设置的响应内容。 + * @readonly + */ + /** + * The callee's response to the call invitation. + * @readonly + */ + readonly response: string; + + /** + * 供主叫查看的呼叫邀请状态。 + * + * 详见: {@link LocalInvitationState} 。 + * @readonly + */ + /** + * State of the outgoing call invitation. + * + * See: {@link LocalInvitationState}. + * @readonly + */ + readonly state: RtmStatusCode.LocalInvitationState; + + /** @zh-cn + * 主叫设置的呼叫邀请内容。 + * @note 最大长度为 8 KB。 + */ + /** + * Call invitation content set by the caller. + * @note The maximum length is 8 KB. + */ + content: string; + + /** @zh-cn + * 被叫的 uid。 + */ + /** + * uid of the callee. + */ + readonly calleeId: string; + + /** @zh-cn + * 主叫设置的频道 ID。 + * @note 与老信令 SDK 互通时你必须设置频道 ID。不过即使在被叫成功接受呼叫邀请后,Agora RTM SDK 也不会把主叫加入指定频道。 + */ + /** + * The channel ID set by the caller. + * @note To intercommunicate with the legacy Agora Signaling SDK, you MUST set the channel ID. However, even if the callee successfully accepts the call invitation, the Agora RTM SDK does not join the channel of the specified channel ID. + */ + channelId: string; + + /** @zh-cn + * 向指定用户(被叫)发送呼叫邀请。该方法无异步回调。如需监听 {@link LocalInvitationState} 变化,请通过 {@link on} 方法注册 {@link LocalInvitationEvents} 中的事件回调。 + */ + /** + * Send a call invitation to a specified remote user (callee). This method has no asynchronous callbacks. To listen for {@link LocalInvitationState} changes, register the event handler in {@link LocalInvitationEvents} via the {@link on} method. + */ + send(): void; + + /** @zh-cn + * 取消已发送的呼叫邀请。该方法无异步回调。如需监听 {@link LocalInvitationState} 变化,请通过 {@link on} 方法注册 {@link LocalInvitationEvents} 中的事件回调。 + */ + /** + * Allows the caller to cancel a sent call invitation. This method has no asynchronous callbacks. To listen for {@link LocalInvitationState} changes, register the event handler in {@link LocalInvitationEvents} via the {@link on} method. + */ + cancel(): void; + /** @zh-cn + * 在该频道实例上添加 `listener` 函数到名为 `eventName` 的事件。其他 `RtmChannel` 实例上的事件方法请参考 [`EventEmitter` API 文档](https://nodejs.org/docs/latest/api/events.html#events_class_eventemitter)。 + * @param eventName 频道事件的名称。事件列表请参考 {@link RtmChannelEvents} 中的属性名。 + * @param listener 事件的回调函数。 + */ + /** + * Adds the `listener` function to the channel for the event named `eventName`. See [the `EventEmitter` API documentation](https://nodejs.org/docs/latest/api/events.html#events_class_eventemitter) for other event methods on the `RtmChannel` instance. + * @param eventName The name of the channel event. See the property names in the {@link RtmChannelEvents} for the list of events. + * @param listener The callback function of the channel event. + */ + on( + eventName: EventName, + listener: ( + ...args: ListenerType + ) => any + ): this; +} + +/** @zh-cn + * 由 SDK 创建供被叫调用的呼叫邀请对象。 + * @noInheritDoc + */ +/** + * The call invitation object created by the SDK and called by the callee. + * @noInheritDoc + */ +declare class RemoteInvitation extends EventEmitter< + RtmEvents.RemoteInvitationEvents +> { + /** @zh-cn + * 供被叫获取主叫的用户 ID。 + * @readonly + */ + /** + * Allows the callee to get the channel ID. + * @readonly + */ + readonly channelId: string; + + /** @zh-cn + * 主叫的 uid。 + * @readonly + */ + /** + * uid of the caller. + * @readonly + */ + readonly callerId: string; + + /** @zh-cn + * 主叫设置的呼叫邀请内容。 + * @readonly + * @note 最大长度为 8 KB。 + */ + /** + * The call invitation content set by the caller. + * @readonly + * @note The maximum length is 8 KB. + */ + readonly content: string; + + /** @zh-cn + * 呼叫邀请的状态。详见: {@link RemoteInvitationState} 。 + * @readonly + */ + /** + * States of the incoming call invitation. See: {@link RemoteInvitationState} . + * @readonly + */ + readonly state: RtmStatusCode.RemoteInvitationState; + + /** @zh-cn + * 被叫设置的响应内容。 + * @note 最大长度为 8 KB。 + */ + /** + * Response to the incoming call invitation. + * @note The maximum length is 8 KB. + */ + response: string; + + /** @zh-cn + * 接受来自主叫的呼叫邀请。该方法无异步回调。如需监听 {@link RemoteInvitationState} 变化,请通过 {@link on} 方法注册 {@link RemoteInvitationEvents} 中的事件回调。 + */ + /** + * Allows the callee to accept an incoming call invitation. This method has no asynchronous callbacks. To listen for {@link RemoteInvitationState} changes, register the event handler in {@link RemoteInvitationEvents} via the {@link on} method. + */ + accept(): void; + + /** @zh-cn + * 拒绝来自主叫的呼叫邀请。该方法无异步回调。如需监听 {@link RemoteInvitationState} 变化,请通过 {@link on} 方法注册 {@link RemoteInvitationEvents} 中的事件回调。 + */ + /** + * Allows the callee to decline an incoming call invitation. This method has no asynchronous callbacks. To listen for {@link RemoteInvitationState} changes, register the event handler in {@link RemoteInvitationEvents} via the {@link on} method. + */ + refuse(): void; + + /** @zh-cn + * 在该频道实例上添加 `listener` 函数到名为 `eventName` 的事件。其他 `RtmChannel` 实例上的事件方法请参考 [`EventEmitter` API 文档](https://nodejs.org/docs/latest/api/events.html#events_class_eventemitter)。 + * @param eventName 频道事件的名称。事件列表请参考 {@link RtmChannelEvents} 中的属性名。 + * @param listener 事件的回调函数。 + */ + /** + * Adds the `listener` function to the channel for the event named `eventName`. See [the `EventEmitter` API documentation](https://nodejs.org/docs/latest/api/events.html#events_class_eventemitter) for other event methods on the `RtmChannel` instance. + * @param eventName The name of the channel event. See the property names in the {@link RtmChannelEvents} for the list of events. + * @param listener The callback function of the channel event. + */ + on( + eventName: EventName, + listener: ( + ...args: ListenerType + ) => any + ): this; +} + +/** @zh-cn + * RTM 频道类。你可以调用 {@link createChannel} 方法创建 RTM 频道实例。 + * @noInheritDoc + */ +/** + * Class to represent an RTM channel. You can call the {@link createChannel} method to create an RtmClient instance. + * @noInheritDoc + */ +declare class RtmChannel extends EventEmitter< + RtmEvents.RtmChannelEvents +> { + /** @zh-cn + * @readonly + * 频道实例的 ID。 + */ + /** + * @readonly + * ID of the RTM channel instance. + */ + readonly channelId: string; + + /** @zh-cn + * 发送频道消息,所有加入频道的用户都会收到该频道消息。 + * + * 发送消息(包括点对点消息和频道消息)的频率上限为 180 次每 3 秒。 + * @example **发送频道消息。** + * + * ```JavaScript + * channel.sendMessage({ text: 'test channel message' }).then(() => { + * // 你的代码:频道消息发送成功处理逻辑。 + * }).catch(error => { + * // 你的代码:频道消息发送失败处理逻辑。 + * }); + * ``` + * @note 在实际开发中,你可以将已发送的频道消息作为应用界面上的用户已发送消息。这样可以在界面中显示用户频道消息的发送状态。发送频道消息的用户本身不会收到频道消息。 + * @param message 要发送的消息实例。 + * @return 该 Promise 会在发送频道消息成功后 resolve。 + */ + /** + * Allows a user to send a message to all users in a channel. + * + * You can send messages, including peer-to-peer and channel messages at a maximum frequency of 180 calls every three seconds. + * @example **Sending a channel message.** + * + * ```JavaScript + * channel.sendMessage({ text: 'test channel message' }).then(() => { + * // Your code for handling the event when the channel message is successfully sent. + * }).catch(error => { + * // Your code for handling the event when the channel message fails to be sent. + * }); + * ``` + * @note In development, you can set the sent channel message as the sent message in the UI of your application. Thus, you can display the message status in the UI. The user who sends the channel message does not receive the same channel message. + * @param message The message instance to be sent. + * @return The Promise resolves after the user successfully sends a channel message. + */ + sendMessage( + message: RtmMessage, + ): Promise; + + /** @zh-cn + * 调用该方法加入该频道,加入频道成功后可收到该频道消息和频道用户进退通知。 + * + * 你最多可以加入 20 个频道。 + * @return 该 Promise 会在加入频道成功后 resolve。 + */ + /** + * Joins a channel. After joining the channel, the user can receive channel messages and notifications of other users joining or leaving the channel. + * + * You can join a maximum of 20 channels. + * @return The Promise resolves after the user successfully joins the channel. + */ + join(): Promise; + + /** @zh-cn + * 调用该方法离开该频道,不再接收频道消息和频道用户进退通知。 + * @return 该 Promise 会在离开频道成功后 resolve。 + */ + /** + * Leaves a channel. After leaving the channel, the user does not receive channel messages or notifications of users joining or leaving the channel. + * @return The Promise resolves after the user successfully leaves the channel. + */ + leave(): Promise; + + /** @zh-cn + * 获取频道用户列表 + * + * @return 该 Promise 会在成功获取频道用户列表后 resolve。Promise 返回的值为该频道所有用户 ID 的数组。 + */ + /** + * Gets the member list of the channel. + * + * @return The Promise resolves after the user gets the member list of the channel in an array with the channel's uids. + */ + getMembers(): Promise; + + /** @zh-cn + * 在该频道实例上添加 `listener` 函数到名为 `eventName` 的事件。其他 `RtmChannel` 实例上的事件方法请参考 [`EventEmitter` API 文档](https://nodejs.org/docs/latest/api/events.html#events_class_eventemitter)。 + * + * @param eventName 频道事件的名称。事件列表请参考 {@link RtmChannelEvents} 中的属性名。 + * @param listener 事件的回调函数。 + */ + /** + * Adds the `listener` function to the channel for the event named `eventName`. See [the `EventEmitter` API documentation](https://nodejs.org/docs/latest/api/events.html#events_class_eventemitter) for other event methods on the `RtmChannel` instance. + * + * @param eventName The name of the channel event. See the property names in the {@link RtmChannelEvents} for the list of events. + * @param listener The callback function of the channel event. + */ + on( + eventName: EventName, + listener: ( + ...args: ListenerType + ) => any + ): this; +} + +/** @zh-cn + * @hidden + */ +/** + * @hidden + */ +type LogFilterType = { + error: boolean; + warn: boolean; + info: boolean; + track: boolean; + debug: boolean; +}; + +/** @zh-cn + * {@link RtmClient} 对象的配置参数。 + * + * 可在初始化时通过 {@link createInstance} 的第 2 个参数或实例上的 {@link updateConfig} 方法进行设置。 + */ +/** + * Interface holding the configuration of an `RtmClient` instance. + * + * You can pass it as the second argument when calling the {@link createInstance} method, or use it when calling the {@link updateConfig} method. + */ +interface RtmConfig { + /** @zh-cn + * 是否上传日志。默认关闭。 + * - `true`: 启用日志上传; + * - `false`: (默认)关闭日志上传。 + */ + /** + * Whether to enable log upload. It is set to `false` by default. + * - `true`: Enable log upload, + * - `false`: (Default) Disable log upload. + */ + enableLogUpload?: boolean; + + /** @zh-cn + * 日志输出等级。 + * + * 设置 SDK 的输出日志输出等级。不同的输出等级可以单独或组合使用。日志级别顺序依次为 OFF、ERROR、WARNING 和 INFO。选择一个级别,你就可以看到在该级别之前所有级别的日志信息。例如,你选择 WARNING 级别,就可以看到在 ERROR 和 WARNING 级别上的所有日志信息。 + * + * - {@link AgoraRTM.LOG_FILTER_OFF} + * - {@link AgoraRTM.LOG_FILTER_ERROR} + * - {@link AgoraRTM.LOG_FILTER_INFO} (默认) + * - {@link AgoraRTM.LOG_FILTER_WARNING} + */ + /** + * Output log level of the SDK. + * + * You can use one or a combination of the filters. The log level follows the sequence of OFF, ERROR, WARNING, and INFO. Choose a level to see the logs preceding that level. If, for example, you set the log level to WARNING, you see the logs within levels ERROR and WARNING. + * + * - {@link AgoraRTM.LOG_FILTER_OFF} + * - {@link AgoraRTM.LOG_FILTER_ERROR} + * - {@link AgoraRTM.LOG_FILTER_INFO} (Default) + * - {@link AgoraRTM.LOG_FILTER_WARNING} + */ + logFilter?: LogFilterType; + + /** + * Whether to enable cloud proxy. + */ + enableCloudProxy?: boolean; +} + +/** @zh-cn + * 表示用户 ID/在线状态键值对的接口。 + *
      + *
    • `true`: 用户已登录到 Agora RTM 系统。
    • + *
    • `false`: 用户已登出 Agora RTM 系统或因其他原因与 Agora RTM 系统断开连接。
    • + *
    + */ +/** + * Interface for the peerId / online status key-value pair. + *
      + *
    • `true`: The user has logged in the Agora RTM system.
    • + *
    • `false`: The user has logged out of the Agora RTM system.
    • + *
    + */ +interface PeersOnlineStatusResult { + [peerId: string]: boolean; +} +/** @zh-cn + * 表示频道名/频道人数键值对的接口。 + */ +/** + * Interface for the channelId / channel member count key-value pair. + */ +interface ChannelMemberCountResult { + [channelId: string]: number; +} + +/** @zh-cn + * RTM 客户端类。你可以通过 {@link AgoraRTM} 上的 {@link createInstance} 方法创建 RTM 客户端实例。Agora RTM SDK 的入口。 + * @noInheritDoc + */ +/** + * Class that represents the RTM client. You can call the {@link createInstance} method of {@link AgoraRTM} to create an `RtmClient` instance. This class is the entry point of the Agora RTM SDK. + * @noInheritDoc + */ +declare class RtmClient extends EventEmitter { + /** @zh-cn + * 用户登录 Agora RTM 系统。 + * @note 在 RTM 和 RTC 结合使用的场景下,Agora 推荐你错时进行登录 RTM 系统和加入 RTC 频道的操作。 + * @note 如果用户在不同的 RtmClient 实例中以相同用户 ID 登录,之前的登录将会失效,用户会被踢出之前加入的频道。 + * @param options.uid 登录 Agora RTM 系统的用户 ID。该字符串不可超过 64 字节。以下为支持的字符集范围:
      + *
    • 26 个小写英文字母 a-z
    • + *
    • 26 个大写英文字母 A-Z
    • + *
    • 10 个数字 0-9
    • + *
    • 空格
    • + *
    • "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ","
    • + *
    + *

    Note

      + *
    • 请不要将 uid 设为空、null,或字符串 "null"。
    • + *
    • uid 不支持 number 类型。建议调用 toString() 方法转化非 string 型 uid。
    • + *
    + * @param options.token 可选的动态密钥,一般由客户的服务端获取。 + * @return 该 Promise 会在登录成功后 resolve。 + */ + /** + * Logs in to the Agora RTM system. + * + * @note If you use the Agora RTM SDK together with the Agora RTC SDK, Agora recommends that you avoid logging in to the RTM system and joining the RTC channel at the same time. + * @note If the user logs in with the same uid from a different instance, the user will be kicked out of your previous login and removed from previously joined channels. + * @param options.uid The uid of the user logging in the Agora RTM system. The string length must be less than 64 bytes with the following character scope:
      + *
    • All lowercase English letters: a to z
    • + *
    • All uppercase English letters: A to Z
    • + *
    • All numeric characters: 0 to 9
    • + *
    • The space character.
    • + *
    • Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ","
    • + *
    + *

    Note

      + *
    • The uid cannot be empty, or set as null or "null".
    • + *
    • We do not support uids of the number type and recommend using the toString() method to convert your non-string uid.
    • + *
    + * @param options.token An optional token generated by the app server. + * @return The Promise resolves after the user logs in to the Agora RTM system successfully. + */ + login(options: { uid: string; token?: string }): Promise; + + /** @zh-cn + * 退出登录,退出后自动断开连接和销毁回调监听。 + * @return 该 Promise 会在登出成功并断开 WebSocket 连接后 resolve。 + */ + /** + * Allows a user to log out of the Agora RTM system. + * + * After the user logs out of the Agora RTM system, the SDK disconnects from the Agora RTM system and destroys the corresponding event listener. + * @return The Promises resolves after the user logs out of the Agora RTM system and disconnects from WebSocket. + */ + logout(): Promise; + + /** @zh-cn + * 本地用户(发送者)向指定用户(接收者)发送点对点消息或点对点的离线消息。 + *

    发送消息(包括点对点消息和频道消息)的频率上限为 180 次每 3 秒。

    + * @example + * ```TypeScript + * client.sendMessageToPeer( + * { text: 'test peer message' }, // 一个 RtmMessage 实例。 + * 'PeerId', // 对端用户的 uid。 + * ).then(sendResult => { + * if (sendResult.hasPeerReceived) { + * // 你的代码:远端用户收到消息事件。 + * } else { + * // 你的代码:服务器已收到消息,对端未收到消息。 + * } + * }).catch(error => { + * // 你的代码:点对点消息发送失败。 + * }); + * ``` + * @param message 要发送的文字消息。 + * @param peerId 远端用户的 uid。 + *

    Note

    + * uid 不支持 number 类型。建议调用 toString() 方法转化非 string 型 uid。 + * @return 该 Promise 会在发送成功后 resolve。Promise 的值代表对方是否在线并接收成功。 + */ + /** + * Allows a user to send an (offline) peer-to-peer message to a specified remote user. + *

    You can send messages, including peer-to-peer and channel messages at a maximum frequency of 180 calls every three second.

    + * @example + * ```TypeScript + * client.sendMessageToPeer( + * { text: 'test peer message' }, // An RtmMessage object. + * 'demoPeerId', // The uid of the remote user. + * ).then(sendResult => { + * if (sendResult.hasPeerReceived) { + * // Your code for handling the event when the remote user receives the message. + * } else { + * // Your code for handling the event when the message is received by the server but the remote user cannot be reached. + * } + * }).catch(error => { + * // Your code for handling the event when the message fails to be sent. + * }); + * ``` + * @param message The message to be sent. + * @param peerId The uid of the peer user. + *

    Note

    + * We do not support uids of the number type. We recommend using the toString() method to convert a non-string uid. + * @return The Promise resolves after the message is successfully sent. The value of the Promise indicates whether the peer user is online and receives the message. + */ + sendMessageToPeer( + message: RtmMessage, + peerId: string, + ): Promise; + + /** @zh-cn + * 该方法创建一个 {@link RtmChannel} 实例。 + * @param channelId 频道名称。该字符串不可超过 64 字节。以下为支持的字符集范围:
      + *
    • 26 个小写英文字母 a-z
    • + *
    • 26 个大写英文字母 A-Z
    • + *
    • 10 个数字 0-9
    • + *
    • 空格
    • + *
    • "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ","
    • + *
    + *

    Note:

      + *
    • 请不要将 channelId 设为空、null,或字符串 "null"。
    + * @return 一个 {@link RtmChannel} 实例。 + */ + /** + * Creates an {@link RtmChannel} instance. + * @param channelId The unique channel name of the Agora RTM channel. The string length must be less than 64 bytes with the following character scope:
      + *
    • All lowercase English letters: a to z
    • + *
    • All uppercase English letters: A to Z
    • + *
    • All numeric characters: 0 to 9
    • + *
    • The space character.
    • + *
    • Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ","
    • + *
    + *

    Note:

      + *
    • The channelId cannot be empty, null, or "null".
    + * @return An {@link RtmChannel} instance. + */ + createChannel(channelId: string): RtmChannel; + /** @zh-cn + * 该方法创建一个 {@link LocalInvitation} 实例。 + * @param calleeId 被叫的 uid。 + * @return 一个 {@link LocalInvitation} 实例。 + */ + /** + * Creates a {@link LocalInvitation} instance. + * @param calleeId The uid of the callee. + * @return A {@link LocalInvitation} instance. + */ + createLocalInvitation(calleeId: string): LocalInvitation; + + /** @zh-cn + * 全量设置本地用户的属性。 + * + * @param attributes 新的属性。 + * @return 该 Promise 会在设置本地用户属性成功后 resolve。 + */ + /** + * Substitutes the local user's attributes with new ones. + * + * @param attributes The new attributes. + * @return The Promise resolves after successfully setting the local user's attributes. + */ + setLocalUserAttributes(attributes: AttributesMap): Promise; + + /** @zh-cn + * 添加或更新本地用户的属性。 + *
      + *
    • 如果属性已存在,该方法更新本地用户的已有属性;
    • + *
    • 如果属性不存在,该方法增加本地用户的属性。
    • + *
    + * + * @param attributes 待增加或更新的属性列表。 + * @return 该 Promise 会在添加或更新本地用户属性成功后 resolve。 + */ + /** + * Adds or updates the local user's attributes. + * + *

    This method updates the local user's attributes if it finds that the attributes has/have the same keys, or adds attributes to the local user if it does not. + * + * @param attributes The attributes to be added or updated. + * @return The Promise resolves after successfully adding or updating the local user's attributes. + */ + addOrUpdateLocalUserAttributes(attributes: AttributesMap): Promise; + + /** @zh-cn + * 删除本地用户的指定属性。 + * + * @param attributeKeys 属性名列表。 + * @return 该 Promise 会在删除指定属性成功后 resolve。 + */ + /** + * Deletes the local user's attributes using attribute keys. + * + * @param attributeKeys A list of the attribute keys to be deleted. + * @return The Promise resolves after successfully deleting the local user's attributes. + */ + deleteLocalUserAttributesByKeys(attributeKeys: string[]): Promise; + + /** @zh-cn + * 清空本地用户的所有属性。 + * @return 该 Promise 会在清空本地用户属性成功后 resolve。 + */ + /** + * Clears all attributes of the local user. + * @return The Promise resolves after successfully clearing the local user's attributes. + */ + clearLocalUserAttributes(): Promise; + + /** @zh-cn + * 获取指定用户的全部属性。 + * + * @param userId 指定用户的用户 ID。 + */ + /** + * Gets all attributes of a specified user. + * + * @param userId The user ID of the specified user. + */ + getUserAttributes(userId: string): Promise; + + /** @zh-cn + * 获取指定用户指定属性名的属性。 + * + * @param userId 指定用户的用户 ID。 + * @param attributeKeys 属性名列表。 + */ + /** + * Gets the attributes of a specified user by attribute keys. + * + * @param userId The user ID of the specified user. + * @param attributeKeys An array of the attribute keys. + */ + getUserAttributesByKeys( + userId: string, + attributeKeys: string[] + ): Promise; + + /** @zh-cn + * 查询指定用户的在线状态。 + * + * @param peerIds 用户 ID 列表。用户 ID 的数量不能超过 256。 + */ + /** + * Queries the online status of the specified users. + * + * @param peerIds A list of the user IDs. The number of user IDs must not exceed 256. + */ + queryPeersOnlineStatus(peerIds: string[]): Promise; + + /** @zh-cn + * 更新当前 Token。 + * + * @param token 新的 Token。 + */ + /** + * Renews the token. + * + * @param token Your new Token. + */ + renewToken(token: string): Promise; + + /** @zh-cn + * 修改 `RtmClient` 实例配置。修改实时生效。 + * + * @param config 设置 SDK 是否上传日志以及日志的输出等级。详见 {@link RtmConfig}。 + */ + /** + * Modifies the `RtmClient` instance configuration. The changes take effect immediately. + * + * @param config Sets whether the SDK uploads logs, and sets the output level of logs. See {@link RtmConfig}. + */ + updateConfig(config: RtmConfig): void; + + /** @zh-cn + * + * 修改 `RtmClient` 实例配置。修改实时生效。 + * + * @deprecated 该方法自 v1.4.2 起已废弃,请使用 {@link updateConfig}。 + * + * + * @param config 设置 SDK 是否上传日志以及日志的输出等级。详见 {@link RtmConfig}。 + */ + /** + * Modifies the `RtmClient` instance configuration. The changes take effect immediately. + * + * @deprecated This method is deprecated as of v1.4.2. Please use {@link updateConfig} instead. + * + * @param config Sets whether the SDK uploads logs, and sets the output level of logs. See {@link RtmConfig}. + */ + setParameters(config: RtmConfig): void; + + /** @zh-cn + * 查询单个或多个频道的成员人数。 + * + *

    Note

    + *
      + *
    • 该方法的调用频率上限为每秒 1 次。
    • + *
    • 不支持一次查询超过 32 个频道的成员人数。
    • + *
    + * @param channelIds 指定频道名列表。 + */ + /** + * Gets the member count of specified channels. + * + *

    Note

    + *
      + *
    • The call frequency limit for this method is one call per second.
    • + *
    • We do not support getting the member counts of more than 32 channels in one method call.
    • + *
    + * @param channelIds An array of the specified channel IDs. + */ + getChannelMemberCount( + channelIds: string[] + ): Promise; + + /** @zh-cn + * 查询某指定频道的全部属性。 + * + *

    Note

    + *
      + *
    • 你无需加入指定频道即可查询该频道的属性。
    • + *
    • {@link getChannelAttributes} 和 {@link getChannelAttributesByKeys} 一并计算在内:调用频率限制为每 5 秒 10 次。
    • + *
    + * @param channelId 该指定频道的 ID。 + */ + /** + * Gets all attributes of a specified channel. + * + *

    Note

    + *
      + *
    • You do not have to join the specified channel to delete its attributes.
    • + *
    • For {@link getChannelAttributes} and {@link getChannelAttributesByKeys} taken together: the call frequency limit is 10 calls every five seconds.
    • + *
    + * @param channelId The ID of the specified channel. + */ + getChannelAttributes(channelId: string): Promise; + + /** @zh-cn + * 查询某指定频道指定属性名的属性。 + * + *

    Note

    + *
      + *
    • 你无需加入指定频道即可查询该频道的属性。
    • + *
    • {@link getChannelAttributes} 和 {@link getChannelAttributesByKeys} 一并计算在内:调用频率限制为每 5 秒 10 次。
    • + *
    + * @param channelId 该指定频道的频道 ID。 + * @param keys 频道属性名列表。 + */ + /** + * Gets the attributes of a specified channel by attribute keys. + * + *

    Note

    + *
      + *
    • You do not have to join the specified channel to get its attributes.
    • + *
    • For {@link getChannelAttributes} and {@link getChannelAttributesByKeys} taken together: the call frequency limit is 10 calls every five seconds.
    • + *
    + * @param channelId The ID of the specified channel. + * @param keys An array of attribute keys. + */ + getChannelAttributesByKeys( + channelId: string, + keys: string[] + ): Promise; + + /** @zh-cn + * 清空某指定频道的属性。 + * + *

    Note

    + *
      + *
    • 你无需加入指定频道即可清空该频道的属性。
    • + *
    • [RtmClient.setChannelAttributes()]{@link setLocalUserAttributes}、 {@link addOrUpdateChannelAttributes}、 {@link deleteChannelAttributesByKeys} 和 {@link clearChannelAttributes} 一并计算在内:调用频率限制为每 5 秒 10 次。
    • + *
    + * @param channelId 该指定频道的频道 ID。 + * @param options 频道属性操作选项。详见 {@link ChannelAttributeOptions}。 + */ + /** + * Clears all attributes of a specified channel. + * + *

    Note

    + * + * - You do not have to join the specified channel to clear its attributes. + * - For {@link RtmClient.setChannelAttributes}, {@link addOrUpdateChannelAttributes}, {@link deleteChannelAttributesByKeys}, and {@link clearChannelAttributes} taken together: the call frequency limit is 10 calls every five seconds. + * @param channelId The channel ID of the specified channel. + * @param options Options for this attribute operation. See {@link ChannelAttributeOptions}. + */ + clearChannelAttributes( + channelId: string, + options?: ChannelAttributeOptions + ): Promise; + + /** @zh-cn + * 删除某指定频道的指定属性。 + * + *

    Note

    + *
      + *
    • 你无需加入指定频道即可删除该频道的属性。
    • + *
    • 当某频道处于空频道状态(无人状态)数分钟后,该频道的频道属性将被清空。
    • + *
    • {@link setLocalUserAttributes}、 {@link addOrUpdateChannelAttributes}、 {@link deleteChannelAttributesByKeys} 和 {@link clearChannelAttributes} 一并计算在内:调用频率限制为每 5 秒 10 次。
    • + *
    + * @param channelId 该指定频道的 ID。 + * @param attributeKeys 属性名列表。 + * @param options 频道属性操作选项。详见 {@link ChannelAttributeOptions}。 + */ + /** + * Deletes the local user's attributes using attribute keys. + * + *

    Note

    + *
      + *
    • You do not have to join the specified channel to delete its attributes.
    • + *
    • The attributes of a channel will be cleared if the channel remains empty (has no members) for a couple of minutes.
    • + *
    • For {@link setLocalUserAttributes}, {@link addOrUpdateChannelAttributes}, {@link deleteChannelAttributesByKeys}, and {@link clearChannelAttributes} taken together: the call frequency limit is 10 calls every five seconds.
    • + *
    + * @param channelId The channel ID of the specified channel. + * @param attributeKeys A list of channel attribute keys. + * @param options Options for this attribute operation. See {@link ChannelAttributeOptions}. + */ + deleteChannelAttributesByKeys( + channelId: string, + attributeKeys: string[], + options?: ChannelAttributeOptions + ): Promise; + + /** @zh-cn + * 添加或更新某指定频道的属性。 + *
      + *
    • 如果属性已存在,该方法更新该频道的已有属性;
    • + *
    • 如果属性不存在,该方法增加该频道的属性。
    • + *
    + *

    Note

    + *
      + *
    • 你无需加入指定频道即可为该频道更新频道属性。
    • + *
    • 当某频道处于空频道状态(无人状态)数分钟后,该频道的频道属性将被清空。
    • + *
    • {@link setLocalUserAttributes}、 {@link addOrUpdateChannelAttributes}、 {@link deleteChannelAttributesByKeys} ,和 {@link clearChannelAttributes} 一并计算在内:调用频率限制为每 5 秒 10 次。
    • + *
    + * @param channelId 该指定频道的 ID。 + * @param attributes 待增加或更新的属性列表。 + * @param options 频道属性操作选项。详见 {@link ChannelAttributeOptions}。 + */ + /** + * Adds or updates the attributes of a specified channel. + * + * This method updates the specified channel's attributes if it finds that the attributes has/have the same keys, or adds attributes to the channel if it does not. + * + *

    Note

    + *
      + *
    • You do not have to join the specified channel to update its attributes.
    • + *
    • The attributes of a channel will be cleared if the channel remains empty (has no members) for a couple of minutes.
    • + *
    • For {@link setLocalUserAttributes}, {@link addOrUpdateChannelAttributes}, {@link deleteChannelAttributesByKeys}, and {@link clearChannelAttributes} taken together: the call frequency limit is 10 calls every five seconds.
    • + *
    + * @param channelId The channel ID of the specified channel. + * @param attributes An array of channel attributes. + * @param options Options for this attribute operation. See {@link ChannelAttributeOptions}. + */ + addOrUpdateChannelAttributes( + channelId: string, + attributes: AttributesMap, + options?: ChannelAttributeOptions + ): Promise; + + /** @zh-cn + * 全量设置某指定频道的属性。 + * + *

    Note

    + *
      + *
    • 你无需加入指定频道即可为该频道设置频道属性。
    • + *
    • 当某频道处于空频道状态(无人状态)数分钟后,该频道的频道属性将被清空。
    • + *
    • {@link setLocalUserAttributes}、 {@link addOrUpdateChannelAttributes}、 {@link deleteChannelAttributesByKeys} ,和 {@link clearChannelAttributes} 一并计算在内:调用频率限制为每 5 秒 10 次。
    • + *
    + * @param channelId 该指定频道的频道 ID。 + * @param attributes 频道属性列表实例。 + * @param options 频道属性操作选项。详见 {@link ChannelAttributeOptions}。 + */ + /** + * Sets the attributes of a specified channel with new ones. + * + *

    Note

    + *
      + *
    • You do not have to join the specified channel to reset its attributes.
    • + *
    • The attributes of a channel will be cleared if the channel remains empty (has no members) for a couple of minutes.
    • + *
    • For {@link setLocalUserAttributes}, {@link addOrUpdateChannelAttributes}, {@link deleteChannelAttributesByKeys}, and {@link clearChannelAttributes} taken together: the call frequency limit is 10 calls every five seconds.
    • + *
    + * @param channelId The channel ID of the specified channel. + * @param attributes An array of channel attributes. + * @param options Options for this attribute operation. See {@link ChannelAttributeOptions}. + */ + setChannelAttributes( + channelId: string, + attributes: AttributesMap, + options?: ChannelAttributeOptions + ): Promise; + + /** @zh-cn + * 订阅指定单个或多个用户的在线状态。 + *
      + *
    • 首次订阅成功后,SDK 会通过 {@link RtmClientEvents.PeersOnlineStatusChanged} 回调返回被订阅用户在线状态。
    • + *
    • 每当被订阅用户在线状态发生变化时,SDK 都会通过 {@link RtmClientEvents.PeersOnlineStatusChanged} 回调通知订阅方。
    • + *
    • 如果 SDK 在断线重连过程中有被订阅用户的在线状态发生改变,SDK 会在重连成功时通过 {@link RtmClientEvents.PeersOnlineStatusChanged} 回调通知订阅方。
    • + *
    + *

    Note

    + *
      + *
    • 用户登出 Agora RTM 系统后,所有之前的订阅内容都会被清空;重新登录后,如需保留之前订阅内容则需重新订阅。
    • + *
    • SDK 会在网络连接中断时进入断线重连状态。重连成功时 SDK 会自动重新订阅之前订阅用户,无需人为干预。
    • + *
    + * @param peerIds + */ + /** + * Subscribes to the online status of the specified users. + *
      + *
    • When the method call succeeds, the SDK returns the {@link RtmClientEvents.PeersOnlineStatusChanged} callback to report the online status of peers, to whom you subscribe.
    • + *
    • When the online status of the peers, to whom you subscribe, changes, the SDK returns the {@link RtmClientEvents.PeersOnlineStatusChanged} callback to report whose online status has changed.
    • + *
    • If the online status of the peers, to whom you subscribe, changes when the SDK is reconnecting to the server, the SDK returns the {@link RtmClientEvents.PeersOnlineStatusChanged} callback to report whose online status has changed when successfully reconnecting to the server.
    • + *
    + *

    Note

    + *
      + *
    • When you log out of the Agora RTM system, all the status that you subscribe to will be cleared. To keep the original subscription after you re-log in the system, you need to redo the whole subscription process.
    • + *
    • When the SDK reconnects to the server from the state of being interrupted, the SDK automatically subscribes to the peers and states before the interruption without human intervention.
    • + *
    + * @param peerIds An array of the specified user IDs. + */ + subscribePeersOnlineStatus(peerIds: string[]): Promise; + + /** @zh-cn + * 退订指定单个或多个用户的在线状态。 + * + * @param peerIds 被退订用户的用户 ID 阵列。 + */ + /** + * Unsubscribes from the online status of the specified users. + * + * @param peerIds An array of the specified user IDs. + */ + unsubscribePeersOnlineStatus(peerIds: string[]): Promise; + + /** @zh-cn + * 获取某特定内容被订阅的用户列表。 + * + * @param option 被订阅的类型。详见 {@link RtmStatusCode.PeerSubscriptionOption}。 + */ + /** + * Gets a list of the peers, to whose specific status you have subscribed. + * + * @param option The status type, to which you have subscribed. See {@link RtmStatusCode.PeerSubscriptionOption}. + */ + queryPeersBySubscriptionOption( + option: RtmStatusCode.PeerSubscriptionOption + ): Promise; + + + + /** @zh-cn + * 创建一个消息实例,可用于发送点对点消息或频道消息。 + * + * @typeParam T {@link RtmMessage} 类型别名。 + * + * @param message 一个包含 {@link RtmMessage} 中任意属性的对象。 + * + * @return 一个 {@link RtmMessage} 实例。你可以用这个实例发送点对点消息或频道消息。 + * + */ + /** + * + * @typeParam T A {@link RtmMessage} type. + * + * @param message An object that includes any property of {@link RtmMessage}. + * + * @return A message instance to send. You can use the message instance to send peer-to-peer or channel messages. + * + */ + createMessage(message: Partial): T; + + /** @zh-cn + * 在该频道实例上添加 `listener` 函数到名为 `eventName` 的事件。其他 `RtmClient` 实例上的事件方法请参考 [`EventEmitter` API 文档](https://nodejs.org/docs/latest/api/events.html#events_class_eventemitter)。 + * @param eventName RTM 客户端事件的名称。事件列表请参考 {@link RtmClientEvents} 中的属性名。 + * @param listener 事件的回调函数。 + */ + /** + * Adds the `listener` function to the channel for the event named `eventName`. See [the `EventEmitter` API documentation](https://nodejs.org/docs/latest/api/events.html#events_class_eventemitter) for other event methods on the `RtmClient` instance. + * @param eventName The name of the RTM client event. See the property names in the {@link RtmClientEvents} for the list of events. + * @param listener The callback function of the RTM client event. + */ + on( + eventName: EventName, + listener: ( + ...args: ListenerType + ) => any + ): this; +} + +/** @zh-cn + * AgoraRTM 是 Agora RTM SDK 的导出模块。 + * + * 使用 ``。 + * + * **Note:** + * + * 此处文件名 `agora-rtm-sdk-0.9.1.js` 中的版本号 `0.9.1` 仅供参考,安装时请使用最新版的 SDK 和链接地址。 + */ +/** + * AgoraRTM is the exported module of the Agora RTM SDK. + * + * If you import the Agora RTM Web SDK using the `` in your HTML. + *

    Note:

    + *

    The version `0.9.1` in the file name `agora-rtm-sdk-0.9.1.js` is for reference only, please use the latest version of the SDK. + */ +declare namespace AgoraRTM { + /** @zh-cn + * 不输出日志信息。 + */ + /** + * Do not output any log information. + */ + const LOG_FILTER_OFF: LogFilterType; + /** @zh-cn + * 输出 ERROR 级别的日志信息。 + */ + /** + * Output ERROR level log information. + */ + const LOG_FILTER_ERROR: LogFilterType; + /** @zh-cn + * 输出 ERROR、WARNING 和 INFO 级别的日志信息。 我们推荐你将日志级别设为该等级。 + */ + /** + * Output ERROR, WARNING, and INFO level log information. + */ + const LOG_FILTER_INFO: LogFilterType; + /** @zh-cn + * 输出 ERROR 和 WARNING 级别的日志信息。 + */ + /** + * Output WARNING and INFO level log information. + */ + const LOG_FILTER_WARNING: LogFilterType; + // const LOG_FILTER_DEBUG: LogFilterType; + + /** @zh-cn + * Agora RTM SDK 的版本号。 + */ + /** + * Version of the Agora RTM SDK. + * @example `AgoraRTM.VERSION` + */ + const VERSION: string; + + /** @zh-cn + * Agora RTM SDK 的编译信息。 + */ + /** + * Compilation information of the Agora RTM SDK. + * @example `AgoraRTM.BUILD` + */ + const BUILD: string; + + const END_CALL_PREFIX: string; + + /** @zh-cn + * 该方法创建并返回一个 {@link RtmClient} 实例。 + *

    Agora RTM SDK 支持多个 {@link RtmClient} 实例。

    + *

    {@link RtmClient} 类的所有接口函数都是异步调用。

    + * @example **创建 RtmClient 对象** + * + * ```JavaScript + * import AgoraRTM from 'agora-rtm-sdk'; + * const client = AgoraRTM.createInstance('demoAppId', { enableLogUpload: false }); // Pass your App ID here. + * ``` + * @param appId 传入项目的 App ID。必须是 ASCII 编码,长度为 32 个字符。 + * @param config {@link RtmClient} 对象的配置参数。详见 {@link RtmConfig}。 + * @return 一个 {@link RtmClient} 实例。 + */ + /** + * Creates and returns an {@link RtmClient} instance. + *

    The Agora RTM SDK supports creating multiple {@link RtmClient} instances.

    + *

    All methods in the {@link RtmClient} class are executed asynchronously.

    + * @example **Create an RtmClient instance** + * + * ```JavaScript + * import AgoraRTM from 'agora-rtm-sdk'; + * const client = AgoraRTM.createInstance('demoAppId', { enableLogUpload: false }); // Pass your App ID here. + * ``` + * @param appId App ID of your project that must be a string containing 32 ASCII characters. + * @param config The configuration of an {@link RtmClient} instance. See {@link RtmConfig}. + * @return An {@link RtmClient} instance. + */ + function createInstance(appId: string, config?: RtmConfig): RtmClient; + + /** @zh-cn + * @deprecated 从 v1.4.3 起废弃,声网不建议你使用。请改用 {@link createInstance} 方法。 + * 该方法创建并返回一个 {@link RtmClient} 实例。 + *

    Agora RTM SDK 支持多个 {@link RtmClient} 实例。

    + *

    {@link RtmClient} 类的所有接口函数都是异步调用。

    + * @example **创建 RtmClient 对象** + * + * ```JavaScript + * import AgoraRTM from 'agora-rtm-sdk'; + * const client = AgoraRTM.createInstance('demoAppId', { enableLogUpload: false }); // Pass your App ID here. + * ``` + * @param appId 传入项目的 App ID。必须是 ASCII 编码,长度为 32 个字符。 + * @param config {@link RtmClient} 对象的配置参数。详见 {@link RtmConfig}。 + * @param areaCodes Agora RTM 服务的限定区域。详见 {@link AreaCode}。 + * @return 一个 {@link RtmClient} 实例。 + */ + /** + * @deprecated From v2.3.2. Use {@link createInstance} instead. + * + * Creates and returns an {@link RtmClient} instance. + *

    The Agora RTM SDK supports creating multiple {@link RtmClient} instances.

    + *

    All methods in the {@link RtmClient} class are executed asynchronously.

    + * @example **Create an RtmClient instance** + * + * ```JavaScript + * import AgoraRTM from 'agora-rtm-sdk'; + * const client = AgoraRTM.createInstance('demoAppId', { enableLogUpload: false }); // Pass your App ID here. + * ``` + * @param appId App ID of your project that must be a string containing 32 ASCII characters. + * @param config The configuration of an {@link RtmClient} instance. See {@link RtmConfig}. + * @param areaCodes Region for the Agora RTM service. See {@link AreaCode}. + * @return An {@link RtmClient} instance. + */ + function createInstance( + appId: string, + config?: RtmConfig, + areaCodes?: RtmStatusCode.AreaCode[] + ): RtmClient; + + /** @zh-cn + * @since 1.4.3 + * + * 设置 Agora RTM SDK 的访问区域。支持设置多个访问区域。 + * + * 注意: + * - 该功能为高级设置,适用于有访问安全限制的场景。 + * - 默认情况下,SDK 会就近选择 Agora 服务器进行连接。设置访问区域之后,SDK 只会连接到指定区域内的 Agora 服务器。 + * - 该方法支持去除访问区域中的个别区域。 + * @param areaConfig 访问区域设置。 + * - areaCodes 访问区域,详见 {@link AreaCode}。 + * - excludedArea 排除区域,支持设置为`CHINA`,`JAPAN` 和 `ASIA`。该参数仅对于 `GLOBAL` 的访问区域有效。 + * @param areaCodes 访问区域,详见 {@link AreaCode}。 + * @param excludedArea 排除区域,支持设置为`CHINA`,`JAPAN` 和 `ASIA`。该参数仅对于 `GLOBAL` 的访问区域有效。 + */ + /** + * @since 1.4.3 + * + * Sets the regions for connection. + * + * **Note:** + * - This advanced feature applies to scenarios that have regional restrictions. + * - By default, the SDK connects to nearby Agora servers. After specifying the regions, the SDK connects to the Agora servers within those regions. + * - You can remove some areas from the region for connection. + * @param areaConfig The configration of regions for connection. + * - areaCodes: The region for connection. For details, see {@link AreaCode}. + * - excludedArea: Exclude areas, which can be set to `CHINA`, `JAPAN` and `ASIA`. This parameter is only valid when the region for connection is `GLOBAL`. + */ + function setArea(areaConfig: { + areaCodes: RtmStatusCode.AreaCode[]; + excludedArea?: RtmStatusCode.AreaCode; + }): void; + + /**@zh-cn + * 连接状态改变原因。 + */ + /** + * The reason of the connection state change. + */ + const ConnectionChangeReason: typeof RtmStatusCode.ConnectionChangeReason; + /**@zh-cn + * 连接状态。 + */ + /** + * The connection state. + */ + const ConnectionState: typeof RtmStatusCode.ConnectionState; + /**@zh-cn + * (返回给主叫)呼叫邀请失败原因。 + */ + /** + * (Return to the caller) The reason of the local invitation failure. + */ + const LocalInvitationFailureReason: typeof RtmStatusCode.LocalInvitationFailureReason; + /**@zh-cn + * 返回给主叫的呼叫邀请状态。 + */ + /** + * Call invitation state returned to the caller. + */ + const LocalInvitationState: typeof RtmStatusCode.LocalInvitationState; + /**@zh-cn + * 返回给被叫的呼叫邀请状态。 + */ + /** + * Call invitation state returned to the callee. + */ + const RemoteInvitationState: typeof RtmStatusCode.RemoteInvitationState; + /**@zh-cn + * (返回给被叫)呼叫邀请失败原因。 + */ + /** + * (Return to the callee) The reason of the local invitation failure. + */ + const RemoteInvitationFailureReason: typeof RtmStatusCode.RemoteInvitationFailureReason; + /**@zh-cn + * 消息类型。 + */ + /** + * Message type. + */ + const MessageType: typeof RtmStatusCode.MessageType; + /**@zh-cn + * 用户的在线状态。 + */ + /** + * Online state of the user. + */ + const PeerOnlineState: typeof RtmStatusCode.PeerOnlineState; + /**@zh-cn + * 订阅类型。 + */ + /** + * Subscription type. + */ + const PeerSubscriptionOption: typeof RtmStatusCode.PeerSubscriptionOption; + /**@zh-cn + * Agora RTM 服务的限定区域。默认为 AgoraAreaGLOB,即限定区域为全球。详见 {@link AreaCode}。 + */ + /** + * Region for the Agora RTM service. The default is `GLOBAL`. See {@link AreaCode}. + */ + const AreaCode: typeof RtmStatusCode.AreaCode; +} + +export default AgoraRTM; +export type { LocalInvitation, RemoteInvitation, RtmChannel, RtmClient, RtmEvents, RtmMessage, RtmRawMessage, RtmStatusCode, RtmTextMessage }; diff --git a/node_modules/agora-rtm-sdk/index.js b/node_modules/agora-rtm-sdk/index.js new file mode 100644 index 000000000..43a2b4461 --- /dev/null +++ b/node_modules/agora-rtm-sdk/index.js @@ -0,0 +1,8 @@ +/* + @preserve + AgoraRTM Web SDK 1.5.1 - commit: v1.5.1-0-g5bbbcd72 + Copyright (C) 2018-2022 Agora Lab. + This file is licensed under the AGORA, INC. SDK LICENSE AGREEMENT + A copy of this license may be found at https://www.agora.io/en/sdk-license-agreement/ +*/ +"use strict";!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).AgoraRTM=t()}(this,(function(){function Be(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Wa(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=Array(t);narguments.length?e:arguments[2];return Ia(e)===r?e[t]:(n=dc.f(e,t))?ka(n,"value")?n.value:void 0===n.get?void 0:n.get.call(r):xa(n=uc(e))?Am(n,t,r):void 0}function bu(e){var t=e.charCodeAt(0)<<24,n=0|cu(~t),r=0,o=0|e.length,i="";if(5>n&&o>=n){for(t=t<>>24+n,r=1;r=t?i+=Ud(t):1114111>=t?i+=Ud(55296+((t=t-65536|0)>>10)|0,56320+(1023&t)|0):r=0}for(;r=t){var n=0|e.charCodeAt(1);if(!(n==n&&56320<=n&&57343>=n))return Ud(239,191,189);if(65535<(t=(t-55296<<10)+n-56320+65536|0))return Ud(240|t>>>18,128|t>>>12&63,128|t>>>6&63,128|63&t)}return 127>=t?e:2047>=t?Ud(192|t>>>6,128|63&t):Ud(224|t>>>12,128|t>>>6&63,128|63&t)}function Cm(){}function Ba(){Ba.init.call(this)}function Wg(e){if("function"!=typeof e)throw new TypeError('The "listener" argument must be of type Function. Received type '+qa(e))}function Dm(e,t,n,r){Wg(n);var o=e._events;if(void 0===o)o=e._events=Object.create(null),e._eventsCount=0;else{void 0!==o.newListener&&(e.emit("newListener",t,n.listener?n.listener:n),o=e._events);var i=o[t]}return void 0===i?(o[t]=n,++e._eventsCount):("function"==typeof i?i=o[t]=r?[n,i]:[i,n]:r?i.unshift(n):i.push(n),0<(n=void 0===e._maxListeners?Ba.defaultMaxListeners:e._maxListeners)&&i.length>n&&!i.warned&&(i.warned=!0,(n=Error("Possible EventEmitter memory leak detected. "+i.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit")).name="MaxListenersExceededWarning",n.emitter=e,n.type=t,n.count=i.length,console&&console.warn&&console.warn(n))),e}function eu(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,0===arguments.length?this.listener.call(this.target):this.listener.apply(this.target,arguments)}function Em(e,t,n){return e={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},(t=eu.bind(e)).listener=n,e.wrapFn=t}function Fm(e,t,n){if(void 0===(e=e._events))return[];if(void 0===(t=e[t]))return[];if("function"==typeof t)return n?[t.listener||t]:[t];if(n)for(n=Array(t.length),e=0;e>>=0)&&256>e)&&(n=Vm[e]))return n;n=Qa(e,0>(0|e)?-1:0,!0),t&&(Vm[e]=n)}else{if((t=-128<=(e|=0)&&128>e)&&(n=Wm[e]))return n;n=Qa(e,0>e?-1:0,!1),t&&(Wm[e]=n)}return n}function ec(e,t){if(isNaN(e))return t?Yd:fc;if(t){if(0>e)return Yd;if(e>=Xm)return Ym}else{if(e<=-Zm)return Ib;if(e+1>=Zm)return $m}return 0>e?ec(-e,t).neg():Qa(e%Me|0,e/Me|0,t)}function Qa(e,t,n){return new Pa(e,t,n)}function Vi(e,t,n){if(0===e.length)throw Error("empty string");if("NaN"===e||"Infinity"===e||"+Infinity"===e||"-Infinity"===e)return fc;if("number"==typeof t?(n=t,t=!1):t=!!t,2>(n=n||10)||36s?(s=ec(ah(n,s)),o=o.mul(s).add(ec(a))):o=(o=o.mul(r)).add(ec(a))}return o.unsigned=t,o}function vc(e,t){return"number"==typeof e?ec(e,t):"string"==typeof e?Vi(e,t):Qa(e.low,e.high,"boolean"==typeof t?t:e.unsigned)}function ha(e,t){function n(){this.constructor=e}Wi(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}function Ne(e){return"function"==typeof e}function Oe(e){setTimeout((function(){throw e}),0)}function Xi(e){return null!==e&&"object"===qa(e)}function an(e){return e.reduce((function(e,t){return e.concat(t instanceof Pf?t.errors:t)}),[])}function Yi(e){for(;e;){var t=e.destination,n=e.isStopped;if(e.closed||n)return!1;e=t&&t instanceof za?t:null}return!0}function wd(e){return e}function Zi(){for(var e=[],t=0;t=e.length?e[0]:e),o.complete()}]))}catch(e){Yi(o)?o.error(e):console.warn(e)}}return o.subscribe(r)}))}}function Du(e){var t=this,n=e.args,r=e.subscriber,o=e.params;e=o.callbackFunc;var i=o.context,s=o.scheduler,a=o.subject;if(!a){a=o.subject=new Sf,o=function(){for(var e=[],n=0;n=e.length?e[0]:e,subject:a}))};try{e.apply(i,n.concat([o]))}catch(e){a.error(e)}}this.add(a.subscribe(r))}function Eu(e){var t=e.subject;t.next(e.value),t.complete()}function hn(e,t,n){if(t){if(!ad(t))return function(){for(var r=[],o=0;o=e.length?e[0]:e),s.complete())}]))}catch(e){Yi(s)?s.error(e):console.warn(e)}}return s.subscribe(r)}))}}function Fu(e){var t=this,n=e.params,r=e.subscriber;e=e.context;var o=n.callbackFunc,i=n.args,s=n.scheduler,a=n.subject;if(!a){a=n.subject=new Sf,n=function(){for(var e=[],n=0;n=e.length?e[0]:e,subject:a}))};try{o.apply(e,i.concat([n]))}catch(e){this.add(s.schedule(jn,0,{err:e,subject:a}))}}this.add(a.subscribe(r))}function Gu(e){var t=e.subject;t.next(e.value),t.complete()}function jn(e){e.subject.error(e.err)}function kn(e){return!!e&&"function"!=typeof e.subscribe&&"function"==typeof e.then}function bj(e,t,n,r,o){if(void 0===o&&(o=new Hu(e,n,r)),!o.closed)return t instanceof ua?t.subscribe(o):Tf(t)(o)}function Iu(e,t){return new ua((function(n){var r=new nb;return r.add(t.schedule((function(){var o=e[Pe]();r.add(o.subscribe({next:function(e){r.add(t.schedule((function(){return n.next(e)})))},error:function(e){r.add(t.schedule((function(){return n.error(e)})))},complete:function(){r.add(t.schedule((function(){return n.complete()})))}}))}))),r}))}function Ju(e,t){return new ua((function(n){var r=new nb;return r.add(t.schedule((function(){return e.then((function(e){r.add(t.schedule((function(){n.next(e),r.add(t.schedule((function(){return n.complete()})))})))}),(function(e){r.add(t.schedule((function(){return n.error(e)})))}))}))),r}))}function Ku(e,t){if(!e)throw Error("Iterable cannot be null");return new ua((function(n){var r,o=new nb;return o.add((function(){r&&"function"==typeof r.return&&r.return()})),o.add(t.schedule((function(){r=e[xd](),o.add(t.schedule((function(){if(!n.closed){try{var e=r.next(),t=e.value,o=e.done}catch(e){return void n.error(e)}o?n.complete():(n.next(t),this.schedule())}})))}))),o}))}function ln(e,t){if(null!=e){if(e&&"function"==typeof e[Pe])return Iu(e,t);if(kn(e))return Ju(e,t);if(mn(e))return $i(e,t);if(e&&"function"==typeof e[xd]||"string"==typeof e)return Ku(e,t)}throw new TypeError((null!==e&&qa(e)||e)+" is not observable")}function Jc(e,t){return t?ln(e,t):e instanceof ua?e:new ua(Tf(e))}function bd(e,t){if(!t.closed){if(e instanceof ua)return e.subscribe(t);try{var n=Tf(e)(t)}catch(e){t.error(e)}return n}}function Cb(e,t,n){return void 0===n&&(n=Number.POSITIVE_INFINITY),"function"==typeof t?function(r){return r.pipe(Cb((function(n,r){return Jc(e(n,r)).pipe(Ea((function(e,o){return t(n,e,r,o)})))}),n))}:("number"==typeof t&&(n=t),function(t){return t.lift(new Lu(e,n))})}function bh(e){return void 0===e&&(e=Number.POSITIVE_INFINITY),Cb(wd,e)}function nn(){for(var e=[],t=0;te)&&(e=0),t&&"function"==typeof t.schedule||(t=cd),new ua((function(n){return n.add(t.schedule(Nu,e,{subscriber:n,counter:0,period:e})),n}))}function Nu(e){var t=e.subscriber,n=e.counter;e=e.period,t.next(n),this.schedule({subscriber:t,counter:n+1,period:e},e)}function Jb(){for(var e=[],t=0;t=e.count?r.complete():(r.next(t),r.closed||(e.index=n+1,e.start=t+1,this.schedule(e)))}function dd(e,t,n){void 0===e&&(e=0);var r=-1;return cj(t)?r=1>Number(t)?1:Number(t):ad(t)&&(n=t),ad(n)||(n=cd),new ua((function(t){var o=cj(e)?e:+e-n.now();return n.schedule(Tu,o,{index:0,period:r,subscriber:t})}))}function Tu(e){var t=e.index,n=e.period,r=e.subscriber;if(r.next(t),!r.closed){if(-1===n)return r.complete();e.index=t+1,this.schedule(e,n)}}function ej(){for(var e=[],t=0;t=arguments.length?0:arguments.length-1)?"number"==typeof(1>=arguments.length?void 0:arguments[1])?t=1>=arguments.length?void 0:arguments[1]:n=1>=arguments.length?void 0:arguments[1]:2==(1>=arguments.length?0:arguments.length-1)&&(t=1>=arguments.length?void 0:arguments[1],n=2>=arguments.length?void 0:arguments[2]);var r=t||1;return function(t){return t.pipe(gh((function(t,o){var i=n.now(),s=i-e;if((t=t.filter((function(e){return e.until>s}))).length>=r){var a=t[t.length-1],c=t[0].until+e*Math.floor(t.length/r);t.push({delay:a.untilt?1:0;if(o&&(t=-t),0===t)e(0<1/t?0:2147483648,n,r);else if(isNaN(t))e(2143289344,n,r);else if(34028234663852886e22>>0,n,r);else if(11754943508222875e-54>t)e((o<<31|Math.round(t/1401298464324817e-60))>>>0,n,r);else{var i=Math.floor(Math.log(t)/Math.LN2);e((o<<31|i+127<<23|8388607&Math.round(t*Math.pow(2,-i)*8388608))>>>0,n,r)}}function n(e,t,n){return n=e(t,n),e=2*(n>>31)+1,t=n>>>23&255,n&=8388607,255===t?n?NaN:1/0*e:0===t?1401298464324817e-60*e*n:e*Math.pow(2,t-150)*(n+8388608)}e.writeFloatLE=t.bind(null,Gn),e.writeFloatBE=t.bind(null,Hn),e.readFloatLE=n.bind(null,In),e.readFloatBE=n.bind(null,Jn)}(),"undefined"!=typeof Float64Array?function(){function t(e,t,n){i[0]=e,t[n]=s[0],t[n+1]=s[1],t[n+2]=s[2],t[n+3]=s[3],t[n+4]=s[4],t[n+5]=s[5],t[n+6]=s[6],t[n+7]=s[7]}function n(e,t,n){i[0]=e,t[n]=s[7],t[n+1]=s[6],t[n+2]=s[5],t[n+3]=s[4],t[n+4]=s[3],t[n+5]=s[2],t[n+6]=s[1],t[n+7]=s[0]}function r(e,t){return s[0]=e[t],s[1]=e[t+1],s[2]=e[t+2],s[3]=e[t+3],s[4]=e[t+4],s[5]=e[t+5],s[6]=e[t+6],s[7]=e[t+7],i[0]}function o(e,t){return s[7]=e[t],s[6]=e[t+1],s[5]=e[t+2],s[4]=e[t+3],s[3]=e[t+4],s[2]=e[t+5],s[1]=e[t+6],s[0]=e[t+7],i[0]}var i=new Float64Array([-0]),s=new Uint8Array(i.buffer),a=128===s[7];e.writeDoubleLE=a?t:n,e.writeDoubleBE=a?n:t,e.readDoubleLE=a?r:o,e.readDoubleBE=a?o:r}():function(){function t(e,t,n,r,o,i){var s=0>r?1:0;if(s&&(r=-r),0===r)e(0,o,i+t),e(0<1/r?0:2147483648,o,i+n);else if(isNaN(r))e(0,o,i+t),e(2146959360,o,i+n);else if(17976931348623157e292>>0,o,i+n);else if(22250738585072014e-324>r)e((r/=5e-324)>>>0,o,i+t),e((s<<31|r/4294967296)>>>0,o,i+n);else{var a=Math.floor(Math.log(r)/Math.LN2);1024===a&&(a=1023),e(4503599627370496*(r*=Math.pow(2,-a))>>>0,o,i+t),e((s<<31|a+1023<<20|1048576*r&1048575)>>>0,o,i+n)}}function n(e,t,n,r,o){return t=e(r,o+t),r=e(r,o+n),e=2*(r>>31)+1,t=4294967296*(1048575&r)+t,2047===(n=r>>>20&2047)?t?NaN:1/0*e:0===n?5e-324*e*t:e*Math.pow(2,n-1075)*(t+4503599627370496)}e.writeDoubleLE=t.bind(null,Gn,0,4),e.writeDoubleBE=t.bind(null,Hn,4,0),e.readDoubleLE=n.bind(null,In,0,4),e.readDoubleBE=n.bind(null,Jn,4,0)}(),e}function Gn(e,t,n){t[n]=255&e,t[n+1]=e>>>8&255,t[n+2]=e>>>16&255,t[n+3]=e>>>24}function Hn(e,t,n){t[n]=e>>>24,t[n+1]=e>>>16&255,t[n+2]=e>>>8&255,t[n+3]=255&e}function In(e,t){return(e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24)>>>0}function Jn(e,t){return(e[t]<<24|e[t+1]<<16|e[t+2]<<8|e[t+3])>>>0}function vb(e,t){this.lo=e>>>0,this.hi=t>>>0}function Wf(e,t,n){this.fn=e,this.len=t,this.next=void 0,this.val=n}function lj(){}function Cv(e){this.head=e.head,this.tail=e.tail,this.len=e.len,this.next=e.states}function Aa(){this.len=0,this.tail=this.head=new Wf(lj,0,0),this.states=null}function mj(e,t,n){t[n]=255&e}function nj(e,t){this.len=e,this.next=void 0,this.val=t}function oj(e,t,n){for(;e.hi;)t[n++]=127&e.lo|128,e.lo=(e.lo>>>7|e.hi<<25)>>>0,e.hi>>>=7;for(;127>>=7;t[n++]=e.lo}function pj(e,t,n){t[n]=255&e,t[n+1]=e>>>8&255,t[n+2]=e>>>16&255,t[n+3]=e>>>24}function Lc(){qj.call(this)}function Dv(e,t,n){40>e.length?pa.utf8.write(e,t,n):t.utf8Write?t.utf8Write(e,n):t.write(e,n)}function wc(e,t){return RangeError("index out of range: "+e.pos+" + "+(t||1)+" > "+e.len)}function ib(e){this.buf=e,this.pos=0,this.len=e.length}function rj(){var e=new Kn(0,0),t=0;if(!(4t;++t){if(this.pos>=this.len)throw wc(this);if(e.lo=(e.lo|(127&this.buf[this.pos])<<7*t)>>>0,128>this.buf[this.pos++])return e}return e.lo=(e.lo|(127&this.buf[this.pos++])<<7*t)>>>0,e}for(;4>t;++t)if(e.lo=(e.lo|(127&this.buf[this.pos])<<7*t)>>>0,128>this.buf[this.pos++])return e;if(e.lo=(e.lo|(127&this.buf[this.pos])<<28)>>>0,e.hi=(e.hi|(127&this.buf[this.pos])>>4)>>>0,128>this.buf[this.pos++])return e;if(t=0,4t;++t)if(e.hi=(e.hi|(127&this.buf[this.pos])<<7*t+3)>>>0,128>this.buf[this.pos++])return e}else for(;5>t;++t){if(this.pos>=this.len)throw wc(this);if(e.hi=(e.hi|(127&this.buf[this.pos])<<7*t+3)>>>0,128>this.buf[this.pos++])return e}throw Error("invalid varint encoding")}function ih(e,t){return(e[t-4]|e[t-3]<<8|e[t-2]<<16|e[t-1]<<24)>>>0}function Ln(){if(this.pos+8>this.len)throw wc(this,8);return new Kn(ih(this.buf,this.pos+=4),ih(this.buf,this.pos+=4))}function be(e){sj.call(this,e)}function Xf(e,t,n){if("function"!=typeof e)throw TypeError("rpcImpl must be a function");pa.EventEmitter.call(this),this.rpcImpl=e,this.requestDelimited=!!t,this.responseDelimited=!!n}function Mn(e){var t=[];return function e(n){if(null===n||"object"!==qa(n))return n;if(-1!==t.indexOf(n))return"[Circular]";if(t.push(n),"function"==typeof n.toJSON)try{var r=e(n.toJSON());return t.pop(),r}catch(e){return"[Throws: "+(e?e.message:"?")+"]"}return Array.isArray(n)?(r=n.map(e),t.pop(),r):(r=Object.keys(n).reduce((function(t,r){e:{if(Ev.call(n,r))try{var o=n[r];break e}catch(e){o="[Throws: "+(e?e.message:"?")+"]";break e}o=n[r]}return t[r]=e(o),t}),{}),t.pop(),r)}(e)}function Fv(e){if(!(100<(e=String(e)).length)&&(e=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(e))){var t=parseFloat(e[1]);switch((e[2]||"ms").toLowerCase()){case"years":case"year":case"yrs":case"yr":case"y":return 315576e5*t;case"weeks":case"week":case"w":return 6048e5*t;case"days":case"day":case"d":return 864e5*t;case"hours":case"hour":case"hrs":case"hr":case"h":return 36e5*t;case"minutes":case"minute":case"mins":case"min":case"m":return 6e4*t;case"seconds":case"second":case"secs":case"sec":case"s":return 1e3*t;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return t}}}function jh(e,t,n,r){return Math.round(e/n)+" "+r+(t>=1.5*n?"s":"")}function Gv(e){var t=e.areas,n=e.excludedArea;if(1===t.length&&t[0]===S.GLOBAL&&n===S.CHINA)return Ve([S.OVERSEA]);if(t.includes(S.GLOBAL)){if(e=Yf(kh).filter((function(e){return e!==S.GLOBAL&&e!==S.OVERSEA})),n in Zf){t=Zf[n];var r=[].concat(Z(null!=t?t:[]),[n]);return Ve(e.filter((function(e){return!r.includes(e)})))}if(Nn(n)){var o=Hv(n);return Ve(e.filter((function(e){return e!==n&&e!==o})))}}if(Nn(n)||n in Zf)return Ve(t);throw new ca("Invalid excludedArea area config")}function jb(e,t,n){void 0===n&&(n=Object.getOwnPropertyDescriptor(e,t));var r=n.value;return n.value=function(){for(var e=this,n=arguments.length,o=Array(n),i=0;i?@[\]^{|}~-]{1,64}$/.test(e)&&"null"!==e}function Pn(e){try{var t=e.split(".").map((function(e){return Number(e)}))}catch(e){return!1}if(4!==t.length||0===t[0])return!1;for(e=0;en||255r)throw new ic("Exceed the limit of ".concat(r," attributes"),Ye);if(0===Object.keys(t).length)throw new ca("The attributes is an empty object",gb);var i=0,s=0;for(t=Object.entries(t);so)throw new ic("Invalid attribute value, over the limit of ".concat(o," bytes"),Ye);if("string"!=typeof c||0===c.length)throw new ca("Invalid attribute value",gb);i+=a,i+=u}if(i>e)throw new ic("The attributes size overflow",Ye);if(void 0!==n){if(Object.keys(n).length>r)throw new ic("Exceed the limit of ".concat(r," attributes"),Ye);for(i=r=0,n=Object.entries(n);io)throw new ic("Invalid attribute value, over the limit of ".concat(o," bytes"),Ye);r+=t,r+=s}if(r>e)throw new ic("The attributes size overflow",Ye)}}function mh(e,t){return Math.floor(Math.random()*(Math.floor(t)-Math.ceil(e)+1))+e}function nh(){var e=mh(0,4294967295),t=mh(1,4294967295);return new P(e,t,!0)}function sb(e){return e.toString().padEnd(32,"0")}function Rn(e,t){return new TypeError("Unexpected ".concat(e,": ").concat(t))}function Sn(e,t){return e=e.split(".").map((function(e){return Number(e)})),t=t.split(".").map((function(e){return Number(e)})),Math.sqrt(1e3*Math.pow(e[0]-t[0],2)+100*Math.pow(e[1]-t[1],2)+10*Math.pow(e[2]-t[2],2)+1*Math.pow(e[3]-t[3],2))}function Tn(e){return e.lessThanOrEqual(Number.MAX_SAFE_INTEGER)?e.toNumber():e.toString()}function uj(e,t){t="".concat(e).concat(t||"");var n=Un.get(t)||1;return Un.set(t,n+1),"".concat(e).concat(n)}function Vn(e,t){var n="number"==typeof t?t:void 0!==t&&"string"!=typeof t?t.code:void 0;return t="number"!=typeof t&&"string"!=typeof t&&void 0!==t&&void 0!==t.serverCode?t.serverCode:void 0,n="".concat(void 0!==n?" Error Code ".concat(n):"").concat(void 0!==t?", server Code ".concat(t):""),e="string"==typeof e&&e?oh(e):Array.isArray(e)&&"string"==typeof e[0]&&e[0]?oh(Wn.apply(void 0,[e[0]].concat(Z(e.slice(1))))):"","".concat(""===n?"":"".concat(n," - ")).concat(e)}function Kv(e,t){return vj.apply(this,arguments)}function vj(){return(vj=ma(N.mark((function e(t,n){return N.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(!n||!n.aborted){e.next=2;break}return e.abrupt("return");case 2:return e.abrupt("return",new Promise((function(e){setTimeout(e,t),null==n||n.addEventListener("abort",e)})));case 3:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function lh(e,t,n){return wj.apply(this,arguments)}function wj(){return(wj=ma(N.mark((function e(t,n,r){var o,i,s,a,c,u,l,f,h,p,d,b,g,v,y,m,E,w,O,_,k,I,A,R,S,T;return N.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(o=n.body,i=n.headers,s=void 0===i?{}:i,a=n.timeout,c=void 0===a?1e4:a,u=n.signal,l=n.withCredentials,f=void 0!==l&&l,h=(r||{}).useBinaryResponse,p=void 0!==h&&h,(d=new XMLHttpRequest).open("POST",t,!0),d.responseType=p?"arraybuffer":"text",d.withCredentials=f,d.timeout=c,b=o instanceof FormData,g=o instanceof Uint8Array,!(1<(v=Object.keys(s).filter((function(e){return"content-type"===e.toLowerCase()}))).length)){e.next=14;break}throw new RangeError("multiple content-type");case 14:0===v.length&&(g?s["Content-Type"]="application/octet-stream":b||(s["Content-Type"]="application/json"));case 15:if("setRequestHeader"in d){e.next=46;break}return d.abort(),e.next=19,fetch(t,{body:b||g?o:JSON.stringify(o),cache:"no-cache",credentials:f?"include":"same-origin",headers:s,method:"POST",mode:"cors",referrer:"no-referrer",signal:u});case 19:if(y=e.sent,!(200<=(m=y.status)&&300>m||304===m)){e.next=31;break}if(!p){e.next=27;break}return e.next=25,y.arrayBuffer();case 25:return E=e.sent,e.abrupt("return",{status:m,responseData:E});case 27:return e.next=29,y.text();case 29:return w=e.sent,e.abrupt("return",{status:m,responseText:w});case 31:return O=new Ja(["Post XHR failure, status %d",m]),e.prev=32,e.next=35,y.text();case 35:throw _=e.sent,O.statusCode=m,O.message=_||"Request failed, status ".concat(m),O;case 41:throw e.prev=41,e.t0=e.catch(32),O.statusCode=m,O.message="Request failed, status ".concat(m),O;case 46:if(0!==Object.keys(s).length)for(k=0,I=Object.entries(s);kn||304===n)e(p?{status:n,responseData:d.response}:{status:n,responseText:d.responseText});else{var r=new Ja(["Post XHR failure, status %d",n]);r.statusCode=n,r.message=d.response||"Request failed, status ".concat(d.status),t(r)}},d.ontimeout=function(e){t(new Ub(["XHR request timed out after %d ms",c],{originalError:e}))},d.onerror=function(){var e=new Ja(["Post XHR failure, status %d",d.status]);e.statusCode=d.status,e.message=d.response||"Request failed, status ".concat(d.status),t(e)},d.onabort=function(){try{t(new DOMException("The request aborted.","AbortError"))}catch(n){var e=Error("The request aborted.");e.name="AbortError",t(e)}}})));case 50:case"end":return e.stop()}}),e,null,[[32,41]])})))).apply(this,arguments)}function Xn(e,t){if(!De(e))throw new ca("message object is not a plain object",t);if(void 0===e.messageType)if(e.rawMessage instanceof Uint8Array){if(e.messageType="RAW",void 0!==e.text)throw new ca("Raw messages cannot have text property. Use description instead",t)}else{if("string"!=typeof e.text)throw new ca("messageType is undefined",t);if(e.messageType="TEXT",void 0!==e.rawMessage)throw new ca("Text messages cannot have rawMessage property",t)}}function ph(e){return xj.apply(this,arguments)}function xj(){return(xj=ma(N.mark((function e(t){var n,r,o,i,s,a,c,u,l,f,h,p,d,b,g,v,y,m,E,w,O;return N.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(n=t.message,r=t.peerId,o=t.toPeer,i=t.session,s=t.errorCodes,a=t.diff,c=t.logger,void 0!==i){e.next=3;break}throw new da("The client is not logged in. Cannot do the operation",s.NOT_LOGGED_IN);case 3:if(u=!1,l=o?"TEXT"===n.messageType?Ka.P2pSMsgNoOfflineFlag:Ka.P2pRMsgNoOfflineFlag:"TEXT"===n.messageType?Ka.ChannelSMsg:Ka.ChannelRMsg,"TEXT"!==n.messageType||!n.text.startsWith("AgoraRTMLegacyEndcallCompatibleMessagePrefix")||!o){e.next=14;break}if(f=n.text.split("_"),h=$a(f,3),p=h[0],d=h[1],void 0!==h[2]&&Ta(d)&&"AgoraRTMLegacyEndcallCompatibleMessagePrefix"===p){e.next=13;break}throw i.emit("messageCount",{messageCategory:l,type:"common",key:"sentcount"}),i.emit("messageCount",{messageCategory:l,type:"common",key:"invalidmessagecount"}),new ca("Message is not valid",bg);case 13:u=!0;case 14:if(b=Date.now(),g=i.messageSentTimes.length-1,!((v=i.messageSentTimes[g])&&v+3e3arguments.length?oo(R[e])||oo(R[e]):R[e]&&R[e][t]||R[e]&&R[e][t]},aw=Math.ceil,bw=Math.floor,yc=function(e){return isNaN(e=+e)?0:(0(e=yc(e))?dw(e+t,0):ew(e,t)},po=function(e){return function(t,n,r){t=Mb(t);var o=Ma(t.length);if(r=Vb(r,o),e&&n!=n){for(;o>r;)if((n=t[r++])!=n)return!0}else for(;o>r;r++)if((e||r in t)&&t[r]===n)return e||r||0;return!e&&-1}},qo=po(!0),Fj=po(!1),ro=function(e,t){e=Mb(e);var n,r=0,o=[];for(n in e)!ka(bf,n)&&ka(e,n)&&o.push(n);for(;t.length>r;)ka(e,n=t[r++])&&(~Fj(o,n)||o.push(n));return o},zh="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),fw=zh.concat("length","prototype"),de={f:Object.getOwnPropertyNames||function(e){return ro(e,fw)}},gg={f:Object.getOwnPropertySymbols},so=Pc("Reflect","ownKeys")||function(e){var t=de.f(Ia(e)),n=gg.f;return n?t.concat(n(e)):t},to=function(e,t){for(var n=so(t),r=qb.f,o=dc.f,i=0;iBd[0]?1:Bd[0]+Bd[1];else df&&(Bd=df.match(/Edge\/(\d+)/),(!Bd||74<=Bd[1])&&(Bd=df.match(/Chrome\/(\d+)/))&&(Jj=Bd[1]));var Cd=Jj&&+Jj,Sc=!!Object.getOwnPropertySymbols&&!la((function(){return!String(Symbol())||!Symbol.sham&&Cd&&41>Cd})),zo=Sc&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,ig=Ad("wks"),jg=R.Symbol,ow=zo?jg:jg&&jg.withoutSetter||af,Fa=function(e){return ka(ig,e)&&(Sc||"string"==typeof ig[e])||(Sc&&ka(jg,e)?ig[e]=jg[e]:ig[e]=ow("Symbol."+e)),ig[e]},pw=Fa("species"),Kj=RegExp.prototype,qw=!la((function(){var e=/./;return e.exec=function(){var e=[];return e.groups={a:"7"},e},"7"!=="".replace(e,"$")})),Ao="$0"==="a".replace(/./,"$0"),Bo=Fa("replace"),Co=!!/./[Bo]&&""===/./[Bo]("a","$0"),rw=!la((function(){var e=/(?:)/,t=e.exec;return e.exec=function(){return t.apply(this,arguments)},2!==(e="ab".split(e)).length||"a"!==e[0]||"b"!==e[1]})),Bh=function(e,t,n,r){var o=Fa(e),i=!la((function(){var t={};return t[o]=function(){return 7},7!=""[e](t)})),s=i&&!la((function(){var t=!1,n=/a/;return"split"===e&&((n={constructor:{}}).constructor[pw]=function(){return n},n.flags="",n[o]=/./[o]),n.exec=function(){return t=!0,null},n[o](""),!t}));if(!i||!s||"replace"===e&&(!qw||!Ao||Co)||"split"===e&&!rw){var a=/./[o],c=(n=n(o,""[e],(function(e,t,n,r,o){var s=t.exec;return s===hg||s===Kj.exec?i&&!o?{done:!0,value:a.call(t,n,r)}:{done:!0,value:e.call(n,t,r)}:{done:!1}}),{REPLACE_KEEPS_$0:Ao,REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE:Co}))[1];Za(String.prototype,e,n[0]),Za(Kj,o,2==t?function(e,t){return c.call(e,this,t)}:function(e){return c.call(e,this)})}r&&kb(Kj[o],"sham",!0)},sw=Fa("match"),Lj=function(e){var t;return xa(e)&&(void 0!==(t=e[sw])?!!t:"RegExp"==xc(e))},Wb=function(e){if("function"!=typeof e)throw TypeError(String(e)+" is not a function");return e},tw=Fa("species"),ee=function(e,t){var n;return void 0===(e=Ia(e).constructor)||null==(n=Ia(e)[tw])?t:Wb(n)},Do=function(e){return function(t,n){t=String(Eb(t)),n=yc(n);var r,o=t.length;if(0>n||n>=o)return e?"":void 0;var i=t.charCodeAt(n);return 55296>i||56319(r=t.charCodeAt(n+1))||57343>>0))return[];if(void 0===e)return[r];if(!Lj(e))return t.call(r,e,n);var o,i,s,a=[],c=0;for(e=new RegExp(e.source,(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.unicode?"u":"")+(e.sticky?"y":"")+"g");(o=hg.call(e,r))&&!((i=e.lastIndex)>c&&(a.push(r.slice(c,o.index)),1=n));)e.lastIndex===o.index&&e.lastIndex++;return c===r.length?(s||!e.test(""))&&a.push(""):a.push(r.slice(c)),a.length>n?a.slice(0,n):a}:"0".split(void 0,0).length?function(e,n){return void 0===e&&0===n?[]:t.call(this,e,n)}:t;return[function(t,n){var o=Eb(this),i=null==t?void 0:t[e];return void 0!==i?i.call(t,o,n):r.call(String(o),t,n)},function(e,o){var i=n(r,e,this,o,r!==t);if(i.done)return i.value;var s=Ia(e);e=String(this);var a=ee(s,RegExp);if(i=s.unicode,s=new a(Rc?"^(?:"+s.source+")":s,(s.ignoreCase?"i":"")+(s.multiline?"m":"")+(s.unicode?"u":"")+(Rc?"g":"y")),0===(o=void 0===o?4294967295:o>>>0))return[];if(0===e.length)return null===ef(s,e)?[e]:[];var c=0,u=0;for(a=[];u>>0||(zw.test(e)?16:10))}:Ch;ea({global:!0,forced:parseInt!=Fo},{parseInt:Fo});var Dd=function(e,t,n){if(Wb(e),void 0===t)return e;switch(n){case 0:return function(){return e.call(t)};case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,o){return e.call(t,n,r,o)}}return function(){return e.apply(t,arguments)}},Ed=Array.isArray||function(e){return"Array"==xc(e)},Aw=Fa("species"),Dh=function(e,t){if(Ed(e)){var n=e.constructor;"function"!=typeof n||n!==Array&&!Ed(n.prototype)?xa(n)&&(null===(n=n[Aw])&&(n=void 0)):n=void 0}return new(void 0===n?Array:n)(0===t?0:t)},Go=[].push,Fd=function(e){var t=1==e,n=2==e,r=3==e,o=4==e,i=6==e,s=7==e,a=5==e||i;return function(c,u,l,f){var h=pb(c),p=fg(h);u=Dd(u,l,3),l=Ma(p.length);var d,b=0;for(f=f||Dh,c=t?f(c,l):n||s?f(c,0):void 0;l>b;b++)if((a||b in p)&&(d=u(f=p[b],b,h),e))if(t)c[b]=d;else if(d)switch(e){case 3:return!0;case 5:return f;case 6:return b;case 2:Go.call(c,f)}else switch(e){case 4:return!1;case 7:Go.call(c,f)}return i?-1:r||o?o:c}},fe=Fd(0),Ho=Fd(1),Io=Fd(2),Bw=Fd(3),Cw=Fd(4),Jo=Fd(5),Dw=Fd(6);Fd(7);var Ew=Fa("species"),kg=function(e){return 51<=Cd||!la((function(){var t=[];return(t.constructor={})[Ew]=function(){return{foo:1}},1!==t[e](Boolean).foo}))},Fw=kg("filter");ea({target:"Array",proto:!0,forced:!Fw},{filter:function(e){return Io(this,e,1c;c++)a=s?i(n[c],c):n[c],hf(r,c,a)}else for(o=(n=a.call(n)).next,r=new r;!(t=o.call(n)).done;c++){if(s){a=n;var l=i;t=[t.value,c];try{u=l(Ia(t)[0],t[1])}catch(e){throw Pj(a),e}}else u=t.value;hf(r,c,a=u)}return r.length=c,r},Lo=Fa("iterator"),Mo=!1;try{var Rw=0,No={next:function(){return{done:!!Rw++}},return:function(){Mo=!0}};No[Lo]=function(){return this},Array.from(No,(function(){throw 2}))}catch(c){}var Eh=function(e,t){if(!t&&!Mo)return!1;var n=!1;try{(t={})[Lo]=function(){return{next:function(){return{done:n=!0}}}},e(t)}catch(e){}return n},Sw=!Eh((function(e){Array.from(e)}));ea({target:"Array",stat:!0,forced:Sw},{from:ge});var Oo=!la((function(){function e(){}return e.prototype.constructor=null,Object.getPrototypeOf(new e)!==e.prototype})),Po=xh("IE_PROTO"),Tw=Object.prototype,uc=Oo?Object.getPrototypeOf:function(e){return e=pb(e),ka(e,Po)?e[Po]:"function"==typeof e.constructor&&e instanceof e.constructor?e.constructor.prototype:e instanceof Object?Tw:null},Sj=Fa("iterator"),Qo=!1,Uw=function(){return this},he;if([].keys){var Ro=[].keys();if("next"in Ro){var So=uc(uc(Ro));So!==Object.prototype&&(he=So)}else Qo=!0}(null==he||la((function(){var e={};return he[Sj].call(e)!==e})))&&(he={}),ka(he,Sj)||kb(he,Sj,Uw);var Fh=he,Gh=Qo,To=wa?Object.defineProperties:function(e,t){Ia(e);for(var n,r=ed(t),o=r.length,i=0;o>i;)qb.f(e,n=r[i++],t[n]);return e},Tj=Pc("document","documentElement"),Uo=xh("IE_PROTO"),Uj=function(){},Vj,Hh=function(){try{Vj=document.domain&&new ActiveXObject("htmlfile")}catch(e){}if(Vj){var e=Vj;e.write("