weibo-pm

0.8.6 • Public • Published

Weibo-PM

Prowered By Edwon Lim


Introduction 介绍:

NPM

  • 从0.5.0版本开始,为完整的稳定版本。
  • 0.6版本增加转发监听
  • 0.7版本增加分词以及更详细文档
    • 0.7.2 整合Util
  • 0.8版本增加了整合微信公共账号后台的功能(无缝从微信迁移到微博
    • 0.8.1 支持把模拟接口放到BAE上(修复文件的本地缓存导致的错误)

Function 功能:

  1. 消息自动回复:回复内容包括文本消息、媒体Card、包含图片的消息、包含地理位置的消息。
  2. 事件自动回复:关注和取消关注时,自动发送私信。
  3. 目录机制:加入目录规则,可根据目录的不同,回复不同的消息,对未处理的消息进行分词后匹配。
  4. 留言箱:用户可以给不同的对象留言,例如投诉、询问,支持将留言转发至私信,邮件以及URL提交。
  5. 活动事件:通过私信进行活动,如抽奖和秒杀,并将结果制成Excel。
  6. 客服系统:通过私信转发,实现一个账号,多人接入的客服系统,一个大V账号可以接多个客服(微博账号),用户与大V账号的私信会被转发到客服账号。

支持二维码生成、邮件功能、上传功能、发微博、分词等。


Install & Use 安装与使用:

npm安装:

    npm install weibo-pm

require引入

    var pm = require("weibo-pm");

Base API 基本接口:

1.Initialize 初始化:

初始化模块 : 用户名,用户id,用户密码,在粉丝服务器管理平台中绑定的appkey (此用户要对APPKEY授权

    pm.init(username, uid, password, appkey);

2.Receive Message 接收消息:

组件:pm.listener

监听所有消息

    pm.listener.on(function(msg) {
        // 处理消息
    });

监听事件消息(关注和取消关注)

    pm.listener.onEvent(function(msg) {
        // 处理消息
    });

监听私信消息(包括文本,图片,地理位置,语音等)

    pm.listener.onMessage(function(msg) {
        // 处理消息
    });

监听@消息 (需要申请高级权限

    pm.listener.onMention(function(msg) {
        // 处理消息
    });

3.Start Listener 启动监听:

启动监听(每4分钟会自动重新建立HTTP长连接(文档上要求的,为了减少服务器压力)

    pm.listener.start();

4.Rely Message 回复消息:

组件:pm.reply

需要回复的消息的id,类型和数据,详细参看文档 (每条消息最多只可被回复 3 次

    pm.reply(msgId, type, data, function(rs) {
        // 处理结果
    });

文档:http://open.weibo.com/wiki/2/messages/reply

5.Send Message 发送消息:

组件:pm.send

用户id,类型和数据,详细参看文档 (只可给粉丝发送消息)

    pm.send(uid, type, data, function(rs) {
        // 处理结果
    });

文档:http://open.weibo.com/wiki/2/messages/send

6.Post Message 推送消息:

订阅用户推送消息 (此接口还没开放,开放后,会及时更新)


Extend API 拓展接口:

1.Open API 开放平台接口:

组件:pm.Util.OpenAPI

可以通过此接口,调用微博开放平台的接口,详细参看文档 (暂不支持Post提交文件

    // GET 请求
    pm.Util.OpenAPI.get("users/show", "uid=1908736117", function(data) {
        // 处返回理数据
    });
    
    // POST 请求
    pm.Util.OpenAPI.post("statuses/update", "status=" + encodeURIComponent("这是一条测试微博"), function(data) {
        // 处返回理数据
    });

2.Upload API 上传接口:

组件:pm.Util.Upload

可以通过此接口,上传文件到微盘

    pm.Util.Upload(options, function(data) {
        // 处理返回数据,返回数据中包含fid, vfid, tovfid及几张缩略图的地址。
    });

options参数如下:

  • toUid : 对方的用户id,必选,否则对方看不到
  • fid : 文件的id(微盘) 可选 自动下载后再上传
  • filePath : 文件的路径 可选
  • url : 文件的网络地址 可选 自动下载后再上传
  • qrCode : 二维码包含的信息 可选 先生成二维码,再上传

fid, filePath, url, qrCode 选择其一。

3.Status 发送微博:

组件:pm.Util.Status

可以通过此接口,发布微博

    pm.Util.Stauts(options, function(data) {
        // 平台标准返回
    });

options参数如下:

  • text : 微博内容,必选
  • pic : 图片路径 可选 (暂时仅支持本地图片,以后会拓展)
  • visible : 可见度 可选

4.Base62 微博ID转换:

组件:pm.Util.Base62

对微博的ID进行转换

    pm.Util.Base62.encode(mid);
    
    pm.Util.Base62.decode(id);

微博的ID为mid,微博的实际路径为http://weibo.com/用户id/base62的微博id

5.Debug 调试输出:

组件:pm.Util.Debug

  • 打开日志输出 pm.Util.Debug.open()
  • 日志输出 pm.Util.Debug.log(......)

Message Model 消息实体:

组件:pm.Message

在每次回复和发送私信的过程中,都可以创建一个消息实体

    var message = new pm.Message();    

设置需要回复的消息的id或者用户的id (两者必选其一)

    message.setId("msg id");
    message.setUid("user id");

设置文本信息,将发出文本消息

    message.setText("message text");

添加图文信息,将发出图文消息,展示为媒体Card

    message.addArticle("title", "summary", "image", "url");

设置地理位置,将发出地理位置的消息

    message.setPosition("longitude", "latitude");

设置图片(上传所得的id),将发出带有图片的消息

    message.setImage(vfid, tovfid);

设置图片路径,将发出带有图片的消息

    message.setImagePath("/path/to/file");

设置图片网络路径,将发出带有图片的消息

    message.setImageUrl("http://path/to/file");

设置图片微盘id,将发出带有图片的消息

    message.setImageId(id);

设置二维码信息,将发出带有图片的消息

    message.setQrCode("This is \"QRCode Info\".");

成功回调

    message.success(function(rs) {
        // 处理成功结果
    });

失败错误回调

    message.error(function(rs) {
        // 处理失败结果
    });

开始发送

    message.send();

简单示例

    new Message()
        .setUid("1908736117")
        .setText("Hello World!")
        .success(function(rs){alert("success")})
        .error(function(rs){alert("error")})
        .send();

Mention Manager @管理器:

组件:pm.MentionManager

需要申请前文所说的Mention权限

启动

    pm.MentionManager.start();

监听某一微博的转发:

    // 微博的id 监听函数
    pm.MentionManager.addRepostListener(statusId, function(user) {
        // 返回的user.uid是用户的id
    });

移除对某一微博的转发的监听:

    pm.MentionManager.removeRepostListener(statusId);

监听某一微博中的@自己的评论:

    // 微博的id 监听函数
    pm.MentionManager.addCommentListener(statusId, function(user) {
        // 返回的user.uid是用户的id
    });

移除对某一微博中的@自己的评论的监听:

    pm.MentionManager.removeCommentListener(statusId);

重置@管理器:

    pm.ReplyManager.reset();

Reply Manager 回复管理器:

组件:pm.ReplyManager

启动:

    pm.ReplyManager.start();

启动后,基本API Listener会失效。(基本API Listener不是队列是单个绑定

开启分级目录功能:

目录配置信息:

  • items : 目录(功能)及进入目录后,提示的信息(下面的配置中jscsshtml对应的是目录,而咨询投诉反馈客服则是对应的功能,将在后面具体讲解)
  • hotKey : 关键词,用户发送关键词,会回复目录帮助信息
  • helpText : 目录帮助信息
  • backText : 退出目录返回的信息
  • backKey : 退出目录的关键词
  • segment : 是否对未匹配的内容分词后,再匹配目录名
  • segmentTip : 匹配后回复的提示信息
  • timeout : 自动退出目录的等待时间,单位是秒 300表示5分钟没有消息,自动退出目录到根目录。
    pm.ReplyManager.openFloor({
        "items": {
            "js": "欢迎来到js脚本目录!发送 1 、 2  、 3 查看相应内容。",
            "css": "欢迎来到css样式目录!发送 1 、 2  、 3 查看相应内容。",
            "html": "欢迎来到html页面目录!发送 1 、 2 、 3 查看相应内容。",
            "咨询": "请输入您需要咨询的问题。",
            "投诉": "请输入您需要投诉的问题。",
            "反馈": "请输入您需要反馈的问题。",
            "客服": null
        },
        "hotKey": ["menu", "菜单"],
        "helpText": "欢迎您的访问:\n请发送\"js\",\"css\",\"html\"进入相应目录,输入\"0\"退出相应目录;\n发送`咨询`,`投诉`,`反馈`,`客服`进入相应功能。",
        "backText": {
            "js": "已经退出 js 目录。",
            "css": "已经退出 css 目录。",
            "html": "已经退出 html 目录。"
        },
        "backKey": ["0"],
        "segment" : true,
        "segmentTip" : "您找的是不是\"KEY\"?可以尝试输入\"KEY\"。",
        "timeout": 300
    });

处理过程:

处理过程是真正处理消息和回复消息的业务逻辑,开发者这可以自定义一些业务逻辑。

处理过程是一个对象,里面要包含onMessage, onEvent, onQuitFloor, onEnterFloor 中的一个或几个方法,当有相应事件时,会调用对应方法,接收到消息后,进项处理。

每个方法都可以有返回值

  • 如果返回值是"break",那么消息不会继续进入到后续的处理过程中,类似于阻止冒泡
  • 如果返回值是"keep",那么此目录的有效时间将变为1天
    var Process = {
        onMessage : function(msg, reply, floor) {}, // 有私信消息
        onEvent : function(msg, reply) {}, // 有事件消息
        onQuitFloor : function(msg, reply, floor) {}, // 退出目录
        onEnterFloor : function(msg, reply, floor) {} // 进入目录
    }

参数中msg是消息,replypm.Message实体,已经设置好iduid,设置回复内容后,可直接发送,floor为目录,开启目录功能后,会有此参数。

增加处理过程:

    pm.ReplyManager.addProcess(process);

添加处理过程后,会为process添加3个方法

销毁处理过程(不是真正的销毁,是从处理过程的队列里移除):

    process.destory();

重置用户至根目录:

    process.resetUser(uid)

移动用户到固定目录:

    // 用户id,目录,目录持续时间
    process.moveUser(uid, floor, time);

删除处理过程:

    pm.ReplyManager.removeProcess(process);

重置回复管理器:

    pm.ReplyManager.reset();

两个简单的处理过程的Demo

根据用户微博账户信息情况,回复不同的内容

根据用户的地域和性别回复相应内容。

    var process = {
        onMessage : function(msg, reply) {
            // 判断消息是不是符合要求
            if (msg.type == "text" && msg.text == "我是") {
                // 查询用户信息
                pm.OpenAPI.get("users/show", "uid=" + msg.fromUid, function(data) {
                    // 回复消息
                    reply.setText(data.location + " " + (data.gender == "m" ? "纯爷们" : "女汉子")).send();
                });
            }
        }
    }

查询外部接口,回复天气信息

    // 城市和代码对应关系
    var cities = {"北京" : "101010100"};
    var process = {
        onMessage : function(msg, reply) {
            // 判断消息是否符合标注
            if (msg.type == "text" && msg.text.indexOf("天气") > -1) {
                // 获取地理位置
                var addr = msg.text.replace(/天气/, "");
                if (cities[addr]) {
                    // 请求天气接口
                    http.request({
                        hostname : "m.weather.com.cn",
                        path : ("/data/" + cities[addr] + ".html")
                    }, function(res){
                        var rs = "";
                        res.on("data", function(chunk) {
                            rs += chunk + '';
                        });
                        res.on("end", function() {
                            rs = JSON.parse(rs).weatherinfo;
                            // 回复消息
                            reply.setText(rs.city + "\n" + rs.date_y + " " + rs.week + "\n天气:" + rs.weather1 + " " + rs.wind1 + "\n温度:" + rs.temp1 + "\n" + rs.index_d).send();
                        });
                    }).end();
                }
            }
        }
    };

查询BTC价格

    (function(module) {

        var btc = require('btc');

        var filter = {
            bitstamp : function(value) {
                var text = 'BitStamp : \n';
                text += 'High : $' + value.high + '\n';
                text += 'Low : $' + value.low + '\n';
                text += 'Ask : $' + value.ask + '\n';
                text += 'Bid : $' + value.bid + '\n';
                text += 'Last : $' + value.last + '\n';
                text += 'Volume : ' + value.volume + '\n';
                return text;
            },
            mtgox : function(value) {
                var ticker = value.data;
                var text = 'Mtgox : \n';
                text += 'High : ' + ticker.high.display + '\n';
                text += 'Low : ' + ticker.low.display + '\n';
                text += 'Avg : ' + ticker.avg.display + '\n';
                text += 'Vwap : ' + ticker.vwap.display + '\n';
                text += 'Last : ' + ticker.last.display + '\n';
                text += 'Volume : ' + ticker.vol.display + '\n';
                return text;
            },
            futures796 : function(value) {
                var ticker = value.ticker;
                var text = 'Futures796 : \n';
                text += 'High : $' + ticker.high + '\n';
                text += 'Low : $' + ticker.low + '\n';
                text += 'Buy : $' + ticker.buy + '\n';
                text += 'Sell : $' + ticker.sell + '\n';
                text += 'Last : $' + ticker.last + '\n';
                text += 'Volume : ' + ticker.vol + '\n';
                return text;
            },
            chbtc : function(value) {
                var ticker = value.ticker;
                var text = 'ChBtc : \n';
                text += 'High : ¥' + ticker.high + '\n';
                text += 'Low : ¥' + ticker.low + '\n';
                text += 'Buy : ¥' + ticker.buy + '\n';
                text += 'Sell : ¥' + ticker.sell + '\n';
                text += 'Last : ¥' + ticker.last + '\n';
                text += 'Volume : ' + ticker.vol + '\n';
                return text;
            },
            okcoin : function(value) {
                var ticker = value.ticker;
                var text = 'OKCoin : \n';
                text += 'High : ¥' + ticker.high + '\n';
                text += 'Low : ¥' + ticker.low + '\n';
                text += 'Buy : ¥' + ticker.buy + '\n';
                text += 'Sell : ¥' + ticker.sell + '\n';
                text += 'Last : ¥' + ticker.last + '\n';
                text += 'Volume : ' + ticker.vol + '\n';
                return text;
            },
            btcchina : function(value) {
                var ticker = value.ticker;
                var text = 'BtcChina : \n';
                text += 'High : ¥' + ticker.high + '\n';
                text += 'Low : ¥' + ticker.low + '\n';
                text += 'Buy : ¥' + ticker.buy + '\n';
                text += 'Sell : ¥' + ticker.sell + '\n';
                text += 'Last : ¥' + ticker.last + '\n';
                text += 'Volume : ' + ticker.vol + '\n';
                return text;
            },
            fxbtc : function(value) {
                var ticker = value.ticker;
                var text = 'FxBtc : \n';
                text += 'High : ¥' + ticker.high + '\n';
                text += 'Low : ¥' + ticker.low + '\n';
                text += 'Bid : ¥' + ticker.bid + '\n';
                text += 'Ask : ¥' + ticker.ask + '\n';
                text += 'Last : ¥' + ticker.last + '\n';
                text += 'Volume : ' + ticker.vol + '\n';
                return text;
            },
            btc100 : function(value) {
                var ticker = value.ticker;
                var text = 'BTC100 : \n';
                text += 'High : ¥' + ticker.high + '\n';
                text += 'Low : ¥' + ticker.low + '\n';
                text += 'Bid : ¥' + ticker.bid + '\n';
                text += 'Ask : ¥' + ticker.ask + '\n';
                text += 'Last : ¥' + ticker.last + '\n';
                text += 'Volume : ' + ticker.vol + '\n';
                return text;
            }
        };

        module.exports = {
            onMessage : function(msg, reply, floor) {
                if (floor == 'btc') {
                    msg.text = msg.text.toLowerCase();
                    if (!filter[msg.text]) {
                        msg.text = 'btcchina';
                    }
                    btc.price(msg.text, function(err, prices){
                        reply.setText(filter[msg.text](prices)).send();
                    });
                }
            }
        };

    })(module);

支持微信公共账号(订阅号/服务号)无缝迁移

  • 模拟微信服务器,向公共账号开发者后台请求数据,格式与微信完全相同,省去开发者代码改造的麻烦。

  • 模拟实现上传下载,用户查询等微信接口,数据格式和微信相同,开发者只需更改API的url的host即可。

支持微信自动回复机制

在不用修改任何代码逻辑的情况下,将自动回复功能从微信迁移到微博公共账号上

组件:pm.WeChat.Process

    pm.ReplyManager.addProcess(
        new pm.WeChat.Process(
            "http://sipc.sinaapp.com/index.php",
            "sipc******",
            "http://weibopm.duapp.com",
            "wechat"
        )
    );
  • 前两个参数是URLToken,和微信后台配置是相同的,如下面的图示。
  • 第三个参数是模拟API的Host(下节将说明)。
  • 第四个参数示floor,表示此目录下的消息会推送给URL,没有此参数,则全部消息都会推送到URL上。

图示:配图

注意:

  • 现在仅支持文字、图片、地理位置的推送。
  • 现在仅支持文字、图片、图文消息的回复。
  • 常用的一般是文字和图文,而且不分目录,因此后两个参数基本上可以忽略。
  • 怎么区分消息是从微信还是微博来?我觉得你的微信ID和微博的ID是不同的,判断ToUserName即可。

支持模拟微信API

微信公共平台给开发者提供了一些API,url前缀为: https://api.weixin.qq.com,在这里为了让开发者更容易迁移,提供一个模拟微信API的模块。

组件:pm.WeChat.Server

    // appid, secret 和 端口
    pm.WeChat.Server("abc", "123", 8080);

这样开发者只需把url改成此服务的部署的地址即可,例如: https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=abc&secret=123改为你的服务地址/cgi-bin/token?grant_type=client_credential&appid=abc&secret=123 即可,返回结果和微信的接口完全相同。

现在支持的常用接口有:

  • /cgi-bin/token
  • /cgi-bin/media/upload
  • /cgi-bin/media/get
  • /cgi-bin/message/custom/send
  • /cgi-bin/user/info

接口形式和文档上完全一样,基本上可以直接迁移


华丽丽地分割一下

上面的是基本的数据交互接口,开发者可以基于它构建自己的自动回复管理工具。

下面将是5类7种已经完成的处理功能,可以配置后直接使用。


Static Auto Reply 静态自动回复:

根据用户的消息/事件,静态匹配,并自动回复静态内容。

1. ReplyForEvent 事件自动回复:

组件: pm.ReplyProcess.replyForEvent

根据用户的关注/取消关注事件,回复静态消息。

示例如下:

    var rfe = pm.ReplyProcess.replyForEvent;

    rfe.init({
    	"follow" : "亲!欢迎关注本账号!输入 menu 或 菜单 查看相应内容。", // 关注回复
    	"unfollow" : "不要离开我,行不行吗?呜呜!" // 取消关注回复
    });

    pm.ReplyManager.addProcess(rfe);

配图

2. ReplyForText 文本消息自动回复:

组件: pm.ReplyProcess.replyForText

根据用户的文本消息,回复静态消息。

示例如下:

    var rft = pm.ReplyProcess.replyForText;

    rft.init({
        "js": {
            "1": ["text", "js是很神奇的东西"],
            "2": [
                "articles",
                [
                    ["js很牛", "js太牛了", "http://tp2.sinaimg.cn/1908736117/180/5678518790/1", "http://weibo.com"],
                    ["js很牛逼", "js太牛逼了", "http://tp2.sinaimg.cn/1908736117/180/5678518790/1", "http://weibo.com"]
                ]
            ],
            "3" : ["imagePath", "/Users/Apple/Documents/npm.png"]
        },
        "css": {
            "1": ["text", "css是很神奇的东西"],
            "2": ["image", 1055597360, 1055597367],
            "3": ["imageUrl", "http://tp2.sinaimg.cn/1908736117/180/5678518790/1"]
        },
        "html": {
            "1": ["text", "html是很神奇的东西"],
            "2": ["position", "116.309868", "39.984371"],
            "3": ["qrCode", "http://weibo.com"]
        }
    });

    pm.ReplyManager.addProcess(rft);
  • 图示1: 配图

  • 图示2: 配图

  • 图示3: 配图

  • 图示4: 配图


Event 活动(纯私信):

1.Lottery 乐透大抽奖

抽奖活动:通过私信发送固定消息后可以参与抽奖,结束时,会随机抽出幸运用户,自动发送获奖和未获奖的消息。 可以创建多次抽奖活动。

组件: pm.ReplyProcess.Lottery

示例如下:

    // 创建示例
    var lot = new pm.ReplyProcess.Lottery();

    // 设置开始和结束时间
    lot.setTime("2013/11/11 00:00:00", "2013/11/11 01:00:00");

    // 设置参与活动的固定消息
    lot.setKey(["抽奖", "cj"]);

    // 设置回复内容
    lot.setContent({
    	beforeEvent : "抽奖还未开始!",
    	onEvent : "成功参与抽奖,请耐心等待结果!",
    	repeat : "您已成功参与抽奖!每人只可参与一次!",
    	afterEvent : "抽奖已经结束!",
    	prize : "恭喜您获得【NAME】- TEXT ,稍后我们将私信联系您。",
    	none : "很遗憾,您没有抽中任何奖项,谢谢您的参与!"
    });

    // 增加奖项
    lot.addPrize("特等奖", "宝马一辆", 1);
    lot.addPrize("一等奖", "Mac Pro一台", 1);
    lot.addPrize("二等奖", "MacBook Pro一台", 1);

    // 设置结果输出文件 Excel
    lot.setLogFile("/Users/Apple/Downloads/lot.xlsx");

    // 增加处理过程
    pm.ReplyManager.addProcess(lot);

获取结果 : lot.getResult();

图示: 图例

2. SecKill 秒杀:

抽奖活动:通过私信发送固定消息后可以参与秒杀,秒杀按照私信先来后到来排序,先到先得,秒完为止。 可以创建多次秒杀活动。

组件: pm.ReplyProcess.SecKill

示例如下:

    // 创建秒杀活动实例
    var sk = new pm.ReplyProcess.SecKill();

    // 设置开始和结束时间
    sk.setTime("2013/11/11 00:00:00", "2013/11/11 01:00:00");

    // 设置参与活动的固定消息
    sk.setKey(["秒杀", "ms"]);

    // 设置回复内容
    sk.setContent({
    	beforeEvent : "秒杀还未开始!",
    	repeat : "您已成功秒杀!每人只可秒杀一次!",
    	afterEvent : "秒杀已经结束!",
    	success : "恭喜您获得 - NAME ,稍后我们将私信联系您。",
    	none : "商品已经全部被秒杀!"
    });
    
    // 增加奖项
    sk.setPrize("宝马一辆", 1);

    // 设置结果输出文件 Excel
    sk.setLogFile("/Users/Apple/Downloads/sk.xlsx");

    // 增加处理过程
    pm.ReplyManager.addProcess(sk);

获取结果 : sk.getResult();

图示:

图例


Event 活动(私信与转发结合):

RepostDiscount 转发获取获取优惠劵:

转发相应微博后,会用私信通知粉丝,然后粉丝回复相应内容,即可获得优惠劵。

组件:pm.ReplyProcess.RepostDiscount

    // 创建活动实例
    var rd = new pm.ReplyProcess.RepostDiscount("转发优惠活动");

    // 设计关键字
    rd.setKey("优惠");

    // 设置优惠劵数量
    rd.setNum(100);

    // 设置时间和发送的微博
    rd.setConf("2013/11/11 00:00:00", "2013/11/11 01:00:00", {
    	text : "[Test] 关注本账号,并转发此微博,有机会获得本店优惠劵一张。【测试测试测试】"
    });

    // 设置回复内容
    rd.setContent({
    	repostSuccess : "非常感谢您转发我们的微博,现在您可以回复\"优惠\"获得优惠券。",
    	success : "您已经成功获得优惠劵,消费时请出示微博昵称即可。",
    	repeat : "您已经获得过优惠券,请不要重复获取。",
    	none : "优惠劵已经派发完,歇歇您的参与"
    });

    // 添加处理过程
    pm.ReplyManager.addProcess(rd);

图示:

图例


MailBox 信箱:

信箱,留言箱,提供用户留言功能,并具有分类的功能(创建多个MailBox实例),为大V提供真正的留言功能。

组件: pm.ReplyProcess.MailBox

它能将用户的留言以三种形式存储:

  1. 以私信的形式转发给其他固定的账号,这是这个账号和大V得私信列表就是留言记录。
  2. 以邮件的形式发到固定的账号,当然两个邮件账号之间的邮件列表就是留言记录,而且方便处理。
  3. 以http post形式提交到指定的url,这个适用于公司有自己的留言系统的。

私信形式:

示例代码

    // 创建MailBox实例
    var mb = new pm.ReplyProcess.MailBox("咨询系统");
    
    // 设置相应关键字
    mb.setKey("咨询");
    
    // 设置回复内容
    mb.setContent({
    	"success": "您的咨询问题已经收到,我们将找专业人员为您解答!",
    	"notSupport": "对不起,系统不支持您的消息类型。"
    });
    
    // 设置类型 message 第二个参数为uid列表,是转发给的用户的id
    mb.setType("message", ["2609545991"]);
    
    // 添加处理过程
    pm.ReplyManager.addProcess(mb);
  • 图示1: 配图
  • 图示2: 配图

邮件形式

示例代码

    // 创建MailBox实例
    var mb = new pm.ReplyProcess.MailBox("投诉系统");
    
    // 设置相应关键字
    mb.setKey("投诉");
    
    // 设置回复内容
    mb.setContent({
    	"success": "您的投诉问题已经收到,我们将找专业人员为您解答!",
    	"notSupport": "对不起,系统不支持您的消息类型。"
    });
    
    // 设置类型 
    mb.setType("mail", {
    	"host": "smtp.163.com", // 邮件服务器,暂时仅支持stmp协议
    	"secureConnection": true, // 加密否
    	"port": 465, // 端口
    	"user": "yinxl_002@163.com", // 发邮件的邮箱账户
    	"pass": "******", // 对应的密码
    	"toUser": "edwon.lim@gmail.com" // 发给的邮箱账户
    });
    
    // 添加处理过程
    pm.ReplyManager.addProcess(mb);
  • 图示1: 配图
  • 图示2: 配图

Post形式

示例代码

    // 创建MailBox实例
    var mb = new pm.ReplyProcess.MailBox("反馈系统");
    
    // 设置相应关键字
    mb.setKey("反馈");
    
    // 设置回复内容
    mb.setContent({
    	"success": "您的反馈问题已经收到,我们将找专业人员为您解答!",
    	"notSupport": "对不起,系统不支持您的消息类型。"
    });
    
    // 设置类型 
    mb.setType("server", {
    	"url" : "http://127.0.0.1:8080/",
    	"token" : "feedback"
    });
    
    
    // 添加处理过程
    pm.ReplyManager.addProcess(mb);

注意:为了防止url被非法提交,server接收的post参数里有tokentagtimestamp三个参数, 其中 token 应该等于 sha1(tag + static_token + timestamp)static_token为配置中的feedback

因为static_token是不公开的,服务器可以通过token验证请求是不是来自本系统,从而排除非法提交。


CustomerService 客服系统:

基于微博私信的客服系统,使一个大V账号,可以连接多个客服账号,而用户只需和大V进行私信交互,就可实现和客服的一对一交交流。首先方便了用户,让用户通过与只一个账号互动,而完成很多事情,然后对于大V用户,更容易管理,并借助微博私信的便利,形成自己的客服系统。

组件: pm.ReplyProcess.CustomerService

示例如下:

    // 创建客服系统实例
    var cs = new pm.ReplyProcess.CustomerService();
    
    // 设置启用时间
    cs.setTime("9:30", "19:00");

    // 设置关键字
    cs.setKey(["客服"]);

    // 设置客服人员名称和对应的微博用户Id
    cs.setWorkers({
    	"小洋" : "2609545991"
    });

    // 设置回复内容
    cs.setContent({
        outerTime : "对不起,现在不是客服服务时间。\n(服务时间9:30~19:00)",
        enter : "欢迎使用客服系统,系统正在自动为您连接客服人员,请稍候!\n(发送0可以退出客服系统)",
        follow : "【注意】由于系统限制,关注本账号,成为本账号的粉丝,才能正常使用客服系统。",
        wait : "【排队中】现在业务非常繁忙,请您稍等片刻!\n(发送0可以退出客服系统)",
        startConv : "已经连接到客服人员,客服【 NAME 】为您服务!\n(发送0可以退出客服系统)",
        stopConv : "您已经退出客服系统,欢迎下次再次使用。",
        worker : "【 NAME 】:\n欢迎进入客服人员工作系统:\n发送next接待下一位客户;\n发送 talk:用户昵称或用户id 与相应直接沟通;\n发送exit退出与当前客户的交流;\n发送0退出客服系统。",
        none : "客服系统中现在没有等待的客户。",
        new : "有新客户进入客服系统,发送next进行接待。",
        startWork : "客户已经接入。",
        stopWork : "和客户的交谈已经结束,发送next接待下一位客户。",
        notSupport : "对不起,客服系统不支持您的消息类型。",
        noUser : "用户不存在或者不是此账号的粉丝。"
    });

    // 添加处理过程
    pm.ReplyManager.addProcess(cs);

用户操作:

  • 对于用户,需要输入关键字客服,即可进入客服系统,进入后会有相应提示。(使用客服系统的用户应是粉丝用户
  • 配图
  • 当客服接入后,会有提示,然后和正常聊天相同,发消息即可。
  • 配图
  • 输入0,可以立刻退出客服系统。
  • 配图

客服操作:

  • 对于客服,需要输入关键字客服,即可进入客服系统,进入后会有相应提示。(客服最好是大V的互粉用户
  • 配图
  • 发送next,可以接待下一位客户。
  • 当然也可以用talk:edwon_lim直接联系客户。
  • 连接成功后,会用客户信息的简介。
  • 配图
  • 对于客服人员,会有特殊的输入规则,
    • qr:二维码信息:客户会收到一个二维码图片,
    • url:图片地址:客户会收到相应图片,
    • pos:精度,纬度:客户会收到一个带有地理位置信息的消息
    • place:地点名:客户会收到一个带有地理位置信息的消息(地点名尽量明确,否则容易有差错
  • 客服人员可以输入exit结束与此客户的连接。
  • 配图
  • 输入0,可以立刻退出客服系统。

Development & Deployment 开发和部署:

开发测试

由于大V账号不是非常容易申请,很有可能很多开发者共用一个账号测试,这样一个人发的测试消息,另一个人的程序也会收到,容易造成错乱。

对于这种情况,可以在初始化时使用filter来解决:

    var allowUids = [1908736117, 2609545991];

    pm.init(username, uid, password, appkey, function(msg) {
        if (allowUids.indexOf(msg.fromUid) > -1) {
            return true;
        }
    });

只处理uid是1908736117和2609545991的消息,这样不同的程序会处理不同的消息。

分离部署

当私信量足够大的时候,单独一个服务可能在压力和处理速度上会遇到瓶颈,而nodejs的效率要与编译性语言稍差,所以这就需要将服务部署很多份,而且互不影响。

  • 对于Event活动,可以单独部署一个服务,这个服务不支持目录,不支持各种回复,只支持此活动,活动的消息,别的服务不会处理,只是这个服务进行处理。活动进行完,可以直接停止服务,不用再占用资源。

  • 同样的,不同类型的处理过程(Process)可以部署到不同的环境,不同的机器上。

  • 也可以使用开发测试时的方法,使用filter设定每个服务处理消息的uid范围,不用的服务处理不同范围用户的消息,这样可以分流压力。


Configure 统一配置:

可以统一配置这些功能:

    pm.configure(options);

配置格式为:

{
    "floor": {
        "items": {
            "js": "欢迎来到js脚本目录!输入 1 、 2  、 3 查看相应内容。",
            "css": "欢迎来到css样式目录!输入 1 、 2  、 3 查看相应内容。",
            "html": "欢迎来到html页面目录!输入 1 、 2 、 3 查看相应内容。",
            "咨询": "请输入您需要咨询的问题。",
            "投诉": "请输入您需要投诉的问题。",
            "反馈": "请输入您需要反馈的问题。",
            "客服": null
        },
        "hotKey": [
            "menu",
            "菜单"
        ],
        "helpText": "欢迎您的访问:\n请发送\"js\",\"css\",\"html\"进入相应目录,输入\"0\"退出相应目录;\n发送`咨询`,`投诉`,`反馈`,`客服`进入相应功能。",
        "backText": {
            "js": "已经退出 js 目录。",
            "css": "已经退出 css 目录。",
            "html": "已经退出 html 目录。"
        },
        "backKey": [
            "0"
        ],
        "segment" : true,
        "segmentTip" : "您找的是不是\"KEY\"?可以尝试输入\"KEY\"。",
        "timeout": 300
    },
    "forText": {
        "js": {
            "1": [
                "text",
                "js是很神奇的东西"
            ],
            "2": [
                "articles",
                [
                    [
                        "js很牛",
                        "js太牛了",
                        "http://tp2.sinaimg.cn/1908736117/180/5678518790/1",
                        "http://weibo.com"
                    ],
                    [
                        "js很牛逼",
                        "js太牛逼了",
                        "http://tp2.sinaimg.cn/1908736117/180/5678518790/1",
                        "http://weibo.com"
                    ]
                ]
            ],
            "3" : [
                "imagePath",
                "/Users/Apple/Documents/npm.png"
            ]
        },
        "css": {
            "1": [
                "text",
                "css是很神奇的东西"
            ],
            "2": [
                "image",
                1055597360,
                1055597367
            ],
            "3": [
                "imageUrl",
                "http://tp2.sinaimg.cn/1908736117/180/5678518790/1"
            ]
        },
        "html": {
            "1": [
                "text",
                "html是很神奇的东西"
            ],
            "2": [
                "position",
                "116.309868",
                "39.984371"
            ],
            "3": [
                "qrCode",
                "http://weibo.com"
            ]
        }
    },
    "forEvent": {
        "follow": "亲!欢迎关注本账号!输入 menu 或 菜单 查看相应内容。",
        "unfollow": "不要离开我,行不行吗?呜呜!"
    },
    "customer": {
        "startTime": "9:00",
        "endTime": "21:30",
        "key": "客服",
        "workers": {
            "小洋": "2609545991"
        },
        "content": {
            "outerTime": "对不起,现在不是客服服务时间。\n(服务时间9:30~21:30)",
            "enter": "欢迎使用客服系统,系统正在自动为您连接客服人员,请稍候!\n(发送0可以退出客服系统)",
            "follow": "【注意】由于系统限制,关注本账号,成为本账号的粉丝,才能正常使用客服系统。",
            "wait": "【排队中】现在业务非常繁忙,请您稍等片刻!\n(发送0可以退出客服系统)",
            "startConv": "已经连接到客服人员,客服【 NAME 】为您服务!\n(发送0可以退出客服系统)",
            "stopConv": "您已经退出客服系统,欢迎下次再次使用。",
            "worker": "【 NAME 】:\n欢迎进入客服人员工作系统:\n发送next接待下一位客户;\n发送 talk:用户昵称或用户id 与相应直接沟通;\n发送exit退出与当前客户的交流;\n发送0退出客服系统。",
            "none": "客服系统中现在没有等待的客户。",
            "new": "有新客户进入客服系统,发送next进行接待。",
            "startWork": "客户已经接入。",
            "stopWork": "和客户的交谈已经结束,发送next接待下一位客户。",
            "notSupport": "对不起,客服系统不支持您的消息类型。",
            "noUser": "用户不存在或者不是此账号的粉丝。",
            "noPlace": "地点不存在。"
        }
    },
    "box": [
        {
            "name": "咨询信箱",
            "key": "咨询",
            "type": "message",
            "data": [
                "2609545991"
            ],
            "content": {
                "success": "您的咨询问题已经收到,我们将找专业人员为您解答!",
                "notSupport": "对不起,系统不支持您的消息类型。"
            }
        },
        {
            "name": "投诉信箱",
            "key": "投诉",
            "type": "mail",
            "data": {
                "host": "smtp.163.com",
                "secureConnection": true,
                "port": 465,
                "user": "yinxl_002@163.com",
                "pass": "******",
                "toUser": "edwon.lim@gmail.com"
            },
            "content": {
                "success": "您的投诉已经受理,谢谢您的支持!",
                "notSupport": "对不起,系统不支持您的消息类型。"
            }
        },
        {
            "name": "反馈信箱",
            "key": "反馈",
            "type": "server",
            "data": {
                "url" : "http://127.0.0.1:8080/",
                "token" : "feedback"
            },
            "content": {
                "success": "您的咨询问题已经收到,我们将找专业人员为您解答!",
                "notSupport": "对不起,系统不支持您的消息类型。"
            }
        }
    ],
    "event": [
        {
            "type": "Lottery",
            "name" : "双11抽奖活动",
            "startTime": "2013/11/11 00:00:00",
            "endTime": "2013/11/11 01:00:00",
            "key": [
                "抽奖",
                "cj"
            ],
            "prize": [
                [
                    "特等奖",
                    "宝马一辆",
                    1
                ],
                [
                    "一等奖",
                    "Mac Pro一台",
                    1
                ],
                [
                    "二等奖",
                    "MacBook Pro一台",
                    1
                ]
            ],
            "content": {
                "beforeEvent": "抽奖还未开始!",
                "onEvent": "成功参与抽奖,请耐心等待结果!",
                "repeat": "您已成功参与抽奖!每人只可参与一次!",
                "afterEvent": "抽奖已经结束!",
                "prize": "恭喜您获得【NAME】- TEXT ,稍后我们将私信联系您。",
                "none": "很遗憾,您没有抽中任何奖项,谢谢您的参与!"
            }
        },
        {
            "type": "SecKill",
            "name" : "双11日秒杀活动",
            "startTime": "2013/11/11 00:00:00",
            "endTime": "2013/11/11 01:00:00",
            "key": [
                "秒杀",
                "ms"
            ],
            "prize": {
                "name": "宝马M",
                "num": 1
            },
            "content": {
                "beforeEvent": "秒杀还未开始!",
                "repeat": "您已成功秒杀!每人只可秒杀一次!",
                "afterEvent": "秒杀已经结束!",
                "success": "恭喜您获得 - NAME ,稍后我们将私信联系您。",
                "none": "商品已经全部被秒杀!"
            }
        },
        {
            "type": "RepostDiscount",
            "name" : "转发微博换优惠劵活动",
            "startTime": "2013/11/11 00:00:00",
            "endTime": "2013/11/11 01:00:00",
            "key": [
                "优惠"
            ],
            "status" : {
                "text" : "[Test] 关注本账号,并转发此微博,有机会获得本店优惠劵一张。"
            },
            "num" : 100,
            "content" : {
                "repostSuccess" : "非常感谢您转发我们的微博,现在您可以回复\"优惠\"获得优惠券。",
                "success" : "您已经成功获得优惠劵,消费时请出示微博昵称即可。",
                "repeat" : "您已经获得过优惠券,请不要重复获取。",
                "none" : "优惠劵已经派发完,歇歇您的参与"
            }
        }
    ]
}

TODO 要做的:

  1. 优化代码。
  2. 集成系统,统一管理多份部署的服务。
  3. 桌面系统,基于Node-Webkit开发桌面端的服务,方便操作,可视直观。

Readme

Keywords

none

Package Sidebar

Install

npm i weibo-pm

Weekly Downloads

23

Version

0.8.6

License

none

Last publish

Collaborators

  • edwonlim