一步一步教你用 nodejs 创建一个 Mixin Network 机器人 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
myrual
V2EX    推广

一步一步教你用 nodejs 创建一个 Mixin Network 机器人

  •  
  •   myrual 2019-01-17 17:07:28 +08:00 2210 次点击
    这是一个创建于 2472 天前的主题,其中的信息可能已经有所发展或是发生改变。

    第一课 一步一步教你用 nodejs 创建一个 Mixin Network 机器人

    Mixin Network 是一个免费的 极速的端对端加密数字货币交易系统. 在本章中,你可以按教程在 Mixin Messenger 中创建一个 bot 来接收用户消息, 学到如何给机器人转帐 或者 让机器人给你转账.

    课程简介

    1. 创建一个接受消息的机器人
    2. 机器人:接受加密货币并立即退还用户

    创建一个接受消息的机器人

    通过本教程,你将学会如何用 nodejs 创建一个机器人 APP,让它能接受消息.

    Node.js 的环境安装

    本教程是用 node.js 写的,在开始之前,我们先安装 node 与 yarn

    macOS

    brew install node yarn 

    Ubuntu

    curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list apt update apt upgrade apt install node yarn 

    下面我们来创建一个项目目录

    打开终端,切换到你的工作目录,创建一个 nodejs-bot 的目录

    mkdir nodejs-bot cd nodejs-bot/ 

    运行 yarn init 指令,按提示完成项目的创建, 完成后会生成 package.json 文件,代码例子如下:

    yarn init 
    { "name": "nodejs-bot", "version": "1.0.0", "main": "app.js",//默认生成的名字是 main.js "license": "MIT" } 

    本教程需要依赖一个 SDK, wangshijun/mixin-node-client. 所以我们先下载这个库. 在新生成的项目目录下,执行 yarn add mixin-node-client 来添加 mixin-node-client

    yarn add mixin-node-client 

    现在,package.json 会增加下面几行:

    "dependencies": { "mixin-node-client": "^0.6.0" } 

    如果你是克隆这个教程,在项目目录下执行 yarn 来下载安装依赖的软件包.

    创建你的第一个机器人

    在写代码之前,我们先看图文教程,创建一个机器人 APP 教程.

    记住下面三项,这是机器人发送接收消息所必须的: user id, session id, private key, Mixin Network 使用这三项进行数字签名。

    https://github.com/wenewzhang/mixin_network-nodejs-bot2/blob/master/mixin_network-keys.png

    创建一个 config.js 文件, 替换 clientID 为你的机器人的 id, sessionId 为你的机器人的 session id, privateKey 为你的私钥,aesKey,clientSecret, assetPin 我们后面才需要,这里可先不修改,但请保留这个数据不要删除!

    config.js

    // NOTE: please update this config file with your own module.exports = { clientId: '21042518-85c7-4903-bb19-f311813d1f51', clientSecret: 'will-generate-later', assetPin: 'will-generate-later', sessionId: '6ca194a4-727f-4e5f-a348-3c62987536ba', aesKey: 'will-generate-later', privateKey: `-----BEGIN RSA PRIVATE KEY----- MIICWwIBAAKBgQC1P7QK7rK8lyX7X5t4A/reu7Q94xJkAllf1NPsW7zUdVgs/BCV f4RA6YK2prTpHHqXSCAzToEmou8R0xBMdnT/IQqijt0NzMpvrphiQrKrXEHrKrLm at6eZHYvLoGEPYjVq6RrgLkt2Mjld+RfHWd4zHXeqSCVfHAH67+gcPHYCwIDAQAB AoGADGotoeYRthtATcSRuJnFMEZ5JRgNpW4HwymnznPGLmNPQ92MIUFXxL555prq n2EFAKG/GuSQsh3M9FKZtjMS9l0aXpXy4T4ieBptkhahKbGVMLbQBru8wo/Pow3r r+DuNJs64ELvBYyydS7r1Fm/mtrd38Aq+4+04Z3UDW50AUkCQQDuhy8FoA3TKdZM mIEiPFb2dW8ohe8MsGM370S8HFPk7kdCaarJbiJCx1E+KjUxbkAeEFcLqKgaALTu IVCikIHNAkEAwoZvPaY0yFB1+V8HuToIR4X7AqWMy6WTBZ9U4wp34aNO21DLcrqf P40FHrHvqbWNK5bS8nSxLiv0kYL6+ezJNwJAO/GxOYKttsGu33T8DvSHDk0Y8GAo YVH6vVXeOkAMPV48fk47439QEOQyYKMO1ytT5bpJhd6O0GoZDjdFInWaiQJAAq4l hDzxBz2MkpYLnjK9gHbJIZ00Vm3+m5o5ajNvuW0tnfn8A6WsogyIYIblHXqB6nLW jz6qXk9+vC6I1L69ewJAasE+oC3TMblSOC9xqeBQgm8BPhb0UwJL4UuZLOSyUETr +bAwyiZ37Cc7r/nxKhVH+FwMCVoeNUMcRIYYMRjwmg== -----END RSA PRIVATE KEY-----`, }; 

    Hello world

    在项目目录下创建一个 app.js, 并将下面的代码粘贴进去.

    const { SocketClient, isMessageType } = require('mixin-node-client'); const { HttpClient } = require('mixin-node-client'); const cOnfig= require('./config'); const client = new SocketClient(config); const ValidActiOns= ["ACKNOWLEDGE_MESSAGE_RECEIPT" ,"CREATE_MESSAGE", "LIST_PENDING_MESSAGES"]; console.log('Supported MessageSenders by SocketClient', client.getMessageSenders()); console.log(client.getMessageSenders()); // Listen and react to socket messages client.on( 'message', client.getMessageHandler(message => { console.log('Message Received', message); if (ValidActions.indexOf(message.action) > -1) { if (message.action === 'ACKNOWLEDGE_MESSAGE_RECEIPT') {console.log("ignore receipt");return;} if (isMessageType(message, 'text')) { const text = message.data.data.toLowerCase(); if ( (message.data.category === "PLAIN_TEXT") && (message.action === "CREATE_MESSAGE") ) { var parameter4IncomingMsg = {"message_id":message.data.message_id, "status":"READ"}; var RspMsg = {"id":client.getUUID(), "action":"ACKNOWLEDGE_MESSAGE_RECEIPT", "params":parameter4IncomingMsg}; client.sendRaw(RspMsg); if (text === 'pay') { // todo: pay } return client.sendText(text, message); } } return Promise.resolve(message); } else console.log("unknow action") })); client.on('error', err => console.error(err.message)); 

    开始执行

    node app.js 

    如果你的配置文件有错,可能会出现下面的提示:

     nodejsdemo node app.js Supported MessageSenders by SocketClient [ 'sendText', 'sendImage', 'sendVideo', 'sendData', 'sendSticker', 'sendContact', 'sendButton', 'sendButtons', 'sendApp' ] [ 'sendText', 'sendImage', 'sendVideo', 'sendData', 'sendSticker', 'sendContact', 'sendButton', 'sendButtons', 'sendApp' ] Message Received { id: '00000000-0000-0000-0000-000000000000', action: 'ERROR', error: { status: 202, code: 401, description: 'Unauthorized, maybe invalid token.' } } 

    如果一切顺利,机器人将连接上服务器并等待服务器的消息,提示如下:

     nodejsdemo node app.js Supported MessageSenders by SocketClient [ 'sendText', 'sendImage', 'sendVideo', 'sendData', 'sendSticker', 'sendContact', 'sendButton', 'sendButtons', 'sendApp' ] [ 'sendText', 'sendImage', 'sendVideo', 'sendData', 'sendSticker', 'sendContact', 'sendButton', 'sendButtons', 'sendApp' ] Message Received { id: '30e3c929-f6b7-46c2-9e46-6634af66daab', action: 'LIST_PENDING_MESSAGES' } 

    打开Mixin Messenger,将你的机器人加为好友,(比如,这个机器人的 ID 是 7000101639) 然后就可以给它发消息了! 比如你发一个"hi"

    https://github.com/wenewzhang/mixin_network-nodejs-bot2/blob/master/mixin_messenger-sayhi.png

    终端将显示如下:

    Message Received { id: 'de4671c2-8873-419b-92b0-0d6ae8381940', action: 'LIST_PENDING_MESSAGES' } Message Received { id: 'a41816ca-2b65-4668-abdd-4526c1d29015', action: 'CREATE_MESSAGE', data: { type: 'message', representative_id: '', quote_message_id: '', conversation_id: 'c5458ec8-5e95-3e64-ae63-d4dfc3135c9e', user_id: '28ee416a-0eaa-4133-bc79-9676909b7b4e', message_id: 'a93ebfca-3d3f-44a9-9d63-3ad41ddca4b8', category: 'PLAIN_TEXT', data: 'hi', status: 'SENT', source: 'CREATE_MESSAGE', created_at: '2019-01-10T03:44:12.600158Z', updated_at: '2019-01-10T03:44:12.600158Z' } } Message Received { id: '810b93d9-56d4-413a-9837-6dc241e36ed0', action: 'ACKNOWLEDGE_MESSAGE_RECEIPT' } ignore receipt Message Received { id: 'd45c5139-8201-4f8a-aa2f-86c98ba3a849', action: 'CREATE_MESSAGE', data: { type: 'message', representative_id: '', quote_message_id: '', conversation_id: '', user_id: 'daf8b473-39a0-4419-991a-77f30d28dd6d', message_id: '9054acea-1a62-4716-9fa3-1a8c70a2165a', category: '', data: '', status: 'SENT', source: 'CREATE_MESSAGE', created_at: '2019-01-10T03:44:22.540536153Z', upated_at: '2019-01-10T03:44:22.540536153Z' } } Message Received { id: 'cf69c7a2-787b-4a91-be22-f51f38338179', action: 'ACKNOWLEDGE_MESSAGE_RECEIPT', data: { type: 'message', representative_id: '', quote_message_id: '', conversation_id: '', user_id: '', message_id: '9054acea-1a62-4716-9fa3-1a8c70a2165a', category: '', data: '', status: 'DELIVERED', source: 'ACKNOWLEDGE_MESSAGE_RECEIPT', created_at: '0001-01-01T00:00:00Z', updated_at: '2019-01-10T03:44:23.236843Z' } } ignore receipt Message Received { id: 'daa66945-abb6-4b8f-bc6a-04c4ccb6a837', action: 'ACKNOWLEDGE_MESSAGE_RECEIPT', data: { type: 'message', representative_id: '', quote_message_id: '', conversation_id: '', user_id: '', message_id: '9054acea-1a62-4716-9fa3-1a8c70a2165a', category: '', data: '', status: 'READ', source: 'ACKNOWLEDGE_MESSAGE_RECEIPT', created_at: '0001-01-01T00:00:00Z', updated_at: '2019-01-10T03:44:23.787562Z' } } ignore receipt 

    下面对代码进行一个简单的解释

    机器人接受消息前,先建立到服务器的连接,再利用签名信息进行登陆认证。

    API 调用

    app.js

    const { SocketClient, isMessageType } = require('mixin-node-client'); const cOnfig= require('./config'); const client = new SocketClient(config); 

    开启一个侦听,在这对收到的消息进行处理

    client.on( 'message', client.getMessageHandler(message => { console.log('Message Received', message); return Promise.resolve(message); }) ); 

    接收消息, 进行pay相关的逻辑处理

    if (ValidActions.indexOf(message.action) > -1) { if (message.action === 'ACKNOWLEDGE_MESSAGE_RECEIPT') {console.log("ignore receipt");return;} if (isMessageType(message, 'text')) { const text = message.data.data.toLowerCase(); if ( (message.data.category === "PLAIN_TEXT") && (message.action === "CREATE_MESSAGE") ) { //todo: tell the server you got this message if (text === 'pay') { //todo: pay } return client.sendText(text, message); } } return Promise.resolve(message); } else console.log("unknow action") 

    除了发送文本消息之外,还可以发送图片等消息,详细的消息类型请参考这里.

    对于每一条接收到的消息,将消息号( message_id)做为参数,回应服务器,action 为 ACKNOWLEDGE_MESSAGE_RECEIPT! 如果不回应,机器人下次登入,会重新获得消息。

     if ( (message.data.category === "PLAIN_TEXT") && (message.action === "CREATE_MESSAGE") ) { // READ message start var parameter4IncomingMsg = {"message_id":message.data.message_id, "status":"READ"}; var RspMsg = {"id":client.getUUID(), "action":"ACKNOWLEDGE_MESSAGE_RECEIPT", "params":parameter4IncomingMsg}; client.sendRaw(RspMsg); // READ message end return client.sendText(text, message); 

    最后, 执行 node app.js 将机器人上线!

    node app.js 

    第二课 发送与接收加密货币

    目前尚无回复
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2740 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 07:52 PVG 15:52 LAX 00:52 JFK 03:52
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86