Skip to content

基础示例

这里提供了一些 OneBot Commander 的基础使用示例,帮助你快速上手。

⚠️ 重要:空格敏感特性

OneBot Commander 对空格非常敏感,这是确保命令精确匹配的重要特性:

  • 模式中的空格必须与输入文本中的空格完全匹配
  • 缺少空格或多余空格都会导致匹配失败
  • 这个特性确保了命令的精确匹配

空格敏感示例

typescript
// 模式: "ping [count:number={value:1}]"
const commander = new Commander('ping [count:number={value:1}]');

commander.action((params) => {
  const count = params.count || { value: 1 };
  return `Pong! (${count.value} times)`;
});

// ✅ 用户输入 "ping " - 匹配成功
const segments1 = [{ type: 'text', data: { text: 'ping ' } }];
const result1 = commander.match(segments1); // ['Pong! (1 times)']

// ❌ 用户输入 "ping" - 匹配失败
const segments2 = [{ type: 'text', data: { text: 'ping' } }];
const result2 = commander.match(segments2); // []

快速开始

1. 简单的文本匹配

typescript
import { Commander } from 'onebot-commander';

// 创建命令解析器(注意空格敏感)
const commander = new Commander('hello <name:text>'); // "hello " 后面的空格

// 设置回调函数
commander.action((params) => {
  console.log(`Hello, ${params.name}!`);
  return { message: `Hello, ${params.name}!` };
});

// 匹配消息段
const segments = [
  { type: 'text', data: { text: 'hello Alice' } } // 注意 "hello " 后面的空格
];

const results = commander.match(segments);
console.log(results[0]); // { name: 'Alice' }

2. 带可选参数的命令

typescript
const commander = new Commander('ping [count:number={value:1}]'); // "ping " 后面的空格

commander.action((params) => {
  const { count = { value: 1 } } = params;
  console.log(`Pinging ${count.value} times...`);
  return { action: 'ping', count };
});

// 有参数的情况
const segments1 = [
  { type: 'text', data: { text: 'ping 5' } } // 注意 "ping " 后面的空格
];
const result1 = commander.match(segments1);
console.log(result1[0]); // { count: 5 }

// 无参数的情况
const segments2 = [
  { type: 'text', data: { text: 'ping ' } } // 注意末尾的空格
];
const result2 = commander.match(segments2);
console.log(result2[0]); // { count: { value: 1 } }

3. 多参数命令

typescript
const commander = new Commander('user <name:text> <age:number> [email:text]'); // 注意参数间的空格

commander.action((params) => {
  const { name, age, email } = params;
  console.log(`用户: ${name}, 年龄: ${age}`);
  if (email) {
    console.log(`邮箱: ${email}`);
  }
  return { user: { name, age, email } };
});

const segments = [
  { type: 'text', data: { text: 'user Alice 25 alice@example.com' } } // 注意参数间的空格
];

const results = commander.match(segments);
console.log(results[0]); // { name: 'Alice', age: 25, email: 'alice@example.com' }

消息段类型示例

1. 表情消息

typescript
const commander = new Commander('{face:1}<message:text>');

commander.action((params) => {
  console.log(`表情消息: ${params.message}`);
  return { type: 'face_message', message: params.message };
});

const segments = [
  { type: 'face', data: { id: 1 } },
  { type: 'text', data: { text: 'Hello!' } }
];

const results = commander.match(segments);
console.log(results[0]); // { message: 'Hello!' }

2. 图片消息

typescript
const commander = new Commander('{image:photo.jpg}<caption:text>');

commander.action((params) => {
  console.log(`图片说明: ${params.caption}`);
  return { type: 'image', caption: params.caption };
});

const segments = [
  { type: 'image', data: { file: 'photo.jpg' } },
  { type: 'text', data: { text: '美丽的风景' } }
];

const results = commander.match(segments);
console.log(results[0]); // { caption: '美丽的风景' }

3. @用户消息

typescript
const commander = new Commander('{at:123456}<message:text>');

commander.action((params) => {
  console.log(`@用户消息: ${params.message}`);
  return { type: 'at_message', message: params.message };
});

const segments = [
  { type: 'at', data: { user_id: '123456' } },
  { type: 'text', data: { text: '请查看这个' } }
];

const results = commander.match(segments);
console.log(results[0]); // { message: '请查看这个' }

链式调用示例

1. 数据处理链

typescript
const commander = new Commander('process <data:text>');

commander
  .action((params) => {
    // 第一步:数据验证
    if (!params.data.trim()) {
      throw new Error('数据不能为空');
    }
    return { data: params.data.trim() };
  })
  .action((params) => {
    // 第二步:数据转换
    return { data: params.data.toUpperCase() };
  })
  .action((params) => {
    // 第三步:数据输出
    console.log(`处理结果: ${params.data}`);
    return { result: params.data };
  });

const segments = [
  { type: 'text', data: { text: 'process hello world' } }
];

const results = commander.match(segments);
console.log(results[0]); // { result: 'HELLO WORLD' }

2. 条件处理链

typescript
const commander = new Commander('check <value:number>');

commander
  .action((params) => {
    // 检查数值范围
    if (params.value < 0) {
      throw new Error('数值不能为负数');
    }
    return params;
  })
  .action((params) => {
    // 根据数值大小分类
    if (params.value < 10) {
      return { ...params, category: 'small' };
    } else if (params.value < 100) {
      return { ...params, category: 'medium' };
    } else {
      return { ...params, category: 'large' };
    }
  })
  .action((params) => {
    // 输出结果
    console.log(`数值 ${params.value} 属于 ${params.category} 类别`);
    return params;
  });

const segments = [
  { type: 'text', data: { text: 'check 25' } }
];

const results = commander.match(segments);
console.log(results[0]); // { value: 25, category: 'medium' }

错误处理示例

1. 基本错误处理

typescript
const commander = new Commander('divide <a:number> <b:number>');

commander.action((params) => {
  const { a, b } = params;
  
  if (b === 0) {
    throw new Error('除数不能为零');
  }
  
  const result = a / b;
  return { result, operation: 'division' };
});

try {
  const segments = [
    { type: 'text', data: { text: 'divide 10 0' } }
  ];
  
  const results = commander.match(segments);
  console.log(results[0]);
} catch (error) {
  console.error('计算错误:', error.message);
}

2. 参数验证

typescript
const commander = new Commander('user <name:text> <age:number>');

commander.action((params) => {
  const { name, age } = params;
  
  // 验证姓名
  if (name.length < 2) {
    throw new Error('姓名长度不能少于2个字符');
  }
  
  // 验证年龄
  if (age < 0 || age > 150) {
    throw new Error('年龄必须在0-150之间');
  }
  
  return { name, age, valid: true };
});

try {
  const segments = [
    { type: 'text', data: { text: 'user A 200' } }
  ];
  
  const results = commander.match(segments);
  console.log(results[0]);
} catch (error) {
  console.error('验证失败:', error.message);
}

实际应用示例

1. 简单的聊天机器人

typescript
class ChatBot {
  private commanders = new Map();
  
  constructor() {
    this.setupCommands();
  }
  
  setupCommands() {
    // 问候命令
    const greetCommander = new Commander('hello [name:text=World]');
    greetCommander.action((params) => {
      return `Hello, ${params.name}!`;
    });
    this.commanders.set('greet', greetCommander);
    
    // 天气查询命令
    const weatherCommander = new Commander('weather <city:text>');
    weatherCommander.action((params) => {
      return `查询 ${params.city} 的天气信息...`;
    });
    this.commanders.set('weather', weatherCommander);
    
    // 计算命令
    const calcCommander = new Commander('calc <expression:text>');
    calcCommander.action((params) => {
      try {
        const result = eval(params.expression);
        return `计算结果: ${result}`;
      } catch (error) {
        return `计算错误: ${error.message}`;
      }
    });
    this.commanders.set('calc', calcCommander);
  }
  
  processMessage(segments) {
    for (const [name, commander] of this.commanders) {
      try {
        const results = commander.match(segments);
        if (results.length > 0) {
          return results[0];
        }
      } catch (error) {
        console.warn(`命令 ${name} 执行失败:`, error.message);
      }
    }
    return '抱歉,我不理解这个命令。';
  }
}

// 使用示例
const bot = new ChatBot();

const messages = [
  { type: 'text', data: { text: 'hello Alice' } },
  { type: 'text', data: { text: 'weather Beijing' } },
  { type: 'text', data: { text: 'calc 2 + 3 * 4' } }
];

messages.forEach(segments => {
  const response = bot.processMessage([segments]);
  console.log('机器人回复:', response);
});

2. 文件处理系统

typescript
class FileProcessor {
  private commanders = new Map();
  
  constructor() {
    this.setupCommands();
  }
  
  setupCommands() {
    // 文件上传命令
    const uploadCommander = new Commander('upload <filename:text> [description:text]');
    uploadCommander.action(async (params) => {
      const { filename, description } = params;
      console.log(`上传文件: ${filename}`);
      if (description) {
        console.log(`文件描述: ${description}`);
      }
      return { action: 'upload', filename, description };
    });
    this.commanders.set('upload', uploadCommander);
    
    // 文件下载命令
    const downloadCommander = new Commander('download <filename:text>');
    downloadCommander.action(async (params) => {
      const { filename } = params;
      console.log(`下载文件: ${filename}`);
      return { action: 'download', filename };
    });
    this.commanders.set('download', downloadCommander);
    
    // 文件列表命令
    const listCommander = new Commander('list [pattern:text=*]');
    listCommander.action(async (params) => {
      const { pattern } = params;
      console.log(`列出文件: ${pattern}`);
      return { action: 'list', pattern };
    });
    this.commanders.set('list', listCommander);
  }
  
  async processCommand(segments) {
    for (const [name, commander] of this.commanders) {
      try {
        const results = await commander.matchAsync(segments);
        if (results.length > 0) {
          return results[0];
        }
      } catch (error) {
        console.error(`命令 ${name} 执行失败:`, error.message);
      }
    }
    throw new Error('未知命令');
  }
}

// 使用示例
const processor = new FileProcessor();

const commands = [
  { type: 'text', data: { text: 'upload document.pdf 重要文档' } },
  { type: 'text', data: { text: 'download image.jpg' } },
  { type: 'text', data: { text: 'list *.pdf' } }
];

async function runCommands() {
  for (const segments of commands) {
    try {
      const result = await processor.processCommand([segments]);
      console.log('处理结果:', result);
    } catch (error) {
      console.error('处理失败:', error.message);
    }
  }
}

runCommands();

性能优化示例

1. 缓存命令解析器

typescript
class CachedCommandManager {
  private cache = new Map();
  
  getCommander(pattern) {
    if (!this.cache.has(pattern)) {
      this.cache.set(pattern, new Commander(pattern));
    }
    return this.cache.get(pattern);
  }
  
  clearCache() {
    this.cache.clear();
  }
  
  getCacheSize() {
    return this.cache.size;
  }
}

const manager = new CachedCommandManager();

// 重复使用相同的模式
const commander1 = manager.getCommander('hello <name:text>');
const commander2 = manager.getCommander('hello <name:text>'); // 从缓存获取

console.log('缓存大小:', manager.getCacheSize()); // 1

2. 批量处理

typescript
function batchProcess(commanders, segments) {
  const results = [];
  
  for (const commander of commanders) {
    try {
      const result = commander.match(segments);
      if (result.length > 0) {
        results.push({ commander, result: result[0] });
        break; // 找到第一个匹配就停止
      }
    } catch (error) {
      console.warn('匹配失败:', error.message);
    }
  }
  
  return results;
}

const commanders = [
  new Commander('hello <name:text>'),
  new Commander('ping [count:number]'),
  new Commander('echo <message:text>')
];

const segments = [
  { type: 'text', data: { text: 'hello Alice' } }
];

const results = batchProcess(commanders, segments);
console.log('批量处理结果:', results);

下一步


💡 提示

这些基础示例展示了 OneBot Commander 的核心功能,建议先掌握这些基础用法,再学习更高级的特性。

Released under the MIT License.