# im-robot **Repository Path**: seek/im-robot ## Basic Information - **Project Name**: im-robot - **Description**: 基于Wechaty的微信机器人,带有娱乐功能 - **Primary Language**: JavaScript - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-08-20 - **Last Updated**: 2021-11-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## nodejs 结合 wechaty 实现你的微信群聊机器人 [![Powered by Wechaty](https://img.shields.io/badge/Powered%20By-Wechaty-green.svg)](https://github.com/chatie/wechaty) [![Wechaty开源激励计划](https://img.shields.io/badge/Wechaty-开源激励计划-green.svg)](https://github.com/juzibot/Welcome/wiki/Everything-about-Wechaty) ### 如何获取免费 Token 1. 添加 `botorange_yeah` 为微信好友,成功填写开源激励计划申请表和项目信息的开发者,即可领取 15 天免费 Token 用于 MVP 版本开发。 2. 15天内,提交到 wechaty 的任何一个项目下的 pull request 被 merge 即可成为 wechaty 的 contributor,可以领取长期有效的 Token。最简单的方式是在 wechaty 的博客项目下发表一篇博客,博客项目地址: https://github.com/wechaty/wechaty.github.io 更多 Token 信息详细见: https://github.com/juzibot/Welcome/wiki/Everything-about-Wechaty ## 前言 几年前大家开始通过微信拜年,基于vbot折腾过机器人,想要给所有alias不为空的好友发送定制问候,在发送不到10人消息之后,自己微信的WEB端口被封。无奈尝下没有技术和被墙的泪水。 作为码农,能自动化处理的事情,为什么一定得人工? ## 项目说明 几天前无意中浏览到Wechaty,于是再次萌发了做个机器人的想法。这次做一个娱乐向的机器人~ ### 游戏特色 本次开发了谁是卧底小游戏,房主无法设置游戏角色及人数,要求至少4人参加。每轮游戏结束后会重新分配各角色人数,增加随机趣味性。 ``` 假定总人数为ALL 平民人数[P]:默认 总人数一半 + 1 向下取整 卧底人数[W]:默认 随机 1 到 总人数 - 平民人数 白板人数[B]:ALL - P - W 额外分配:若W大于3则会再次分配,随机减少 0 或 W - 2人数,减少的人数加到P头上 因此一般的人数规律是:3/1/0,3/1/1,3/2/0,4/1/1,4/2/0.... ``` 游戏规则: ``` 游戏结束: 存活人数/游戏人数 <= 1/2时,即 2/4,2/5,3/6,3/7,4/8 胜利条件: 1.平民淘汰所有卧底和白板 平民胜 2.卧底存活至游戏结束 卧底胜 3.所有卧底出局后白板仍然存活 白板胜 ``` 附上部分逻辑代码说明。 ```javascript /** * 定义当前轮次游戏角色数目 * @param {Number} playLength [游戏总人数] * @return {Array} [平民、卧底、白板每种角色的具体人数] */ Word.defRoleNum = function (playLength) { let Civilian, Undercover = 0 Civilian = parseInt(playLength / 2) + 1 // 一半 + 1 Undercover = randomNum(1, playLength - Civilian) // 随机卧底数目 if (Undercover > 3) { // 如果卧底大于3个 const rand = randomNum(0, Undercover - 2) Civilian += rand // 最少保留1个卧底 其它归到平民 Undercover -= rand } const Blank = playLength - Civilian - Undercover // 白板人数 return [Civilian, Undercover, Blank]; } // 定义当前轮次每玩家对应角色 Word.defTurn = function (playsList) { const playLength = playsList.length if (playLength < 4) { return } const roles = this.defRoleNum(playLength) const roleList = deepClone(roles) const randomWord = randomNum(1) ? this.randomWord() : this.randomWord().reverse() // 难得再转化 直接汉字 let role = '平民'; let word = ''; let newPlaysList = [] for (var i = 0; i < playLength; i++) { var index = randomNum(playsList.length - 1); //随机下标 if (roles[2]) { role = '白板'; word = ''; roles[2]--; } else if (roles[1]) { role = '卧底'; word = randomWord[1]; roles[1]--; } else { role = '平民'; word = randomWord[0]; } playsList[index].role = role playsList[index].word = word // 顺便按顺序排号 newPlaysList.push(playsList[index]) playsList.splice(index, 1); // 将随机出的元素在arr中删除 // console.log(roles) } // 排序 newPlaysList.sort((a, b) => { return a.self_id - b.self_id }) const first = randomNum(1, newPlaysList.length) return { roleList, playsList: newPlaysList, first } } ``` ## 项目使用 ### 目录结构 - `config`文件夹存放公共配置文件以及`flyio`请求相关配置 - `imgs`存放相关图片 - `listeners`存放机器人初始化后一系列事件处理(分模块) - `games` 游戏模块 - `iswho.js` 谁是卧底核心模块 - `on-friendship.js` 处理好友请求 - `on-login.js` 处理登录 - `on-message.js` 处理用户消息、群消息 - `on-scan.js` 处理登录二维码 - `on-work.js` 做一些额外任务 - `schedule` 对定时任务`node-schedule`库进行了封装 - `migrations` 数据库迁移文件 - `api` 存放所有的数据请求、接口封装都在此 - `utils` 公用方法的封装 - `app.js` 入口文件 - `db.js` 数据库入口文件 - `knexfile.js` 数据库配置文件 ### 如何使用 1. 修改`config`配置 打开`config/index.js` 文件,将里面的配置改为自己的。 token 和 name 必填 appToken.tianxin 也必填 2. 修改天行接口配置 天行 api 官网 :[https://tianapi.com/](https://tianapi.com/) 注册成功后,申请以下接口: - [每日英语一句话](https://www.tianapi.com/apiview/62) - [神回复](https://www.tianapi.com/apiview/39) 3. 依赖sqlite3 和 redis, redis应需要单独安装 然后就可以运行了 ```bash npm install npm run initdb npm start ``` ### 已实现功能 - [x] 发送加群关键字,自动拉人进群。 - [x] 场景模式 - [x] 谁是卧底 - [x] 神回复 - [x] 英语一句话 - [x] 天气查询 - [x] 发送关键字,踢人 列几个有趣的功能,后续慢慢完善: - [ ] 随机匿名好友聊天 - [ ] 生活向文字冒险游戏 ### 谁是卧底小游戏 ![Image text](/imgs/a.png) ![Image text](/imgs/b.png) ![Image text](/imgs/c.png) ![Image text](/imgs/qrbread.jpg)