You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tailchat/server/plugins/com.msgbyte.agora/services/agora.service.dev.ts

174 lines
4.3 KiB
TypeScript

import { DataNotFoundError, TcContext } from 'tailchat-server-sdk';
import { TcService, TcDbService } from 'tailchat-server-sdk';
import type { AgoraDocument, AgoraModel } from '../models/agora';
import { RtcTokenBuilder, Role as RtcRole } from './utils/RtcTokenBuilder2';
import got from 'got';
// Reference: https://docs.agora.io/cn/metachat/rtc_channel_management_restfulapi#查询用户列表
interface ChannelUserListRet {
success: boolean;
data:
| {
channel_exist: false;
}
| {
channel_exist: true;
mode: 1 | 2;
total: number;
users: string[]; // 频道内所有用户的用户 ID
broadcasters: string[]; // 频道内所有主播的用户 ID。该字段仅在直播场景
audience: string[]; // 频道内观众的用户 ID。最多包含当前频道内前 10,000 名观众的用户 ID。该字段仅在直播场景 mode 的值为 2下返回。
audience_total: number; // 频道内的观众总人数。该字段仅在直播场景 mode 的值为 2下返回。
};
}
/**
*
*
* Tailchat
*/
interface AgoraService
extends TcService,
TcDbService<AgoraDocument, AgoraModel> {}
class AgoraService extends TcService {
get serviceName() {
return 'plugin:com.msgbyte.agora';
}
/**
* appid
*/
get serverAppId() {
return process.env.AGORA_APP_ID;
}
/**
* app
*/
get serverAppCertificate() {
return process.env.AGORA_APP_CERT;
}
/**
* restful ID
*/
get serverCustomerKey() {
return process.env.AGORA_CUSTOMER_KEY;
}
/**
* restful
*/
get serverCustomerSecret() {
return process.env.AGORA_CUSTOMER_SECRET;
}
onInit() {
if (
!this.serverAppId ||
!this.serverAppCertificate ||
!this.serverCustomerKey ||
!this.serverCustomerSecret
) {
this.logger.warn(
'声网服务启动失败, 缺少必要的环境变量。AGORA_APP_ID, AGORA_APP_CERT, AGORA_CUSTOMER_KEY, AGORA_CUSTOMER_SECRET'
);
return;
}
// this.registerLocalDb(require('../models/agora').default);
this.registerAction('generateToken', this.generateToken, {
params: {
channelName: 'string',
appId: { type: 'string', optional: true },
appCert: { type: 'string', optional: true },
},
});
this.registerAction('getChannelUserList', this.getChannelUserList, {
params: {
channelName: 'string',
},
});
}
generateToken(
ctx: TcContext<{
channelName: string;
appId?: string;
appCert?: string;
}>
) {
const {
channelName,
appId = this.serverAppId,
appCert = this.serverAppCertificate,
} = ctx.params;
if (!appId || !appCert) {
throw new Error('Agora.io AppId/AppCert not init');
}
const role = RtcRole.PUBLISHER;
const userId = ctx.meta.userId;
const tokenExpirationInSecond = 3600; // 1h
const privilegeExpirationInSecond = 3600; // 1h
// Build token with user account
const token = RtcTokenBuilder.buildTokenWithUserAccount(
appId,
appCert,
channelName,
userId,
role,
tokenExpirationInSecond,
privilegeExpirationInSecond
);
return token;
}
/**
*
*/
async getChannelUserList(
ctx: TcContext<{
channelName: string;
}>
): Promise<ChannelUserListRet['data']> {
const { channelName } = ctx.params;
const { data } = await got
.get(
`https://api.agora.io/dev/v1/channel/user/${this.serverAppId}/${channelName}`,
{
headers: this.generateRESTfulHeaders(),
}
)
.json<ChannelUserListRet>();
if (data.channel_exist === false) {
throw new DataNotFoundError('Channel not exist');
}
return data;
}
/**
* restful api
*/
private generateRESTfulHeaders() {
const encodedCredential = Buffer.from(
this.serverCustomerKey + ':' + this.serverCustomerSecret
).toString('base64');
return {
Authorization: 'Basic ' + encodedCredential,
'Content-Type': 'application/json',
};
}
}
export default AgoraService;