最近开始尝试再b站发一些视频,为了第一时间获取到用户的反馈,我用node-red写了个b站的消息提醒。
<hr/>
演示
<br/>
<iframe src="//player.bilibili.com/player.html?aid=593596306&bvid=BV1Pq4y1h7Jt&cid=494196792&page=1" scrolling="no" width="90%" height="500px" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>
<hr/>
首先介绍一下node-red,这是一个低代码平台,界面看起来有点像那些少儿编程或者益智游戏,你只需要把不同功能的组件连接起来即可。
![image.png](https://s2.loli.net/2022/01/28/XcfFoEZi9aY58HA.png)
不过低代码≠你不需要懂代码。
这里我也是单独写了一个组件,用于向qq机器人发送消息。
这个组件本质上只是简单调用mirai这个qq机器人的接口。你只需要再组件内输入必要的信息即可,有兴趣的可以去我的[github](https://github.com/thetbw/node-red-contrib-mirai-http)上查看,同样我也发布在了npm仓库
![image.png](https://s2.loli.net/2022/01/28/IPlyWzSRVvpmhkw.png)
<hr/>
接着就是调用b站的接口。
b站评论的接口是
>https://api.bilibili.com/x/msgfeed/reply
返回的信息大概是这样
```javascript
{
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"cursor": {
"is_end": false,
"id": 3445626300,
"time": 1641300620
},
"items": [
{
"id": 3538922281,
"user": {},
"item": {},
"counts": 1,
"is_multi": 0,
"reply_time": 1643328622
},
],
"last_view_at": 1643356484
}
}
```
`items`就是评论列表了,我们只需要判断 大于`last_view_at`的评论信息,这个就是我们未读的信息。
当然,评论可能一页显示不完,我们还需要根据cursor来请求下一页。
<hr/>
基本上的就是这些了
下面是我导出的流程信息,如果你有兴趣的话,也可以安装 [node-red-contrib-mirai-http](https://github.com/thetbw/node-red-contrib-mirai-http)插件后复制导入流程(注意有些参数需要修改)
<details>
<summary>node-red流程</summary>
<pre><code class="language-javascript">
[
{
"id": "3388168cf65261ed",
"type": "tab",
"label": "b站消息自动通知",
"disabled": false,
"info": "",
"env": []
},
{
"id": "c886832d3cd18c74",
"type": "inject",
"z": "3388168cf65261ed",
"name": "启动",
"props": [],
"repeat": "10",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 150,
"y": 240,
"wires": [
[
"d70cbcc1707ac9e1"
]
]
},
{
"id": "0e579a886a127567",
"type": "http request",
"z": "3388168cf65261ed",
"name": "请求b站接口",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"authType": "",
"senderr": false,
"x": 590,
"y": 380,
"wires": [
[
"d2a8860e9220b6bf",
"3c8b0af265fe0ffd"
]
]
},
{
"id": "2498722ff33d997b",
"type": "debug",
"z": "3388168cf65261ed",
"name": "输出调试",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1100,
"y": 380,
"wires": []
},
{
"id": "d2a8860e9220b6bf",
"type": "function",
"z": "3388168cf65261ed",
"name": "处理数据",
"func": "if(!flow.get('datas') ){\n flow.set('datas',[])\n}\nlet payload = msg.payload\nlet data = payload.data\nlet hasMore = true\nlet last_view_at = null\nif(flow.get(\"last_view_at\")){\n last_view_at = flow.get(\"last_view_at\")\n}else{\n last_view_at = data.last_view_at\n flow.set(\"last_view_at\",last_view_at)\n}\nfor(let item of data.items){\n if(item.reply_time > last_view_at ){\n flow.get('datas').push(item)\n }else {\n hasMore = false\n }\n}\n\nif(hasMore && !data.cursor.is_end ) {\n flow.set(\"id\",data.cursor.id)\n flow.set(\"reply_time\",data.cursor.time)\n return [msg,null]\n}else{\n return [null,msg]\n}",
"outputs": 2,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 540,
"y": 280,
"wires": [
[
"dca21e6b2324083f"
],
[
"2eb9be98b0fdf5c1"
]
],
"inputLabels": [
"请求的数据"
],
"outputLabels": [
"数据未完全请求",
"数据已完全请求"
]
},
{
"id": "08160ef483af5b31",
"type": "mirai-send-message",
"z": "3388168cf65261ed",
"name": "通知到QQ",
"server": "bb07cc136badfef5",
"target_type": "friend",
"target": "2994581874",
"send_type": "text",
"x": 1110,
"y": 320,
"wires": [
[]
]
},
{
"id": "76d2737e5d252207",
"type": "template",
"z": "3388168cf65261ed",
"name": "",
"field": "payload",
"fieldType": "msg",
"format": "handlebars",
"syntax": "mustache",
"template": "你的视频'{{payload.item.title}}'收到一个回复。\n回复人:{{payload.user.nickname}},\n回复信息:{{payload.item.source_content}}\n",
"output": "str",
"x": 930,
"y": 340,
"wires": [
[
"2498722ff33d997b",
"08160ef483af5b31"
]
]
},
{
"id": "2eb9be98b0fdf5c1",
"type": "function",
"z": "3388168cf65261ed",
"name": "循环输出",
"func": "\nfor(let item of flow.get('datas')){\n let msg = {\n payload : item\n }\n node.send(msg);\n}\nreturn;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 780,
"y": 280,
"wires": [
[
"76d2737e5d252207"
]
]
},
{
"id": "62a455307c0ae711",
"type": "catch",
"z": "3388168cf65261ed",
"name": "",
"scope": null,
"uncaught": false,
"x": 500,
"y": 120,
"wires": [
[
"c1cc3837a5f36a8e",
"6ed15831168dcae3"
]
]
},
{
"id": "c1cc3837a5f36a8e",
"type": "template",
"z": "3388168cf65261ed",
"name": "",
"field": "payload",
"fieldType": "msg",
"format": "handlebars",
"syntax": "mustache",
"template": "b站评论通知发生异常\n节点:{{error.source.name}}\n异常信息:{{error.message}}",
"output": "str",
"x": 670,
"y": 160,
"wires": [
[
"e4701157988c446a"
]
]
},
{
"id": "e4701157988c446a",
"type": "mirai-send-message",
"z": "3388168cf65261ed",
"name": "通知到QQ",
"server": "bb07cc136badfef5",
"target_type": "friend",
"target": "你的qq号",
"send_type": "text",
"x": 850,
"y": 160,
"wires": [
[]
]
},
{
"id": "6ed15831168dcae3",
"type": "debug",
"z": "3388168cf65261ed",
"name": "异常信息",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "error",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 680,
"y": 100,
"wires": []
},
{
"id": "3c8b0af265fe0ffd",
"type": "debug",
"z": "3388168cf65261ed",
"name": "接口请求输出",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 980,
"y": 480,
"wires": []
},
{
"id": "8b816bd4d1f7ea26",
"type": "change",
"z": "3388168cf65261ed",
"name": "设置请求参数",
"rules": [
{
"t": "set",
"p": "headers",
"pt": "msg",
"to": "{\"cookie\":\"这里输入你的cookie\"}",
"tot": "json"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 420,
"y": 380,
"wires": [
[
"0e579a886a127567"
]
]
},
{
"id": "d70cbcc1707ac9e1",
"type": "change",
"z": "3388168cf65261ed",
"name": "重置数据",
"rules": [
{
"t": "set",
"p": "datas",
"pt": "flow",
"to": "[]",
"tot": "json"
},
{
"t": "set",
"p": "id",
"pt": "flow",
"to": "null",
"tot": "json"
},
{
"t": "set",
"p": "reply_time",
"pt": "flow",
"to": "null",
"tot": "json"
},
{
"t": "set",
"p": "last_view_at",
"pt": "flow",
"to": "null",
"tot": "json"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 300,
"y": 240,
"wires": [
[
"dca21e6b2324083f"
]
]
},
{
"id": "dca21e6b2324083f",
"type": "template",
"z": "3388168cf65261ed",
"name": "请求url",
"field": "url",
"fieldType": "msg",
"format": "handlebars",
"syntax": "mustache",
"template": "https://api.bilibili.com/x/msgfeed/reply?platform=web&build=0&mobi_app=web&id={{flow.id}}&reply_time={{flow.reply_time}}",
"output": "str",
"x": 270,
"y": 380,
"wires": [
[
"8b816bd4d1f7ea26"
]
]
},
{
"id": "bb07cc136badfef5",
"type": "mirai-server-config",
"name": "默认配置",
"server_url": "http://127.0.0.1:8088",
"server_key": "1",
"server_main_bot_id": "1"
}
]
</code></pre>
</details>
给我的QQ机器人加上B站评论提醒