UNPKG

polyv-live-cli

Version:

CLI tool for managing PolyV live streaming services.

483 lines 22.1 kB
"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