参数提取
参数提取是 OneBot Commander 的重要功能,它允许你从匹配的消息段中获取和处理各种类型的参数。
参数类型
基础类型参数
文本参数
typescript
const commander = new Commander('echo <message:text>');
const segments = [
{ type: 'text', data: { text: 'echo Hello World' } }
];
const result = commander.match(segments);
// result[0] = { message: 'Hello World' }
数字参数
typescript
const commander = new Commander('count <number:number>');
const segments = [
{ type: 'text', data: { text: 'count 123' } }
];
const result = commander.match(segments);
// result[0] = { number: 123 }
布尔参数
typescript
const commander = new Commander('toggle <state:boolean>');
const segments = [
{ type: 'text', data: { text: 'toggle true' } }
];
const result = commander.match(segments);
// result[0] = { state: true }
OneBot 消息段参数
表情参数
typescript
const commander = new Commander('react <emoji:face>');
const segments = [
{ type: 'text', data: { text: 'react' } },
{ type: 'face', data: { id: 1 } }
];
const result = commander.match(segments);
// result[0] = { emoji: { type: 'face', data: { id: 1 } } }
图片参数
typescript
const commander = new Commander('upload <image:image>');
const segments = [
{ type: 'text', data: { text: 'upload' } },
{ type: 'image', data: { file: 'photo.jpg' } }
];
const result = commander.match(segments);
// result[0] = { image: { type: 'image', data: { file: 'photo.jpg' } } }
@用户参数
typescript
const commander = new Commander('ping <user:at>');
const segments = [
{ type: 'text', data: { text: 'ping' } },
{ type: 'at', data: { user_id: 123456 } }
];
const result = commander.match(segments);
// result[0] = { user: { type: 'at', data: { user_id: 123456 } } }
参数处理技巧
1. 参数验证
typescript
const commander = new Commander('user <name:text> <age:number>');
commander.action((params) => {
// 验证必需参数
if (!params.name || params.name.trim() === '') {
throw new Error('用户名不能为空');
}
if (params.age < 0 || params.age > 150) {
throw new Error('年龄必须在 0-150 之间');
}
return { name: params.name, age: params.age };
});
2. 参数转换
typescript
const commander = new Commander('config <key:text> <value:text>');
commander.action((params) => {
// 转换参数格式
const key = params.key.toLowerCase().replace(/\s+/g, '_');
const value = params.value.trim();
return { key, value };
});
3. 参数组合
typescript
const commander = new Commander('search <query:text> [...filters:text]');
commander.action((params) => {
const { query, filters = [] } = params;
// 组合搜索条件
const searchCriteria = {
query: query.trim(),
filters: filters.map(f => f.trim()).filter(f => f.length > 0)
};
return searchCriteria;
});
高级参数提取
1. 嵌套参数
typescript
const commander = new Commander('api <endpoint:text> <data:json>');
const segments = [
{ type: 'text', data: { text: 'api /users' } },
{ type: 'json', data: { data: '{"name":"Alice","age":25}' } }
];
const result = commander.match(segments);
// result[0] = {
// endpoint: '/users',
// data: { name: 'Alice', age: 25 }
// }
2. 剩余参数
typescript
const commander = new Commander('forward [...messages]');
const segments = [
{ type: 'text', data: { text: 'forward' } },
{ type: 'text', data: { text: 'message1' } },
{ type: 'face', data: { id: 1 } },
{ type: 'image', data: { file: 'img.jpg' } }
];
const result = commander.match(segments);
// result[0] = {
// messages: [
// { type: 'text', data: { text: 'message1' } },
// { type: 'face', data: { id: 1 } },
// { type: 'image', data: { file: 'img.jpg' } }
// ]
// }
3. 类型化剩余参数
typescript
const commander = new Commander('gallery [...images:image]');
const segments = [
{ type: 'text', data: { text: 'gallery' } },
{ type: 'image', data: { file: 'img1.jpg' } },
{ type: 'image', data: { file: 'img2.jpg' } },
{ type: 'text', data: { text: 'caption' } }
];
const result = commander.match(segments);
// result[0] = {
// images: [
// { type: 'image', data: { file: 'img1.jpg' } },
// { type: 'image', data: { file: 'img2.jpg' } }
// ]
// }
// 剩余: [{ type: 'text', data: { text: 'caption' } }]
参数处理最佳实践
1. 默认值处理
typescript
const commander = new Commander('ping [count:number] [message:text]');
commander.action((params) => {
// 设置默认值
const count = params.count || 1;
const message = params.message || 'pong';
return { count, message };
});
2. 参数清理
typescript
const commander = new Commander('user <name:text> [email:text]');
commander.action((params) => {
// 清理和验证参数
const name = params.name.trim();
const email = params.email ? params.email.trim().toLowerCase() : null;
// 验证邮箱格式
if (email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
throw new Error('邮箱格式不正确');
}
return { name, email };
});
3. 参数类型转换
typescript
const commander = new Commander('calc <a:number> <op:text> <b:number>');
commander.action((params) => {
const { a, op, b } = params;
// 类型转换和验证
const numA = Number(a);
const numB = Number(b);
if (isNaN(numA) || isNaN(numB)) {
throw new Error('参数必须是数字');
}
// 执行计算
let result;
switch (op) {
case '+': result = numA + numB; break;
case '-': result = numA - numB; break;
case '*': result = numA * numB; break;
case '/': result = numA / numB; break;
default: throw new Error('不支持的运算符');
}
return { a: numA, op, b: numB, result };
});
错误处理
1. 参数验证错误
typescript
const commander = new Commander('user <name:text> <age:number>');
commander.action((params) => {
try {
// 参数验证
if (!params.name || params.name.length < 2) {
throw new Error('用户名至少需要2个字符');
}
if (params.age < 0 || params.age > 150) {
throw new Error('年龄必须在0-150之间');
}
return { name: params.name, age: params.age };
} catch (error) {
return { error: error.message };
}
});
2. 类型转换错误
typescript
const commander = new Commander('convert <value:text> <type:text>');
commander.action((params) => {
try {
const { value, type } = params;
let result;
switch (type) {
case 'number':
result = Number(value);
if (isNaN(result)) throw new Error('无法转换为数字');
break;
case 'boolean':
result = value.toLowerCase() === 'true';
break;
case 'json':
result = JSON.parse(value);
break;
default:
throw new Error('不支持的转换类型');
}
return { original: value, converted: result, type };
} catch (error) {
return { error: error.message };
}
});
性能优化
1. 参数缓存
typescript
const paramCache = new Map();
function processParam(param, type) {
const key = `${param}_${type}`;
if (!paramCache.has(key)) {
let processed;
switch (type) {
case 'number':
processed = Number(param);
break;
case 'boolean':
processed = param.toLowerCase() === 'true';
break;
default:
processed = param;
}
paramCache.set(key, processed);
}
return paramCache.get(key);
}
2. 批量参数处理
typescript
function batchProcessParams(params, processors) {
const results = {};
for (const [key, processor] of Object.entries(processors)) {
if (params[key] !== undefined) {
results[key] = processor(params[key]);
}
}
return results;
}
// 使用示例
const processors = {
name: (value) => value.trim(),
age: (value) => Number(value),
email: (value) => value.toLowerCase()
};
const processed = batchProcessParams(params, processors);
调试技巧
1. 参数日志
typescript
const commander = new Commander('debug <param:text>');
commander.action((params) => {
console.log('原始参数:', params);
console.log('参数类型:', typeof params.param);
console.log('参数长度:', params.param.length);
return { debug: true, param: params.param };
});
2. 参数验证工具
typescript
function validateParams(params, schema) {
const errors = [];
for (const [key, rules] of Object.entries(schema)) {
const value = params[key];
if (rules.required && (value === undefined || value === null)) {
errors.push(`${key} 是必需的`);
}
if (value !== undefined && rules.type && typeof value !== rules.type) {
errors.push(`${key} 必须是 ${rules.type} 类型`);
}
if (value !== undefined && rules.min && value < rules.min) {
errors.push(`${key} 不能小于 ${rules.min}`);
}
if (value !== undefined && rules.max && value > rules.max) {
errors.push(`${key} 不能大于 ${rules.max}`);
}
}
return errors;
}
// 使用示例
const schema = {
name: { required: true, type: 'string', min: 2 },
age: { required: false, type: 'number', min: 0, max: 150 }
};
const errors = validateParams(params, schema);
if (errors.length > 0) {
console.error('参数验证失败:', errors);
}
下一步
💡 提示
参数提取是处理用户输入的关键步骤,良好的参数处理可以提高代码的健壮性和用户体验。