├── .github └── workflows │ ├── init.yml │ ├── plug_caiyun_weather.yml │ ├── plug_dujitang.yml │ ├── plug_good_morning.yml │ ├── plug_one.yml │ ├── plug_v2ex_hot.yml │ ├── plug_v2ex_latest.yml │ └── plug_w7_message.yml ├── .gitignore ├── README.md ├── app.js ├── assets └── geekbot.png ├── modules ├── bot.js ├── cache.js └── date-format.js ├── package.json └── plugins ├── caiyun_weather.js ├── dujitang.js ├── good_morning.js ├── one.js ├── v2ex_hot.js ├── v2ex_latest.js └── w7_message.js /.github/workflows/init.yml: -------------------------------------------------------------------------------- 1 | name: 'GeekBot' 2 | 3 | on: 4 | push: 5 | pull_request: 6 | watch: 7 | types: [started] 8 | 9 | jobs: 10 | bot: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@master 14 | - uses: actions/setup-node@v1 15 | with: 16 | node-version: '12' 17 | - run: npm install 18 | - run: npm start 19 | env: 20 | bot_api: ${{ secrets.bot_api }} 21 | secrets_caiyun_key: ${{ secrets.caiyun_key }} 22 | secrets_caiyun_gps: ${{ secrets.caiyun_gps }} -------------------------------------------------------------------------------- /.github/workflows/plug_caiyun_weather.yml: -------------------------------------------------------------------------------- 1 | name: '彩云天气' 2 | 3 | on: 4 | watch: 5 | types: [started] 6 | schedule: 7 | - cron: '0 0-15 * * *' 8 | 9 | jobs: 10 | bot: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@master 14 | - uses: actions/setup-node@v1 15 | with: 16 | node-version: '12' 17 | - run: npm install 18 | - run: node ./plugins/caiyun_weather.js 19 | env: 20 | bot_api: ${{ secrets.bot_api }} 21 | caiyun_key: ${{ secrets.caiyun_key }} 22 | caiyun_gps: ${{ secrets.caiyun_gps }} -------------------------------------------------------------------------------- /.github/workflows/plug_dujitang.yml: -------------------------------------------------------------------------------- 1 | name: '毒鸡汤' 2 | 3 | on: 4 | watch: 5 | types: [started] 6 | schedule: 7 | - cron: '00 0-14 * * *' 8 | 9 | jobs: 10 | bot: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@master 14 | - uses: actions/setup-node@v1 15 | with: 16 | node-version: '12' 17 | - run: npm install 18 | - run: node ./plugins/dujitang.js 19 | env: 20 | bot_api: ${{ secrets.bot_api }} 21 | plug_disabled: ${{ secrets.plug_dujitang_disabled }} -------------------------------------------------------------------------------- /.github/workflows/plug_good_morning.yml: -------------------------------------------------------------------------------- 1 | name: '早安心语' 2 | 3 | on: 4 | watch: 5 | types: [started] 6 | schedule: 7 | - cron: '5 0 * * *' 8 | 9 | jobs: 10 | bot: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@master 14 | - uses: actions/setup-node@v1 15 | with: 16 | node-version: '12' 17 | - run: npm install 18 | - run: node ./plugins/good_morning.js 19 | env: 20 | bot_api: ${{ secrets.bot_api }} 21 | tianapi_key: ${{ secrets.tianapi_key }} -------------------------------------------------------------------------------- /.github/workflows/plug_one.yml: -------------------------------------------------------------------------------- 1 | name: '一个图文ONE' 2 | 3 | on: 4 | watch: 5 | types: [started] 6 | schedule: 7 | - cron: '20 0 * * *' 8 | 9 | jobs: 10 | bot: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@master 14 | - uses: actions/setup-node@v1 15 | with: 16 | node-version: '12' 17 | - run: npm install 18 | - run: node ./plugins/one.js 19 | env: 20 | bot_api: ${{ secrets.bot_api }} -------------------------------------------------------------------------------- /.github/workflows/plug_v2ex_hot.yml: -------------------------------------------------------------------------------- 1 | name: 'v2ex每日最热主题' 2 | 3 | on: 4 | watch: 5 | types: [started] 6 | schedule: 7 | - cron: '0 10 * * *' 8 | 9 | jobs: 10 | bot: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@master 14 | - uses: actions/setup-node@v1 15 | with: 16 | node-version: '12' 17 | - run: npm install 18 | - run: node ./plugins/v2ex_hot.js 19 | env: 20 | bot_api: ${{ secrets.bot_api }} -------------------------------------------------------------------------------- /.github/workflows/plug_v2ex_latest.yml: -------------------------------------------------------------------------------- 1 | name: 'v2ex每日最新主题' 2 | 3 | on: 4 | watch: 5 | types: [started] 6 | schedule: 7 | - cron: '0 0 * * *' 8 | 9 | jobs: 10 | bot: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@master 14 | - uses: actions/setup-node@v1 15 | with: 16 | node-version: '12' 17 | - run: npm install 18 | - run: node ./plugins/v2ex_latest.js 19 | env: 20 | bot_api: ${{ secrets.bot_api }} -------------------------------------------------------------------------------- /.github/workflows/plug_w7_message.yml: -------------------------------------------------------------------------------- 1 | name: '微擎信息提醒' 2 | 3 | on: 4 | watch: 5 | types: [started] 6 | schedule: 7 | - cron: '*/5 * * * *' 8 | 9 | jobs: 10 | bot: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@master 14 | - uses: actions/setup-node@v1 15 | with: 16 | node-version: '12' 17 | - run: npm install 18 | - run: node ./plugins/w7_message.js 19 | env: 20 | bot_api: ${{ secrets.bot_api }} 21 | w7_cookie: ${{ secrets.w7_cookie }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | package-lock.json -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GeekBot 2 | > 企业微信机器人每日定时推送信息脚本。 3 | > **也许是最有上班感觉的摸鱼神器!** 4 | 5 | ![](assets/geekbot.png) 6 | 7 | ![](https://i.loli.net/2020/05/20/MgEONhb2WKuQ6c4.gif) 8 | 9 | ### 目前支持如下插件: 10 | - 毒鸡汤文本(dujitang,每1小时推送) 11 | - v2ex 每日最新帖子(v2ex_latest,每天08:00推送) 12 | - v2ex 每日最热帖子(v2ex_hot, 每天18:00推送) 13 | - 彩云天气预报(caiyun_weather,每小时整推送) 14 | - ONE一个图文(one,每天08:20推送) 15 | - 早安心语(good_morning,每天 08:05) 16 | 17 | ## 配置 18 | 在项目的 `settings` -> `Secrets` 中添加 `bot_api` 字段,内容为企业群机器人webhook接口地址 19 | 可自行更改`.github/workflows/*.yml`配置文件,比如修改任务的执行时间 20 | 21 | 22 | ### 彩云天气配置 23 | 在项目`settings`->`Secrets` 中,添加: 24 | 1. `caiyun_key`,为彩云API的开发者令牌(前往[彩云天气开发者中心](https://dashboard.caiyunapp.com/)申请),或使用官方测试KEY(仅供测试):`TAkhjf8d1nlSlspN` 25 | 2. `caiyun_gps`,为要获取的天气的GPS坐标,可在[百度地图GPS获取](https://api.map.baidu.com/lbsapi/getpoint/index.html)页面获取后复制,多个GPS坐标请用`|`符号分割,地名在坐标后用`@`符号链接 26 | 27 | `caiyun_gps` 格式如下: 28 | > `111.22,333.44@地址1|444.55,555.66@地址2` 29 | 30 | ### 早安心语配置 31 | 需要用到[天行数据](https://www.tianapi.com/gethttp/143) 接口,你需要自行前往注册登录,申请api后,得到一个key,设置到仓库的secrets中,名称为:`good_morning_key` 32 | 33 | ## 禁用插件 34 | 比如禁用毒鸡汤,则添加`secrets`->`plug_dujitang_disabled`=`true` 35 | 36 | ## 注意 37 | cron 时间为美国时间,需要北京时间减去8小时设置。 38 | 比如你想在北京时间`08:00`运行,则需要设置(8-8=0)成:`0 0 * * *` 39 | 40 | 由于`GitHub Actions`容器启动耗时等限制,定时任务不一定能`准时`执行 41 | 42 | ## 开发文档 43 | > 整理中.. 44 | 45 | 1. 在 `plugins` 目录添加一个`module_name.js`插件,代码采用`node.js`编写,示例可以看看`plugins/dujitang.js`插件代码。 46 | 2. 可以在本地测试代码(先设置一个`bot_api`环境变量,然后直接`node plugins/module_name.js`) 47 | 3. 测试没问题后,在`.github/workflows/`中添加`plug_模块名.yml`配置文件,代码参考`plug_caiyun_weather.yml` 48 | 49 | 50 | ## 如何使用 51 | 1. `fork` 本项目到你的仓库 52 | 2. 在仓库`settings`中添加`secrets`配置,比如`bot_api`为你的企业微信机器人webhook 53 | 3. 点击你的项目的`star`按钮,会自动启动。 54 | 55 | > 更多人性化的启动方法正在研究中。。。 -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | const Bot = require('./modules/bot'); 2 | const process = require('process'); 3 | 4 | require('./modules/date-format'); 5 | 6 | class Plugin extends Bot { 7 | constructor () { 8 | super(); 9 | } 10 | async run () { 11 | const now = new Date().Format('M/d h:m:s'); 12 | await this.sendImage('assets/geekbot.png'); 13 | // 发送环境配置信息 14 | const CONF_DATA = ` 15 | ## GeekBot Secrets Dump 16 | > 备份导出您的项目\`secrets\`设置数据 17 | 18 | ## 1. \`bot_api\` 19 | \`\`\` 20 | ${process.env.bot_api} 21 | \`\`\` 22 | 23 | ## 2. \`caiyun_gps\` 24 | \`\`\` 25 | ${process.env.secrets_caiyun_gps} 26 | \`\`\` 27 | 28 | ## 2. \`caiyun_key\` 29 | \`\`\` 30 | ${process.env.secrets_caiyun_key} 31 | \`\`\` 32 | 33 | > 导出时间:${now} 34 | > https://github.com/im3x/GeekBot`; 35 | const f = await this.uploadFile("配置数据备份.md", Buffer.from(CONF_DATA)); 36 | await this.sendFile(f); 37 | await this.sendMarkdown("🤖 Hello! GeekBot!\n> 项目地址:[@GeekBot](https://github.com/im3x/GeekBot)\n> 启动时间:" + now); 38 | 39 | // test env 40 | // const $f = await this.uploadFile("env.txt", new Buffer(JSON.stringify(process.env))); 41 | // await this.sendFile($f); 42 | } 43 | } 44 | 45 | new Plugin().run(); -------------------------------------------------------------------------------- /assets/geekbot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/im3x/GeekBot/3be755e2f160fbbd99242f1d714ffc087633e426/assets/geekbot.png -------------------------------------------------------------------------------- /modules/bot.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios').default; 2 | const fs = require('fs'); 3 | const crypto = require('crypto'); 4 | const process = require('process'); 5 | const FormData = require('form-data'); 6 | 7 | class Bot { 8 | constructor () { 9 | // 企业微信机器人API地址 10 | const { bot_api } = process.env; 11 | if (!bot_api) { 12 | console.log('[!] 请先设置企业微信群机器人webhook'); 13 | return this.exit(); 14 | } 15 | this.BOT_API = process.env.bot_api; 16 | this.BOT_KEY = this.BOT_API.split('key=')[1]; 17 | } 18 | 19 | exit () { 20 | process.exit(0); 21 | } 22 | 23 | /** 24 | * 发送HTTP请求到API 25 | * @param {string} type 26 | * @param {object} data 27 | */ 28 | async _send (type, data) { 29 | return await axios.post(this.BOT_API, Object.assign({ 30 | msgtype: type, 31 | }, data)) 32 | } 33 | 34 | // 计算md5 35 | _md5 (data) { 36 | let hash = crypto.createHash('md5'); 37 | return hash.update(data).digest('hex'); 38 | } 39 | 40 | /** 41 | * 发送纯文本信息,第一个参数必选,后两个参数可选 42 | * @param {string} content 要发送的文本内容 43 | * @param {array} mentioned_list 要AT的用户ID列表 44 | * @param {array} mentioned_mobile_list 要AT的用户手机列表 45 | */ 46 | async sendText (content, mentioned_list = [], mentioned_mobile_list = []) { 47 | return await this._send('text', { 48 | text: { 49 | mentioned_list, 50 | mentioned_mobile_list, 51 | content 52 | } 53 | }) 54 | } 55 | 56 | /** 57 | * 发送markdown富文本内容 58 | * @param {string} content 59 | */ 60 | async sendMarkdown (content) { 61 | return await this._send('markdown', { 62 | markdown: { 63 | content 64 | } 65 | }) 66 | } 67 | 68 | /** 69 | * 发送文件,media_id为上传文件后获得的id 70 | * @param {string} media_id 临时文件的id,也可以直接传递this.uploadFile后的返回值 71 | */ 72 | async sendFile (media_id) { 73 | if (typeof media_id === 'object') media_id = media_id.media_id; 74 | return await this._send("file", { 75 | file: { 76 | media_id 77 | } 78 | }); 79 | } 80 | 81 | /** 82 | * 发送图片 83 | * @param {string} src 图片路径,可以是本地仓库(path/file.jpg),或者远程URL(http.. 84 | */ 85 | async sendImage (src) { 86 | return await new Promise(RES => { 87 | if (src.startsWith('http')) { 88 | // 远程图片 89 | axios.get(src, { 90 | responseType: 'arraybuffer' 91 | }).then(res => { 92 | RES(res.data); 93 | }); 94 | } else { 95 | // 本地仓库图片 96 | RES(fs.readFileSync(src)); 97 | } 98 | }).then(async data => { 99 | const _md5 = this._md5(data); 100 | const _b64 = Buffer.from(data).toString("base64"); 101 | return await this._send("image", { 102 | image: { 103 | base64: _b64, 104 | md5: _md5 105 | } 106 | }) 107 | }); 108 | } 109 | 110 | /** 111 | * 发送文章列表 112 | * @param {array} articles 文章列表(title,description,url,picurl) 113 | */ 114 | async sendNews (articles) { 115 | return await this._send('news', { 116 | news: { 117 | articles 118 | } 119 | }) 120 | } 121 | 122 | /** 123 | * 上传文件,返回文件media_id,media_id仅三天内有效,且只能在同一个企业应用内共享 124 | * @param {string} filename 文件名称,在文件卡片显示 125 | * @param {buffer} data 文件内容 126 | */ 127 | async uploadFile (filename, data) { 128 | const UPLOAD_API = `https://qyapi.weixin.qq.com/cgi-bin/webhook/upload_media?key=${this.BOT_KEY}&type=file`; 129 | const file = new FormData(); 130 | file.append("media", data, { 131 | filename, 132 | knownLength: Buffer.from(data).byteLength 133 | }); 134 | 135 | return await axios({ 136 | method: 'POST', 137 | url: UPLOAD_API, 138 | data: file, 139 | headers: { 140 | 'Content-Type': 'multipart/form-data' 141 | } 142 | }).then(async r => { 143 | return await r.data; 144 | }) 145 | } 146 | } 147 | module.exports = Bot -------------------------------------------------------------------------------- /modules/cache.js: -------------------------------------------------------------------------------- 1 | const os = require('os'); 2 | const fs = require('fs'); 3 | const path = require('path'); 4 | 5 | class Cache { 6 | constructor () { 7 | this.PATH = os.tmpdir(); 8 | } 9 | set (key, value) { 10 | try { 11 | fs.writeFileSync(path.join(this.PATH, 'w7_'+String(key)), value); 12 | return true; 13 | } catch(e) { 14 | return false; 15 | } 16 | } 17 | get (key) { 18 | try { 19 | const data = fs.readFileSync(path.join(this.PATH, 'w7_'+String(key))); 20 | return data.toString(); 21 | } catch(e) { 22 | return false; 23 | } 24 | } 25 | } 26 | 27 | module.exports = Cache; -------------------------------------------------------------------------------- /modules/date-format.js: -------------------------------------------------------------------------------- 1 | Date.prototype.Format = function(fmt) 2 | { //author: meizz 3 | var o = { 4 | "M+" : this.getMonth()+1, //月份 5 | "d+" : this.getDate(), //日 6 | "h+" : this.getHours(), //小时 7 | "m+" : this.getMinutes(), //分 8 | "s+" : this.getSeconds(), //秒 9 | "q+" : Math.floor((this.getMonth()+3)/3), //季度 10 | "S" : this.getMilliseconds() //毫秒 11 | }; 12 | if(/(y+)/.test(fmt)) 13 | fmt=fmt.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length)); 14 | for(var k in o) 15 | if(new RegExp("("+ k +")").test(fmt)) 16 | fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length))); 17 | return fmt; 18 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "GeekBot", 3 | "version": "1.0.0", 4 | "description": "企业微信机器人摸鱼神器", 5 | "main": "app.js", 6 | "scripts": { 7 | "start": "node app.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/im3x/GeekBot.git" 12 | }, 13 | "author": "", 14 | "license": "ISC", 15 | "bugs": { 16 | "url": "https://github.com/im3x/GeekBot/issues" 17 | }, 18 | "homepage": "https://github.com/im3x/GeekBot#readme", 19 | "dependencies": { 20 | "axios": "^0.19.2", 21 | "form-data": "^3.0.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /plugins/caiyun_weather.js: -------------------------------------------------------------------------------- 1 | // 彩云天气 2 | // 获取GPS地址:https://api.map.baidu.com/lbsapi/getpoint/index.html 3 | // 请先在secrets中设置caiyun_key 和caiyun_gps 4 | // 多个gps坐标,请使用|分隔开,比如11.11,22.22|33.33,44.44 5 | 6 | const Bot = require('../modules/bot'); 7 | const axios = require('axios').default; 8 | const process = require('process'); 9 | 10 | class Plugin extends Bot { 11 | constructor () { 12 | super(); 13 | const { caiyun_key, caiyun_gps } = process.env; 14 | if (!caiyun_key || !caiyun_gps) { 15 | console.error('! 请先配置secrets:caiyun_gps,caiyun_key'); 16 | return this.exit(); 17 | } 18 | this.API_KEY = caiyun_key; 19 | this.GPS = caiyun_gps; 20 | } 21 | 22 | async run () { 23 | // 判断是否是多gps 24 | const _gps = this.GPS.split('|'); 25 | _gps.map(async gps => { 26 | const tmp = gps.split('@'); 27 | const api = `https://api.caiyunapp.com/v2.5/${this.API_KEY}/${tmp[0]}/weather.json?alert=true`; 28 | await axios.get(api).then(async res => { 29 | const { data } = res; 30 | await this._sendData(data, tmp[1]); 31 | }) 32 | }); 33 | } 34 | 35 | async _sendData (data, addr = '') { 36 | // 预警信息 37 | let alert_md = ''; 38 | if (data.result.alert.content.length > 0) { 39 | alert_md += '天气预警 ⚠\n'; 40 | data.result.alert.content.map(a => { 41 | alert_md += `**${a.title}**\n> ${a.description}\n\n`; 42 | }); 43 | } 44 | await this.sendMarkdown(` 45 | 彩云天气 🌤 ${addr || ''} 46 | 47 | **降雨提醒:** 48 | > ${data.result.minutely.description.trim()} 49 | 50 | **天气预报:** 51 | > ${data.result.hourly.description.trim()} 52 | 53 | ${alert_md}`); 54 | } 55 | } 56 | 57 | new Plugin().run() -------------------------------------------------------------------------------- /plugins/dujitang.js: -------------------------------------------------------------------------------- 1 | const Bot = require('../modules/bot'); 2 | const axios = require('axios').default; 3 | 4 | class Plugin extends Bot { 5 | constructor () { 6 | super(); 7 | this.API = 'https://api.qinor.cn/soup/'; 8 | if (process.env.plug_disabled === 'true') this.exit(); 9 | } 10 | run () { 11 | axios.get(this.API).then(res => { 12 | this.sendMarkdown(`> 🌺🐔来碗毒鸡汤\n\n${res.data}`); 13 | }) 14 | } 15 | } 16 | 17 | new Plugin().run(); -------------------------------------------------------------------------------- /plugins/good_morning.js: -------------------------------------------------------------------------------- 1 | // 早安心语 2 | // 早上是阳光太阳东升的时间,一句励志的话给新的一天注入动力。 3 | // 注意:需申请API KEY,设置到secrets中,名称:tianapi_key 4 | // https://www.tianapi.com/apiview/143 5 | 6 | const Bot = require('../modules/bot'); 7 | const axios = require('axios').default; 8 | 9 | class Plugin extends Bot { 10 | constructor () { 11 | super(); 12 | this.API = 'https://api.tianapi.com/txapi/zaoan/index'; 13 | this.API_KEY = process.env.tianapi_key; 14 | if (!this.API_KEY) return this.exit(); 15 | } 16 | 17 | run () { 18 | axios.get(this.API + '?key=' + this.API_KEY).then(res => { 19 | const c = res.data.newslist[0].content; 20 | this.sendText(c); 21 | }); 22 | } 23 | } 24 | 25 | new Plugin().run(); -------------------------------------------------------------------------------- /plugins/one.js: -------------------------------------------------------------------------------- 1 | // 一个图文 2 | const Bot = require('../modules/bot'); 3 | const axios = require('axios').default; 4 | 5 | class Plugin extends Bot { 6 | constructor () { 7 | super(); 8 | this.API = "http://m.wufazhuce.com/one"; 9 | } 10 | 11 | async run () { 12 | const { cookie, token } = await this._getInfo(); 13 | const data = await this._getData(cookie, token); 14 | this.sendNews([ 15 | { 16 | title: data.title, 17 | description: data.content, 18 | picurl: data.img_url, 19 | url: data.url 20 | } 21 | ]); 22 | } 23 | 24 | async _getInfo () { 25 | const res = await axios.get(this.API); 26 | const cookie = res.headers['set-cookie']; 27 | const token = res.data.split("One.token = '")[1].split("'")[0]; 28 | return { 29 | token, 30 | cookie: cookie[0], 31 | } 32 | } 33 | 34 | async _getData (cookie, token) { 35 | const api = "http://m.wufazhuce.com/one/ajaxlist/0?_token="+token; 36 | const res = await axios.get(api, { 37 | headers: { 38 | 'Cookie': cookie 39 | } 40 | }); 41 | const data = res.data; 42 | return data.data[0]; 43 | } 44 | } 45 | 46 | new Plugin().run(); -------------------------------------------------------------------------------- /plugins/v2ex_hot.js: -------------------------------------------------------------------------------- 1 | // v2ex 每日最热帖子列表 2 | const Bot = require('../modules/bot'); 3 | const axios = require('axios').default; 4 | 5 | class Plugin extends Bot { 6 | constructor () { 7 | super(); 8 | this.API = "https://www.v2ex.com/api/topics/hot.json"; 9 | } 10 | run () { 11 | axios.get(this.API).then(res => { 12 | const { data } = res; 13 | const articles = []; 14 | data.map(d => { 15 | articles.push({ 16 | title: d.title, 17 | description: d.content, 18 | url: d.url, 19 | picurl: d.member.avatar_large.replace('_mini', '_large') 20 | }) 21 | }); 22 | this.sendNews(articles.slice(0, 8)); 23 | }) 24 | } 25 | } 26 | 27 | new Plugin().run(); -------------------------------------------------------------------------------- /plugins/v2ex_latest.js: -------------------------------------------------------------------------------- 1 | // v2ex 每日最新帖子列表 2 | 3 | const Bot = require('../modules/bot'); 4 | const axios = require('axios').default; 5 | 6 | class Plugin extends Bot { 7 | constructor () { 8 | super(); 9 | this.API = "https://www.v2ex.com/api/topics/latest.json"; 10 | } 11 | run () { 12 | axios.get(this.API).then(res => { 13 | const { data } = res; 14 | const articles = []; 15 | data.map(d => { 16 | articles.push({ 17 | title: d.title, 18 | description: d.content, 19 | url: d.url, 20 | picurl: d.member.avatar_large.replace('_mini', '_large') 21 | }) 22 | }); 23 | this.sendNews(articles.slice(0, 8)); 24 | }) 25 | } 26 | } 27 | 28 | new Plugin().run(); -------------------------------------------------------------------------------- /plugins/w7_message.js: -------------------------------------------------------------------------------- 1 | // 微擎商城信息列表 2 | 3 | const Bot = require('../modules/bot'); 4 | const Cache = require('../modules/cache'); 5 | const axios = require('axios').default; 6 | 7 | class Plugin extends Bot { 8 | constructor () { 9 | super(); 10 | this.COOKIE = process.env.w7_cookie; 11 | if (!this.COOKIE) return this.exit(); 12 | } 13 | run () { 14 | const cache = new Cache(); 15 | axios.get('https://user.w7.cc/v1/message/list?page=1', { 16 | headers: { 17 | 'Cookie': this.COOKIE 18 | } 19 | }).then(res => { 20 | const { data } = res.data; 21 | if (!data) return this.sendText("w7_message: cookie过期了"); 22 | const d = data[0]; 23 | const c = cache.get(d.createtime); 24 | if (c) return console.log('sended'); 25 | this.sendMarkdown(`# ${d.type_text}\n> ${d.create_date_format}\n\n${d.detail}`); 26 | cache.set(d.createtime, "ok"); 27 | }); 28 | } 29 | } 30 | 31 | new Plugin().run(); --------------------------------------------------------------------------------