polyv-live-cli
Version:
CLI tool for managing PolyV live streaming services.
470 lines (448 loc) • 21.9 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateOutputFormat = validateOutputFormat;
exports.validateStatus = validateStatus;
exports.validateDocType = validateDocType;
exports.registerDocumentCommands = registerDocumentCommands;
const manager_1 = require("../config/manager");
const auth_adapter_1 = require("../config/auth-adapter");
const errors_1 = require("../utils/errors");
const api_command_1 = require("../utils/api-command");
async function loadAuthAndServiceConfig(parentOptions) {
const authResult = auth_adapter_1.authAdapter.tryGetAuthConfig(parentOptions);
if (!authResult) {
throw new Error(auth_adapter_1.authAdapter.getStatusMessage(parentOptions));
}
let configResult;
try {
configResult = await manager_1.configManager.load({
cliOptions: parentOptions,
});
}
catch (error) {
if (error instanceof Error && error.message.includes('Auth configuration is incomplete')) {
configResult = {
config: {
baseUrl: 'https://api.polyv.net',
timeout: 30000,
debug: false,
},
};
}
else {
throw error;
}
}
const serviceConfig = {
baseUrl: configResult.config.baseUrl,
timeout: configResult.config.timeout,
debug: configResult.config.debug,
};
const isVerbose = !!parentOptions.verbose;
if (isVerbose) {
console.log(`🔐 Authentication Source: ${authResult.source}`);
if (authResult.accountName) {
console.log(`👤 Account: ${authResult.accountName}`);
}
console.log('');
}
const result = {
authConfig: authResult.config,
serviceConfig,
isVerbose,
};
if (authResult.source) {
result.authSource = authResult.source;
}
if (authResult.accountName) {
result.accountName = authResult.accountName;
}
return result;
}
function validateOutputFormat(value) {
if (!['table', 'json'].includes(value)) {
throw new Error('Output format must be either "table" or "json"');
}
return value;
}
function validateStatus(value) {
const validStatuses = ['normal', 'waitUpload', 'failUpload', 'waitConvert', 'failConvert'];
if (!validStatuses.includes(value)) {
throw new Error(`Status must be one of: ${validStatuses.join(', ')}`);
}
return value;
}
function validateDocType(value) {
if (!['common', 'animate'].includes(value)) {
throw new Error('Document type must be either "common" or "animate"');
}
return value;
}
function validateRelationOperation(value) {
const parsed = (0, api_command_1.parsePositiveInteger)(value);
if (parsed !== 1 && parsed !== 2) {
throw new Error('operation must be 1 or 2');
}
return parsed;
}
async function runDocumentAction(program, action) {
try {
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(program.opts());
const { DocumentHandler } = await Promise.resolve().then(() => __importStar(require('../handlers/document.handler')));
await action(new DocumentHandler(authConfig, serviceConfig));
}
catch (error) {
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
}
function registerDocumentCommands(program) {
const documentCmd = program.command('document');
documentCmd.description('课件管理命令');
const listCmd = documentCmd
.command('list')
.description(`获取频道课件文档列表
Examples:
$ polyv-live-cli document list -c "3151318"
$ polyv-live-cli document list -c "3151318" --status normal
$ polyv-live-cli document list -c "3151318" --page 2 --page-size 20 -o json`)
.requiredOption('-c, --channel-id <channelId>', '频道ID')
.option('--status <status>', '文档状态 (normal|waitUpload|failUpload|waitConvert|failConvert)', validateStatus)
.option('--page <number>', '页码,默认为1', (value) => parseInt(value, 10), 1)
.option('--page-size <number>', '每页数量,默认为10', (value) => parseInt(value, 10), 10)
.option('-o, --output <format>', '输出格式 (table|json)', validateOutputFormat, 'table')
.action(async function (options) {
try {
const parentOptions = this.optsWithGlobals();
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions);
const { DocumentHandler } = await Promise.resolve().then(() => __importStar(require('../handlers/document.handler')));
const documentHandler = new DocumentHandler(authConfig, serviceConfig);
const listOptions = {
channelId: options.channelId,
status: options.status,
page: options.page,
pageSize: options.pageSize,
output: options.output,
};
await documentHandler.listDocuments(listOptions);
}
catch (error) {
if (error instanceof Error && error.message.includes('Authentication')) {
const diagnostics = auth_adapter_1.authAdapter.getDiagnostics(program.opts());
console.error('\n🔍 Authentication Diagnostics:');
diagnostics.availableSources.forEach(source => {
const status = source.appId && source.appSecret ? '✅' : '❌';
console.error(` ${status} ${source.metadata.source}: ${source.type}`);
});
if (diagnostics.errors.length > 0) {
console.error('\n❌ Errors:');
diagnostics.errors.forEach(err => console.error(` - ${err}`));
}
}
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
});
listCmd.addHelpText('after', `
Examples:
# 获取频道课件列表
$ polyv-live-cli document list -c "3151318"
# 按状态过滤
$ polyv-live-cli document list -c "3151318" --status normal
# 指定分页参数
$ polyv-live-cli document list -c "3151318" --page 2 --page-size 20
# JSON格式输出
$ polyv-live-cli document list -c "3151318" -o json
Options:
-c, --channel-id 频道ID (必填)
--status 文档状态过滤: normal(正常)|waitUpload(等待上传)|failUpload(上传失败)|waitConvert(转换中)|failConvert(转换失败)
--page 页码,默认为1
--page-size 每页数量,默认为10
-o, --output 输出格式: table 或 json,默认为table
Notes:
- 频道ID是必填参数
- 课件文档包含PPT、PDF等教学资料
`);
const uploadCmd = documentCmd
.command('upload')
.description(`上传课件文档到频道
Examples:
$ polyv-live-cli document upload -c "3151318" --url "https://example.com/doc.pdf"
$ polyv-live-cli document upload -c "3151318" --url "https://example.com/ppt.pptx" --type animate
$ polyv-live-cli document upload -c "3151318" --url "..." --doc-name "培训课件" --callback-url "http://example.com/callback"
$ polyv-live-cli document upload -c "3151318" --url "..." -o json`)
.requiredOption('-c, --channel-id <channelId>', '频道ID')
.requiredOption('--url <url>', '文件URL')
.option('--type <type>', '转换类型 (common|animate)', validateDocType, 'common')
.option('--doc-name [name]', '文档名称')
.option('--callback-url [url]', '文档转换完成回调地址')
.option('-o, --output <format>', '输出格式 (table|json)', validateOutputFormat, 'table')
.action(async function (options) {
try {
const parentOptions = this.optsWithGlobals();
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions);
const { DocumentHandler } = await Promise.resolve().then(() => __importStar(require('../handlers/document.handler')));
const documentHandler = new DocumentHandler(authConfig, serviceConfig);
const uploadOptions = {
channelId: options.channelId,
url: options.url,
type: options.type,
docName: options.docName,
callbackUrl: options.callbackUrl,
output: options.output,
};
await documentHandler.uploadDocument(uploadOptions);
}
catch (error) {
if (error instanceof Error && error.message.includes('Authentication')) {
const diagnostics = auth_adapter_1.authAdapter.getDiagnostics(program.opts());
console.error('\n🔍 Authentication Diagnostics:');
diagnostics.availableSources.forEach(source => {
const status = source.appId && source.appSecret ? '✅' : '❌';
console.error(` ${status} ${source.metadata.source}: ${source.type}`);
});
if (diagnostics.errors.length > 0) {
console.error('\n❌ Errors:');
diagnostics.errors.forEach(err => console.error(` - ${err}`));
}
}
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
});
uploadCmd.addHelpText('after', `
Examples:
# 通过URL上传课件
$ polyv-live-cli document upload -c "3151318" --url "https://example.com/doc.pdf"
# 指定转换类型为动画PPT
$ polyv-live-cli document upload -c "3151318" --url "https://example.com/ppt.pptx" --type animate
# 设置文档名称和回调URL
$ polyv-live-cli document upload -c "3151318" --url "..." --doc-name "培训课件" --callback-url "http://example.com/callback"
# JSON格式输出
$ polyv-live-cli document upload -c "3151318" --url "..." -o json
Options:
-c, --channel-id 频道ID (必填)
--url 文件URL (必填)
--type 转换类型: common(普通)|animate(动画),默认为common
--doc-name 文档名称
--callback-url 文档转换完成回调地址
-o, --output 输出格式: table 或 json,默认为table
Notes:
- 频道ID和文件URL是必填参数
- 支持的文件格式: ppt/pdf/pptx/doc/docx/wps
- 文件大小不超过200M
`);
const deleteCmd = documentCmd
.command('delete')
.description(`删除课件文档
Examples:
$ polyv-live-cli document delete -c "3151318" --file-id "abc123"
$ polyv-live-cli document delete -c "3151318" --file-id "abc123" --force
$ polyv-live-cli document delete -c "3151318" --file-id "abc123" --force -o json`)
.requiredOption('-c, --channel-id <channelId>', '频道ID')
.requiredOption('--file-id <fileId>', '文件ID')
.option('--type [type]', '文档类型 (old|new)')
.option('--force', '跳过确认提示,直接删除', false)
.option('-o, --output <format>', '输出格式 (table|json)', validateOutputFormat, 'table')
.action(async function (options) {
try {
const parentOptions = this.optsWithGlobals();
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions);
const { DocumentHandler } = await Promise.resolve().then(() => __importStar(require('../handlers/document.handler')));
const documentHandler = new DocumentHandler(authConfig, serviceConfig);
const deleteOptions = {
channelId: options.channelId,
fileId: options.fileId,
type: options.type,
force: options.force,
output: options.output,
};
await documentHandler.deleteDocument(deleteOptions);
}
catch (error) {
if (error instanceof Error && error.message.includes('Authentication')) {
const diagnostics = auth_adapter_1.authAdapter.getDiagnostics(program.opts());
console.error('\n🔍 Authentication Diagnostics:');
diagnostics.availableSources.forEach(source => {
const status = source.appId && source.appSecret ? '✅' : '❌';
console.error(` ${status} ${source.metadata.source}: ${source.type}`);
});
if (diagnostics.errors.length > 0) {
console.error('\n❌ Errors:');
diagnostics.errors.forEach(err => console.error(` - ${err}`));
}
}
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
});
deleteCmd.addHelpText('after', `
Examples:
# 删除课件文档(需要确认)
$ polyv-live-cli document delete -c "3151318" --file-id "abc123"
# 跳过确认直接删除
$ polyv-live-cli document delete -c "3151318" --file-id "abc123" --force
# JSON格式输出
$ polyv-live-cli document delete -c "3151318" --file-id "abc123" --force -o json
Options:
-c, --channel-id 频道ID (必填)
--file-id 文件ID (必填)
--type 文档类型: old(旧版)|new(新版)
--force 跳过确认提示,直接删除
-o, --output 输出格式: table 或 json,默认为table
Notes:
- 频道ID和文件ID是必填参数
- 默认需要确认,使用 --force 可以跳过确认
- 此操作不可撤销,请谨慎使用
`);
const statusCmd = documentCmd
.command('status')
.description(`查询文档转码状态
Examples:
$ polyv-live-cli document status -c "3151318" --file-id "abc123"
$ polyv-live-cli document status -c "3151318" --file-id "id1,id2"
$ polyv-live-cli document status -c "3151318" --file-id "abc123" -o json`)
.requiredOption('-c, --channel-id <channelId>', '频道ID')
.requiredOption('--file-id <fileId>', '文件ID(多个用逗号分隔)')
.option('-o, --output <format>', '输出格式 (table|json)', validateOutputFormat, 'table')
.action(async function (options) {
try {
const parentOptions = this.optsWithGlobals();
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions);
const { DocumentHandler } = await Promise.resolve().then(() => __importStar(require('../handlers/document.handler')));
const documentHandler = new DocumentHandler(authConfig, serviceConfig);
const statusOptions = {
channelId: options.channelId,
fileId: options.fileId,
output: options.output,
};
await documentHandler.getDocumentStatus(statusOptions);
}
catch (error) {
if (error instanceof Error && error.message.includes('Authentication')) {
const diagnostics = auth_adapter_1.authAdapter.getDiagnostics(program.opts());
console.error('\n🔍 Authentication Diagnostics:');
diagnostics.availableSources.forEach(source => {
const status = source.appId && source.appSecret ? '✅' : '❌';
console.error(` ${status} ${source.metadata.source}: ${source.type}`);
});
if (diagnostics.errors.length > 0) {
console.error('\n❌ Errors:');
diagnostics.errors.forEach(err => console.error(` - ${err}`));
}
}
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
});
statusCmd.addHelpText('after', `
Examples:
# 查询单个文档转码状态
$ polyv-live-cli document status -c "3151318" --file-id "abc123"
# 查询多个文档转码状态
$ polyv-live-cli document status -c "3151318" --file-id "id1,id2"
# JSON格式输出
$ polyv-live-cli document status -c "3151318" --file-id "abc123" -o json
Options:
-c, --channel-id 频道ID (必填)
--file-id 文件ID(多个用逗号分隔) (必填)
-o, --output 输出格式: table 或 json,默认为table
Notes:
- 频道ID和文件ID是必填参数
- 文件ID可以用英文逗号分隔来查询多个文档
`);
const teacherDocCmd = documentCmd
.command('teacher-doc')
.description('管理讲师与文档关系');
teacherDocCmd
.command('relation')
.description('新增或移除讲师文档关系')
.requiredOption('--teacher-id <teacherId>', '讲师ID')
.requiredOption('--file-ids <fileIds>', '文档ID,逗号分隔', api_command_1.parseStringList)
.requiredOption('--operation <operation>', '操作类型:1 新增关系,2 移除关系', validateRelationOperation)
.option('-f, --force', '跳过确认提示')
.option('-o, --output <format>', '输出格式 (table|json)', validateOutputFormat, 'table')
.action((options) => runDocumentAction(program, (handler) => handler.updateTeacherDocRelation(options)));
const mediaCmd = documentCmd
.command('media')
.description('管理频道关联音视频资源');
mediaCmd
.command('vids')
.description('查询频道关联音视频 VID 列表')
.requiredOption('-c, --channel-id <channelId>', '频道ID')
.option('--page <number>', '页码', api_command_1.parsePositiveInteger)
.option('--page-size <number>', '每页数量', api_command_1.parsePositiveInteger)
.option('-o, --output <format>', '输出格式 (table|json)', validateOutputFormat, 'table')
.action((options) => runDocumentAction(program, (handler) => handler.listChannelMultimediaResourceVids(options)));
mediaCmd
.command('details')
.description('查询频道关联音视频文件详情')
.requiredOption('-c, --channel-id <channelId>', '频道ID')
.option('--page <number>', '页码', api_command_1.parsePositiveInteger)
.option('--page-size <number>', '每页数量', api_command_1.parsePositiveInteger)
.option('-o, --output <format>', '输出格式 (table|json)', validateOutputFormat, 'table')
.action((options) => runDocumentAction(program, (handler) => handler.listChannelMultimediaResourceDetails(options)));
mediaCmd
.command('link')
.description('关联音视频文件到频道')
.requiredOption('-c, --channel-id <channelId>', '频道ID')
.requiredOption('--vids <vids>', '音视频 VID,逗号分隔', api_command_1.parseStringList)
.option('-f, --force', '跳过确认提示')
.option('-o, --output <format>', '输出格式 (table|json)', validateOutputFormat, 'table')
.action((options) => runDocumentAction(program, (handler) => handler.linkChannelMultimediaResource(options)));
mediaCmd
.command('unlink')
.description('取消频道关联音视频文件')
.requiredOption('-c, --channel-id <channelId>', '频道ID')
.requiredOption('--vids <vids>', '音视频 VID,逗号分隔', api_command_1.parseStringList)
.option('-f, --force', '跳过确认提示')
.option('-o, --output <format>', '输出格式 (table|json)', validateOutputFormat, 'table')
.action((options) => runDocumentAction(program, (handler) => handler.unlinkChannelMultimediaResource(options)));
mediaCmd
.command('user-detail')
.description('查询用户音视频文件详情')
.requiredOption('--vids <vids>', '音视频 VID,逗号分隔,最多100个', api_command_1.parseStringList)
.option('-o, --output <format>', '输出格式 (table|json)', validateOutputFormat, 'table')
.action((options) => runDocumentAction(program, (handler) => handler.getUserMultimediaResourceDetail(options)));
mediaCmd
.command('user-delete')
.description('删除用户音视频文件')
.requiredOption('--vids <vids>', '音视频 VID,逗号分隔,最多100个', api_command_1.parseStringList)
.option('-f, --force', '跳过确认提示')
.option('-o, --output <format>', '输出格式 (table|json)', validateOutputFormat, 'table')
.action((options) => runDocumentAction(program, (handler) => handler.deleteUserMultimediaResource(options)));
}
//# sourceMappingURL=document.commands.js.map