基于electron的微信小机器人

wechat4u.js

地址

https://github.com/nodeWechat/wechat4u

Features

  • 导出和导入保持微信登录的必要数据 bot.botData (#160)
  • 修改联系人备注 bot.updateRemarkName(UserName, RemarkName) (#121)
  • 修改群名 bot.updateChatRoomName(ChatRoomUserName, NewName) (#168)
  • 转发消息 bot.forwardMsg(msg, toUserName)
  • 撤回消息 bot.revokeMsg(MsgID, toUserName)

Changes

  • 发送消息的一类方法在成功时会返回完整响应数据
  • bot.user 对象中不再存储用户头像的 base64 数据
  • 移除 example 目录
  • 修复 Contact 和 Message 中数据某些数据不可枚举
  • 向上层代码传递完整的 Error 对象,并将原来的中文错误描述放在 err.tips
  • bot.getContact(Seq) 方法增加 Seq 参数,支持增量获取完整联系人

安装使用

npm install --save wechat4u@latest
const Wechat = require('wechat4u')
let bot = new Wechat()
bot.start()
// 或使用核心API
// const WechatCore = require('wechat4u/lib/core')

开发测试

git clone https://github.com/nodeWechat/wechat4u.git
cd wechat4u
npm install
npm run core // 命令行模式
npm run compile // babel编译

使用范例

node run-core.js

逻辑见代码,简明完整,一定要看

实例化Wechat类

let bot = new Wechat([botData])

若传入botData,则使用此机器人信息,重新开始之前的同步

实例属性

所有属性均只读

bot.botData

可导出的实例基本信息,在下次new新bot时,可以填入此信息,重新同步

bot.PROP

保持登录状态的必要信息

bot.CONF

配置信息,包括当前服务器地址,API路径和一些常量

程序中需要使用CONF中的常量来判断当前状态的新消息类型

bot.state == bot.CONF.STATE.init // 初始化状态
bot.state == bot.CONF.STATE.uuid // 已获取 UUID
bot.state == bot.CONF.STATE.login // 已登录
bot.state == bot.CONF.STATE.logout // 已退出登录
msg.MsgType == bot.CONF.MSGTYPE_TEXT // 文本消息
msg.MsgType == bot.CONF.MSGTYPE_IMAGE // 图片消息
msg.MsgType == bot.CONF.MSGTYPE_VOICE // 语音消息
msg.MsgType == bot.CONF.MSGTYPE_EMOTICON // 自定义表情消息
msg.MsgType == bot.CONF.MSGTYPE_MICROVIDEO // 小视频消息
msg.MsgType == bot.CONF.MSGTYPE_VIDEO // 视频消息

bot.state

当前状态

bot.user

当前登录用户信息

bot.contacts

所有联系人,包括通讯录联系人,近期联系群,公众号

key为联系人UserName,UserName是本次登录时每个联系人的UUID,不过下次登录会改变

value为Contact对象,具体属性方法见src/interface/contact.js

msg

登录后接受到的所有消息

msg为Message对象,具体属性方法见src/interface/message.js

实例API

bot.start()

启动实例,登录和保持同步

调用该方法后,通过监听事件来处理消息

bot.restart()

利用实例已获取的必要信息,重新登录和进行同步

bot.stop()

停止实例,退出登录

调用该方法后,通过监听logout事件来登出

bot.setPollingMessageGetter(getter)

自定义心跳消息内容

getter 函数返回心跳消息内容

typeof(getter()) 应为 "string"

bot.setRollingMessageGetter(function () {
  //
  return (new Date()).toJSON();
});

bot.setPollingIntervalGetter(getter)

自定义心跳间隔

getter 函数返回心跳间隔(以毫秒为单位)

typeof(getter()) 应为 "number"

bot.setRollingIntervalGetter(function () {
  return 2 * 60 * 1000;
});

bot.setPollingTargetGetter(getter)

自定义心跳目标用户

getter 函数返回目标用户的 UserName (形如 @xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

typeof(getter()) 应为 "string"

注: 如要使用 bot.user.UserName ,需在 login 事件后定义目标用户

bot.setRollingmeGetter(function () {
  return bot.user.UserName;
});

以下方法均返回Promise

bot.sendText(msgString, toUserName)

发送文本消息,可以包含emoji(😒)和QQ表情([坏笑])

bot.uploadMedia(Buffer | Stream | File, filename, toUserName)

上传媒体文件

返回

{
  name: name,
  size: size,
  ext: ext,
  mediatype: mediatype,
  mediaId: mediaId
}

bot.sendPic(mediaId, toUserName)

发送图片,mediaId为uploadMedia返回的mediaId

bot.uploadMedia(fs.createReadStream('test.png'))
  .then(res => {
    return bot.sendPic(res.mediaId, ToUserName)
  })
  .catch(err => {
    console.log(err)
  })

bot.sendEmoticon(md5 | mediaId, toUserName)

发送表情,可是是表情的MD5或者uploadMedia返回的mediaId

表情的MD5,可以自己计算但是可能不存在在微信服务器中,也可以从微信返回的表情消息中获得

bot.sendVideo(mediaId, toUserName)

发送视频

bot.sendDoc(mediaId, name, size, ext, toUserName)

以应用卡片的形式发送文件,可以通过这个API发送语音

bot.sendMsg(msg, toUserName)

对以上发送消息的方法的封装,是发送消息的通用方法

msg为string时,发送文本消息

msg{file:xxx,filename:'xxx.ext'}时,发送对应媒体文件

msg{emoticonMd5:xxx}时,发送表情

bot.sendMsg({
    file: request('https://raw.githubusercontent.com/nodeWechat/wechat4u/master/bot-qrcode.jpg'),
    filename: 'bot-qrcode.jpg'
  }, ToUserName)
  .catch(err => {
    console.log(err)
  })

bot.forwardMsg(msg, toUserName)

转发消息,msgmessage事件传递的msg对象

bot.revokeMsg(MsgID, toUserName)

撤回消息

MsgID为发送消息后返回的代表消息的ID

bot.sendMsg('测试撤回', toUserName)
  .then(res => {
    return bot.revokeMsg(res.MsgID, toUserName)
  })
  .catch(err => {
    console.log(err)
  })

bot.getContact(Seq)

获取通讯录中的联系人

Seq 上一次调用 bot.getContact 后返回的 seq,第一次调用可不传

bot.batchGetContact(contacts)

批量获取指定联系人数据

contacts 数组,指定需要获取的数据

contacts[{UserName: xxx}]时,可获取指定联系人或群信息

contacts[{UserName: xxx, EncryChatRoomId: xxx}]时,可获取指定群内成员详细信息,EncryChatRoomId 可从群信息中获得

bot.getHeadImg(HeadImgUrl)

获取联系人头像

bot.getHeadImg(bot.contacts[UserName].HeadImgUrl).then(res => {
  fs.writeFileSync(`${UserName}.jpg`, res.data)
}).catch(err => {
  console.log(err)
})

bot.getMsgImg(MsgId)

获取图片或表情

bot.getMsgImg(msg.MsgId).then(res => {
  fs.writeFileSync(`${msg.MsgId}.jpg`, res.data)
}).catch(err => {
  console.log(err)
})

bot.getVoice(MsgId)

获取语音

bot.getVideo(MsgId)

获取小视频或视频

bot.getDoc(UserName, MediaId, FileName)

获取文件,消息的MsgType为49且AppMsgType为6时即为文件。

bot.addFriend(UserName, Content)

添加好友

UserName 一般可从群信息中获得

Content 验证信息

bot.verifyUser(UserName, Ticket)

通过好友添加请求

bot.createChatroom(Topic, MemberList)

创建群

Topic 群聊名称

MemberList 数组, 除自己外至少两人的UserName,格式为 [ {"UserName":"@250d8d156ad9f8b068c2e3df3464ecf2"}, {"UserName":"@42d725733741de6ac53cbe3738d8dd2e"} ]

bot.updateChatroom(ChatRoomUserName, MemberList, fun)

更新群成员

ChatRoomUserName '@@'开头的群UserName

MemberList 数组,联系人UserNa

fun 可选'addmember','delmember','invitemember'

bot.updateChatRoomName(ChatRoomUserName, NewName)

更新群名称

ChatRoomUserName '@@'开头的群UserName

NewName 字符串,新的群名称

bot.opLog(UserName, OP)

置顶或取消置顶联系人,可通过直接取消置顶群来获取群ChatRoomOwner

OP == 0 取消置顶

OP == 1 置顶

bot.updateRemarkName(UserName, RemarkName)

设置联系人备注或标签

实例事件

uuid

得到uuid,之后可以构造二维码或从微信服务器取得二维码

bot.on('uuid', uuid => {
  qrcode.generate('https://login.weixin.qq.com/l/' + uuid, {
    small: true
  })
  console.log('二维码链接:', 'https://login.weixin.qq.com/qrcode/' + uuid)
})

user-avatar

手机扫描后可以得到登录用户头像的Data URL

login

手机确认登录

logout

成功登出

contacts-updated

联系人更新,可得到已更新的联系人列表

message

所有通过同步得到的消息,通过msg.MsgType判断消息类型

bot.on('message', msg => {
  switch (msg.MsgType) {
    case bot.CONF.MSGTYPE_STATUSNOTIFY:
      break
    case bot.CONF.MSGTYPE_TEXT:
      break
    case bot.CONF.MSGTYPE_RECALLED:
      break
  }
})

error

Contact对象和Message对象

每个contact,继承自 interface/contact,除原本 json 外,扩展以下属性:

contact.AvatarUrl // 处理过的头像地址
contact.isSelf    // 是否是登录用户本人

contact.getDisplayName()
contact.canSearch(keyword)

此外,wechat4u 在实例上提供 Contact 作为联系人的通用接口,扩展以下属性:

wechat.Contact.isRoomContact()
wechat.Contact.isSpContact()
wechat.Contact.isPublicContact()

wechat.Contact.getUserByUserName()
wechat.Contact.getSearchUser(keyword)

每个msg 对象继承自 interface/message,出原本 json 外,具有以下属性:

message.isSendBySelf // 是否是本人发送

message.isSendBy(contact)
message.getPeerUserName() // 获取所属对话的联系人 UserName
message.getDisplayTime() // 获取形如 12:00 的时间戳信息
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,064评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,606评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,011评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,550评论 1 269
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,465评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,919评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,428评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,075评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,208评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,185评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,191评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,914评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,482评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,585评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,825评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,194评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,703评论 2 339

推荐阅读更多精彩内容