@juzi/wechaty
Version:
Wechaty is a RPA SDK for Chatbot Makers.
270 lines • 12.4 kB
JavaScript
;
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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WechatyBase = void 0;
/**
* Wechaty Chatbot SDK - https://github.com/wechaty/wechaty
*
* @copyright 2016 Huan LI (李卓桓) <https://github.com/huan>, and
* Wechaty Contributors <https://github.com/wechaty>.
*
* 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 state_switch_1 = require("state-switch");
const fp_ts_1 = require("fp-ts");
const PUPPET = __importStar(require("@juzi/wechaty-puppet"));
const config_js_1 = require("../config.js");
const mod_js_1 = require("../wechaty-mixins/mod.js");
const wechaty_skeleton_js_1 = require("./wechaty-skeleton.js");
const mixinBase = fp_ts_1.function.pipe(wechaty_skeleton_js_1.WechatySkeleton, mod_js_1.gErrorMixin, mod_js_1.wechatifyUserModuleMixin, mod_js_1.ioMixin, mod_js_1.puppetMixin, mod_js_1.loginMixin, mod_js_1.miscMixin, mod_js_1.pluginMixin,
/**
* Huan(202002):
*
* The `serviceCtlMixin` must be the most outer mixin
* because the `wechaty.start/stop()` should first entry `serviceCtlMixin.start/stop()`
* which can be managed correctly by the `serviceCtlMixin`
*/
(0, state_switch_1.serviceCtlMixin)('Wechaty', { log: config_js_1.log }));
/**
* Huan(2021211): Keep the below call back hell
* because it's easy for testing
* especially when there's some typing mismatch and we need to figure it out.
*/
// const mixinTest = serviceCtlMixin('Wechaty', { log })(
// pluginMixin(
// puppetMixin(
// wechatifyUserModuleMixin(
// gErrorMixin(
// WechatySkeleton,
// ),
// ),
// ),
// ),
// )
/**
* Main bot class.
*
* A `Bot` is a WeChat client depends on which puppet you use.
* It may equals
* - web-WeChat, when you use: [puppet-puppeteer](https://github.com/wechaty/wechaty-puppet-puppeteer)/[puppet-wechat4u](https://github.com/wechaty/wechaty-puppet-wechat4u)
* - ipad-WeChat, when you use: [puppet-padchat](https://github.com/wechaty/wechaty-puppet-padchat)
* - ios-WeChat, when you use: puppet-ioscat
*
* See more:
* - [What is a Puppet in Wechaty](https://github.com/wechaty/getting-started/wiki/FAQ#31-what-is-a-puppet-in-wechaty)
*
* > If you want to know how to send message, see [Message](#Message) <br>
* > If you want to know how to get contact, see [Contact](#Contact)
*
* @example <caption>The World's Shortest ChatBot Code: 6 lines of JavaScript</caption>
* import { WechatyBuilder } from 'wechaty'
* const bot = WechatyBuilder.build()
* bot.on('scan', (qrCode, status) => console.log('https://wechaty.js.org/qrcode/' + encodeURIComponent(qrcode)))
* bot.on('login', user => console.log(`User ${user} logged in`))
* bot.on('message', message => console.log(`Message: ${message}`))
* bot.start()
*/
class WechatyBase extends mixinBase {
__options;
static VERSION = config_js_1.VERSION;
wechaty;
_stopCallbackList = [];
/**
* The term [Puppet](https://wechaty.js.org/docs/specs/puppet) in Wechaty is an Abstract Class for implementing protocol plugins.
* The plugins are the component that helps Wechaty to control the WeChat(that's the reason we call it puppet).
* The plugins are named XXXPuppet, for example:
* - [PuppetWeChat](https://github.com/wechaty/puppet-wechat):
* - [PuppetWeChat](https://github.com/wechaty/puppet-service):
* - [PuppetXP](https://github.com/wechaty/puppet-xp)
*
* @typedef PuppetModuleName
* @property {string} PUPPET_DEFAULT
* The default puppet.
* @property {string} wechaty-puppet-wechat4u
* The default puppet, using the [wechat4u](https://github.com/nodeWechat/wechat4u) to control the [WeChat Web API](https://wx.qq.com/) via a chrome browser.
* @property {string} wechaty-puppet-service
* - Using the gRPC protocol to connect with a Protocol Server for controlling the any protocol of any IM program.
* @property {string} wechaty-puppet-wechat
* - Using the [google puppeteer](https://github.com/GoogleChrome/puppeteer) to control the [WeChat Web API](https://wx.qq.com/) via a chrome browser.
* @property {string} wechaty-puppet-mock
* - Using the mock data to mock wechat operation, just for test.
*/
/**
* The option parameter to create a wechaty instance
*
* @typedef WechatyOptions
* @property {string} name -Wechaty Name. </br>
* When you set this: </br>
* `new Wechaty({name: 'wechaty-name'}) ` </br>
* it will generate a file called `wechaty-name.memory-card.json`. </br>
* This file stores the login information for bot. </br>
* If the file is valid, the bot can auto login so you don't need to scan the qrCode to login again. </br>
* Also, you can set the environment variable for `WECHATY_NAME` to set this value when you start. </br>
* eg: `WECHATY_NAME="your-cute-bot-name" node bot.js`
* @property {PuppetModuleName | Puppet} puppet -Puppet name or instance
* @property {Partial<PuppetOptions>} puppetOptions -Puppet TOKEN
* @property {string} ioToken -Io TOKEN
*/
/**
* Creates an instance of Wechaty.
* @param {WechatyOptions} [options={}]
*
*/
constructor(__options = {}) {
super(__options);
this.__options = __options;
config_js_1.log.verbose('Wechaty', 'constructor()');
this.__memory = this.__options.memory;
this.wechaty = this;
}
async start() {
config_js_1.log.verbose('Wechaty', 'start()');
await this.init();
return super.start();
}
async onStart() {
config_js_1.log.verbose('Wechaty', 'onStart()');
config_js_1.log.verbose('Wechaty', '<%s>(%s) onStart() v%s is starting...', this.__options.puppet || config_js_1.config.systemPuppetName(), this.__options.name || '', this.version());
config_js_1.log.verbose('Wechaty', 'id: %s', this.id);
const lifeTimer = setInterval(() => {
config_js_1.log.silly('Wechaty', 'onStart() setInterval() this timer is to keep Wechaty running...');
}, 1000 * 60 * 60);
this._stopCallbackList.push(() => clearInterval(lifeTimer));
this.emit('start');
config_js_1.log.verbose('Wechaty', 'onStart() ... done');
}
async onStop() {
config_js_1.log.verbose('Wechaty', 'onStop()');
config_js_1.log.verbose('Wechaty', '<%s> onStop() v%s is stopping ...', this.__options.puppet || config_js_1.config.systemPuppetName(), this.version());
// put to the end of the event loop in case of it need to be executed while stopping
this._stopCallbackList.map(setImmediate);
this._stopCallbackList.length = 0;
this.emit('stop');
config_js_1.log.verbose('Wechaty', 'onStop() ... done');
}
/**
* Send message to currentUser, in other words, bot send message to itself.
* > Tips:
* This function is depending on the Puppet Implementation, see [puppet-compatible-table](https://github.com/wechaty/wechaty/wiki/Puppet#3-puppet-compatible-table)
*
* @param {(string | Contact | FileBox | UrlLink | MiniProgram | Location | Channel | ChannelCard | ConsultCard | PremiumOnlineAppointmentCard)} sayable
* send text, Contact, or file to bot. </br>
* You can use {@link https://www.npmjs.com/package/file-box|FileBox} to send file
*
* @returns {Promise<void>}
*
* @example
* const bot = new Wechaty()
* await bot.start()
* // after logged in
*
* // 1. send text to bot itself
* await bot.say('hello!')
*
* // 2. send Contact to bot itself
* const contact = await bot.Contact.find()
* await bot.say(contact)
*
* // 3. send Image to bot itself from remote url
* import { FileBox } from 'wechaty'
* const fileBox = FileBox.fromUrl('https://wechaty.github.io/wechaty/images/bot-qr-code.png')
* await bot.say(fileBox)
*
* // 4. send Image to bot itself from local file
* import { FileBox } from 'wechaty'
* const fileBox = FileBox.fromFile('/tmp/text.jpg')
* await bot.say(fileBox)
*
* // 5. send Link to bot itself
* const linkPayload = new UrlLink ({
* description : 'WeChat Bot SDK for Individual Account, Powered by TypeScript, Docker, and Love',
* thumbnailUrl: 'https://avatars0.githubusercontent.com/u/25162437?s=200&v=4',
* title : 'Welcome to Wechaty',
* url : 'https://github.com/wechaty/wechaty',
* })
* await bot.say(linkPayload)
*
* // 6. send MiniProgram to bot itself
* const miniPayload = new MiniProgram ({
* username : 'gh_xxxxxxx', //get from mp.weixin.qq.com
* appid : '', //optional, get from mp.weixin.qq.com
* title : '', //optional
* pagepath : '', //optional
* description : '', //optional
* thumbnailurl : '', //optional
* })
* await bot.say(miniPayload)
*/
async say(sayable) {
config_js_1.log.verbose('Wechaty', 'say(%s)', sayable);
await this.currentUser.say(sayable);
}
async publish(post) {
config_js_1.log.verbose('Wechaty', 'publish(%s)', post.payload.sayableList
.map(s => s.type).join(','));
const postId = await this.puppet.postPublish(post.payload);
if (postId) {
return this.Post.find({ id: postId });
}
}
async unpublish(post) {
config_js_1.log.verbose('Wechaty', 'unpublish(%s)', post.id);
if (!post.id) {
throw new Error('cannot unpublish a post without id');
}
if (post.payload.type !== PUPPET.types.Post.Moment) {
throw new Error('cannot unpublish a post that is not a moment');
}
await this.puppet.postUnpublish(post.id);
}
async enterVerifyCode(id, code) {
config_js_1.log.verbose('Wechaty', 'enterVerifyCode(%s, %s)', id, code);
return this.puppet.enterVerifyCode(id, code);
}
async cancelVerifyCode(id) {
config_js_1.log.verbose('Wechaty', 'cancelVerifyCode(%s)', id);
return this.puppet.cancelVerifyCode(id);
}
async refreshQrCode() {
config_js_1.log.verbose('Wechaty', 'refreshQrCode(%s)');
if (this.isLoggedIn) {
throw new Error('cannot refresh qr because bot is logged in');
}
return this.puppet.refreshQRCode();
}
}
exports.WechatyBase = WechatyBase;
//# sourceMappingURL=wechaty-base.js.map