polyv-live-cli
Version:
CLI tool for managing PolyV live streaming services.
760 lines (738 loc) • 33 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.loadAuthAndServiceConfig = loadAuthAndServiceConfig;
exports.validateEnabledValue = validateEnabledValue;
exports.validateOutputFormat = validateOutputFormat;
exports.validateUrlFormat = validateUrlFormat;
exports.registerPlatformCommands = registerPlatformCommands;
const platform_handler_1 = require("../handlers/platform.handler");
const manager_1 = require("../config/manager");
const auth_adapter_1 = require("../config/auth-adapter");
const errors_1 = require("../utils/errors");
const confirmation_1 = require("../utils/confirmation");
const api_command_1 = require("../utils/api-command");
const platform_1 = require("../types/platform");
const DEFAULT_TIMEOUT_MS = 30000;
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: DEFAULT_TIMEOUT_MS,
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('');
}
return {
authConfig: authResult.config,
serviceConfig,
isVerbose,
};
}
function validateEnabledValue(value) {
if (value !== 'Y' && value !== 'N') {
throw new Error('enabled 必须是 Y 或 N');
}
return value;
}
function validateOutputFormat(value) {
if (!['table', 'json'].includes(value)) {
throw new Error('Invalid output format. Must be "table" or "json"');
}
return value;
}
function validateUrlFormat(value) {
if (!value.startsWith('http://') && !value.startsWith('https://')) {
throw new Error('url 必须以 http:// 或 https:// 开头');
}
return value;
}
function parsePositiveInteger(value) {
const parsed = Number(value);
if (!Number.isInteger(parsed) || parsed <= 0) {
throw new Error('value must be a positive integer');
}
return parsed;
}
function parseNonNegativeInteger(value) {
const parsed = Number(value);
if (parsed !== 0 && parsed !== 1) {
throw new Error('value must be 0 or 1');
}
return parsed;
}
function parseTimestamp(value) {
const parsed = Number(value);
if (!Number.isFinite(parsed) || parsed <= 0) {
throw new Error('timestamp must be a positive number');
}
return parsed;
}
function parseIdList(value) {
const ids = value.split(',').map(item => Number(item.trim())).filter(Number.isFinite);
if (ids.length === 0 || ids.some(id => !Number.isInteger(id) || id <= 0)) {
throw new Error('ids must be positive integers separated by comma');
}
return ids;
}
function parseStringList(value) {
const ids = value.split(',').map(item => item.trim()).filter(Boolean);
if (ids.length === 0) {
throw new Error('ids must not be empty');
}
return ids;
}
function parseJsonObject(value) {
const parsed = JSON.parse(value);
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
throw new Error('config must be a JSON object');
}
return parsed;
}
function validateSex(value) {
if (value !== 'M' && value !== 'W') {
throw new Error('sex must be M or W');
}
return value;
}
function validateContentGroupType(value) {
if (value !== 'script' && value !== 'robot') {
throw new Error('type must be script or robot');
}
return value;
}
function validateReceiveSource(value) {
if (value !== 'CHANNEL' && value !== 'AGGREGATE_PAGE') {
throw new Error('receive-source must be CHANNEL or AGGREGATE_PAGE');
}
return value;
}
async function confirmPlatformWrite(force, message) {
if (force)
return;
const confirmed = await (0, confirmation_1.confirmDeletion)(message);
if (!confirmed) {
throw new Error('Operation cancelled.');
}
}
function registerPlatformCommands(program) {
const platformCmd = program.command('platform');
platformCmd.description('Platform account info management commands (平台账号信息管理)');
const getCmd = platformCmd
.command('get')
.description('Get account info (获取账号信息)')
.option('-o, --output <format>', 'output format (table|json)', validateOutputFormat, 'table')
.action(async (options) => {
try {
const parentOptions = program.opts();
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions);
const platformHandler = new platform_handler_1.PlatformHandler(authConfig, serviceConfig);
const getOptions = {
output: options.output,
};
await platformHandler.getAccountInfo(getOptions);
}
catch (error) {
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
});
getCmd.addHelpText('after', `
Examples:
$ polyv-live-cli platform get
$ polyv-live-cli platform get -o json
Output Formats:
table - Formatted table output (default)
json - JSON format for programmatic use
`);
const switchCmd = platformCmd.command('switch');
switchCmd.description('Switch configuration management (开关配置管理)');
const switchGetCmd = switchCmd
.command('get')
.description('Get switch configuration (获取开关配置)')
.option('-o, --output <format>', 'output format (table|json)', validateOutputFormat, 'table')
.action(async (options) => {
try {
const parentOptions = program.opts();
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions);
const platformHandler = new platform_handler_1.PlatformHandler(authConfig, serviceConfig);
const getOptions = {
output: options.output,
};
await platformHandler.getSwitchConfig(getOptions);
}
catch (error) {
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
});
switchGetCmd.addHelpText('after', `
Examples:
$ polyv-live-cli platform switch get
$ polyv-live-cli platform switch get -o json
Output Formats:
table - Formatted table output (default)
json - JSON format for programmatic use
`);
const switchUpdateCmd = switchCmd
.command('update')
.description('Update switch configuration (更新开关配置)')
.requiredOption('--param <name>', `switch parameter name (${platform_1.VALID_SWITCH_PARAMS.join('|')})`)
.requiredOption('--enabled <value>', 'enable status (Y|N)', validateEnabledValue)
.option('-f, --force', 'skip confirmation prompt')
.option('-o, --output <format>', 'output format (table|json)', validateOutputFormat, 'table')
.action(async (options) => {
try {
const parentOptions = program.opts();
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions);
const platformHandler = new platform_handler_1.PlatformHandler(authConfig, serviceConfig);
const updateOptions = {
param: options.param,
enabled: options.enabled,
output: options.output,
};
await confirmPlatformWrite(options.force, `Update platform switch ${options.param}?`);
await platformHandler.updateSwitchConfig(updateOptions);
}
catch (error) {
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
});
switchUpdateCmd.addHelpText('after', `
Examples:
# Enable chat
$ polyv-live-cli platform switch update --param chat --enabled Y
# Disable barrage (danmu)
$ polyv-live-cli platform switch update --param closeDanmu --enabled Y
# JSON output
$ polyv-live-cli platform switch update --param autoPlay --enabled N -o json
Tip: run \`platform switch get\` to see the available switch \`type\` values and their
current status; pass any of those \`type\` values to \`--param\`.
Available Parameters (same as the \`type\` values returned by \`switch get\`):
${platform_1.VALID_SWITCH_PARAMS.join(', ')}
Enable Values:
Y - Enable the switch
N - Disable the switch
`);
const callbackCmd = platformCmd.command('callback');
callbackCmd.description('Callback settings management (回调设置管理)');
const callbackGetCmd = callbackCmd
.command('get')
.description('Get callback settings (获取回调设置)')
.option('-o, --output <format>', 'output format (table|json)', validateOutputFormat, 'table')
.action(async (options) => {
try {
const parentOptions = program.opts();
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions);
const platformHandler = new platform_handler_1.PlatformHandler(authConfig, serviceConfig);
const getOptions = {
output: options.output,
};
await platformHandler.getCallbackSettings(getOptions);
}
catch (error) {
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
});
callbackGetCmd.addHelpText('after', `
Examples:
$ polyv-live-cli platform callback get
$ polyv-live-cli platform callback get -o json
Output Formats:
table - Formatted table output (default)
json - JSON format for programmatic use
`);
const callbackUpdateCmd = callbackCmd
.command('update')
.description('Update callback settings (更新回调设置)')
.option('--url <url>', 'live status callback URL / streamCallbackUrl (must start with http:// or https://)', validateUrlFormat)
.option('--clear-url', 'clear the live status callback URL / streamCallbackUrl (sets it to empty)')
.option('--enabled <value>', 'enable status (Y|N)', validateEnabledValue)
.option('-f, --force', 'skip confirmation prompt')
.option('-o, --output <format>', 'output format (table|json)', validateOutputFormat, 'table')
.action(async (options) => {
try {
const parentOptions = program.opts();
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions);
const platformHandler = new platform_handler_1.PlatformHandler(authConfig, serviceConfig);
const updateOptions = {
url: options.url,
clearUrl: options.clearUrl,
enabled: options.enabled,
output: options.output,
};
await confirmPlatformWrite(options.force, 'Update platform callback settings?');
await platformHandler.updateCallbackSettings(updateOptions);
}
catch (error) {
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
});
callbackUpdateCmd.addHelpText('after', `
Examples:
# Update live status callback URL (streamCallbackUrl)
$ polyv-live-cli platform callback update --url https://example.com/callback
# Enable/disable callback
$ polyv-live-cli platform callback update --enabled Y
$ polyv-live-cli platform callback update --enabled N
# Combined update
$ polyv-live-cli platform callback update --url https://example.com/new-callback --enabled Y
# Clear live status callback URL (streamCallbackUrl)
$ polyv-live-cli platform callback update --clear-url
# JSON output
$ polyv-live-cli platform callback update --url https://example.com/callback -o json
URL Format:
URL must start with http:// or https://
Enable Values:
Y - Enable callback
N - Disable callback
Note:
At least one parameter (--url, --enabled, or --clear-url) must be provided.
--url/--clear-url only target streamCallbackUrl (直播状态改变回调URL).
--enabled N only disables rebirthVodCallbackEnabled; use --clear-url to remove streamCallbackUrl itself.
`);
const settingCmd = platformCmd.command('setting');
settingCmd.description('Global channel settings management (全局频道设置管理)');
const settingGetCmd = settingCmd
.command('get')
.description('Get global channel settings (获取全局频道设置)')
.option('-o, --output <format>', 'output format (table|json)', validateOutputFormat, 'table')
.action(async (options) => {
try {
const parentOptions = program.opts();
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions);
const platformHandler = new platform_handler_1.PlatformHandler(authConfig, serviceConfig);
const getOptions = {
output: options.output,
};
await platformHandler.getGlobalSettings(getOptions);
}
catch (error) {
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
});
settingGetCmd.addHelpText('after', `
Examples:
$ polyv-live-cli platform setting get
$ polyv-live-cli platform setting get -o json
Output Formats:
table - Formatted table output (default)
json - JSON format for programmatic use
Note:
The backend GET endpoint returns: channelConcurrencesEnabled, timelyConvertEnabled,
donateEnabled, rebirthAutoUploadEnabled, rebirthAutoConvertEnabled, pptCoveredEnabled,
coverImgType. The \`testModeButtonEnabled\` switch is WRITE-ONLY (set via
\`platform setting update --test-mode-button-enabled\`) and is NOT returned here, so it
cannot be read back through this command.
`);
const settingUpdateCmd = settingCmd
.command('update')
.description('Update global channel settings (更新全局频道设置)')
.option('--channel-concurrences-enabled <value>', 'enable max concurrent viewers (Y|N)', validateGlobalSettingEnabledValue)
.option('--timely-convert-enabled <value>', 'enable auto convert (Y|N)', validateGlobalSettingEnabledValue)
.option('--donate-enabled <value>', 'enable donation (Y|N)', validateGlobalSettingEnabledValue)
.option('--rebirth-auto-upload-enabled <value>', 'enable rebirth auto upload (Y|N)', validateGlobalSettingEnabledValue)
.option('--rebirth-auto-convert-enabled <value>', 'enable rebirth auto convert (Y|N)', validateGlobalSettingEnabledValue)
.option('--ppt-covered-enabled <value>', 'enable PPT full screen (Y|N)', validateGlobalSettingEnabledValue)
.option('--cover-img-type <value>', 'cover image type (contain|cover)', validateCoverImgType)
.option('--test-mode-button-enabled <value>', 'enable test mode button (Y|N) — write-only, NOT returned by `setting get`', validateGlobalSettingEnabledValue)
.option('-f, --force', 'skip confirmation prompt')
.option('-o, --output <format>', 'output format (table|json)', validateOutputFormat, 'table')
.action(async (options) => {
try {
const parentOptions = program.opts();
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions);
const platformHandler = new platform_handler_1.PlatformHandler(authConfig, serviceConfig);
const updateOptions = {
channelConcurrencesEnabled: options.channelConcurrencesEnabled,
timelyConvertEnabled: options.timelyConvertEnabled,
donateEnabled: options.donateEnabled,
rebirthAutoUploadEnabled: options.rebirthAutoUploadEnabled,
rebirthAutoConvertEnabled: options.rebirthAutoConvertEnabled,
pptCoveredEnabled: options.pptCoveredEnabled,
coverImgType: options.coverImgType,
testModeButtonEnabled: options.testModeButtonEnabled,
output: options.output,
};
await confirmPlatformWrite(options.force, 'Update global channel settings?');
await platformHandler.updateGlobalSettings(updateOptions);
}
catch (error) {
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
});
settingUpdateCmd.addHelpText('after', `
Examples:
# Update single setting
$ polyv-live-cli platform setting update --channel-concurrences-enabled Y
$ polyv-live-cli platform setting update --donate-enabled N
$ polyv-live-cli platform setting update --cover-img-type contain
# Update multiple settings
$ polyv-live-cli platform setting update \\
--channel-concurrences-enabled Y \\
--timely-convert-enabled Y \\
--donate-enabled N \\
--cover-img-type contain
# JSON output
$ polyv-live-cli platform setting update --donate-enabled Y -o json
Boolean Parameters:
Y - Enable the setting
N - Disable the setting
Cover Image Types:
contain - Contain mode
cover - Cover mode
Note:
At least one parameter must be provided
`);
const anchorCmd = platformCmd
.command('anchor')
.description('Anchor management (主播管理)');
anchorCmd
.command('list')
.description('List anchors')
.option('--page <page>', 'page number', parsePositiveInteger)
.option('--page-size <size>', 'page size', parsePositiveInteger)
.option('--status <status>', 'status (0|1)', parseNonNegativeInteger)
.option('--sex <sex>', 'sex (M|W)', validateSex)
.option('--nickname <nickname>', 'nickname keyword')
.option('--start-time <timestamp>', 'start timestamp', parseTimestamp)
.option('--end-time <timestamp>', 'end timestamp', parseTimestamp)
.option('-o, --output <format>', 'output format (table|json)', validateOutputFormat, 'table')
.action(async (options) => {
try {
const parentOptions = program.opts();
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions);
const platformHandler = new platform_handler_1.PlatformHandler(authConfig, serviceConfig);
const listOptions = {
pageNumber: options.page,
pageSize: options.pageSize,
status: options.status,
sex: options.sex,
nickname: options.nickname,
startTime: options.startTime,
endTime: options.endTime,
output: options.output,
};
await platformHandler.listAnchors(listOptions);
}
catch (error) {
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
});
anchorCmd
.command('get')
.description('Get anchor detail')
.requiredOption('--anchor-id <id>', 'anchor ID', parsePositiveInteger)
.option('-o, --output <format>', 'output format (table|json)', validateOutputFormat, 'table')
.action(async (options) => {
try {
const parentOptions = program.opts();
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions);
const platformHandler = new platform_handler_1.PlatformHandler(authConfig, serviceConfig);
const getOptions = {
anchorId: options.anchorId,
output: options.output,
};
await platformHandler.getAnchor(getOptions);
}
catch (error) {
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
});
anchorCmd
.command('create')
.description('Create anchor')
.requiredOption('--nickname <nickname>', 'anchor nickname')
.requiredOption('--sex <sex>', 'sex (M|W)', validateSex)
.requiredOption('--avatar <url>', 'avatar URL')
.option('--description <text>', 'description')
.option('--add-channel-ids <ids>', 'channel IDs to associate, comma-separated', parseIdList)
.option('-f, --force', 'skip confirmation prompt')
.option('-o, --output <format>', 'output format (table|json)', validateOutputFormat, 'table')
.action(async (options) => {
try {
const parentOptions = program.opts();
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions);
const platformHandler = new platform_handler_1.PlatformHandler(authConfig, serviceConfig);
const createOptions = {
nickname: options.nickname,
sex: options.sex,
avatar: options.avatar,
description: options.description,
addChannelIds: options.addChannelIds,
force: options.force,
output: options.output,
};
await platformHandler.createAnchor(createOptions);
}
catch (error) {
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
});
anchorCmd
.command('update')
.description('Update anchor')
.requiredOption('--anchor-id <id>', 'anchor ID', parsePositiveInteger)
.option('--nickname <nickname>', 'anchor nickname')
.option('--sex <sex>', 'sex (M|W)', validateSex)
.option('--avatar <url>', 'avatar URL')
.option('--description <text>', 'description')
.option('--add-channel-ids <ids>', 'channel IDs to add, comma-separated', parseIdList)
.option('--del-channel-ids <ids>', 'channel IDs to remove, comma-separated', parseIdList)
.option('-f, --force', 'skip confirmation prompt')
.option('-o, --output <format>', 'output format (table|json)', validateOutputFormat, 'table')
.action(async (options) => {
try {
const parentOptions = program.opts();
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions);
const platformHandler = new platform_handler_1.PlatformHandler(authConfig, serviceConfig);
const updateOptions = {
anchorId: options.anchorId,
nickname: options.nickname,
sex: options.sex,
avatar: options.avatar,
description: options.description,
addChannelIds: options.addChannelIds,
delChannelIds: options.delChannelIds,
force: options.force,
output: options.output,
};
await platformHandler.updateAnchor(updateOptions);
}
catch (error) {
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
});
anchorCmd
.command('update-status')
.description('Update anchor status')
.requiredOption('--anchor-id <id>', 'anchor ID', parsePositiveInteger)
.requiredOption('--status <status>', 'status (0|1)', parseNonNegativeInteger)
.option('-f, --force', 'skip confirmation prompt')
.option('-o, --output <format>', 'output format (table|json)', validateOutputFormat, 'table')
.action(async (options) => {
try {
const parentOptions = program.opts();
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions);
const platformHandler = new platform_handler_1.PlatformHandler(authConfig, serviceConfig);
const updateOptions = {
anchorId: options.anchorId,
status: options.status,
force: options.force,
output: options.output,
};
await platformHandler.updateAnchorStatus(updateOptions);
}
catch (error) {
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
});
anchorCmd
.command('relation-list')
.description('List channels related to an anchor')
.requiredOption('--anchor-id <id>', 'anchor ID', parsePositiveInteger)
.option('--page <page>', 'page number', parsePositiveInteger)
.option('--page-size <size>', 'page size', parsePositiveInteger)
.option('-o, --output <format>', 'output format (table|json)', validateOutputFormat, 'table')
.action(async (options) => {
try {
const parentOptions = program.opts();
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions);
const platformHandler = new platform_handler_1.PlatformHandler(authConfig, serviceConfig);
const relationOptions = {
anchorId: options.anchorId,
pageNumber: options.page,
pageSize: options.pageSize,
output: options.output,
};
await platformHandler.listAnchorRelations(relationOptions);
}
catch (error) {
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
});
anchorCmd
.command('unrelation-list')
.description('List channels not related to an anchor')
.requiredOption('--anchor-id <id>', 'anchor ID', parsePositiveInteger)
.option('--page <page>', 'page number', parsePositiveInteger)
.option('--page-size <size>', 'page size', parsePositiveInteger)
.option('-o, --output <format>', 'output format (table|json)', validateOutputFormat, 'table')
.action(async (options) => {
try {
const parentOptions = program.opts();
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions);
const platformHandler = new platform_handler_1.PlatformHandler(authConfig, serviceConfig);
const relationOptions = {
anchorId: options.anchorId,
pageNumber: options.page,
pageSize: options.pageSize,
output: options.output,
};
await platformHandler.listAnchorUnrelations(relationOptions);
}
catch (error) {
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
});
const contentGroupCmd = platformCmd
.command('content-group')
.description('Content group management');
contentGroupCmd
.command('list')
.description('List content groups')
.requiredOption('--type <type>', 'content type (script|robot)', validateContentGroupType)
.option('-o, --output <format>', 'output format (table|json)', validateOutputFormat, 'table')
.action(async (options) => {
try {
const parentOptions = program.opts();
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions);
const platformHandler = new platform_handler_1.PlatformHandler(authConfig, serviceConfig);
const listOptions = {
type: options.type,
output: options.output,
};
await platformHandler.listContentGroups(listOptions);
}
catch (error) {
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
});
const couponCmd = platformCmd
.command('coupon')
.description('Platform coupon operations');
couponCmd
.command('viewer-list')
.description('List viewers that received a coupon')
.requiredOption('--coupon-id <id>', 'coupon ID')
.option('--page <page>', 'page number', parsePositiveInteger)
.option('--page-size <size>', 'page size', parsePositiveInteger)
.option('--keyword <keyword>', 'viewer keyword')
.option('--receive-source <source>', 'receive source (CHANNEL|AGGREGATE_PAGE)', validateReceiveSource)
.option('-o, --output <format>', 'output format (table|json)', validateOutputFormat, 'table')
.action(async (options) => {
try {
const parentOptions = program.opts();
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions);
const platformHandler = new platform_handler_1.PlatformHandler(authConfig, serviceConfig);
const listOptions = {
couponId: options.couponId,
pageNumber: options.page,
pageSize: options.pageSize,
keyword: options.keyword,
receiveSource: options.receiveSource,
output: options.output,
};
await platformHandler.listCouponViewers(listOptions);
}
catch (error) {
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
});
couponCmd
.command('update')
.description('Update coupon fields from a JSON object')
.requiredOption('--coupon-id <id>', 'coupon ID')
.option('--config-json <json>', 'coupon update JSON object', parseJsonObject)
.option('-f, --force', 'skip confirmation prompt')
.option('-o, --output <format>', 'output format (table|json)', validateOutputFormat, 'table')
.action(async (options) => {
try {
const parentOptions = program.opts();
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions);
const platformHandler = new platform_handler_1.PlatformHandler(authConfig, serviceConfig);
const config = (0, api_command_1.resolveJsonObjectOption)(options.configJson, parentOptions['config']);
const updateOptions = {
couponId: options.couponId,
force: options.force,
output: options.output,
};
if (config) {
updateOptions.config = config;
}
await platformHandler.updateCoupon(updateOptions);
}
catch (error) {
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
});
couponCmd
.command('status-batch')
.description('Batch update coupon status')
.requiredOption('--coupon-ids <ids>', 'coupon IDs, comma-separated', parseStringList)
.option('-f, --force', 'skip confirmation prompt')
.option('-o, --output <format>', 'output format (table|json)', validateOutputFormat, 'table')
.action(async (options) => {
try {
const parentOptions = program.opts();
const { authConfig, serviceConfig } = await loadAuthAndServiceConfig(parentOptions);
const platformHandler = new platform_handler_1.PlatformHandler(authConfig, serviceConfig);
const updateOptions = {
couponIds: options.couponIds,
force: options.force,
output: options.output,
};
await platformHandler.updateCouponsStatusBatch(updateOptions);
}
catch (error) {
(0, errors_1.logError)(error instanceof Error ? error : new Error(String(error)));
process.exit(1);
}
});
}
function validateGlobalSettingEnabledValue(value) {
if (value !== 'Y' && value !== 'N') {
throw new Error('参数值必须是 Y 或 N');
}
return value;
}
function validateCoverImgType(value) {
if (value !== 'contain' && value !== 'cover') {
throw new Error('cover-img-type 必须是 contain 或 cover');
}
return value;
}
//# sourceMappingURL=platform.commands.js.map