wechaty-puppet-wechat4u
Version:
Wechat4u Puppet for Wechaty
907 lines • 38.4 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PuppetWechat4u = void 0;
/**
* Wechaty - https://github.com/chatie/wechaty
*
* @copyright 2016-2018 Huan LI <zixia@zixia.net>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
const wechat4u_1 = __importDefault(require("wechat4u"));
const quick_lru_1 = __importDefault(require("@alloc/quick-lru"));
const PUPPET = __importStar(require("wechaty-puppet"));
const wechaty_puppet_1 = require("wechaty-puppet");
const file_box_1 = require("file-box");
const gerror_1 = require("gerror");
const config_js_1 = require("./config.js");
const web_schemas_js_1 = require("./web-schemas.js");
const mod_js_1 = require("./wechat4u/events/mod.js");
const message_js_1 = require("./wechat4u/schema-mapper/message.js");
// 解析小程序数据格式
const message_miniprogram_js_1 = require("./wechat4u/messages/message-miniprogram.js");
// 解析appmsg 数据格式
const message_appmsg_js_1 = require("./wechat4u/messages/message-appmsg.js");
// 解析表情数据格式
const message_emotion_js_1 = require("./wechat4u/messages/message-emotion.js");
const contact_js_1 = require("./wechat4u/schema-mapper/contact.js");
const room_js_1 = require("./wechat4u/schema-mapper/room.js");
const is_type_js_1 = require("./wechat4u/utils/is-type.js");
const MEMORY_SLOT_NAME = 'PUPPET-WECHAT4U';
class PuppetWechat4u extends PUPPET.Puppet {
options;
static VERSION = config_js_1.VERSION;
/**
* Wecaht4u
*
* Code from:
* https://github.com/nodeWechat/wechat4u/blob/46931e78bcb56899b8d2a42a37b919e7feaebbef/run-core.js
*
*/
wechat4u;
scanQrCode;
// 启动时间 为了处理历史消息
startTime = 0;
unknownContactId = [];
getContactInterval;
_heartBeatTimer;
cacheMessageRawPayload;
constructor(options = {}) {
super(options);
this.options = options;
const lruOptions = {
maxAge: 1000 * 60 * 60,
maxSize: 10000,
onEviction(key, val) {
wechaty_puppet_1.log.silly('PuppetWechat4u', 'constructor() lruOptions.dispose(%s, %s)', key, JSON.stringify(val));
},
};
this.cacheMessageRawPayload = new quick_lru_1.default(lruOptions);
}
version() { return `${config_js_1.VERSION}<${super.version()}>`; }
name() { return `${config_js_1.NAME}<${super.name()}>`; }
async onStart() {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'onStart() with %s', this.memory.name || 'NONAME');
if (this.wechat4u) {
wechaty_puppet_1.log.warn('PuppetWechat4u', 'onStart() wechat4u exist, will be overwrited');
}
this.startTime = parseInt(String(new Date().getTime() / 1000));
/**
* Huan(202110): rename `onStart()` to `tryStart()`
* then we will be able to use `MemoryMixin`
* to init MemoryCard for the child puppet
*/
try {
await this.memory.load();
}
catch (_) { }
// console.info('faint 1')
const syncData = await this.memory.get(MEMORY_SLOT_NAME);
// console.info('faint 2')
if (syncData) {
this.wechat4u = new wechat4u_1.default(syncData);
}
else {
this.wechat4u = new wechat4u_1.default();
}
this.monkeyPatch(this.wechat4u);
this.initHookEvents(this.wechat4u);
/**
* Should not `await` onStart/restart for wechat4u
* because it will blocks...
*/
if (this.wechat4u.PROP.uin) {
// 存在登录数据时,可以随时调用restart进行重启
this.wechat4u.restart();
}
else {
this.wechat4u.start();
}
}
/**
* At present, if a user information that does not exist is found, it will be called once.
* If it is a group message, it will send a lot of information requests, and finally most of the interface requests will fail.
* At present, the method of timer is used to regularly obtain user information
* 1、A timer is started when the search request is triggered for the first time
* 2、All requested unknown user ids will be stored in unknownContactId
* 3、The timer will be executed once every 500ms, each time fetching 50 pieces of data in unknownContactId
* 4、If the data of unknownContactId is empty, the timer will be cleared and wait for the next establishment
* @private
*/
getContactsInfo() {
const tempArray = this.unknownContactId.splice(0, 40);
if (tempArray.length === 0 && this.getContactInterval) {
clearInterval(this.getContactInterval);
this.getContactInterval = undefined;
}
if (tempArray.length) {
const userDataList = tempArray.map(contact => {
return {
EncryChatRoomId: contact[1],
UserName: contact[0],
};
});
this.wechat4u.batchGetContact(userDataList).then((result) => {
result.forEach((item) => {
if ((0, is_type_js_1.isRoomId)(item.UserName)) {
const membersList = item.MemberList.map((mItem) => {
return {
...mItem,
EncryChatRoomId: item.UserName,
};
});
this.wechat4u.updateContacts(membersList);
}
});
this.wechat4u.updateContacts(result);
return null;
}).catch((e) => {
wechaty_puppet_1.log.warn('PuppetWechat4u', 'contactRawPayload(%s) wechat4u.batchGetContact() exception: %s', e);
});
}
}
monkeyPatch(wechat4u) {
wechaty_puppet_1.log.silly('PuppetWechat4u', 'monkeyPatch()');
// fake wechat4u to think as we had logined.)
this.monkeyPatchOffState(wechat4u, 'checkLogin', Promise.resolve({ code: 200 }));
this.monkeyPatchOffState(wechat4u, 'login', Promise.resolve());
this.monkeyPatchOffState(wechat4u, '_init', Promise.resolve());
this._startPuppetHeart(true, wechat4u);
/**
* Disable Wechat4u for Sending Message to Filehelper when Heartbeat.
*/
// tslint:disable-next-line
wechat4u.setPollingTargetGetter(() => {
return '';
});
wechat4u.setPollingMessageGetter(() => {
return '';
});
// 自定义心跳间隔(以毫秒为单位)
// 25 days: https://stackoverflow.com/a/12633556/1123955
// this.wechat4u.setPollingIntervalGetter(() => Math.pow(2,31) - 1)
}
// 开始监听心跳
_startPuppetHeart(firstTime = true, wechat4u) {
if (firstTime && this._heartBeatTimer) {
return;
}
let status = wechat4u.state;
if (status === wechat4u.CONF.STATE.login) {
status = 'normal';
}
else if (status === wechat4u.CONF.STATE.logout) {
status = 'logout';
}
else if (status === wechat4u.CONF.STATE.init) {
status = 'init';
}
else if (status === wechat4u.CONF.STATE.uuid) {
status = 'uuid';
}
this.emit('heartbeat', { data: `heartbeat@puppet-wechat4u:${status}` });
// eslint-disable-next-line @typescript-eslint/no-misused-promises
this._heartBeatTimer = setTimeout(async () => {
await this._startPuppetHeart(false, wechat4u);
return undefined;
}, 15 * 1000); // 15s
}
/**
* Monkey Patch for Wechat4u
* - https://www.audero.it/blog/2016/12/05/monkey-patching-javascript/#what-is-monkey-patching
*
* What is Monkey patching?
* Monkey patching is a technique to add, modify, or suppress
* the default behavior of a piece of code at runtime
* without changing its original source code.
*/
monkeyPatchOffState(wechat4u, func, valueWhenLogouted) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'monkeyPatchOffState(wechat4u, %s)', func);
const puppetThis = this;
const funcOrig = wechat4u[func];
function funcNew() {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'monkeyPatchOffState(%s) funcNew()', func);
if (puppetThis.state.inactive()) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'monkeyPatchOffState(%s) funcNew() state.off() is true, return', func);
return valueWhenLogouted;
}
return funcOrig.call(this);
}
wechat4u[func] = funcNew;
}
/**
* @private
* For issue https://github.com/wechaty/puppet-wechat/issues/107
*/
async waitStable() {
wechaty_puppet_1.log.verbose('PuppetWeChat', 'waitStable()');
let maxNum = 0;
let curNum = 0;
let unchangedNum = 0;
const SLEEP_SECOND = 4;
const STABLE_CHECK_NUM = 5;
while (unchangedNum < STABLE_CHECK_NUM) {
// wait 1 second
await new Promise(resolve => setTimeout(resolve, SLEEP_SECOND * 1000));
const contactList = await this.contactList();
curNum = contactList.length;
if (curNum > 0 && curNum === maxNum) {
unchangedNum++;
}
else /* curNum < maxNum */ {
unchangedNum = 0;
}
if (curNum > maxNum) {
maxNum = curNum;
}
wechaty_puppet_1.log.silly('PuppetWeChat', 'readyStable() while() curNum=%s, maxNum=%s, unchangedNum=%s', curNum, maxNum, unchangedNum);
}
wechaty_puppet_1.log.verbose('PuppetWeChat', 'readyStable() emit(ready)');
this.emit('ready', { data: 'stable' });
}
initHookEvents(wechat4u) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'initHookEvents()');
/**
* uuid事件,参数为uuid,根据uuid生成二维码
*/
this.wechat4u.on('uuid', (uuid) => {
wechaty_puppet_1.log.silly('PuppetWechat4u', 'initHookEvents() wechat4u.on(uuid)');
this.scanQrCode = 'https://login.weixin.qq.com/l/' + uuid;
this.emit('scan', { qrcode: this.scanQrCode, status: PUPPET.types.ScanStatus.Waiting });
});
/**
* 登录用户头像事件,手机扫描后可以得到登录用户头像的Data URL
*/
wechat4u.on('user-avatar', (avatarDataUrl) => {
this.emit('scan', {
data: avatarDataUrl,
qrcode: this.scanQrCode || '',
status: PUPPET.types.ScanStatus.Scanned,
});
});
/**
* 登录成功事件
*/
wechat4u.on('login', async () => {
// 由于初始好友列表没有存储当前bot的基础信息,所以在登录后直接更新当前机器人的信息
this.wechat4u.updateContacts([this.wechat4u.user]);
this.startTime = parseInt(String(new Date().getTime() / 1000));
// FIXME: where's the logined user id?
const userId = this.wechat4u.user.UserName;
if (!userId) {
this.emit('error', {
data: gerror_1.GError.stringify(new Error('login event can not found selfId')),
});
return;
}
// we do not wait `ready` before emit `login`
this.waitStable().catch(e => {
wechaty_puppet_1.log.error('PuppetWeChatEvent', 'onLogin() this.waitStable() rejection: %s', e && e.message);
});
await this.login(userId);
// 保存数据,将数据序列化之后保存到任意位置
await this.memory.set(MEMORY_SLOT_NAME, wechat4u.botData);
await this.memory.save();
});
/**
* 登出成功事件
*/
wechat4u.on('logout', async () => {
wechaty_puppet_1.log.silly('PuppetWechat4u', 'initHookEvents() wechat4u.on(logout)');
if (this.isLoggedIn) {
await this.logout();
}
// 清除数据
await this.memory.delete(MEMORY_SLOT_NAME);
await this.memory.save();
this.wechat4u.start();
});
/**
* 联系人更新事件,参数为被更新的联系人列表
*/
wechat4u.on('contacts-updated', (contacts) => {
wechaty_puppet_1.log.silly('PuppetWechat4u', 'initHookEvents() wechat4u.on(contacts-updated) new/total contacts.length=%d/%d', contacts.length, Object.keys(wechat4u.contacts).length);
contacts.forEach((item) => {
if ((0, is_type_js_1.isRoomId)(item.UserName)) {
const membersList = item.MemberList.map((mItem) => {
this.unknownContactId.push([mItem.UserName, item.UserName]);
return {
...mItem,
EncryChatRoomId: item.UserName,
};
});
this.wechat4u.updateContacts(membersList);
}
});
if (!this.getContactInterval) {
this.getContactsInfo();
this.getContactInterval = setInterval(() => {
this.getContactsInfo();
}, 2000);
}
});
/**
* 错误事件,参数一般为Error对象
*/
wechat4u.on('error', (err) => {
this.emit('error', {
data: gerror_1.GError.stringify(err),
});
});
/**
* 如何处理会话消息
*/
wechat4u.on('message', async (msg) => {
if (!msg.MsgId) {
wechaty_puppet_1.log.warn('PuppetWechat4u', 'initHookEvents() wechat4u.on(message) no message id: %s', JSON.stringify(msg));
throw new Error('no id');
}
// 如果是消息的创建时间小于机器人启动的时间 直接丢弃
if (msg.CreateTime < this.startTime) {
// log.warn('PuppetWechat4u', 'initHookEvents() wechat4u.on(message) is history message: %s', JSON.stringify(msg))
return;
}
this.cacheMessageRawPayload.set(msg.MsgId, msg);
const event = await (0, mod_js_1.parseEvent)(this, msg);
switch (event.type) {
case mod_js_1.EventType.Message:
this.emit('message', { messageId: msg.MsgId });
break;
case mod_js_1.EventType.Friendship: {
this.emit('friendship', {
friendshipId: msg.MsgId,
});
break;
}
case mod_js_1.EventType.RoomInvite: {
this.emit('room-invite', {
roomInvitationId: msg.MsgId,
});
break;
}
case mod_js_1.EventType.RoomJoin: {
const roomJoin = event.payload;
this.emit('room-join', roomJoin);
break;
}
case mod_js_1.EventType.RoomLeave: {
const roomLeave = event.payload;
this.emit('room-leave', roomLeave);
break;
}
case mod_js_1.EventType.RoomTopic: {
const roomTopic = event.payload;
this.emit('room-topic', roomTopic);
break;
}
}
});
}
async onStop() {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'onStop()');
this.wechat4u.stop();
this.wechat4u = undefined;
if (this._heartBeatTimer) {
clearTimeout(this._heartBeatTimer);
this._heartBeatTimer = undefined;
}
}
async ding(data) {
wechaty_puppet_1.log.silly('PuppetWechat4u', 'ding(%s)', data || '');
this.emit('dong', { data });
}
/**
*
* ContactSelf
*
*
*/
async contactSelfQRCode() {
return PUPPET.throwUnsupportedError();
}
async contactSelfName(name) {
return PUPPET.throwUnsupportedError(name);
}
async contactSelfSignature(signature) {
return PUPPET.throwUnsupportedError(signature);
}
async contactAlias(contactId, alias) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'contactAlias(%s, %s)', contactId, alias);
if (typeof alias === 'undefined') {
const payload = await this.contactPayload(contactId);
return payload.alias;
}
await this.wechat4u.updateRemarkName(contactId, alias);
}
async contactList() {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'contactList()');
const idList = Object.keys(this.wechat4u.contacts)
.filter((contact) => !this.wechat4u.Contact.isRoomContact(this.wechat4u.contacts[contact]));
return idList;
}
async contactAvatar(contactId, file) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'contactAvatar(%s)', contactId);
if (file) {
return PUPPET.throwUnsupportedError();
}
const rawPayload = await this.contactRawPayload(contactId);
const payload = await this.contactPayload(contactId);
const name = payload.name;
// add '&type=big' to get big image
if (rawPayload.HeadImgUrl) {
const res = await this.wechat4u.getHeadImg(rawPayload.HeadImgUrl + '&type=big');
/**
* 如何获取联系人头像
*/
return file_box_1.FileBox.fromBuffer(res.data, `wechaty-contact-avatar-${name}.jpg`);
}
}
async contactRawPayload(contactId) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'contactRawPayload(%s) with contacts.length=%d', contactId, Object.keys(this.wechat4u.contacts).length);
if (!(contactId in this.wechat4u.contacts)) {
this.unknownContactId.push([contactId, '']);
if (!this.getContactInterval) {
this.getContactsInfo();
this.getContactInterval = setInterval(() => {
this.getContactsInfo();
}, 2000);
}
}
const rawPayload = await (0, config_js_1.retry)(async (retryException, attempt) => {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'contactRawPayload(%s) retry() attempt=%d', contactId, attempt);
if (contactId in this.wechat4u.contacts) {
return this.wechat4u.contacts[contactId];
}
retryException(new Error('no this.wechat4u.contacts[' + contactId + ']'));
});
return rawPayload;
}
async contactRawPayloadParser(rawPayload) {
return (0, contact_js_1.wechat4uContactToWechaty)(rawPayload);
}
/**
*
* Message
*
*/
async messageContact(messageId) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'messageContact(%s)', messageId);
return PUPPET.throwUnsupportedError();
}
// web支持撤回消息 https://github.com/nodeWechat/wechat4u/blob/8e20b34507dbe783ada8c769b72ef1792f33c94a/src/core.js#L1219
async messageRecall(messageId) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'messageRecall(%s)', messageId);
const rawPayload = await this.messageRawPayload(messageId);
this.wechat4u.revokeMsg(messageId, rawPayload.ToUserName);
return true;
}
async messageImage(messageId, imageType) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'messageImage(%s, %s[%s])', messageId, imageType, PUPPET.types.Image[imageType]);
/**
* 图片消息
*/
// console.log('图片消息,保存到本地')
const filename = `${messageId}.jpg`;
const msg = await this.wechat4u.getMsgImg(messageId);
const file = file_box_1.FileBox.fromStream(msg.data, filename);
return file;
}
async messageFile(id) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'messageFile(%s)', id);
const payload = await this.messagePayload(id);
const rawPayload = await this.messageRawPayload(id);
let filename = payload.filename || 'unknown.txt';
/**
* 判断消息类型
*/
switch (payload.type) {
case PUPPET.types.Message.Text:
/**
* 文本消息
*/
throw new Error('msg type is text');
case PUPPET.types.Message.Emoticon: {
/**
* 表情消息
*/
const emotionPayload = await (0, message_emotion_js_1.parseEmotionMessagePayload)(rawPayload);
const emoticonBox = file_box_1.FileBox.fromUrl(emotionPayload.cdnurl, { name: `message-${id}-emoticon.jpg` });
emoticonBox.metadata = {
payload: emotionPayload,
type: 'emoticon',
};
return emoticonBox;
}
// eslint-disable-next-lint no-fallthrough
case PUPPET.types.Message.Image: {
/**
* 图片消息
*/
// console.log('图片消息,保存到本地')
filename = `${rawPayload.MsgId}.jpg`;
const msg = await this.wechat4u.getMsgImg(rawPayload.MsgId);
const file = file_box_1.FileBox.fromBuffer(msg.data, filename);
return file;
}
case PUPPET.types.Message.Audio: {
/**
* 语音消息
*/
const audioFileBox = file_box_1.FileBox.fromBuffer((await this.wechat4u.getVoice(rawPayload.MsgId)).data, `message-${id}-audio.sil`);
const voiceLength = rawPayload.VoiceLength;
audioFileBox.metadata = {
voiceLength,
};
// console.log('语音消息,保存到本地')
return audioFileBox;
}
case PUPPET.types.Message.Video:
/**
* 视频消息
*/
// console.log('视频消息,保存到本地')
return file_box_1.FileBox.fromBuffer((await this.wechat4u.getVideo(rawPayload.MsgId)).data, `message-${id}-video.mp4`);
case PUPPET.types.Message.Attachment:
if (rawPayload.AppMsgType === 6) {
/**
* 文件消息
*/
// console.log('文件消息,保存到本地')
filename = rawPayload.FileName;
return file_box_1.FileBox.fromBuffer((await this.wechat4u.getDoc(rawPayload.FromUserName, rawPayload.MediaId, rawPayload.FileName)).data, filename);
}
break;
default:
break;
}
throw new Error('unsupported message. id: ' + id);
}
async messageUrl(messageId) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'messageUrl(%s)', messageId);
const rawPayload = this.cacheMessageRawPayload.get(messageId);
if (!rawPayload) {
throw new Error('id not found');
}
const message = await this.messageRawPayloadParser(rawPayload);
if (message.type !== PUPPET.types.Message.Url) {
throw new Error('Can not get url from non url payload');
}
const appPayload = await (0, message_appmsg_js_1.parseAppmsgMessagePayload)(rawPayload.Content);
return {
description: appPayload.des,
thumbnailUrl: appPayload.thumburl,
title: appPayload.title,
url: appPayload.url,
};
}
async messageMiniProgram(messageId) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'messageMiniProgram(%s)', messageId);
const rawPayload = this.cacheMessageRawPayload.get(messageId);
if (!rawPayload) {
throw new Error('id not found');
}
const message = await this.messageRawPayloadParser(rawPayload);
if (message.type !== PUPPET.types.Message.MiniProgram) {
throw new Error('message is not mini program, can not get MiniProgramPayload');
}
return (0, message_miniprogram_js_1.parseMiniProgramMessagePayload)(rawPayload);
}
async messageRawPayload(id) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'messageRawPayload(%s)', id);
const rawPayload = this.cacheMessageRawPayload.get(id);
if (!rawPayload) {
throw new Error('id not found');
}
return rawPayload;
}
async messageRawPayloadParser(rawPayload) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'messageRawPayloadParser(%s) @ %s', rawPayload, this);
// console.log(rawPayload)
const payload = (0, message_js_1.webMessageToWechaty)(this, rawPayload);
return payload;
}
async messageSendText(conversationId, text) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'messageSend(%s, %s)', conversationId, text);
/**
* 发送文本消息,可以包含emoji(😒)和QQ表情([坏笑])
*/
await this.wechat4u.sendMsg(text, conversationId);
/**
* { BaseResponse: { Ret: 0, ErrMsg: '' },
* MsgID: '830582407297708303',
* LocalID: '15279119663740094' }
*/
}
async messageSendFile(conversationId, file) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'messageSend(%s, %s)', conversationId, file);
/**
* 通过表情MD5发送表情
*/
// wechat4u.sendMsg({
// emoticonMd5: '00c801cdf69127550d93ca52c3f853ff'
// }, ToUserName)
// .catch(err => {
// bot.emit('error', err)
// })
/**
* 以下通过上传文件发送图片,视频,附件等
* 通用方法为入下
* file为多种类型
* filename必填,主要为了判断文件类型
*/
await this.wechat4u.sendMsg({
file: await file.toStream(),
filename: file.name,
}, conversationId);
}
async messageSendContact(conversationId, contactId) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'messageSend("%s", %s)', conversationId, contactId);
PUPPET.throwUnsupportedError();
}
async messageSendUrl(conversationId, urlLinkPayload) {
PUPPET.throwUnsupportedError(conversationId, urlLinkPayload);
}
async messageSendMiniProgram(conversationId, miniProgramPayload) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'messageSendMiniProgram("%s", %s)', JSON.stringify(conversationId), JSON.stringify(miniProgramPayload));
PUPPET.throwUnsupportedError(conversationId, miniProgramPayload);
}
async messageForward(conversationid, messageId) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'messageForward(%s, %s)', conversationid, messageId);
const rawPayload = await this.messageRawPayload(messageId);
/**
* 如何直接转发消息
*/
await this.wechat4u.forwardMsg(rawPayload, conversationid);
}
async conversationReadMark(conversationId, hasRead) {
return PUPPET.throwUnsupportedError(conversationId, hasRead);
}
/**
*
* Room Invitation
*
*/
async roomInvitationAccept(roomInvitationId) {
return PUPPET.throwUnsupportedError(roomInvitationId);
}
async roomInvitationRawPayload(roomInvitationId) {
return PUPPET.throwUnsupportedError(roomInvitationId);
}
async roomInvitationRawPayloadParser(rawPayload) {
return PUPPET.throwUnsupportedError(rawPayload);
}
/**
*
* Room
*
*/
async roomRawPayload(id) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'roomRawPayload(%s)', id);
const rawPayload = await (0, config_js_1.retry)((retryException, attempt) => {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'contactRawPayload(%s) retry() attempt=%d', id, attempt);
if (!this.wechat4u.contacts[id]) {
retryException(new Error('no this.wechat4u.contacts[' + id + ']'));
}
return this.wechat4u.contacts[id];
});
return rawPayload;
}
async roomRawPayloadParser(rawPayload) {
return (0, room_js_1.wechat4uRoomToWechaty)(rawPayload);
}
async roomList() {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'roomList()');
const idList = Object.keys(this.wechat4u.contacts)
.filter((contact) => this.wechat4u.Contact.isRoomContact(this.wechat4u.contacts[contact]));
return idList;
}
async roomDel(roomId, contactId) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'roomDel(%s, %s)', roomId, contactId);
const type = 'delmember';
// XXX: [contactId] or [{ UserName: id }, ...] ?
await this.wechat4u.updateChatroom(roomId, [contactId], type);
}
async roomAvatar(roomId) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'roomAvatar(%s)', roomId);
const payload = await this.roomPayload(roomId);
if (payload.avatar) {
// FIXME: set http headers with cookies
return file_box_1.FileBox.fromUrl(payload.avatar);
}
wechaty_puppet_1.log.warn('PuppetWechat4u', 'roomAvatar() avatar not found, use the chatie default.');
return (0, config_js_1.qrCodeForChatie)();
}
async roomAdd(roomId, contactId) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'roomAdd(%s, %s)', roomId, contactId);
const roomPayload = await this.roomPayload(roomId);
// TODO: if the room owner enabled "invite only?"
let type = 'addmember'; // invitemember ???
if (roomPayload.memberIdList.length > 40) {
type = 'invitemember';
}
// https://github.com/nodeWechat/wechat4u/tree/46931e78bcb56899b8d2a42a37b919e7feaebbef#botupdatechatroomchatroomusername-memberlist-fun
const ret = await this.wechat4u.updateChatroom(roomId, [contactId], type);
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'roomAdd(%s, %s) ret: %s', roomId, contactId, JSON.stringify(ret));
}
async roomTopic(roomId, topic) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'roomTopic(%s, %s)', roomId, topic);
const roomPayload = await this.roomPayload(roomId);
if (typeof topic === 'undefined') {
return roomPayload.topic;
}
await this.wechat4u.updateChatRoomName(roomId, topic);
}
async roomCreate(contactIdList, topic) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'roomCreate(%s, %s)', contactIdList, topic);
const memberList = contactIdList.map(id => ({ UserName: id }));
const roomId = await this.wechat4u.createChatroom(topic, memberList);
return roomId;
}
async roomAnnounce(roomId, text) {
return PUPPET.throwUnsupportedError(roomId, text);
}
async roomQuit(roomId) {
return PUPPET.throwUnsupportedError(roomId);
}
async roomQRCode(roomId) {
return PUPPET.throwUnsupportedError(roomId);
}
async roomMemberList(roomId) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'roommemberList(%s)', roomId);
const rawPayload = await this.roomRawPayload(roomId);
const memberIdList = (rawPayload.MemberList || [])
.map(member => member.UserName);
return memberIdList;
}
async roomMemberRawPayload(roomId, contactId) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'roomMemberRawPayload(%s, %s)', roomId, contactId);
const rawPayload = await this.roomRawPayload(roomId);
const memberPayloadList = rawPayload.MemberList || [];
const memberPayloadResult = memberPayloadList.filter(payload => payload.UserName === contactId);
if (memberPayloadResult.length > 0) {
return memberPayloadResult[0];
}
else {
throw new Error('not found');
}
}
async roomMemberRawPayloadParser(rawPayload) {
return (0, room_js_1.wechat4uRoomMemberToWechaty)(rawPayload);
}
/**
*
* Friendship
*
*/
async friendshipSearchPhone(phone) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'friendshipSearchPhone(%s)', phone);
return PUPPET.throwUnsupportedError();
}
async friendshipSearchWeixin(weixin) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'friendshipSearchWeixin(%s)', weixin);
return PUPPET.throwUnsupportedError();
}
async friendshipAdd(contactId, hello) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'friendshipAdd(%s, %s)', contactId, hello);
return PUPPET.throwUnsupportedError();
// await this.wechat4u.addFriend(contactId, hello)
}
async friendshipAccept(friendshipId) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'friendshipAccept(%s)', friendshipId);
const payload = await this.friendshipPayload(friendshipId);
await this.wechat4u.verifyUser(payload.contactId, payload.ticket);
}
async friendshipRawPayload(id) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'friendshipRawPayload(%s)', id);
const rawPayload = this.cacheMessageRawPayload.get(id);
if (!rawPayload) {
throw new Error('no rawPayload');
}
return rawPayload;
}
async friendshipRawPayloadParser(rawPayload) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'friendshipRawPayloadParser(%s)', rawPayload);
const timestamp = Math.floor(Date.now() / 1000); // in seconds
switch (rawPayload.MsgType) {
case web_schemas_js_1.WebMessageType.VERIFYMSG: {
const recommendInfo = rawPayload.RecommendInfo;
if (!recommendInfo) {
throw new Error('no recommendInfo');
}
const payloadReceive = {
contactId: recommendInfo.UserName,
hello: recommendInfo.Content,
id: rawPayload.MsgId,
ticket: recommendInfo.Ticket,
timestamp,
type: PUPPET.types.Friendship.Receive,
};
return payloadReceive;
}
case web_schemas_js_1.WebMessageType.SYS: {
const payloadConfirm = {
contactId: rawPayload.FromUserName,
id: rawPayload.MsgId,
timestamp,
type: PUPPET.types.Friendship.Confirm,
};
return payloadConfirm;
}
default:
throw new Error('not supported friend request message raw payload');
}
}
/**
*
* Tag
*
*/
async tagContactAdd(tagId, contactId) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'tagContactAdd(%s)', tagId, contactId);
}
async tagContactRemove(tagId, contactId) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'tagContactRemove(%s)', tagId, contactId);
}
async tagContactDelete(tagId) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'tagContactDelete(%s)', tagId);
}
async tagContactList(contactId) {
wechaty_puppet_1.log.verbose('PuppetWechat4u', 'tagContactList(%s)', contactId);
return [];
}
contactCorporationRemark(..._) {
return PUPPET.throwUnsupportedError();
}
contactDescription(..._) {
return PUPPET.throwUnsupportedError();
}
contactPhone(..._) {
return PUPPET.throwUnsupportedError();
}
async messageLocation(messageId) {
return PUPPET.throwUnsupportedError(messageId);
}
async messageSendLocation(conversationId, locationPayload) {
return PUPPET.throwUnsupportedError(conversationId, locationPayload);
}
}
exports.PuppetWechat4u = PuppetWechat4u;
exports.default = PuppetWechat4u;
//# sourceMappingURL=puppet-wechat4u.js.map