代码拉取完成,页面将自动刷新
/**
* @project weixin
* @author ddc <jncpp@qq.com>
*/
var EVENT_EMITTER = require("events").EventEmitter;
var SHA1 = require("crypto").createHash('sha1');
var UTIL = require("util");
var HTTP = require("http");
var XML2JS = require("xml2js").parseString;
var LOGGER = require("./config.js").Logger;
/**
* 微信类,处理消息和发送消息
*
* @constructor
*/
function Weixin() {}
UTIL.inherits(Weixin, EVENT_EMITTER); // 继承自EventEmitter的原型
exports.Weixin = Weixin;
/**
* 全局配置数据
*
* @namespace
* @name config
*/
Weixin.prototype.config = {
/**
* Weixin Token
*
* @type String
* @memberof config
*/
token: "kingddc314",
/**
* 关注后给用户发送的文本消息
*
* @type String
* @memberof config
*/
subscribeMsg: "欢迎关注wp8,请回复任意文字,机器人能自动回复的哟!/::$/::$\n" +
"/::B收听电台回复:\n" +
"\t\t电台\n" +
"\t\tfm\n" +
"/:8-)搜索歌曲回复v加任意歌名或歌手关键字:\n" +
"\t\tv光辉岁月\n" +
"\t\tv张杰 领悟\n" +
"\t\tv平凡之路 朴树\n" +
"/::P更多功能敬请期待.../:,@f/:,@f/:,@f",
/**
* 当前订阅号ID
*
* @type String
* @memberof config
*/
userId: null,
/**
* Weixin内部自定义的错误消息,一般用于结果查找不到情况
*
* @type String
* @memberof config
*/
errorMsg: {
meessage: "unknown error",
code: 9527
},
/**
* 百度音乐中的音质码率设置,支持128和320
*
* @type String
* @memberof config
*/
rate: "&rate=128",
/**
* 百度音乐电台的频道key值和名称
*
* @type Array
* @memberof config
*/
fmList: [
{ key: "public_tuijian_winter", name: "温暖冬日" },
{ key: "public_tuijian_zhongguohaoshengyin", name: "中国好声音" },
{ key: "public_tuijian_rege", name: "热歌" },
{ key: "public_tuijian_ktv", name: "KTV金曲" },
{ key: "public_tuijian_billboard", name: "Billboard" },
{ key: "public_tuijian_chengmingqu", name: "成名曲" },
{ key: "public_tuijian_wangluo", name: "网络红歌" },
{ key: "public_tuijian_kaiche", name: "开车" },
{ key: "public_tuijian_yingshi", name: "影视" },
{ key: "public_tuijian_suibiantingting", name: "随便听听" },
{ key: "public_shiguang_jingdianlaoge", name: "经典老歌" },
{ key: "public_shiguang_70hou", name: "70后" },
{ key: "public_shiguang_80hou", name: "80后" },
{ key: "public_shiguang_90hou", name: "90后" },
{ key: "public_shiguang_xinge", name: "火爆新歌" }
],
/**
* 关注用户列表,包含每个用户的状态和数据, ["default"]为默认数据
*
* @type Object
* @memberof config
*/
userList: {
"default": {
status: 0, // 状态0为默认状态,状态1为用户输入音乐搜索,状态2为用户输入电台列表。。。然后等待输入数字进行选择
data: [], // 状态改变携带的数据
fmKey: "public_tuijian_suibiantingting" // 频道
}
}
};
/**
* 获取用户状态和数据
*
* @param {String} user
* @return {Object}
*/
Weixin.prototype.getUser = function(user){
var self = this;
// 不能对undefined进行任何运算
if(!self.config.userList[user]){
self.config.userList[user] = self.config.userList["default"];
}
return self.config.userList[user];
};
/**
* 设置用户状态和数据
*
* @param {String} user
* @param {Number} status - 0,默认状态 1,音乐选择状态 2,电台选择状态 3,公交站点选择状态
* @param {Array } data
* @param {String} fmKey - fmKey为空时使用默认值
*/
Weixin.prototype.setUser = function(user, status, data, fmKey){
var self = this;
if(!fmKey){
if(self.config.userList[user]){
fmKey = self.config.userList[user].fmKey;
}else{
fmKey = self.config.userList["default"].fmKey;
}
}
self.config.userList[user] = {
status: status,
data: data,
fmKey: fmKey
};
LOGGER.trace("status:", self.config.userList[user].status);
};
/**
* 删除用户
*
* @param {String} user
*/
Weixin.prototype.delUser = function(user){
var self = this;
self.config.userList[user] = null;
};
/**
* 重置用户状态和用户数据
*
* @param {String} user
*/
Weixin.prototype.resetUser = function(user){
var self = this;
self.setUser(user, 0, null, null);
};
/**
* 检查微信接口申请
*
* @param {Object} value
* @return {Boolean}
*/
Weixin.prototype.checkSignature = function (value) {
var arr = [this.config.token, value.timestamp, value.nonce];
arr.sort();
var check_str = SHA1.update(arr.join("")).digest('hex');
return (check_str == value.signature);
};
/**
* 解析并处理接收到的微信消息
*
* @param {Object} body
* @param {Object} response
*/
Weixin.prototype.parse = function (body, response) {
var self = this;
var date = new Date();
date.setTime(body.CreateTime[0] * 1000); // setTime是向1970添加毫秒,所以此处需要乘以1000
// 解析接收消息
var msgType = body.MsgType[0] ? body.MsgType[0] : "text";
switch (msgType) {
case "text":{
LOGGER.trace(UTIL.format("[%s] [%s] %s:\n\t%s",
body.MsgType[0], date.toString(), body.FromUserName[0], body.Content[0]));
self.parseTextMsg(body.FromUserName[0], body.Content[0], response);
break;
}
case "image":{
LOGGER.trace(UTIL.format("[%s] [%s] %s:\n\t%s\n\t",
body.MsgType[0], date.toString(), body.FromUserName[0], body.PicUrl[0]), body.MediaId[0]);
self.parseImageMsg(body.FromUserName[0], body.MediaId[0], response);
break;
}
case "voice":{
LOGGER.trace(UTIL.format("[%s] [%s] %s:\n\t%s",
body.MsgType[0], date.toString(), body.FromUserName[0], body.MediaId[0]));
self.parseVoiceMsg(body.FromUserName[0], body.MediaId[0], response);
break;
}
case "video":
break;
case "location":
break;
case "link":
break;
case "event":{
// 处理订阅或取消订阅事件
LOGGER.trace(UTIL.format("[%s] [%s] %s: %s",
body.MsgType[0], date.toString(), body.FromUserName[0], body.Event[0]));
self.parseEventMsg(body.FromUserName[0], body.Event[0], response);
break;
}
default :
break;
}
};
/**
* 解析文本消息
*
* @param {String} toUser
* @param {String} content
* @param {Object} response
*/
Weixin.prototype.parseTextMsg = function (toUser, content, response) {
var self = this;
// 播放百度音乐电台
if(content === "电台" || content === "fm" || content === "f")
{
self.processFmMsg(toUser, response);
}else if(content === "电台列表" || content === "fmlist" || content === "fl") {
self.processFmList(toUser, response);
}else{
// 使用百度音乐搜索,格式如"v领悟 张杰"
var match = content.match(new RegExp("v(.+)"));
if(match){
var title = match[1];
self.processMusicSearch(toUser, title, response);
}else{
// 是**路的线路查询
// 这里先匹配**路,再匹配**
var match2 = content.match(new RegExp("\\b(\\d+)路"));
if(match2){
self.processBusSearch(toUser, match2[1], false, response);
}else{
// 数字选择结果
match2 = content.match(new RegExp("\\b(\\d+)"));
if(match2) {
self.processChoiceResult(toUser, self.getUser(toUser).status, Number(match2[1]), response);
}else{
// 使用小黄鸡接口
//self.processXiaohuangji(toUser, content, response);
// 使用百度新闻搜索接口
self.processNewsSearch(toUser, content, response);
}
}
}
}
};
/**
* 处理文字消息中的电台消息
*
* @param {String} toUser
* @param {Object} response
*/
Weixin.prototype.processFmMsg = function(toUser, response){
var self = this;
// 发送FM歌曲列表的图文消息
var sendFmSongsByPlayList = function(){
if(self.playlist.length >= 5){
var items = [];
for(var i = 0; i <5; i++){
var songInfo = self.playlist.shift();
var str_size = UTIL.format(" [%dM]", Math.round(songInfo.size / 1024 / 1024 * 100) / 100);
var str_time = UTIL.format(" [%d:%d]", Math.floor(songInfo.time / 60), songInfo.time % 60);
var str_hq = songInfo.rate == 320 ? " [HQ]" : "";
items.push({
title: songInfo.songName + " - " + songInfo.artistName + str_hq,
desc: songInfo.albumName + str_size + str_time,
picUrl: songInfo.songPicRadio,
url: "http://music.baidu.com/song/" + songInfo.songId
});
}
self.sendNewsMsg({
toUser: toUser,
fromUser: self.config.userId,
items: items,
response: response
});
}
};
// 电台消息通过图文发送
if(!self.playlist || self.playlist.length < 5){
self.getBaiduFmPlayList(toUser, function(err, songs) {
if (!err && songs) {
LOGGER.info(UTIL.format("get new douban.fm playlist [%d]", songs.length));
self.playlist = songs;
sendFmSongsByPlayList();
}
});
}else{
sendFmSongsByPlayList();
}
};
/**
* 处理文本消息中的电台列表消息
*
* @param {String} toUser
* @param {Object} response
*/
Weixin.prototype.processFmList = function(toUser, response){
var self = this;
var str = '电台列表如下,回复数字选择相应频道:\n';
for (var i in self.config.fmList) {
str += UTIL.format("[%d] %s", Number(i) + 1, // 这里i是string类型,需要转换成number
self.config.fmList[i].name);
if(i != self.config.fmList.length - 1){
str += "\n";
}
}
self.sendTextMsg({
toUser: toUser,
fromUser: self.config.userId,
text: str,
response: response
});
self.setUser(toUser, 2, null, null);
};
/**
* 处理文本消息中的音乐搜索消息
*
* @param {String} toUser
* @param {String} title
* @param {Object} response
*/
Weixin.prototype.processMusicSearch = function(toUser, title, response){
var self = this;
self.getBaiduMusic(title, function(err, result){
if (!err) {
var str = '搜索"' + title + '"结果如下,回复数字选择播放:\n';
for (var i in result) {
if(Number(i) + 1 > 9){
break;
}
str += UTIL.format("[%d] %s", Number(i) + 1, // 这里i是string类型,需要转换成number
result[i].songName + " - " + result[i].artistName);
if(Number(i) + 1 < 9 && i != result.length - 1){
str += "\n";
}
}
self.sendTextMsg({
toUser: toUser,
fromUser: self.config.userId,
text: str,
response: response
});
self.setUser(toUser, 1, result, null);
}else{
self.processXiaohuangji(toUser, title, response);
}
});
};
/**
* 处理文本消息中的公交线路搜索
*
* @param {String} toUser
* @param {String} xianlu
* @param {Boolean} isBack
* @param {Object} response
*/
Weixin.prototype.processBusSearch = function(toUser, xianlu, isBack, response){
var self = this;
self.getBusInfo(xianlu, isBack, function(err, list){
if(err || list.result.length === 0){
self.sendTextMsg({
toUser: toUser,
fromUser: self.config.userId,
text: "公交线路[" + xianlu + "]查询结果不存在,请检查是否拼写有误",
response: response
});
}else{
var text = UTIL.format("%d路\n%s(%s)\n->\n%s(%s)\n\n换向请回复0\n\n", xianlu,
list.begin.name, list.begin.time, list.end.name, list.end.time);
for(var i in list.result){
var index = list.result[i].index.length === 1 ? (" " + list.result[i].index) : list.result[i].index;
text += (index + ": " + list.result[i].name + "\n");
}
self.sendTextMsg({
toUser: toUser,
fromUser: self.config.userId,
text: text,
response: response
});
self.setUser(toUser, 3, list, null);
}
});
};
/**
* 处理文本消息中发生数字选择结果的消息
*
* @param {String} toUser
* @param {Number} status
* @param {String | Number} number
* @param {Object} response
*/
Weixin.prototype.processChoiceResult = function(toUser, status, number, response){
var self = this;
switch(status){
case 1 :{
// 处理当搜索音乐后,等待用户选择的状态
var result = self.getUser(toUser).data[Number(number) - 1];
if(result){
var str_size = UTIL.format(" [%dM]", Math.round(result.size / 1024 / 1024 * 100) / 100);
var str_time = UTIL.format(" [%d:%d]", Math.floor(result.time / 60), result.time % 60);
var str_hq = result.rate == 320 ? " [HQ]" : "";
self.sendMusicMsg({
toUser: toUser,
fromUser: self.config.userId,
title: result.songName + " - " + result.artistName + str_hq,
desc: result.albumName + str_size + str_time,
url: result.songLink,
urlHD: result.songLink,
response: response
});
LOGGER.trace(result.songName + " - " + result.artistName, result.albumName);
LOGGER.trace(result.songLink);
}else{
self.processXiaohuangji(toUser, number, response);
}
break;
}
case 2:{
// 处理当发送电台列表后,等待用户选择的状态
var result = self.config.fmList[Number(number) - 1];
if(result){
self.setUser(toUser, 2, null, result.key); // 状态不变
self.playlist = null; // 清空歌曲列表
self.processFmMsg(toUser, response);
}else{
self.processXiaohuangji(toUser, number, response);
}
break;
}
case 3:{
// 处理当发送线路后,等待用户选择线路站点
var list = self.getUser(toUser).data;
if(Number(number) === 0){
self.processBusSearch(toUser, list.id, true, response);
}else if(Number(number) <= list.result.length){
self.getBusArriveInfo(list.id, list.result[Number(number) - 1].id, function(err, body){
var text = "";
if(err){
text = "未知错误,请重试";
}else{
var res = JSON.parse(body);
if(res.status === "101"){
for(var i in res.busList){
text += UTIL.format("距今%s站,在%s,预计%s分钟到站\n",
res.busList[i].lineDist, res.busList[i].currentStation, res.busList[i].arriveTime);
}
}else{
LOGGER.trace("bus arrive code: %s", res.status);
text = res.resultdes;
}
}
self.sendTextMsg({
toUser: toUser,
fromUser: self.config.userId,
text: text,
response: response});
});
}else{
self.processBusSearch(toUser, Number(number), false, response);
}
break;
}
default :{
//self.processXiaohuangji(toUser, number, response);
self.processBusSearch(toUser, number, false, response);
}
}
};
/**
* 处理文本消息中的其他消息,使用小黄鸡自动回复
*
* @param {String} toUser
* @param {String} content
* @param {Object} response
*/
Weixin.prototype.processXiaohuangji = function (toUser, content, response){
var self = this;
// 关键字预处理
if(content == "wp8"){ // wp8小黄鸡会自动回复垃圾,好吧,和谐一下
content = "WP8";
}
var addUrl = function(msg, url) {
return UTIL.format("<a href='%s'>%s</a>", url, msg);
};
self.getXiaohuangji(content, function(err, msg){
if(!err){
// 前置处理
if(content == "热门微博"){
msg = addUrl(msg, "http://m.weibo.cn/p/102803");
}else if(content == "微博"){
msg = addUrl(msg, "http://m.weibo.cn/");
}
self.sendTextMsg({
toUser: toUser,
fromUser: self.config.userId,
text: msg,
response: response
});
}else{
LOGGER.error("xiaohuangji error:", err);
}
self.resetUser(toUser);
});
};
/**
* 处理文本消息中的新闻搜索
*
* @param {String} toUser
* @param {String} content
* @param {Object} response
*/
Weixin.prototype.processNewsSearch = function(toUser, content, response){
var self = this;
var addUrl = function(msg, url) {
return UTIL.format("<a href='%s'>%s</a>", url, msg);
};
//http://news.baidu.com/ns?word=%s&tn=news&from=news&cl=2&rn=20&ct=1
//http://news.baidu.com/ns?ct=1&rn=20&ie=utf-8&rsv_bp=1&sr=0&cl=2&f=8&prevct=no&word=%s&tn=news&inputT=0
self.get(UTIL.format("http://news.baidu.com/ns?word=%s&tn=news&from=news&cl=2&rn=20&ct=1", content,content), function(err, body){
if(err){
self.processXiaohuangji(toUser,content, response);
}else{
var reg = new RegExp('<li[\\s\\S]+?' +
'<a\\s*href="(.+?)"[\\s\\S]+?' + // 匹配url
'>([\\s\\S]+?)</a>[\\s\\S]+?' + // 匹配标题
'class="c-author"> ([\\s\\S]+?) ' + // 匹配出处
'([\\s\\S]+?)</span>[\\s\\S]+?' + // 匹配时间
'</li>', "g");
var result;
var res = [];
while ((result = reg.exec(body)) != null) {
res.push({
url: result[1],
title: result[2].replace(/[<em>|<\/em>]/g, ""),
ref: result[3],
time: result[4]
});
}
if(res.length != 0){
var str = "";
for(var i in res){
if(Number(i) + 1 > 6){
break;
}
str += UTIL.format("[%d] %s\n\t\t[%s %s]", Number(i) + 1,
addUrl(res[i].title, res[i].url), res[i].ref, res[i].time
);
if(Number(i) + 1 < 6 && i != res.length - 1){
str += "\n\n";
}
}
self.sendTextMsg({
toUser: toUser,
fromUser: self.config.userId,
text: str,
response: response
});
self.resetUser(toUser);
}else{
self.processXiaohuangji(toUser,content, response);
}
}
});
};
/**
* 解析图片消息
*
* @param {String} toUser
* @param {String} mediaId
* @param {Object} response
*/
Weixin.prototype.parseImageMsg = function (toUser, mediaId, response) {
var self = this;
self.sendImageMsg({
toUser: toUser,
fromUser: self.config.userId,
mediaId: mediaId,
response: response
});
self.resetUser(toUser);
};
/**
* 解析语音消息
*
* @param {String} toUser
* @param {String} mediaId
* @param {Object} response
*/
Weixin.prototype.parseVoiceMsg = function (toUser, mediaId, response) {
var self = this;
self.sendVoiceMsg({
toUser: toUser,
fromUser: self.config.userId,
mediaId: mediaId,
response: response
});
self.resetUser(toUser);
};
/**
* 解析事件消息
*
* @param {String} toUser
* @param {String} event
* @param {Object} response
*/
Weixin.prototype.parseEventMsg = function (toUser, event, response) {
var self = this;
if(event == "subscribe")
{
// 订阅
self.sendTextMsg({
toUser: toUser,
fromUser: self.config.userId,
text: this.config.subscribeMsg,
response: response
});
self.resetUser(toUser);
}else if(event == "unsubscribe"){
// 取消订阅
response.end();
self.delUser(toUser);
}else{
self.resetUser(toUser);
response.end();
}
};
/**
* 发送文本消息
*
* @param {Object} value
* @example
* self.sendTextMsg({
* toUser: "接收消息用户",
* fromUser: "发送者",
* text: "文本内容",
* response: "http响应对象"
* })
*/
Weixin.prototype.sendTextMsg = function (value) {
var createTime = Math.round(Date.now() / 1000);
var str = UTIL.format("<xml>\
<ToUserName><![CDATA[%s]]></ToUserName>\
<FromUserName><![CDATA[%s]]></FromUserName>\
<CreateTime>%d</CreateTime>\
<MsgType><![CDATA[text]]></MsgType>\
<Content><![CDATA[%s]]></Content>\
</xml>", value.toUser, value.fromUser, createTime, value.text);
value.response.write(str, "utf8");
value.response.end();
};
/**
* 发送音乐消息
*
* @param {Object} value
* @example
* self.sendMusicMsg({
* toUser: "接收消息用户",
* fromUser: "发送者",
* title: "音乐标题",
* desc: "音乐描述",
* url: "音乐链接",
* urlHD: "高质量音乐链接,WIFI下优选此链接",
* mediaId: "缩略图的媒体ID[可选参数]"
* response: "http响应对象"
* })
*/
Weixin.prototype.sendMusicMsg = function(value){
var createTime = Math.round(Date.now() / 1000);
var media_str = "";
if(value.mediaId){
media_str = "<ThumbMediaId><![CDATA[" + value.mediaId + "]]></ThumbMediaId>";
}
var str = UTIL.format(
"<xml>\
<ToUserName><![CDATA[%s]]></ToUserName>\
<FromUserName><![CDATA[%s]]></FromUserName>\
<CreateTime>%d</CreateTime>\
<MsgType><![CDATA[music]]></MsgType>\
<Music>\
<Title><![CDATA[%s]]></Title>\
<Description><![CDATA[%s]]></Description>\
<MusicUrl><![CDATA[%s]]></MusicUrl>\
<HQMusicUrl><![CDATA[%s]]></HQMusicUrl>\
%s\
</Music>\
</xml>", value.toUser, value.fromUser, createTime,
value.title, value.desc, value.url, value.urlHD, media_str
);
value.response.write(str, "utf8");
value.response.end();
};
/**
* 发送图片消息
*
* @param {Object} value
* @example
* self.sendImageMsg({
* toUser: "接收消息用户",
* fromUser: "发送者",
* mediaId: "多媒体文件ID",
* response: "http响应对象"
* })
*/
Weixin.prototype.sendImageMsg = function(value){
var createTime = Math.round(Date.now() / 1000);
var str = UTIL.format("<xml>\
<ToUserName><![CDATA[%s]]></ToUserName>\
<FromUserName><![CDATA[%s]]></FromUserName>\
<CreateTime>%d</CreateTime>\
<MsgType><![CDATA[image]]></MsgType>\
<Image>\
<MediaId><![CDATA[%s]]></MediaId>\
</Image>\
</xml>", value.toUser, value.fromUser, createTime, value.mediaId);
value.response.write(str, "utf8");
value.response.end();
};
/**
* 发送语音消息
*
* @param {Object} value
* @example
* self.sendVoiceMsg({
* toUser: "接收消息用户",
* fromUser: "发送者",
* mediaId: "多媒体文件ID",
* response: "http响应对象"
* })
*/
Weixin.prototype.sendVoiceMsg = function(value){
var createTime = Math.round(Date.now() / 1000);
var str = UTIL.format("<xml>\
<ToUserName><![CDATA[%s]]></ToUserName>\
<FromUserName><![CDATA[%s]]></FromUserName>\
<CreateTime>%d</CreateTime>\
<MsgType><![CDATA[voice]]></MsgType>\
<Voice>\
<MediaId><![CDATA[%s]]></MediaId>\
</Voice>\
</xml>", value.toUser, value.fromUser, createTime, value.mediaId);
value.response.write(str, "utf8");
value.response.end();
};
/**
* 发送图文消息
*
* @param {Object} value
* @example
* self.sendNewsMsg({
* toUser: "接收消息用户",
* fromUser: "发送者",
* items: [
* {
* title: "标题",
* desc: "副标题(描述)",
* picUrl: "图片链接",
* url: "点击图文消息跳转连接"
* },
* {
* title: "标题",
* desc: "副标题(描述)",
* picUrl: "图片链接",
* url: "点击图文消息跳转连接"
* }
* ],
* response: "http响应对象"
* })
*/
Weixin.prototype.sendNewsMsg = function(value){
var createTime = Math.round(Date.now() / 1000);
var newsItems = "";
var items = value.items;
for(var i in items){
newsItems += UTIL.format("<item>\
<Title><![CDATA[%s]]></Title>\
<Description><![CDATA[%s]]></Description>\
<PicUrl><![CDATA[%s]]></PicUrl>\
<Url><![CDATA[%s]]></Url>\
</item>", items[i].title, items[i].desc, items[i].picUrl, items[i].url);
}
var str = UTIL.format("<xml>\
<ToUserName><![CDATA[%s]]></ToUserName>\
<FromUserName><![CDATA[%s]]></FromUserName>\
<CreateTime>%d</CreateTime>\
<MsgType><![CDATA[news]]></MsgType>\
<ArticleCount>%d</ArticleCount>\
<Articles>\
%s\
</Articles>\
</xml> ", value.toUser, value.fromUser, createTime, items.length, newsItems);
value.response.write(str, "utf8");
value.response.end();
};
/**
* 获取豆瓣电台列表
*
* @param {Function} cb
* @example
* self.getDoubanFmPlayList(function(err, resultList){
* });
*/
Weixin.prototype.getDoubanFmPlayList = function(cb){
var self = this;
self.get("http://douban.fm/j/mine/playlist?type=n&pt=5.1&channel=1&pb=64&from=mainsite", function(err, res_body){
if(err){
cb(err);
}else{
var result = JSON.parse(res_body);
result.song.shift(); // 忽略第一首歌
cb(null, result.song);
}
});
};
/**
* 获取百度电台列表
*
* @param {String} toUser
* @param {Function} cb
* @example
* self.getBaiduFmPlayList(toUser, function(err, resultList){
* });
*/
Weixin.prototype.getBaiduFmPlayList = function(toUser, cb){
var self = this;
self.get(UTIL.format("http://fm.baidu.com/dev/api/?tn=playlist&id=%s&special=flash&prepend=&format=json", self.getUser(toUser).fmKey), function(err, res_body){
if(err){
cb(err);
}else{
var result = JSON.parse(res_body);
for(var i in result.list){
result.list[i] = result.list[i].id;
}
var idlist = result.list.join(",");
var songinfo = UTIL.format("http://music.baidu.com/data/music/fmlink?songIds=%s&type=mp3%s", idlist, self.config.rate);
self.get(songinfo, function(err2, res_body2){
if(err2){
cb(err2);
}else {
var result2 = JSON.parse(res_body2);
if(result2.errorCode == 22000) {
cb(null, result2.data.songList);
}else{
cb(self.config.errorMsg, null);
}
}
});
}
});
};
/**
* 获取小黄鸡自动回复结果
*
* @param {String} content
* @param {Function} cb
* @example
* self.getXiaohuangji(content, function(err, content){
* });
*/
Weixin.prototype.getXiaohuangji = function(content, cb) {
var options = {
hostname: 'www.xiaohuangji.com',
path: '/ajax.php',
method: 'POST',
headers: {
"Accept":"*/*",
"Accept-Encoding":"gzip,deflate,sdch",
"Accept-Language":"zh-CN,zh;q=0.8",
"Connection":"keep-alive",
//"Content-Length":"6",
"Content-Type":"application/x-www-form-urlencoded",
//"Cookie":"bdshare_firstime=1407140631155",
"Host":"www.xiaohuangji.com",
"Origin":"http://www.xiaohuangji.com",
"Referer":"http://www.xiaohuangji.com/",
"User-Agent":"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36",
"X-Requested-With":"XMLHttpRequest"
}
};
// 发送小黄鸡请求
var req = HTTP.request(options, function(res){
res.setEncoding("utf8");
var res_body = "";
res.on("data", function(chunk) {
res_body += chunk;
});
res.on("end", function(){
cb(null, res_body);
});
res.on("error", function(err){
cb(err);
});
});
req.on("error", function(err){
LOGGER.error("problem with request: ", err.message);
cb(err);
});
// 写入请求主体
var contents = "para=" + content;
req.write(contents);
req.end();
};
/**
* 获取百度音乐搜索结果
*
* @param {String} title
* @param {Function} cb
* @example
* self.getBaiduMusic(title, function(err, resultList){
* });
*/
Weixin.prototype.getBaiduMusic = function(title, cb){
var self = this;
var url = UTIL.format("http://sug.music.baidu.com/info/suggestion?format=json&version=2&from=0&word=%s",
title);
self.get(url, function(err, res_body){
if(err){
cb(err, null);
}else{
var result = JSON.parse(res_body);
if(result.data.song && result.data.song.length > 0){
for(var i in result.data.song){
result.data.song[i] = result.data.song[i].songid;
}
var idlist = result.data.song.join(",");
self.get("http://ting.baidu.com/data/music/links?songIds=" + idlist + self.config.rate, function(err2, res_body2){
if(err2){
cb(err2, null);
}else{
var result2 = JSON.parse(res_body2);
if(result2.errorCode == 22000){
// 部分链接中带有&src=""需去除才能正常播放
for(var i in result2.data.songList){
var match = result2.data.songList[i].songLink.match(new RegExp('\\b(.+)&src=.+\\b"'));
if(match){
result2.data.songList[i].songLink = match[1];
}
}
cb(null, result2.data.songList);
}else{
cb(self.config.errorMsg, null);
}
}
});
}else{
cb(self.config.errorMsg, null);
}
}
});
};
/**
* 获取线路搜索结果信息
*
* @param {Number} xianlu
* @param {Boolean} isBack 是否是返程线路
* @param {Function} cb
* @return {Object}
* @example
* self.getBusInfo(xianlu, function(err, resultList){
* });
*/
Weixin.prototype.getBusInfo = function(xianlu, isBack, cb){
var self = this;
var url = UTIL.format("http://www.basbus.cn/m/line?id=%d%s", xianlu, isBack ? "&t=2" : "");
self.get(url, function(err, body){
if(err){
cb(err, null);
}else{
var reg = new RegExp('"li_01">(.+?)</li>[\\s\\S]*?"yuanicon">(\\d+)</div>' +
'[\\s\\S]*?"display:none">(\\d+)</p>', "g");
var result;
var list = { id: xianlu, result: []};
while((result = reg.exec(body)) != null){
list.result.push({
name: result[1],
index: result[2],
id: result[3]
})
}
reg = new RegExp('"leftspan01">(.+?)</span>[\\s\\S]*?"leftspan02">(.+?)</span>' +
'[\\s\\S]*?"rightspan01">(.+?)</span>[\\s\\S]*?"rightspan02">(.+?)</span>');
var match = body.match(reg);
if(match){
list.begin = {name: match[1], time: match[2]};
list.end = {name: match[3], time: match[4]};
}
cb(null, list);
}
});
};
/**
* 获取某线路的某站点的距离站点信息
* @param {String} id
* @param {String} gps
* @param {Function} cb
*/
Weixin.prototype.getBusArriveInfo = function(id, gps, cb){
// 写入请求主体
var contents = "id=" + id + "&g=" + gps;
var options = {
hostname: 'www.basbus.cn',
path: '/m/station',
method: 'POST',
headers: {
"Accept":"*/*",
"Accept-Encoding":"gzip,deflate,sdch",
"Accept-Language":"zh-CN,zh;q=0.8",
"Cache-Control": "no-cache",
"Connection":"keep-alive",
"Content-Length": contents.length,
"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8",
"Host":"www.basbus.cn",
"Origin":"http://www.basbus.cn",
"Referer":"http://www.basbus.cn/m/line?id=" + id,
"User-Agent":"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36",
"X-Requested-With":"XMLHttpRequest"
}
};
// 发送小黄鸡请求
var req = HTTP.request(options, function(res){
res.setEncoding("utf8");
var res_body = "";
res.on("data", function(chunk) {
res_body += chunk;
});
res.on("end", function(){
cb(null, res_body);
});
res.on("error", function(err){
cb(err);
});
});
req.on("error", function(err){
LOGGER.error("problem with request: ", err.message);
cb(err);
});
req.write(contents);
req.end();
};
/**
* 简化http.get操作
*
* @param {String} url
* @param {Function} cb
* @example
* self.get(url, function(err, body){
* });
*/
Weixin.prototype.get = function(url, cb){
HTTP.get(url, function(res){
res.setEncoding("utf8");
var res_body = "";
res.on("data", function(chunk) {
res_body += chunk;
});
res.on("end", function() {
cb(null, res_body);
});
res.on("error", function(err){
cb(err);
});
});
};
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。