polyv-live-cli
Version:
CLI tool for managing PolyV live streaming services.
483 lines • 22.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PlatformHandler = void 0;
const base_handler_1 = require("./base.handler");
const errors_1 = require("../utils/errors");
const confirmation_1 = require("../utils/confirmation");
const platform_service_1 = require("../services/platform-service");
const platform_1 = require("../types/platform");
class PlatformHandler extends base_handler_1.BaseHandler {
constructor(authConfig, serviceConfig) {
super();
this.platformService = new platform_service_1.PlatformServiceSdk(authConfig, serviceConfig);
}
async getAccountInfo(options) {
return this.executeWithErrorHandling(async () => {
const format = options.output || 'table';
const userInfo = await this.platformService.getUserInfo();
if (format === 'json') {
this.displayData(userInfo, 'json');
}
else {
this.displayUserInfoTable(userInfo);
}
}, 'platform.getAccountInfo');
}
async getSwitchConfig(options) {
return this.executeWithErrorHandling(async () => {
const format = options.output || 'table';
const switchConfig = await this.platformService.getSwitchConfig();
if (format === 'json') {
this.displayData(switchConfig, 'json');
}
else {
this.displaySwitchConfigTable(switchConfig);
}
}, 'platform.getSwitchConfig');
}
async updateSwitchConfig(options) {
return this.executeWithErrorHandling(async () => {
const format = options.output || 'table';
this.validateUpdateOptions(options);
const result = await this.platformService.updateSwitchConfig({
param: options.param,
enabled: options.enabled,
});
if (format === 'json') {
this.displayData({ success: result.success, param: options.param, enabled: options.enabled }, 'json');
}
else {
this.displaySuccess(`Successfully updated switch config: ${options.param} = ${options.enabled}`);
}
}, 'platform.updateSwitchConfig');
}
async getCallbackSettings(options) {
return this.executeWithErrorHandling(async () => {
const format = options.output || 'table';
const callbackSettings = await this.platformService.getCallbackSettings();
if (format === 'json') {
this.displayData(callbackSettings, 'json');
}
else {
this.displayCallbackSettingsTable(callbackSettings);
}
}, 'platform.getCallbackSettings');
}
async updateCallbackSettings(options) {
return this.executeWithErrorHandling(async () => {
const format = options.output || 'table';
this.validateCallbackOptions(options);
const enabledBoolean = options.enabled !== undefined ? options.enabled === 'Y' : undefined;
const updateParams = {};
if (options.clearUrl) {
updateParams.url = '';
}
else if (options.url !== undefined) {
updateParams.url = options.url;
}
if (enabledBoolean !== undefined) {
updateParams.enabled = enabledBoolean;
}
await this.platformService.updateCallbackSettings(updateParams);
if (format === 'json') {
this.displayData({ success: true, streamCallbackUrl: options.clearUrl ? '' : options.url, enabled: options.enabled }, 'json');
}
else {
this.displaySuccess(`Successfully updated callback settings.`);
if (options.clearUrl) {
this.displayInfo(`Live status callback URL cleared.`);
}
if (options.url) {
this.displayInfo(`Live status callback URL: ${options.url}`);
}
if (options.enabled) {
this.displayInfo(`Enabled: ${options.enabled === 'Y' ? 'Yes' : 'No'}`);
}
}
}, 'platform.updateCallbackSettings');
}
async getGlobalSettings(options) {
return this.executeWithErrorHandling(async () => {
const format = options.output || 'table';
const globalSettings = await this.platformService.getGlobalChannelSettings();
if (format === 'json') {
this.displayData(globalSettings, 'json');
}
else {
this.displayGlobalSettingsTable(globalSettings);
}
}, 'platform.getGlobalSettings');
}
async updateGlobalSettings(options) {
return this.executeWithErrorHandling(async () => {
const format = options.output || 'table';
this.validateGlobalSettingsOptions(options);
const updateParams = {};
if (options.channelConcurrencesEnabled !== undefined) {
updateParams.channelConcurrencesEnabled = options.channelConcurrencesEnabled;
}
if (options.timelyConvertEnabled !== undefined) {
updateParams.timelyConvertEnabled = options.timelyConvertEnabled;
}
if (options.donateEnabled !== undefined) {
updateParams.donateEnabled = options.donateEnabled;
}
if (options.rebirthAutoUploadEnabled !== undefined) {
updateParams.rebirthAutoUploadEnabled = options.rebirthAutoUploadEnabled;
}
if (options.rebirthAutoConvertEnabled !== undefined) {
updateParams.rebirthAutoConvertEnabled = options.rebirthAutoConvertEnabled;
}
if (options.pptCoveredEnabled !== undefined) {
updateParams.pptCoveredEnabled = options.pptCoveredEnabled;
}
if (options.coverImgType !== undefined) {
updateParams.coverImgType = options.coverImgType;
}
if (options.testModeButtonEnabled !== undefined) {
updateParams.testModeButtonEnabled = options.testModeButtonEnabled;
}
await this.platformService.updateGlobalChannelSettings(updateParams);
if (format === 'json') {
this.displayData({ success: true, ...updateParams }, 'json');
}
else {
this.displaySuccess('Successfully updated global settings.');
this.displayUpdatedGlobalSettingsTable(updateParams);
}
}, 'platform.updateGlobalSettings');
}
async listAnchors(options) {
return this.executeWithErrorHandling(async () => {
const result = await this.platformService.listAnchors(this.compact({
pageNumber: options.pageNumber,
pageSize: options.pageSize,
status: options.status,
sex: options.sex,
nickname: options.nickname,
startTime: options.startTime,
endTime: options.endTime,
}));
this.displayData(result, options.output || 'table');
}, 'platform.listAnchors');
}
async getAnchor(options) {
return this.executeWithErrorHandling(async () => {
this.validatePositiveNumber(options.anchorId, 'anchorId');
const result = await this.platformService.getAnchor(options.anchorId);
this.displayData(result, options.output || 'table');
}, 'platform.getAnchor');
}
async createAnchor(options) {
return this.executeWithErrorHandling(async () => {
this.validateAnchorCreateOptions(options);
await this.confirmWrite(options.force, `Create anchor "${options.nickname}"?`);
const result = await this.platformService.createAnchor(this.compact({
nickname: options.nickname,
sex: options.sex,
avatar: options.avatar,
description: options.description,
addChannelIds: options.addChannelIds,
}));
this.displayData(result, options.output || 'table');
}, 'platform.createAnchor');
}
async updateAnchor(options) {
return this.executeWithErrorHandling(async () => {
this.validatePositiveNumber(options.anchorId, 'anchorId');
if (options.nickname === undefined &&
options.sex === undefined &&
options.avatar === undefined &&
options.description === undefined &&
options.addChannelIds === undefined &&
options.delChannelIds === undefined) {
throw this.validationError('At least one update option is required', 'options', options);
}
await this.confirmWrite(options.force, `Update anchor ${options.anchorId}?`);
await this.platformService.updateAnchor(this.compact({
anchorId: options.anchorId,
nickname: options.nickname,
sex: options.sex,
avatar: options.avatar,
description: options.description,
addChannelIds: options.addChannelIds,
delChannelIds: options.delChannelIds,
}));
this.displayData({ success: true, anchorId: options.anchorId }, options.output || 'table');
}, 'platform.updateAnchor');
}
async updateAnchorStatus(options) {
return this.executeWithErrorHandling(async () => {
this.validatePositiveNumber(options.anchorId, 'anchorId');
if (options.status !== 0 && options.status !== 1) {
throw this.validationError('status must be 0 or 1', 'status', options.status);
}
await this.confirmWrite(options.force, `Update anchor ${options.anchorId} status?`);
await this.platformService.updateAnchorStatus({
anchorId: options.anchorId,
status: options.status,
});
this.displayData({ success: true, anchorId: options.anchorId, status: options.status }, options.output || 'table');
}, 'platform.updateAnchorStatus');
}
async listAnchorRelations(options) {
return this.executeWithErrorHandling(async () => {
this.validatePositiveNumber(options.anchorId, 'anchorId');
const result = await this.platformService.listAnchorRelations(this.compact({
anchorId: options.anchorId,
pageNumber: options.pageNumber,
pageSize: options.pageSize,
}));
this.displayData(result, options.output || 'table');
}, 'platform.listAnchorRelations');
}
async listAnchorUnrelations(options) {
return this.executeWithErrorHandling(async () => {
this.validatePositiveNumber(options.anchorId, 'anchorId');
const result = await this.platformService.listAnchorUnrelations(this.compact({
anchorId: options.anchorId,
pageNumber: options.pageNumber,
pageSize: options.pageSize,
}));
this.displayData(result, options.output || 'table');
}, 'platform.listAnchorUnrelations');
}
async listContentGroups(options) {
return this.executeWithErrorHandling(async () => {
const result = await this.platformService.listContentGroups(options.type);
this.displayData(result, options.output || 'table');
}, 'platform.listContentGroups');
}
async listCouponViewers(options) {
return this.executeWithErrorHandling(async () => {
this.validateRequiredString(options.couponId, 'couponId');
const result = await this.platformService.searchCouponViewers(this.compact({
couponId: options.couponId,
pageNumber: options.pageNumber,
pageSize: options.pageSize,
keyword: options.keyword,
receiveSource: options.receiveSource,
}));
this.displayData(result, options.output || 'table');
}, 'platform.listCouponViewers');
}
async updateCoupon(options) {
return this.executeWithErrorHandling(async () => {
this.validateRequiredString(options.couponId, 'couponId');
const config = options.config || {};
if (Object.keys(config).length === 0) {
throw this.validationError('At least one coupon update field is required', 'config', config);
}
await this.confirmWrite(options.force, `Update coupon ${options.couponId}?`);
await this.platformService.updateCoupon({
couponId: options.couponId,
...config,
});
this.displayData({ success: true, couponId: options.couponId }, options.output || 'table');
}, 'platform.updateCoupon');
}
async updateCouponsStatusBatch(options) {
return this.executeWithErrorHandling(async () => {
if (!options.couponIds || options.couponIds.length === 0) {
throw this.validationError('couponIds is required', 'couponIds', options.couponIds);
}
await this.confirmWrite(options.force, `Update status for ${options.couponIds.length} coupon(s)?`);
await this.platformService.updateCouponsStatusBatch({
couponIds: options.couponIds,
});
this.displayData({ success: true, couponIds: options.couponIds }, options.output || 'table');
}, 'platform.updateCouponsStatusBatch');
}
displayGlobalSettingsTable(settings) {
const fieldNames = {
channelConcurrencesEnabled: '最大并发人数开关',
timelyConvertEnabled: '自动转码开关',
donateEnabled: '打赏开关',
rebirthAutoUploadEnabled: '复活自动上传PPT',
rebirthAutoConvertEnabled: '复活自动转码',
pptCoveredEnabled: 'PPT全屏开关',
coverImgType: '封面图类型',
testModeButtonEnabled: '测试模式按钮',
};
const rows = Object.entries(settings)
.filter(([_, value]) => value !== undefined)
.map(([key, value]) => {
const displayName = fieldNames[key] || key;
let displayValue = value;
if (key !== 'coverImgType' && (value === 'Y' || value === 'N')) {
displayValue = value === 'Y' ? '开启' : '禁用';
}
return [displayName, String(displayValue)];
});
this.displayAsTable(rows.map(([displayName, displayValue]) => ({
'设置项': displayName,
'值': displayValue
})));
}
displayUpdatedGlobalSettingsTable(settings) {
const fieldNames = {
channelConcurrencesEnabled: '最大并发人数开关',
timelyConvertEnabled: '自动转码开关',
donateEnabled: '打赏开关',
rebirthAutoUploadEnabled: '复活自动上传PPT',
rebirthAutoConvertEnabled: '复活自动转码',
pptCoveredEnabled: 'PPT全屏开关',
coverImgType: '封面图类型',
testModeButtonEnabled: '测试模式按钮',
};
const rows = Object.entries(settings)
.filter(([key]) => key !== 'output')
.filter(([_, value]) => value !== undefined)
.map(([key, value]) => {
const displayName = fieldNames[key] || key;
let displayValue = value;
if (key !== 'coverImgType' && (value === 'Y' || value === 'N')) {
displayValue = value === 'Y' ? '开启' : '禁用';
}
return [displayName, String(displayValue)];
});
this.displayAsTable(rows.map(([displayName, displayValue]) => ({
'设置项': displayName,
'新值': displayValue
})));
}
validateUpdateOptions(options) {
const errors = [];
if (!options.param || typeof options.param !== 'string' || options.param.trim().length === 0) {
errors.push('param (配置项名称) 是必需的');
}
else if (!platform_1.VALID_SWITCH_PARAMS.includes(options.param)) {
errors.push(`不支持的配置项: ${options.param}。可用配置项: ${platform_1.VALID_SWITCH_PARAMS.join(', ')}`);
}
if (!options.enabled || typeof options.enabled !== 'string') {
errors.push('enabled 必须是 Y 或 N');
}
else if (options.enabled !== 'Y' && options.enabled !== 'N') {
errors.push('enabled 必须是 Y 或 N');
}
if (errors.length > 0) {
throw new errors_1.PolyVValidationError(errors.join('; '), 'options', options, 'validation_failed');
}
}
validateCallbackOptions(options) {
const errors = [];
if (!options.url && !options.enabled && !options.clearUrl) {
errors.push('至少需要提供一个参数 (url、enabled 或 --clear-url)');
}
if (options.url !== undefined && options.url !== '') {
if (!options.url.startsWith('http://') && !options.url.startsWith('https://')) {
errors.push('url 必须以 http:// 或 https:// 开头');
}
}
if (options.enabled !== undefined) {
if (options.enabled !== 'Y' && options.enabled !== 'N') {
errors.push('enabled 必须是 Y 或 N');
}
}
if (errors.length > 0) {
throw new errors_1.PolyVValidationError(errors.join('; '), 'options', options, 'validation_failed');
}
}
displayUserInfoTable(userInfo) {
const tableData = {
'用户 ID': userInfo.userId,
'邮箱': userInfo.email,
'最大频道数': userInfo.maxChannels,
'总频道数': userInfo.totalChannels,
'可用频道数': userInfo.availableChannels,
'连麦限制': userInfo.linkMicLimit,
'观看域名': userInfo.watchDomain || '-',
};
this.displayAsTable(tableData);
}
displaySwitchConfigTable(config) {
const configItems = Array.isArray(config)
? config
: Object.entries(config.config || {}).map(([type, enabled]) => ({ type, enabled }));
const tableData = configItems.map(item => ({
'开关名称': item.type,
'状态': String(item.enabled).toUpperCase() === 'Y' ? 'enabled' : 'disabled',
}));
this.displayAsTable(tableData);
}
displayCallbackSettingsTable(settings) {
const tableData = Object.entries(settings)
.filter(([_, value]) => value !== undefined)
.map(([key, value]) => ({
'设置项': key,
'值': String(value),
}));
this.displayAsTable(tableData);
}
validateGlobalSettingsOptions(options) {
const errors = [];
if (options.channelConcurrencesEnabled === undefined &&
options.timelyConvertEnabled === undefined &&
options.donateEnabled === undefined &&
options.rebirthAutoUploadEnabled === undefined &&
options.rebirthAutoConvertEnabled === undefined &&
options.pptCoveredEnabled === undefined &&
options.coverImgType === undefined &&
options.testModeButtonEnabled === undefined) {
errors.push('至少需要提供一个参数 (At least one parameter is required)');
}
const booleanFields = [
'channelConcurrencesEnabled',
'timelyConvertEnabled',
'donateEnabled',
'rebirthAutoUploadEnabled',
'rebirthAutoConvertEnabled',
'pptCoveredEnabled',
'testModeButtonEnabled',
];
for (const field of booleanFields) {
const value = options[field];
if (value !== undefined) {
if (value !== 'Y' && value !== 'N') {
errors.push(`${field} 必须是 Y 或 N`);
}
}
}
if (options.coverImgType !== undefined) {
if (options.coverImgType !== 'contain' && options.coverImgType !== 'cover') {
errors.push('coverImgType 必须是 contain 或 cover');
}
}
if (errors.length > 0) {
throw new errors_1.PolyVValidationError(errors.join('; '), 'options', options, 'validation_failed');
}
}
validatePositiveNumber(value, field) {
if (!Number.isFinite(value) || Number(value) <= 0) {
throw this.validationError(`${field} must be a positive number`, field, value);
}
}
validateRequiredString(value, field) {
if (!value || value.trim().length === 0) {
throw this.validationError(`${field} is required`, field, value);
}
}
validateAnchorCreateOptions(options) {
this.validateRequiredString(options.nickname, 'nickname');
this.validateRequiredString(options.avatar, 'avatar');
if (options.sex !== 'M' && options.sex !== 'W') {
throw this.validationError('sex must be M or W', 'sex', options.sex);
}
}
compact(params) {
return Object.fromEntries(Object.entries(params).filter(([, value]) => value !== undefined));
}
validationError(message, field, value) {
return new errors_1.PolyVValidationError(message, field, value, 'validation_failed');
}
async confirmWrite(force, message) {
if (force)
return;
const confirmed = await (0, confirmation_1.confirmDeletion)(message);
if (!confirmed) {
throw new Error('Operation cancelled.');
}
}
}
exports.PlatformHandler = PlatformHandler;
//# sourceMappingURL=platform.handler.js.map