UNPKG

polyv-live-cli

Version:

CLI tool for managing PolyV live streaming services.

521 lines (496 loc) 24.6 kB
"use strict"; 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.validateListType = validateListType; exports.registerPlaybackCommands = registerPlaybackCommands; 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 validateListType(value) { if (!['playback', 'vod'].includes(value)) { throw new Error('List type must be either "playback" or "vod"'); } return value; } function validateYN(value) { const upper = value.toUpperCase(); if (upper !== 'Y' && upper !== 'N') { throw new Error('Value must be Y or N'); } return upper; } function validateMoveType(value) { if (value !== 'up' && value !== 'down') { throw new Error('Move type must be up or down'); } return value; } async function runPlaybackAction(program, action) { try { const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(program.opts()); const { PlaybackHandler } = await Promise.resolve().then(() => __importStar(require('../handlers/playback.handler'))); await action(new PlaybackHandler(authConfig, serviceConfig)); } catch (error) { (0, errors_1.logError)(error instanceof Error ? error : new Error(String(error))); process.exit(1); } } function registerPlaybackCommands(program) { const playbackCmd = program.command('playback'); playbackCmd.description('回放管理命令'); const listCmd = playbackCmd .command('list') .description(`获取频道回放列表 Examples: $ polyv-live-cli playback list -c "2191532" $ polyv-live-cli playback list -c "2191532" --list-type vod $ polyv-live-cli playback list -c "2191532" --page 2 --page-size 20 -o json`) .requiredOption('-c, --channel-id <channelId>', '频道ID') .option('--page <number>', '页码,默认为1', (value) => parseInt(value, 10), 1) .option('--page-size <number>', '每页数量,默认为10', (value) => parseInt(value, 10), 10) .option('--list-type <type>', '列表类型 (playback|vod)', validateListType, 'playback') .option('-o, --output <format>', '输出格式 (table|json)', validateOutputFormat, 'table') .action(async function (options) { try { const parentOptions = this.optsWithGlobals(); const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions); const { PlaybackHandler } = await Promise.resolve().then(() => __importStar(require('../handlers/playback.handler'))); const playbackHandler = new PlaybackHandler(authConfig, serviceConfig); const listOptions = { channelId: options.channelId, page: options.page, pageSize: options.pageSize, listType: options.listType, output: options.output }; await playbackHandler.listPlayback(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 playback list -c "2191532" # 获取点播列表 $ polyv-live-cli playback list -c "2191532" --list-type vod # 指定分页参数 $ polyv-live-cli playback list -c "2191532" --page 2 --page-size 20 # JSON格式输出 $ polyv-live-cli playback list -c "2191532" -o json Options: -c, --channel-id 频道ID (必填) --page 页码,默认为1 --page-size 每页数量,默认为10 --list-type 列表类型: playback(回放) 或 vod(点播),默认为playback -o, --output 输出格式: table 或 json,默认为table Notes: - 频道ID是必填参数 - 回放列表包含直播生成的回放视频 - 点播列表包含手动上传的视频 `); const getCmd = playbackCmd .command('get') .description(`获取单个回放视频详情 Examples: $ polyv-live-cli playback get -c "2191532" --video-id "1b96d90bf5" $ polyv-live-cli playback get -c "2191532" --video-id "1b96d90bf5" --list-type vod $ polyv-live-cli playback get -c "2191532" --video-id "1b96d90bf5" -o json`) .requiredOption('-c, --channel-id <channelId>', '频道ID') .requiredOption('--video-id <videoId>', '视频ID') .option('--list-type <type>', '列表类型 (playback|vod)', validateListType, 'playback') .option('-o, --output <format>', '输出格式 (table|json)', validateOutputFormat, 'table') .action(async function (options) { try { const parentOptions = this.optsWithGlobals(); const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions); const { PlaybackHandler } = await Promise.resolve().then(() => __importStar(require('../handlers/playback.handler'))); const playbackHandler = new PlaybackHandler(authConfig, serviceConfig); const getOptions = { channelId: options.channelId, videoId: options.videoId, listType: options.listType, output: options.output }; await playbackHandler.getPlayback(getOptions); } 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); } }); getCmd.addHelpText('after', ` Examples: # 获取回放视频详情 $ polyv-live-cli playback get -c "2191532" --video-id "1b96d90bf5" # 获取点播视频详情 $ polyv-live-cli playback get -c "2191532" --video-id "1b96d90bf5" --list-type vod # JSON格式输出 $ polyv-live-cli playback get -c "2191532" --video-id "1b96d90bf5" -o json Options: -c, --channel-id 频道ID (必填) --video-id 视频ID (必填) --list-type 列表类型: playback(回放) 或 vod(点播),默认为playback -o, --output 输出格式: table 或 json,默认为table Notes: - 频道ID和视频ID都是必填参数 - 如果视频不存在,会显示友好的错误提示 `); const deleteCmd = playbackCmd .command('delete') .description(`删除回放视频 Examples: $ polyv-live-cli playback delete -c "3151318" --video-id "1b96d90bf5" $ polyv-live-cli playback delete -c "3151318" --video-id "1b96d90bf5" --force $ polyv-live-cli playback delete -c "3151318" --video-id "1b96d90bf5" --list-type vod --force $ polyv-live-cli playback delete -c "3151318" --video-id "1b96d90bf5" --force -o json`) .requiredOption('-c, --channel-id <channelId>', '频道ID') .requiredOption('--video-id <videoId>', '视频ID') .option('--list-type <type>', '列表类型 (playback|vod)', validateListType, 'playback') .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 { PlaybackHandler } = await Promise.resolve().then(() => __importStar(require('../handlers/playback.handler'))); const playbackHandler = new PlaybackHandler(authConfig, serviceConfig); const deleteOptions = { channelId: options.channelId, videoId: options.videoId, listType: options.listType, force: options.force, output: options.output }; await playbackHandler.deletePlayback(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 playback delete -c "3151318" --video-id "1b96d90bf5" # 跳过确认直接删除 $ polyv-live-cli playback delete -c "3151318" --video-id "1b96d90bf5" --force # 删除点播视频 $ polyv-live-cli playback delete -c "3151318" --video-id "1b96d90bf5" --list-type vod --force # JSON格式输出 $ polyv-live-cli playback delete -c "3151318" --video-id "1b96d90bf5" --force -o json Options: -c, --channel-id 频道ID (必填) --video-id 视频ID (必填) --list-type 列表类型: playback(回放) 或 vod(点播),默认为playback --force 跳过确认提示,直接删除 -o, --output 输出格式: table 或 json,默认为table Notes: - 频道ID和视频ID都是必填参数 - 默认需要确认,使用 --force 可以跳过确认 - 此操作不可撤销,请谨慎使用 `); const mergeCmd = playbackCmd .command('merge') .description(`合并录制文件 Examples: $ polyv-live-cli playback merge -c "3151318" --file-ids "file1,file2,file3" $ polyv-live-cli playback merge -c "3151318" --file-ids "file1,file2" --file-name "合并回放" $ polyv-live-cli playback merge -c "3151318" --file-ids "file1,file2" --async $ polyv-live-cli playback merge -c "3151318" --file-ids "file1,file2" --async --callback-url "http://example.com/callback" $ polyv-live-cli playback merge -c "3151318" --file-ids "file1,file2" --async --auto-convert --merge-mp4 $ polyv-live-cli playback merge -c "3151318" --file-ids "file1,file2" -o json`) .requiredOption('-c, --channel-id <channelId>', '频道ID') .requiredOption('--file-ids <fileIds>', '要合并的录制文件ID,多个ID用逗号分隔') .option('--file-name [fileName]', '合并后的文件名') .option('--async', '使用异步合并模式', false) .option('--callback-url [url]', '合并完成后的回调URL(异步模式)') .option('--auto-convert', '自动转存到点播(异步模式)', false) .option('--merge-mp4', '合并为MP4文件(异步模式)', 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 { PlaybackHandler } = await Promise.resolve().then(() => __importStar(require('../handlers/playback.handler'))); const playbackHandler = new PlaybackHandler(authConfig, serviceConfig); const mergeOptions = { channelId: options.channelId, fileIds: options.fileIds, fileName: options.fileName, async: options.async, callbackUrl: options.callbackUrl, autoConvert: options.autoConvert, mergeMp4: options.mergeMp4, output: options.output }; await playbackHandler.mergePlayback(mergeOptions); } 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); } }); mergeCmd.addHelpText('after', ` Examples: # 同步合并录制文件 $ polyv-live-cli playback merge -c "3151318" --file-ids "file1,file2,file3" # 设置合并后的文件名 $ polyv-live-cli playback merge -c "3151318" --file-ids "file1,file2" --file-name "合并回放" # 异步合并模式 $ polyv-live-cli playback merge -c "3151318" --file-ids "file1,file2" --async # 异步合并 + 回调URL $ polyv-live-cli playback merge -c "3151318" --file-ids "file1,file2" --async --callback-url "http://example.com/callback" # 异步合并 + 自动转存点播 + 合并为MP4 $ polyv-live-cli playback merge -c "3151318" --file-ids "file1,file2" --async --auto-convert --merge-mp4 # JSON格式输出 $ polyv-live-cli playback merge -c "3151318" --file-ids "file1,file2" -o json Options: -c, --channel-id 频道ID (必填) --file-ids 要合并的录制文件ID,多个ID用逗号分隔 (必填) --file-name 合并后的文件名 --async 使用异步合并模式 --callback-url 合并完成后的回调URL(异步模式) --auto-convert 自动转存到点播(异步模式) --merge-mp4 合并为MP4文件(异步模式) -o, --output 输出格式: table 或 json,默认为table Notes: - 频道ID和文件ID是必填参数 - 多个文件ID用英文逗号分隔 - 同步合并会等待合并完成后返回结果 - 异步合并会立即返回,合并完成后可通过回调URL通知 `); playbackCmd .command('setting-list') .description('批量查询频道回放设置') .requiredOption('--channel-ids <ids>', '频道ID,逗号分隔', api_command_1.parseStringList) .option('-o, --output <format>', '输出格式 (table|json)', validateOutputFormat, 'table') .action((options) => runPlaybackAction(program, (handler) => handler.listPlaybackSettings(options))); playbackCmd .command('video-info') .description('批量查询频道单个回放信息') .requiredOption('--channel-ids <ids>', '频道ID,逗号分隔', api_command_1.parseStringList) .option('-o, --output <format>', '输出格式 (table|json)', validateOutputFormat, 'table') .action((options) => runPlaybackAction(program, (handler) => handler.getPlaybackVideoInfo(options))); const enabledCmd = playbackCmd .command('enabled') .description('管理频道回放开关'); enabledCmd .command('get') .description('查询频道回放开关') .requiredOption('-c, --channel-id <channelId>', '频道ID') .option('-o, --output <format>', '输出格式 (table|json)', validateOutputFormat, 'table') .action((options) => runPlaybackAction(program, (handler) => handler.getPlaybackEnabled(options))); enabledCmd .command('set') .description('修改用户或频道回放开关') .requiredOption('--user-id <userId>', '用户ID') .requiredOption('--play-back-enabled <value>', '回放开关 (Y|N)', validateYN) .option('-c, --channel-id <channelId>', '频道ID') .option('-f, --force', '跳过确认提示') .option('-o, --output <format>', '输出格式 (table|json)', validateOutputFormat, 'table') .action((options) => runPlaybackAction(program, (handler) => handler.setPlaybackEnabled(options))); playbackCmd .command('add-vod') .description('将点播视频添加到频道回放视频库') .requiredOption('-c, --channel-id <channelId>', '频道ID') .requiredOption('--vid <vid>', '点播视频ID') .option('--set-as-default <value>', '是否设为默认回放 (Y|N)', validateYN) .option('--list-type <type>', '列表类型 (playback|vod)', validateListType) .option('-f, --force', '跳过确认提示') .option('-o, --output <format>', '输出格式 (table|json)', validateOutputFormat, 'table') .action((options) => runPlaybackAction(program, (handler) => handler.addVodPlayback(options))); const titleCmd = playbackCmd .command('title') .description('管理回放标题'); titleCmd .command('update') .description('修改回放视频名称') .requiredOption('-c, --channel-id <channelId>', '频道ID') .requiredOption('--video-id <videoId>', '回放视频ID') .requiredOption('--title <title>', '新标题') .option('-f, --force', '跳过确认提示') .option('-o, --output <format>', '输出格式 (table|json)', validateOutputFormat, 'table') .action((options) => runPlaybackAction(program, (handler) => handler.updatePlaybackTitle(options))); const sortCmd = playbackCmd .command('sort') .description('管理回放视频排序'); sortCmd .command('move') .description('上移或下移单个回放视频') .requiredOption('-c, --channel-id <channelId>', '频道ID') .requiredOption('--video-id <videoId>', '回放视频ID') .requiredOption('--type <type>', '移动方向 (up|down)', validateMoveType) .option('--list-type <type>', '列表类型 (playback|vod)', validateListType) .option('-f, --force', '跳过确认提示') .option('-o, --output <format>', '输出格式 (table|json)', validateOutputFormat, 'table') .action((options) => runPlaybackAction(program, (handler) => handler.movePlaybackVideo(options))); sortCmd .command('set') .description('按完整视频 ID 列表设置回放排序') .requiredOption('-c, --channel-id <channelId>', '频道ID') .requiredOption('--video-ids <ids>', '回放视频ID,逗号分隔', api_command_1.parseStringList) .option('--list-type <type>', '列表类型 (playback|vod)', validateListType) .option('-f, --force', '跳过确认提示') .option('-o, --output <format>', '输出格式 (table|json)', validateOutputFormat, 'table') .action((options) => runPlaybackAction(program, (handler) => handler.sortPlaybackVideos(options))); const subtitleCmd = playbackCmd .command('subtitle') .description('管理回放字幕'); subtitleCmd .command('update-batch') .description('批量修改频道回放字幕') .requiredOption('-c, --channel-id <channelId>', '频道ID') .requiredOption('--body-json <json>', '字幕数组 JSON,例如 [{"id":1,"name":"字幕","status":"publish"}]', api_command_1.parseJsonArray) .option('-f, --force', '跳过确认提示') .option('-o, --output <format>', '输出格式 (table|json)', validateOutputFormat, 'table') .action((options) => runPlaybackAction(program, (handler) => handler.updateChannelSubtitles({ channelId: options.channelId, body: options.bodyJson, force: options.force, output: options.output, }))); } //# sourceMappingURL=playback.commands.js.map