Git Product home page Git Product logo

weixin-robot's Introduction

微信公共帐号机器人(Weixin Robot)

Build Status repo dependency

A node.js robot for wechat.

微信公众平台提供的开放信息接口的自动回复系统。

weixin-robotwebotwechat-mp 的 高级包装。webot 负责定义回复规则,wechat-mp 负责与微信服务器通信。

功能特色:

  1. 方便灵活的规则定义,轻松实现文本匹配流程控制
  2. 基于正则表达式的对话设定,配置简单,可以给一句话随机回复不同内容
  3. 支持等待后续操作模式,如可以提示用户“需要我执行xxx操作吗?”
  4. 可直接从 yaml 或 json 文件中载入对话规则

使用示例:

添加微信帐号,试试效果:

豆瓣同城微信帐号二维码:douban-event 微信机器人测试帐号:webot-test

更多使用此项目的微信机器人列表

快速入门 | FAQ | 示例

var express = require('express');
var webot = require('weixin-robot');

var app = express();

// 指定回复消息
webot.set('hi', '你好');

webot.set('subscribe', {
  pattern: function(info) {
    return info.is('event') && info.param.event === 'subscribe';
  },
  handler: function(info) {
    return '欢迎订阅微信机器人';
  }
});

webot.set('test', {
  pattern: /^test/i,
  handler: function(info, next) {
    next(null, 'roger that!')
  }
})

// 你可以获取已定义的 rule
//
// webot.get('subscribe') ->
//
// {
//   name: 'subscribe',
//   pattern: function(info) {
//     return info.is('event') && info.param.event === 'subscribe';
//   },
//   handler: function(info) {
//     return '欢迎订阅微信机器人';
//   }
// }
//

// 接管消息请求
webot.watch(app, { token: 'your1weixin2token', path: '/wechat' });

// 如果需要多个实例(即为多个微信账号提供不同回复):
var webot2 = new webot.Webot();
webot2.set({
  '/hi/i': 'Hello',
  '/who (are|r) (you|u)/i': 'I\'m a robot.'
});
webot2.watch(app, {
  token: 'token2',
  path: '/wechat_en', // 这个path不能为之前已经监听过的path的子目录
});

// 启动 Web 服务
// 微信后台只允许 80 端口
app.listen(80);

// 如果你不想让 node 应用直接监听 80 端口
// 可以尝试用 nginx 或 apache 自己做一层 proxy
// app.listen(process.env.PORT);
// app.enable('trust proxy');

然后你就可以在微信公众平台后台填入你的接口地址和 token , 或者使用 webot-cli 来调试消息。

如果一切顺利,你也搭建好了自己的机器人,欢迎到此项目的 Wiki 页面添加你的帐号。

命令行工具

提供可执行文件 webot 用于发送测试消息。 使用 npm 安装 webot-cli

npm install webot-cli -g

微信公共账号自定义菜单

webot-cli 提供处理微信自定义菜单的功能,安装好之后执行:

webot help menu

版本历史 | 详细

  • 0.5.0 - 换用更精简的 wechat-mp 模块

    注意: 现在如果要启用session支持,webot.watch 必须在 app.use(connect.session()) 之前

API 参考

微信自动回复API流程图

Wechat API flow

规则定义

> 具体的规则定义部分,请参考 webot 的文档。

主要API:

info 对象

webot rule 的 handler 接收到的 info 对象,包含请求消息内容和 session 支持。

请求消息属性

wexin-robotinfo 把微信的请求内容包装为了更符合 js 命名规则的值,并根据 MsgType 的不同, 将额外参数存入了 info.param 对象。这样做能保证 info 对象的标准化,方便你在 不同平台使用相同的机器人。

你可以通过 info.raw 拿到与微信官方文档一致的参数对象。

原始请求参数与 info 属性的对照表:

官方参数名        定义                        info对象属性                     备注
-------------------------------------------------------------------------------------------------------

ToUserName      开发者微信号                   info.sp                      sp means "service provider"
FromUserName    发送方帐号(一个OpenID)       info.uid
CreateTime      消息创建时间 (整型)
MsgId           消息id                         info.id
MsgType         消息类型                       info.type
-------------------------------------------------------------------------------------------------------
Content         文本消息内容                   info.text                    MsgType == text
-------------------------------------------------------------------------------------------------------
PicUrl          图片链接                       info.param.picUrl            MsgType == image
-------------------------------------------------------------------------------------------------------
Location_X      地理位置纬度(lat)              info.param.lat               MsgType == location
Location_Y      地理位置经度(lng)              info.param.lng
Scale           地图缩放大小                   info.param.scale
Label           地点名                         info.param.label             可能为空
-------------------------------------------------------------------------------------------------------
Title           消息标题                       info.param.title              MsgType == link
Description     消息描述                       info.param.description
Url             消息链接                       info.param.url
-------------------------------------------------------------------------------------------------------
Event           事件类型                       info.param.event              MsgType == event
                subscribe(订阅)、
                unsubscribe(取消订阅)、
                CLICK(自定义菜单点击事件)
                LOCATION(上报地理位置事件)

EventKey        事件KEY值,与自定义菜单接      info.param.eventKey
                口中KEY值对应
--------------------------------------------------------------------------------------------------------
MediaId         媒体文件的 id                  info.param.mediaId             MsgType == voice / video
Recognition     语音识别的文本                 info.param.recognition         MsgType == voice
ThumbMediaId    视频消息缩略图的媒体id         info.param.thumbMediaId        MsgType == video
Format          音频文件的格式                 info.param.format

注意:

  • 大部分属性值只是把首字母大写换成了小写。地理信息的 Location_XLocation_Y 除外。
  • recognition 参数需要开通微信的语音识别功能,同时为方便调用,此文本也会直接存到 info.text 也就是说,语音识别消息与普通文本消息都有 info.text ,只不过 info.type 不同

例如,地理位置消息( MsgType === 'location') 会被转化为:

{
  uid: 'the_FromUserName',
  sp: 'the_ToUserName',
  id: 'the_MsgId',
  type: 'location',
  param: {
    lat: 'the_Location_X',
    lng: 'the_Location_Y',
    scale: 'the_Scale',
    label: 'the_Label'
  }
}

info.reply

大部分时候你并不需要直接给 info.reply 赋值

你只需在 rule.handler 的返回值或 callbak 里提供回复消息的内容, webot.watch 自带的 express 中间件会自动给 info.reply 赋值, 并将其打包成 XML 发送给微信服务器。

info.reply 支持的数据类型:

  • {String} 直接回复文本消息,不能超过2048字节
  • {Object} 单条 图文消息/音乐消息
  • {Array} 多条图文消息

回复文本消息

info.reply = '收到你的消息了,谢谢'

回复图文消息

title        消息标题
url          消息网址
description  消息描述
picUrl       消息图片网址
info.reply = {
  title: '消息标题',
  url: 'http://example.com/...',
  picUrl: 'http://example.com/....a.jpg',
  description: '对消息的描述出现在这里',
}

// or

info.reply = [{
  title: '消息1',
  url: 'http://example.com/...',
  picUrl: 'http://example.com/....a.jpg',
  description: '对消息的描述出现在这里',
}, {
  title: '消息2',
  url: 'http://example.com/...',
  picUrl: 'http://example.com/....a.jpg',
  description: '对消息的描述出现在这里',
}]

回复音乐消息

title             标题
description       描述
musicUrl          音乐链接
hqMusicUrl        高质量音乐链接,wifi 环境下会优先使用该链接播放音乐

需指定 reply.type'music'

info.reply = {
  type: 'music',
  title: 'Music 101',
  musicUrl: 'http://....x.mp3',
  hqMusicUrl: 'http://....x.m4a'
}

Have fun with wechat, and enjoy being a robot!

info.noReply

如果对不想回复的消息,可设置 info.noReply = true

// 比如对于语音类型的消息不回复
webot.set('ignore', {
  pattern: function(info) {
    return info.is('voice');
  },
  handler: function(info) {
    info.noReply = true;
    return;
  }
});

LICENSE

(The MIT License)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Bitdeli Badge

weixin-robot's People

Contributors

atian25 avatar bit3725 avatar bitdeli-chef avatar jacksontian avatar ktmud avatar nasawz avatar yyfrankyy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

weixin-robot's Issues

建议把node-expat换为纯JS的实现,如node-xml

很多虚拟主机如nae, cloudfoundry都是不支持c++的类库的.
建议换为pure javascript的类库.

PS1: 本想写个类库的, 却发现仁兄把我想写的都写了....

PS2: 正在看waitor那块,因为想做的东西是有流程的,而不仅仅是一两个来回的问答

繁体支持

提供办法将繁体转换成简体消息。可以先用 iconv 搞搞,然后再试一下 opencc 。

语音识别接口还是有bug

webot.set('voice', {
        pattern: function(info) {
            return info.is('voice');
        },
        handler: function(info) {
            console.log(info.text);
            console.log(info.param.recognition);
            if (info.text) {
                return info.text;
            };
        }
    });

我的代码如上,发送语音消息之后,info.text,info.param.recognition均是空字符串

经常会出现204请求

部署上微信号之后,有的时候是好的,能正常回复信息。
有的时候是204请求,无法接受到发送内容,不能正常回复信息。
请问有没有人知道这是怎么回事?

去 underscore ,去 wind.js

wind.js 写出来的代码难以调试,而且有潜在的性能问题。不了解这套机制的人维护起来也比较困难

underscore 是浏览器端产物,服务器端大部分时候不需要用到

各种 type 判断可以使用原生代码,extend defaults 等 utils 方法可以自己 include

模版工具可以用 lodash-template 代替

cc @atian25

新更新的example测试无法通过

看见@ktmud在一个小时前更新了实例,估计现在还在弄,我测试了下,无法跑起来哦。在app.js里使用了webot.watch来监听消息请求,之前是webot.monitor(app, 'your1weixin2token');我测试的时候,显示no method of "watch".

webot 使用问题

运行您的example,修改了端口号和WX_TOKEN。部署到服务器上微信能成功调用。
我在本地做测试时候遇到了如下的问题。请问这个应该怎么解决 ?

nasaAir:bin nasa$ webot -t mytest
the text: hi

events.js:71
        throw arguments[1]; // Unhandled 'error' event
                       ^
Error: connect ECONNREFUSED
    at errnoException (net.js:769:11)
    at Object.afterConnect [as oncomplete] (net.js:760:19)
nasaAir:bin nasa$ 

无法使用其他路径

由于wechat包本身有带一些接口,我本来希望通过express做一个和微信对接以及一个微信代理接口。但是所有页面都是显示invalid signature。大致代码如下

app = express();
//All Requests return "invalid signature"
app.get('/media/', routes.media);
wechat.watch(app, { token: data.token, path: '/' });
wechat.set('welcome', {
  pattern: function(info) {
    return info.is('event') && info.param.event == 'subscribe';
  },
  handler: data.welcome
});

其他文件干嘛用的?

已经成功在本地与appfog上配置,并且微信可以使用。
不过只用到了examples文件夹内的app.js rules.js support.js
外面的一些文件,比如index.js引用的lib文件夹下是用来干嘛的?
能举例说明下其他文件干嘛用的吗?

handler里使用异步事件

是否能在handler里面使用异步事件, 异步事件里面需要调动handler callback里面的info. 不知道应该如何实现

    function generate_req(one_row) { //factory函数

      return function(info) {

          urllib.request(one_row.content, { data: info.param }, function (err, data) {
              if (err) {
                  console.log('callback error. ' + err.toString());
              }

              data = data.toString();
              try {
                  data = JSON.parse(data);
              } catch(e) {
                  console.log('callback JSON parse error. ' + e.toString());
              }

              //return data to function(info) here
              return data;

          });

      };

    }

微信多次发送消息

如果消息设置不做回复(info.ended = true),微信服务器则会发送同样的消息3次。我如何避免让微信服务器重发消息?

多层回复

现在我的菜单需要输出一些内容,然后依照用户的输入来判断回复。之前在使用wechat包的时候,直接测试

List.add('stuff', [
  ['回复{a}', '成功回复a']
  ['回复{b}', '成功回复b']
]);
var eventResponse = function (info, req, res, next) {
    res.wait('stuff');
};
var wechatObj = wechat(mytoken, wechat.event(eventResponse).text(textResponse));

然后挂一个List在eventResponse里面执行。现在如果得到同样的结果呢?我只能通过webot.set调回一个str或者obj或者arr。如何在webot.set里面回复另外一个webot.set?

特殊消息的shorthand api

使支持:

webot.image(function() {
   // ...
}).location(function() {
   // ...
}).event(function() {
   // ...
});

谁建个群交流啊

因为刚接触,所以很多东西不懂。
希望有哪个大大建个Q群大家交流交流,如果没有的话。我这边有个空的群。
3616268 欢迎大家。

Doc里面似乎有个小错误

关于Info对象:

ToUserName      开发者微信号                   info.uid
FromUserName    发送方帐号(一个OpenID)        info.sp                     sp means "service provider"

是不是反了?

ps 感谢,正在整合weixin-robot到我们的项目中。

链接菜单没有跳转

我使用包含的wechat包创建了带有链接的菜单。但是点击的时候没有跳转。查询菜单的时候看起来是对的。Log告诉我请求返回到了我的服务器这里由wechat包处理,因为没有匹配的rule,最后匹配失败。

代码生成的菜单大致是这样的

{ button: 
   [ { name: 'StuffParent', sub_button: 
     [ { key: 'FARM_LIST', type: 'click', name: 'StuffStuff' },
       { key: 'RESELLER_LIST', type: 'click', name: 'Stuff1' },
       { url: '"http://example.com"', type: 'view', name: 'Stuff2' },
       { key: 'EVENT_LIST', type: 'click', name: 'Stuff3' } ] } ] }

附加微信调试工具出的菜单截图

screen shot 2014-01-02 at 21 36 21

取消对 js-yaml 的依赖

既然载入一个 yaml 模块只是 require('a.yaml') 那样简单,
就可以把是否使用 yaml 的决定权交还给用户。

联动问题

请问如何实现example里的waits到routes的联动?

比如说 在 routes中 输入 ‘搜索500’ 联动到 waites中询问 ‘您是要搜索伍佰吗?’ 得到确定回复后 联动到routes中执行搜索。

求问一下webot中关于yaml的问题

@ktmud ,你好,我最近尝试了下你的weixin-robot和webot-douban-event,感觉非常爽,现在遇到一个问题请教一下:

在webot-douban-event中,rules/dialogs下边有很多的.yaml文件,我直接把文件夹复制过来了,然后尝试了一下,出现下边这种问题:

webot:robot:log define route: [jielong] +0ms
webot:robot:log require dialog file: /home/ymcdull/node_funny/webot-example/rules/dialogs/basic.yaml +3ms

/......./webot-example/rules/dialogs/basic.yaml:1
require, module, __filename, __dirname) { /^(都?有(哪些|什么)(好玩的)?)?活动[??!!]_$/:
^
SyntaxError: Unexpected token :
at Module._compile (module.js:439:25)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module.load (module.js:312:12)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at /home/ymcdull/node_funny/webot-example/node_modules/weixin-robot/node_modules/webot/lib/webot.js:216:11
at Array.forEach (native)
at Webot.dialog (/home/ymcdull/node_funny/webot-example/node_modules/weixin-robot/node_modules/webot/lib/webot.js:212:8)
at module.exports (/home/ymcdull/node_funny/webot-example/rules/dialogs/index.js:3:7)
npm ERR! weird error 8
npm ERR! not ok code 0
make: *
* [start] 错误 1

貌似是.yaml中的问题,如果我在正则匹配或者字符串前后加上引号,这个错误就没有了,请教一下这是什么原因?有没有什么方法可以不用把所有的匹配都加上引号来排除这个问题?多谢

noReply = true无效

目前我的第一条rule是基于用户是否启动会话从而判断是否由weixin-robot来回复,否的话,noReply = true。但是不知为何,程序总是会跳到下一条rule,而且这是info为空,导致程序崩溃。大致代码如下

    wechat.set('SUPPORT', {
      pattern: function(info) {
        return info.session.chatUsers.indexOf(info.uid) !== -1;
      },
      handler: function(info) {
        if( info.is('event') ) {
          info.reply = 'Doing Stuff...';
        } else {
          eventEmitter.emit('userMessage', info.uid, info.text);
          info.noReply = true; //这里就不应该继续跳下去
        }
      }
    });
    wechat.set('SERVICE_DELIVERY', {
      pattern: function(info) {
        return info.param.eventKey.toLowerCase() === 'service_delivery'; //这里崩溃了
      },
      handler: 'some reply'
    });

location的用法

请问example中的location是怎么使用了? 我在客户端发送什么能返回给我location

自我介绍的的问题

rules.js中的这段代码

  webot.set({
    name: 'your_name',
    description: '自我介绍下吧, 发送: I am [enter_your_name]',
    pattern: /^(?:my name is|i am|我(?:的名字)?(?:是|叫)?)\s*(.*)$/i,
    // handler: function(info, action){
    //   return '您好,' + info.query[1]
    // }

    //或者更简单一点
    handler: '您好,{1}'
  });

我在dialog.yaml中定义了"我爱你“的自动回复截断无效
IMG_0872

不维护更新了?

这个项目其实挺好的,不过微信公布的接口有更新,作者不同步更新了吗?比如微信支持回复音乐和视频之类~
还想问一个小问题:
文档中的:
4. set DEBUG=weixin.* (设置环境变量方可查看调试信息)
我在shell里做了,不起作用?请问是什么原因?我google这个debug模块的使用也找不到相关的使用介绍...

无法通过接入

你好,我在服务器上安装调试您的程序,然后准备接入微信公众平台,我修改了监听地址和token,但管网说无法响应,服务器上的webot调试成功,求解,谢谢。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.