简介:这是一套基于Wechaty框架开发的智能微信群聊机器人开源实现,面向具备Node.js基础的开发者及群运营管理者,解决疫情常态化下微信群信息过载、关键消息易丢失、多群协同低效等实际管理痛点。资源包共23个文件,含11个核心JS逻辑模块(如onMessage、nCoV、room-message-forward等)、6个JSON配置与记忆文件、1个.env环境变量配置、1个Dockerfile支持容器化部署,以及说明文档和附赠资源,整体仅127KB,轻量易集成。已有168人学习下载,提供完整可运行代码结构、多场景功能模块划分(自动回复、撤回消息捕获、疫情/天气/新闻API对接、定时提醒、娱乐游戏逻辑)、配套说明文件与使用指引,开箱即可调试部署,适合快速掌握微信自动化开发实践并拓展企业群、教育群等真实业务场景。

1. 项目缘起:一个“不务正业”的微信群聊机器人

几年前,我接手了一个需要管理几十个微信社群的运营工作。每天光是手动回复“在吗?”、“这个怎么用?”这类重复问题,就占去了大半时间。更头疼的是,群里总有人发完消息又撤回,留下一串“XXX撤回了一条消息”的提示,让人摸不着头脑,有时甚至会错过重要的通知或反馈。当时市面上的一些“外挂”工具要么不稳定,要么功能单一,要么有封号风险。作为一个有点技术底子的运营,我萌生了自己动手做一个“全能型”微信群助手的想法。

我的核心需求很明确:它得稳定、安全(不能动不动就封号)、功能全面,并且最好能让我用自己熟悉的语言来开发。在对比了多个开源框架后,我最终选择了 Wechaty 。它最大的优势在于提供了一个跨平台、统一的对微信协议的抽象层,让我可以用JavaScript/TypeScript(后来也支持了Python、Go等)像操作一个普通的聊天对象一样去控制微信,而无需深入理解底层复杂的协议细节。这大大降低了开发门槛。

于是,这个项目就从一个简单的自动回复脚本,逐渐演变成了一个集成了 自动回复、防消息撤回、疫情/天气/新闻查询、娱乐游戏、多群管理、定时任务 于一体的智能机器人助手。它彻底把我从繁琐的重复劳动中解放了出来,也让群内的信息流转和互动体验上了一个台阶。今天,我就把这个项目的核心设计思路、关键技术实现,以及我踩过的那些“坑”完整地分享出来。无论你是想做一个提升效率的办公助手,还是想打造一个有趣的社群互动机器人,相信都能从中获得启发。

2. Wechaty框架选型与核心原理剖析

为什么是Wechaty?在项目启动前,我评估过几种主流方案:

  1. 基于Web协议的模拟操作 :如早期通过浏览器插件模拟点击。这种方式极不稳定,微信前端稍有改动就会失效,且容易被检测到异常行为导致封号。
  2. 逆向工程与协议封装 :直接调用微信的私有协议。这种方式功能强大且高效,但技术门槛极高,需要持续跟进制服方的更新,法律和安全风险也最大。
  3. 基于开放API的机器人平台 :一些第三方平台提供API。这种方式简单,但通常需要付费,功能受平台限制,且数据经过第三方服务器,存在隐私顾虑。

Wechaty 走的是第二条路,但它通过开源社区的力量,将协议层的复杂性封装起来,对上层开发者提供了一个干净、一致的 Puppet (傀儡)抽象层。你可以把它理解为一个“驱动程序”。Wechaty本身不实现任何微信协议,它定义了一套标准接口(如登录、发消息、监听事件),具体的协议实现由不同的 Puppet Provider 来完成。

目前主流的Puppet实现有:

  • wechaty-puppet-wechat :基于PC版微信的协议,通过Hook或注入方式实现。它最稳定,功能最接近人工操作,但需要运行在桌面环境(Windows/macOS)。
  • wechaty-puppet-padlocal / wechaty-puppet-service :基于iPad协议,可以运行在服务器(Linux)上,实现7x24小时在线。这是目前社群机器人的主流选择,稳定性好,但通常需要付费获取token。
  • wechaty-puppet-xp :基于Windows原生API,仅限Windows。

注意 :选择Puppet是实现方案的第一步,也直接决定了你的机器人的运行环境和成本。对于需要长期在线的生产环境,我强烈推荐使用基于iPad协议的付费Puppet服务(如PadLocal),虽然有一定费用,但换来了在Linux服务器上稳定运行的能力,省去了维护桌面环境的麻烦。

其核心工作原理可以概括为 “事件驱动” 。你的机器人代码本质上是一个“监听器”,等待着Wechaty框架抛出各种事件,然后你编写对应的处理函数。

// 一个最简化的Wechaty机器人骨架
const { WechatyBuilder } = require('wechaty');

const bot = WechatyBuilder.build({
  puppet: 'wechaty-puppet-wechat', // 指定使用的Puppet
});

bot
  .on('scan', (qrcode, status) => console.log(`扫码登录: ${status}`))
  .on('login', (user) => console.log(`用户 ${user} 登录了`))
  .on('message', async (message) => {
    console.log(`收到消息: ${message.text()}`);
    // 在这里处理消息,实现自动回复、防撤回等功能
    if (message.text() === 'ding') {
      await message.say('dong');
    }
  })
  .on('logout', (user) => console.log(`用户 ${user} 登出了`));

bot.start();

当机器人启动后,它会通过指定的Puppet尝试登录微信(弹出二维码)。登录成功后,任何发生在该微信账号上的事件(如收到消息、有人入群、有人撤回消息)都会被Puppet捕获,并转换成Wechaty的标准事件抛给你的代码。你的任务就是在 on(‘message’) 等事件回调函数里,编写业务逻辑。

3. 核心功能模块设计与实现详解

一个功能丰富的机器人不是一蹴而就的,需要模块化设计。我将我的机器人拆解为以下几个核心模块,每个模块相对独立,通过一个中央调度器(或称为消息路由)来协调工作。

3.1 消息路由与自动回复引擎

这是机器人的“大脑”。所有收到的消息首先经过这里进行解析和分发。我的设计目标是高扩展性和易维护性。

1. 消息预处理 : 首先,需要过滤掉机器人自己发出的消息、系统通知等无效信息,避免自问自答或陷入死循环。

async function onMessage(msg) {
  // 1. 忽略自己发送的消息
  if (msg.self()) return;
  // 2. 忽略非文本消息(如图片、语音),或根据需求特殊处理
  if (msg.type() !== bot.Message.Type.Text) return;
  // 3. 获取发送者和聊天上下文
  const talker = msg.talker();
  const room = msg.room();
  const text = msg.text().trim();
  
  // 将消息交给路由处理器
  await messageRouter.handle(msg, text, talker, room);
}

2. 路由规则设计 : 我采用“关键词触发 + 命令模式”的路由策略。将功能划分为不同的“技能”(Skill)或“插件”(Plugin)。

  • 精确命令 :以特定前缀开头,如 #天气 北京 #新闻 #游戏 猜数字 。路由器识别前缀后,将剩余参数传递给对应的插件。
  • 模糊匹配/智能回复 :针对常见问题(如“你好”、“在吗”、“功能介绍”),使用关键词匹配或简单的NLP(如结巴分词)来触发预设回复。
  • 上下文会话 :对于多轮对话(如玩猜谜游戏),需要维护一个简单的会话上下文(Session),记录当前用户和群聊的状态。

我实现了一个简单的路由表:

class MessageRouter {
  constructor() {
    this.commandHandlers = new Map(); // 存储命令前缀对应的处理函数
    this.keywordHandlers = []; // 存储关键词和对应的处理函数
  }
  
  registerCommand(prefix, handler) {
    this.commandHandlers.set(prefix, handler);
  }
  
  registerKeyword(keyword, handler) {
    this.keywordHandlers.push({ keyword, handler });
  }
  
  async handle(msg, text, talker, room) {
    // 优先检查命令
    for (const [prefix, handler] of this.commandHandlers) {
      if (text.startsWith(prefix)) {
        const args = text.slice(prefix.length).trim();
        await handler(msg, args, talker, room);
        return; // 匹配成功即返回
      }
    }
    // 其次检查关键词
    for (const { keyword, handler } of this.keywordHandlers) {
      if (text.includes(keyword)) {
        await handler(msg, talker, room);
        return;
      }
    }
    // 未匹配任何规则,可进入默认回复或智能聊天流程(如调用ChatGPT API)
  }
}

3. 自动回复的实现 : 自动回复的核心就是 msg.say(content) 方法。但要做好,需要注意:

  • 回复格式 :根据内容类型(纯文本、图片、链接、文件)使用不同的方法。
  • @发言人 :在群聊中回复时,最好能@一下发送者,体验更友好。 await room.say(new bot.Contact(talker.id), textContent)
  • 频率限制 :避免被腾讯判定为营销骚扰。可以设计一个简单的频率限制器,例如同一用户/群N秒内只回复一次。

3.2 “防消息撤回”功能的逆向实现

这是最受群友欢迎的功能之一。其原理是:在用户撤回消息的瞬间,Wechaty的Puppet能够捕获到“消息被撤回”这个事件,并提供了被撤回消息的原始内容。

实现步骤:

  1. 监听撤回事件 :Wechaty提供了 message 事件的子类型 recall
  2. 获取被撤回消息 :在撤回事件的回调函数中,可以通过 messageRecallListener 参数获取到被撤回的原始消息对象。
  3. 重新发送 :将原始消息的内容、发送者信息重新组织成一条新消息,发送到原聊天中。
bot.on('message', async (message) => {
  // 判断是否为撤回消息
  if (message.type() === bot.Message.Type.Recalled) {
    // 获取被撤回的消息
    const recalledMessage = message.toRecalled();
    if (!recalledMessage) return;
    
    const originalText = recalledMessage.text();
    const originalTalker = recalledMessage.talker();
    const room = recalledMessage.room();
    
    if (room) {
      // 在群聊中,构造提示信息并发送
      const recallTip = `【防撤回小助手】\n` +
                       `@${originalTalker.name()} 撤回了以下消息:\n` +
                       `“${originalText}”`;
      // 注意:直接发送可能包含敏感信息,可根据需要做内容过滤
      await room.say(recallTip);
    }
  }
});

实操心得与重要警告

  1. 隐私与合规 :这是本功能最大的“坑”。未经他人同意公开其撤回的消息,可能侵犯隐私,甚至在部分社群中引发矛盾。 强烈建议 :a) 仅在管理员明确同意的内部群或测试群开启此功能;b) 可以对撤回内容进行脱敏处理(如只提示“某人撤回了一条消息”,不显示内容);c) 提供开关,允许群主动态开启/关闭此功能。
  2. 性能考虑 :需要缓存近期消息(因为撤回事件触发时,需要能取到原消息对象)。可以维护一个简单的LRU缓存,键为消息ID,值为消息内容。
  3. 消息类型 :撤回的可能是图片、表情、语音等。上述代码仅处理了文本。处理其他类型消息更复杂,需要保存文件后再转发,实现时要考虑文件存储和清理。

3.3 外部数据集成:天气、新闻与疫情查询

这类功能属于“信息查询类”插件,实现模式高度一致: 解析用户命令 -> 调用第三方API -> 格式化返回结果

以天气查询为例:

  1. 命令设计 #天气 城市名 ,例如 #天气 北京
  2. API选择 :我使用的是高德开放平台的天气API。它免费、稳定,返回JSON格式数据。
  3. 实现代码骨架
const axios = require('axios');
const WEATHER_API_KEY = '你的高德API Key'; // 务必从环境变量读取,不要硬编码

async function weatherHandler(msg, args, talker, room) {
  if (!args) {
    await reply(msg, '请输入城市名,例如:#天气 北京');
    return;
  }
  
  try {
    // 1. 调用高德地理编码API,将城市名转换为adcode(区域代码)
    const geoUrl = `https://restapi.amap.com/v3/geocode/geo?key=${WEATHER_API_KEY}&address=${encodeURIComponent(args)}`;
    const geoResp = await axios.get(geoUrl);
    if (geoResp.data.status !== '1' || !geoResp.data.geocodes.length) {
      await reply(msg, `找不到城市“${args}”`);
      return;
    }
    const adcode = geoResp.data.geocodes[0].adcode;
    
    // 2. 调用高德天气API
    const weatherUrl = `https://restapi.amap.com/v3/weather/weatherInfo?key=${WEATHER_API_KEY}&city=${adcode}&extensions=base`; // base:实时天气 all:预报
    const weatherResp = await axios.get(weatherUrl);
    if (weatherResp.data.status !== '1' || !weatherResp.data.lives.length) {
      await reply(msg, '获取天气信息失败');
      return;
    }
    
    const weather = weatherResp.data.lives[0];
    // 3. 格式化回复
    const replyText = `【${weather.province}${weather.city}天气】\n` +
                      `天气:${weather.weather}\n` +
                      `温度:${weather.temperature}℃\n` +
                      `风向:${weather.winddirection} 风力:${weather.windpower}级\n` +
                      `湿度:${weather.humidity}%\n` +
                      `发布时间:${weather.reporttime}`;
    
    await reply(msg, replyText);
  } catch (error) {
    console.error('天气查询失败:', error);
    await reply(msg, '天气查询服务暂时不可用,请稍后再试。');
  }
}

// 在路由器中注册
router.registerCommand('#天气 ', weatherHandler);

疫情与新闻查询 的实现模式完全相同:

  • 疫情数据 :可以聚合国家卫健委、腾讯/丁香园等公开数据接口。注意数据的权威性和更新频率。
  • 新闻推送 :可以调用聚合数据、天行数据等新闻API。关键在于 信息过滤和摘要生成 ,直接返回一大段新闻原文体验很差。我通常会提取标题、来源和首段,并附上原文链接。

经验之谈

  • API Key管理 :所有第三方API的密钥必须通过环境变量(如 process.env.AMAP_KEY )或配置文件读取,绝不能写在代码里提交到Git。
  • 错误处理与降级 :网络请求必须用 try...catch 包裹,做好超时设置。当主API失效时,应有备用API或返回友好的错误提示。
  • 频率限制 :免费API通常有调用次数限制,需要在代码层面做全局的频率控制,避免超额。
  • 结果缓存 :对于天气、疫情这类更新不频繁的数据,可以引入内存缓存(如node-cache),5-10分钟内相同的查询直接返回缓存结果,大幅减少API调用。

3.4 娱乐互动游戏:猜数字与成语接龙

游戏功能是提升群活跃度的利器。其核心是 状态管理 。机器人需要为每个群(甚至每个用户)维护一个独立的游戏状态。

以“猜数字”游戏为例:

  1. 状态设计 :我们需要记录游戏是否开始、神秘数字是多少、当前轮到谁猜、猜了几次等信息。
class GuessNumberGame {
  constructor(roomId) {
    this.roomId = roomId;
    this.isPlaying = false;
    this.secretNumber = 0;
    this.guessCount = 0;
    this.playerId = null; // 当前玩家
  }
  
  start(playerId) {
    this.isPlaying = true;
    this.secretNumber = Math.floor(Math.random() * 100) + 1; // 1-100
    this.guessCount = 0;
    this.playerId = playerId;
    return `游戏开始!我已想好一个1-100之间的数字,@${playerId} 请开始猜吧!`;
  }
  
  guess(number, playerId) {
    if (!this.isPlaying) return '游戏还没开始呢,发送“猜数字”开始游戏。';
    if (playerId !== this.playerId) return `现在轮到 @${this.playerId} 猜哦~`;
    
    this.guessCount++;
    if (number === this.secretNumber) {
      const msg = `恭喜 @${playerId} !猜对了!数字就是 ${this.secretNumber},一共用了 ${this.guessCount} 次。`;
      this.reset();
      return msg;
    } else if (number < this.secretNumber) {
      return `第${this.guessCount}次:${number} 小了,再猜猜?`;
    } else {
      return `第${this.guessCount}次:${number} 大了,再猜猜?`;
    }
  }
  
  reset() {
    this.isPlaying = false;
    this.secretNumber = 0;
    this.guessCount = 0;
    this.playerId = null;
  }
}
  1. 游戏管理器 :需要一个全局的 GameManager 来管理所有群的游戏实例,键为群ID。
  2. 消息处理 :当收到“猜数字”命令时,调用对应群游戏实例的 start 方法。当收到纯数字消息时,检查该群是否在游戏中,并调用 guess 方法。

成语接龙 逻辑更复杂一些,需要维护一个已说成语的列表,并验证用户新说的成语是否接得上(尾字音同或音近),以及是否有效(可通过本地词库或在线API验证)。其状态管理模型与猜数字类似,但状态数据更多。

3.5 多群管理与定时任务提醒

多群管理 对于Wechaty来说是天然支持的,因为机器人登录的账号本身就在多个群里。关键在于如何区分消息来自哪个群,并执行不同的策略。

  • msg.room() 可以获取到消息来源的群对象,通过 room.id 可以唯一标识一个群。
  • 你可以为不同的群设置不同的功能开关、欢迎语、定时任务等。我通常使用一个简单的JSON配置文件或数据库表来存储群配置。
const groupConfig = {
  '123456@chatroom': { // 群ID
    welcome: true,
    recallGuard: false, // 该群关闭防撤回
    gameEnabled: true,
  },
  '654321@chatroom': {
    welcome: true,
    recallGuard: true, // 该群开启防撤回
    gameEnabled: false,
  }
};

在消息路由或功能函数中,先获取 room.id ,然后查询配置,决定是否执行。

定时任务提醒 是另一个解放生产力的神器。例如,每天上午10点推送新闻,每周五下午提醒提交周报。我使用了 node-schedule 这个库来实现。

const schedule = require('node-schedule');

// 定义一个每天上午10点执行的任务
schedule.scheduleJob('0 10 * * *', async () => {
  console.log('开始执行每日新闻推送任务');
  // 1. 获取所有开启了新闻推送的群
  const targetRooms = await getRoomsWithNewsPushEnabled();
  // 2. 获取今日新闻
  const news = await fetchDailyNews();
  // 3. 向每个群发送新闻摘要
  for (const room of targetRooms) {
    try {
      await room.say(news);
    } catch (e) {
      console.error(`向群 ${room.id} 发送新闻失败:`, e);
    }
  }
});

// 定义一个更复杂的Cron表达式:每周五下午5点
schedule.scheduleJob('0 17 * * 5', () => {
  // 提醒提交周报
});

踩坑记录

  1. 时区问题 node-schedule 默认使用本地系统时区。如果你的服务器在UTC时区,而你想在“北京时间10点”运行,需要显式指定时区,或使用 0 2 * * * (假设UTC+8)来换算。
  2. 任务持久化 node-schedule 的任务是内存态的,一旦机器人进程重启,所有定时任务都会丢失。对于重要的生产任务,需要将任务配置(如Cron表达式、目标群、推送内容模板)存入数据库,并在机器人启动时重新加载和调度。
  3. 长任务阻塞 :定时任务里的操作(如调用API、循环发消息)如果耗时很长,可能会阻塞主线程,影响消息的实时响应。务必将耗时操作包装在 async 函数中,并使用 Promise.all 等方式进行适当的异步控制。

4. 工程化实践:部署、监控与踩坑大全

一个玩具脚本和一个可用的机器人服务之间,隔着工程化的鸿沟。

4.1 部署方案选型:从PC到服务器

  • 开发/测试阶段(Puppet: wechaty-puppet-wechat) : 直接在本地Windows/Mac电脑上运行。优点是调试方便,扫码即登录。缺点是不能关机,不适合长期运行。

  • 生产环境(Puppet: wechaty-puppet-padlocal) : 这是主流选择。你需要购买PadLocal等服务商的token。部署流程如下:

    1. 准备一台Linux服务器(Ubuntu/CentOS)。
    2. 安装Node.js环境。
    3. 将你的机器人代码上传至服务器。
    4. 使用 pm2 systemd 等进程管理工具来启动和守护你的机器人进程。
    # 使用pm2的例子
    npm install -g pm2
    pm2 start bot.js --name wechat-bot
    pm2 save
    pm2 startup # 设置开机自启
    
    1. 配置 WECHATY_PUPPET WECHATY_TOKEN 等环境变量。 登录过程会在服务器终端显示二维码,你需要用手机扫码。扫码登录成功后,会话会保持,即使进程重启,通常也无需重新扫码(取决于Puppet服务商)。

4.2 稳定性保障与监控

机器人最怕两件事: 掉线 内存泄漏

  • 掉线处理 :Wechaty有 logout error 事件。需要在 logout 事件中实现自动重启逻辑,在 error 事件中记录日志并评估是否重启。

    bot.on('logout', (user) => {
      console.error(`机器人 ${user} 登出,尝试重启...`);
      // 可以在这里调用 pm2.restart 或 process.exit(1) 让外部进程管理器重启
      process.exit(1);
    });
    
    bot.on('error', (error) => {
      console.error('机器人发生错误:', error);
      // 某些特定错误可能需要重启
      if (error.message.includes('critical')) {
        process.exit(1);
      }
    });
    

    配合 pm2 --restart-delay --max-restarts 参数,可以实现掉线自动恢复。

  • 日志记录 :使用 winston log4js 等日志库,将运行日志、收到消息、发送消息、API调用错误等记录到文件,并区分不同级别(info, error, debug)。这是排查问题的唯一依据。

  • 内存监控 :长期运行的Node.js进程可能内存缓慢增长。使用 pm2 可以方便地查看内存和CPU占用。定期(如每天)重启一次进程是一个简单粗暴但有效的预防措施。

4.3 我踩过的那些“坑”与解决方案

  1. 消息重复发送/死循环

    • 现象 :机器人自己发了一条消息,又触发了自己的消息监听,导致不停自己回复自己。
    • 根因 :没有在 onMessage 最开始过滤掉 msg.self() 的消息。
    • 解决 :务必在消息处理逻辑入口处添加 if (msg.self()) return;
  2. 扫码登录失败或频繁掉线

    • 现象 :二维码一直失效,或者登录后几分钟就掉线。
    • 根因 :网络环境不稳定(尤其是服务器在海外);使用的Puppet协议被腾讯风控;同一IP登录多个微信账号。
    • 解决 :确保服务器网络稳定(国内服务器最佳);更换Puppet服务商或协议(从免费切换到付费的PadLocal/IPad协议通常更稳);避免一机多号。
  3. 发送消息频率过高被限制

    • 现象 :消息发不出,或账号出现功能限制。
    • 根因 :腾讯对消息发送频率有严格限制,短时间内向太多人或群发送相同内容,极易被判定为营销号。
    • 解决 :为消息发送添加延迟。例如,群发消息时,在每个 room.say() 之间加一个 setTimeout 随机延迟(如1-3秒)。对于主动推送,严格控制频率,如每个群每天不超过3条。
  4. 依赖包版本冲突

    • 现象 npm install 后运行报错,提示某些模块找不到或方法不存在。
    • 根因 :Wechaty及其Puppet包更新较快,API可能有变动。
    • 解决 :在 package.json 中固定核心依赖的版本号,而不是使用 ^ ~ 。尤其是 wechaty wechaty-puppet-* 这些。升级前,务必查看GitHub的Release Notes。
  5. 文件路径与权限问题(服务器部署)

    • 现象 :本地运行正常,上服务器后无法保存图片、录音或日志。
    • 根因 :Node.js进程运行用户(如 www-data nobody )对目标目录没有写权限。
    • 解决 :明确指定所有文件输出的绝对路径(如 /var/log/wechaty-bot/app.log ),并确保该路径存在且进程用户有读写权限。使用 path.join(__dirname, ‘../logs’) 来构建相对项目根目录的路径是个好习惯。

5. 进阶思考:从机器人到智能体

实现基础功能后,你可以思考如何让它变得更“智能”。

  1. 接入大语言模型(LLM) :这是当前最热的方向。你可以将群聊消息(经过过滤和总结)作为上下文,调用 OpenAI API、通义千问或文心一言等,让机器人进行自由对话、解答问题、创作内容。关键在于设计好的 System Prompt ,限定机器人的身份和回答范围,避免胡说八道或产生敏感内容。同时,需要处理API的token长度限制和成本控制。

  2. 连接外部系统(RPA) :让机器人成为触发器。例如,当群里有人说“订会议室下午两点”,机器人可以解析指令,通过内部系统的API自动预订会议室,并将结果反馈到群里。这需要你为机器人开发更多的“技能插件”,每个插件对应一个外部系统的操作。

  3. 数据化运营 :机器人可以默默收集群内的讨论热点、活跃时段、成员互动数据(在合规前提下),定期生成群活跃度报告,帮助管理员更好地运营社群。

  4. 微服务架构拆分 :当功能越来越多,一个庞大的 bot.js 文件会变得难以维护。可以考虑将不同的功能模块拆分为独立的微服务(例如,消息路由一个服务,天气查询一个服务,游戏引擎一个服务),通过消息队列(如Redis)或RPC进行通信。这样提高了可维护性和可扩展性,但架构复杂度也大大增加。

这个基于Wechaty的微信群机器人项目,从一个简单的需求开始,逐渐成长为一个功能丰富的工具。它带给我的不仅是效率的提升,更是一次完整的全栈项目实践——从前端的协议交互、业务逻辑,到后端的服务部署、运维监控。最让我有成就感的时刻,是看到群友们因为这个机器人而互动得更频繁、更开心。技术最终要服务于人,创造价值,这可能就是做这类项目最大的乐趣所在。如果你也想动手做一个,不妨就从监听一条消息并回复“你好”开始吧。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐