From 105eae286309048178addc1378390be6ab94433e Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 4 Mar 2020 21:55:55 +0800 Subject: [PATCH 001/598] update hostie version --- src/puppet-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 3fe28241e..1cb71528b 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -11,7 +11,7 @@ export const PUPPET_DEPENDENCIES = { * DEPRECATED by Huan(202002): The Above is Alias for the following full NPM module names * *******************************************************************************************/ - 'wechaty-puppet-hostie' : '^0.3.18', // https://www.npmjs.com/package/wechaty-puppet-hostie + 'wechaty-puppet-hostie' : '^0.3.20', // https://www.npmjs.com/package/wechaty-puppet-hostie 'wechaty-puppet-mock' : '^0.17.5', // https://www.npmjs.com/package/wechaty-puppet-mock // 'wechaty-puppet-dll' : '^0.3.1', // https://www.npmjs.com/package/wechaty-puppet-dll From b037e1a87e3a65b36a35ea0b046451df8f94f6ca Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 4 Mar 2020 22:02:49 +0800 Subject: [PATCH 002/598] 0.32.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 802ef00ae..bdc2a73f0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.32.2", + "version": "0.32.3", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From eb34a5616c266a093f8c99e5a23070a4b3c2bab9 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 4 Mar 2020 22:03:31 +0800 Subject: [PATCH 003/598] 0.32.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bdc2a73f0..c6921c243 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.32.3", + "version": "0.32.4", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From a8c0c41de15c70bda61aafefdf0b7326f47122bf Mon Sep 17 00:00:00 2001 From: Huan LI Date: Fri, 6 Mar 2020 23:46:42 +0800 Subject: [PATCH 004/598] code clean --- examples/ding-dong-bot.ts | 24 ++++++++++++++---------- package.json | 2 +- src/accessory.ts | 5 +++-- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/examples/ding-dong-bot.ts b/examples/ding-dong-bot.ts index d6dda96ac..4efba04b0 100644 --- a/examples/ding-dong-bot.ts +++ b/examples/ding-dong-bot.ts @@ -72,16 +72,20 @@ bot.start() * */ function onScan (qrcode: string, status: ScanStatus) { - generate(qrcode) - - // Generate a QR Code online via - // http://goqr.me/api/doc/create-qr-code/ - const qrcodeImageUrl = [ - 'https://api.qrserver.com/v1/create-qr-code/?data=', - encodeURIComponent(qrcode), - ].join('') - - console.info('%s(%s) - %s', ScanStatus[status], status, qrcodeImageUrl) + if (status === ScanStatus.Waiting || status === ScanStatus.Timeout) { + generate(qrcode) + + // Generate a QR Code online via + // http://goqr.me/api/doc/create-qr-code/ + const qrcodeImageUrl = [ + 'https://api.qrserver.com/v1/create-qr-code/?data=', + encodeURIComponent(qrcode), + ].join('') + + console.info('onScan: %s(%s) - %s', ScanStatus[status], status, qrcodeImageUrl) + } else { + console.info('onScan: %s(%s)', ScanStatus[status], status) + } // console.info(`[${ScanStatus[status]}(${status})] ${qrcodeImageUrl}\nScan QR Code above to log in: `) } diff --git a/package.json b/package.json index c6921c243..5e6e97263 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ }, "dependencies": { "brolog": "^1.8.1", - "clone-class": "^0.6.11", + "clone-class": "^0.7.3", "cuid": "^2.1.1", "hot-import": "^0.2.1", "in-gfw": "^1.2.0", diff --git a/src/accessory.ts b/src/accessory.ts index 839529866..dde5a9416 100644 --- a/src/accessory.ts +++ b/src/accessory.ts @@ -9,8 +9,8 @@ import { Wechaty } from './wechaty' // use Symbol to prevent conflicting with the child class properties // This symbol must be exported (for now). // See: https://github.com/Microsoft/TypeScript/issues/20080 -export const SYMBOL_NAME = Symbol('name') -export const SYMBOL_COUNTER = Symbol('counter') +const SYMBOL_NAME = Symbol('name') +const SYMBOL_COUNTER = Symbol('counter') let COUNTER = 0 @@ -155,6 +155,7 @@ export abstract class Accessory extends EventEmitter { * FriendRequest.wechaty * Message.wechaty * Room.wechaty + * ... etc * * So it only need one `wechaty` for all the instances */ From ae67b2b50cd631a74ee68a2b53a6f3bd8b7a5a59 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Fri, 6 Mar 2020 23:46:58 +0800 Subject: [PATCH 005/598] 0.32.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5e6e97263..78e0d5666 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.32.4", + "version": "0.32.5", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 13092f74f55266661f390db534acd4556046cba2 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 7 Mar 2020 11:10:11 +0800 Subject: [PATCH 006/598] 0.33.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 78e0d5666..d55c71935 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.32.5", + "version": "0.33.0", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From ede129ba9af33f1bbbd574c08a7e9453f8ce9228 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 7 Mar 2020 11:30:06 +0800 Subject: [PATCH 007/598] simpilify the Accesory class (#1924) --- src/accessory.spec.ts | 10 ++++------ src/accessory.ts | 38 +++++++++++++------------------------- src/wechaty.ts | 19 +++++++------------ 3 files changed, 24 insertions(+), 43 deletions(-) diff --git a/src/accessory.spec.ts b/src/accessory.spec.ts index 6ed99e724..ee6d576bc 100755 --- a/src/accessory.spec.ts +++ b/src/accessory.spec.ts @@ -71,11 +71,9 @@ test('Two clone-ed classes have different static puppet value', async t => { test('Throw error when set the value again', async t => { class FixtureClass extends Accessory {} - const fixture = new FixtureClass() + t.doesNotThrow(() => { FixtureClass.wechaty = {} as any }, 'instance: should not throw when set wechaty at 1st time') + t.throws(() => { FixtureClass.wechaty = {} as any }, 'instance: should throw when set wechaty at 2nd time') - t.doesNotThrow(() => { fixture.puppet = {} as any }, 'instance: should not throw when set at 1st time') - t.throws(() => { fixture.puppet = {} as any }, 'instance: should throw when set at 2nd time') - - t.doesNotThrow(() => { FixtureClass.puppet = {} as any }, 'static: should not throw when set at 1st time') - t.throws(() => { FixtureClass.puppet = {} as any }, 'static: should throw when set at 2nd time') + t.doesNotThrow(() => { FixtureClass.puppet = {} as any }, 'static: should not throw when set puppet at 1st time') + t.throws(() => { FixtureClass.puppet = {} as any }, 'static: should throw when set puppet at 2nd time') }) diff --git a/src/accessory.ts b/src/accessory.ts index dde5a9416..c5ae28587 100644 --- a/src/accessory.ts +++ b/src/accessory.ts @@ -98,35 +98,22 @@ export abstract class Accessory extends EventEmitter { * * 2. Instance Properties & Methods * - * The ability of set different `puppet` to the instance is required. - * For example: the Wechaty instances have to have different `puppet`. + * DEPRECATED: The ability of set different `puppet` to the instance is required. + * For example: the Wechaty instances have to have different `puppet`. + * + * Huan(202003): simplify the logic: do not use Accessory to + * set different puppet for different instances */ - private _puppet? : Puppet - - /** - * @ignore - */ - public set puppet (puppet: Puppet) { - log.silly('Accessory', '<%s> set puppet = "%s"', - this[SYMBOL_NAME] || this, - puppet, - ) - if (this._puppet) { - throw new Error('puppet can not be set twice') - } - this._puppet = puppet - } /** * @ignore * * instance.puppet * - * Needs to support different `puppet` between instances. - * - * For example: every Wechaty instance needs its own `puppet` - * - * So: that's the reason that there's no `private _wechaty: Wechaty` for the instance. + * Huan(202003) + * DEPRECATED: Needs to support different `puppet` between instances. + * For example: every Wechaty instance needs its own `puppet` + * So: that's the reason that there's no `private _wechaty: Wechaty` for the instance. * */ public get puppet (): Puppet { @@ -135,9 +122,10 @@ export abstract class Accessory extends EventEmitter { // this[SYMBOL_NAME] || this, // ) - if (this._puppet) { - return this._puppet - } + // Huan(202003): DEPRECATED + // if (this._puppet) { + // return this._puppet + // } /** * Get `puppet` from Class Static puppet property diff --git a/src/wechaty.ts b/src/wechaty.ts index b7ebfd446..da4d8a5d4 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -17,8 +17,9 @@ * * @ignore */ -import cuid from 'cuid' -import os from 'os' +import cuid from 'cuid' +import { EventEmitter } from 'events' +import os from 'os' import { // Constructor, @@ -45,9 +46,6 @@ import { ScanStatus, } from 'wechaty-puppet' -import { - Accessory, -} from './accessory' import { FileBox, Raven, @@ -139,7 +137,7 @@ const PUPPET_MEMORY_NAME = 'puppet' * bot.on('message', message => console.log(`Message: ${message}`)) * bot.start() */ -export class Wechaty extends Accessory implements Sayable { +export class Wechaty extends EventEmitter implements Sayable { public static readonly VERSION = VERSION @@ -157,6 +155,8 @@ export class Wechaty extends Accessory implements Sayable { private lifeTimer? : NodeJS.Timer private io? : Io + public puppet!: Puppet + /** * the cuid * @ignore @@ -568,12 +568,7 @@ export class Wechaty extends Accessory implements Sayable { private async initPuppet (): Promise { log.verbose('Wechaty', 'initPuppet() %s', this.options.puppet || '') - let inited = false - try { - inited = !!this.puppet - } catch (e) { - inited = false - } + const inited = !!this.puppet if (inited) { log.verbose('Wechaty', 'initPuppet(%s) had already been inited, no need to init twice', this.options.puppet) From 54eb88fe8e2448f958211c9cc3642fd3e5faa6c0 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 7 Mar 2020 11:30:23 +0800 Subject: [PATCH 008/598] 0.33.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d55c71935..dc5ae7759 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.33.0", + "version": "0.33.1", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From b99b2abeeddab555f4b2528330326dda4c81de9a Mon Sep 17 00:00:00 2001 From: Huan LI Date: Mon, 9 Mar 2020 08:45:04 +0800 Subject: [PATCH 009/598] add name() for wechaty --- src/wechaty.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/wechaty.ts b/src/wechaty.ts index da4d8a5d4..8e97de9a4 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -298,6 +298,14 @@ export class Wechaty extends EventEmitter implements Sayable { ].join('') } + /** + * Wechaty bot name set by `optoins.name` + * default: `wechaty` + */ + public name () { + return this.options.name || 'wechaty' + } + public emit (event: 'dong', data?: string) : boolean public emit (event: 'error', error: Error) : boolean public emit (event: 'friendship', friendship: Friendship) : boolean From 389194a24215e3aedda6a65cc1b5a807791f1591 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Mon, 9 Mar 2020 08:45:20 +0800 Subject: [PATCH 010/598] 0.33.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dc5ae7759..489e903ff 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.33.1", + "version": "0.33.2", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 05f69f2b2061d2025c75f86b6fe863461e4425f3 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Mon, 9 Mar 2020 08:55:31 +0800 Subject: [PATCH 011/598] 0.33.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 489e903ff..c634b758a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.33.2", + "version": "0.33.3", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From eb256aef81d0573c7f01f93805f169646d7a7b11 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Mon, 9 Mar 2020 09:52:47 +0800 Subject: [PATCH 012/598] 0.33.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c634b758a..ae2a50d1a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.33.3", + "version": "0.33.4", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 9d52ddd0af30dfae363f4b6667bf3a4bccbc3165 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Tue, 10 Mar 2020 19:49:40 +0800 Subject: [PATCH 013/598] add name to license --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index b8010724d..9935b1bdc 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2016-2018 Huan LI + Copyright 2016-2018 Huan LI (李卓桓) Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 3cc294bd5f2bfe504739da8265e208c51c8cf2e0 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 11 Mar 2020 02:43:32 +0800 Subject: [PATCH 014/598] doc clean --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index d94b46377..068107cd2 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ You can find more examples from [Wiki](https://github.com/Wechaty/wechaty/wiki/E [![node](https://img.shields.io/node/v/wechaty.svg?maxAge=604800)](https://nodejs.org/) -* Wechaty Starter Repository - +- Wechaty Starter Repository - We have a Wechaty starter repository for beginners with the simplest setting. It will be **just work** out-of-the-box after you `clone` & `npm install` & `npm start`. @@ -102,7 +102,7 @@ node mybot.js [![Docker Pulls](https://img.shields.io/docker/pulls/zixia/wechaty.svg?maxAge=2592000)](https://hub.docker.com/r/zixia/wechaty/) [![Docker Layers](https://images.microbadger.com/badges/image/zixia/wechaty.svg)](https://microbadger.com/#/images/zixia/wechaty) -* Wechaty Starter Repository for Docker - +- Wechaty Starter Repository for Docker - > Wechaty Docker supports both JavaScript and TypeScript. To use TypeScript just write in TypeScript and save with extension name `.ts`, no need to compile because we use `ts-node` to run it. @@ -155,7 +155,7 @@ Main bot class. A `Bot` is a Wechaty instance that control a specific [wechaty-puppet](https://github.com/Wechaty/wechaty/wiki/Puppet). -* `new Wechaty(options?: WechatyOptions)` +- `new Wechaty(options?: WechatyOptions)` 1. `options.name?: string` the name of this bot(optional) 2. `optoins.puppet?: string` select which puppet provider we want to use. must be one of the: 1. [wechaty-puppet-puppeteer](https://github.com/Wechaty/wechaty-puppet-puppeteer) - Angular Hook for Web Wechat <- This is the DEFAULT @@ -314,8 +314,8 @@ Get to know more about the tests from [Wiki:Tests](https://github.com/Wechaty/we ## RELEASE NOTES -* [Latest Release](https://github.com/Wechaty/wechaty/releases/latest)(All releases [here](https://github.com/Wechaty/wechaty/releases)) -* [Changelog](https://github.com/Wechaty/wechaty/blob/master/CHANGELOG.md) +- [Latest Release](https://github.com/Wechaty/wechaty/releases/latest)(All releases [here](https://github.com/Wechaty/wechaty/releases)) +- [Changelog](https://github.com/Wechaty/wechaty/blob/master/CHANGELOG.md) ### Views Since Feb 15, 2019 @@ -363,7 +363,7 @@ The following VPS providers are used by the Wechaty team, and they worked perfec ## See Also -* [RelatedProject](https://github.com/Wechaty/wechaty/wiki/RelatedProject) +- [RelatedProject](https://github.com/Wechaty/wechaty/wiki/RelatedProject) ## The Story @@ -371,8 +371,8 @@ In 2017 ... Huan's daily life/work depends on too much chat on wechat. -* Almost 14,000 wechat friends in May 2014, before wechat restricts a total number of friends to 5,000. -* Almost 400 wechat rooms, and most of them have more than 400 members. +- Almost 14,000 wechat friends in May 2014, before wechat restricts a total number of friends to 5,000. +- Almost 400 wechat rooms, and most of them have more than 400 members. Can you imagine that? He was dying... @@ -415,6 +415,6 @@ Support this project by becoming a sponsor. Your logo will show up here with a l ## Copyright & License -* Code & Docs © 2016-now Huan LI \ -* Code released under the Apache-2.0 License -* Docs released under Creative Commons +- Code & Docs © 2016-now Huan LI \ +- Code released under the Apache-2.0 License +- Docs released under Creative Commons From 9eb10428bb948a5211b77280307cd1979402e5c5 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 11 Mar 2020 02:44:03 +0800 Subject: [PATCH 015/598] code clean --- src/io-client.ts | 1 + src/io.ts | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/io-client.ts b/src/io-client.ts index 2ae6b98e6..b4fdf7686 100644 --- a/src/io-client.ts +++ b/src/io-client.ts @@ -103,6 +103,7 @@ export class IoClient { await this.startIo() await this.options.wechaty.start() + await this.startHostie() this.state.on(true) diff --git a/src/io.ts b/src/io.ts index 3e6da9027..b6e48b30f 100644 --- a/src/io.ts +++ b/src/io.ts @@ -149,8 +149,6 @@ export class Io { this.state.on(true) - return - } catch (e) { log.warn('Io', 'start() exception: %s', e.message) this.state.off(true) From 2ae881b063c5351de95ecbdfbead6564eb109f13 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 11 Mar 2020 02:44:26 +0800 Subject: [PATCH 016/598] 0.33.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ae2a50d1a..fc61f8312 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.33.4", + "version": "0.33.5", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 2c5b7da4e1def4657a82547d621e2b62ebaf5467 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 11 Mar 2020 02:58:58 +0800 Subject: [PATCH 017/598] puppet hostie service discovery --- src/puppet-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 1cb71528b..ef6e20e57 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -11,7 +11,7 @@ export const PUPPET_DEPENDENCIES = { * DEPRECATED by Huan(202002): The Above is Alias for the following full NPM module names * *******************************************************************************************/ - 'wechaty-puppet-hostie' : '^0.3.20', // https://www.npmjs.com/package/wechaty-puppet-hostie + 'wechaty-puppet-hostie' : '^0.3.21', // https://www.npmjs.com/package/wechaty-puppet-hostie 'wechaty-puppet-mock' : '^0.17.5', // https://www.npmjs.com/package/wechaty-puppet-mock // 'wechaty-puppet-dll' : '^0.3.1', // https://www.npmjs.com/package/wechaty-puppet-dll From d05f2690f54e72b8c1e9b17e6e7685314c219cc4 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 11 Mar 2020 03:12:36 +0800 Subject: [PATCH 018/598] 0.33.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fc61f8312..3d04f99fd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.33.5", + "version": "0.33.6", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From da6f0e24d22b168149d9f9ae3a5f772a02c5a903 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 11 Mar 2020 09:50:09 +0800 Subject: [PATCH 019/598] meaningful unit test token name for server loggging --- src/io.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/io.spec.ts b/src/io.spec.ts index dea551b34..64800dfb6 100755 --- a/src/io.spec.ts +++ b/src/io.spec.ts @@ -7,7 +7,7 @@ import { Wechaty } from './wechaty' test('Io restart without problem', async t => { const io = new Io({ - token : 'mock_token', + token : 'mock token in wechaty/wechaty/src/io.spec.ts', wechaty : new Wechaty(), }) From f4de13b60868480db5557a48e467e54baefbe2e1 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 11 Mar 2020 09:50:25 +0800 Subject: [PATCH 020/598] 0.33.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3d04f99fd..4442e553a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.33.6", + "version": "0.33.7", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From b186354849d3213558062ab72bbbf68b4ad8be00 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 11 Mar 2020 10:30:57 +0800 Subject: [PATCH 021/598] fix token mock --- src/io.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/io.spec.ts b/src/io.spec.ts index 64800dfb6..64db358d3 100755 --- a/src/io.spec.ts +++ b/src/io.spec.ts @@ -7,7 +7,8 @@ import { Wechaty } from './wechaty' test('Io restart without problem', async t => { const io = new Io({ - token : 'mock token in wechaty/wechaty/src/io.spec.ts', + // token must not contain any white spaces + token : 'mock_token_in_wechaty/wechaty/src/io.spec.ts', wechaty : new Wechaty(), }) From cdda8c35668e0cb1d64888cd42d360b980086b65 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 11 Mar 2020 10:31:14 +0800 Subject: [PATCH 022/598] 0.33.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4442e553a..f030c1c69 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.33.7", + "version": "0.33.8", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 4a84fa6ac7139a7bca816d0e7ddfe083889ea258 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Fri, 13 Mar 2020 17:03:48 +0800 Subject: [PATCH 023/598] add check for skipping exist version when publishing to NPM --- .github/workflows/npm.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index 4dc17512f..41827d12e 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -63,7 +63,12 @@ jobs: fi # See: https://stackoverflow.com/a/58869470/1123955 - name: Is A Publish Branch if: steps.check-branch.outputs.match == 'true' - run: npm publish + run: | + VERSION=$(npx pkg-jq -r .version package.json) + if npx version-exists @chatie/grpc "$VERSION" + then "Version $VERSION exists on NPM, skipped." + else npm publish + fi env: NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }} - name: Is Not A Publish Branch From c21cf65a9675e43ca95a330f04554680101e7a03 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Fri, 13 Mar 2020 17:03:59 +0800 Subject: [PATCH 024/598] code clean --- src/io-client.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/io-client.ts b/src/io-client.ts index b4fdf7686..ca1f44af3 100644 --- a/src/io-client.ts +++ b/src/io-client.ts @@ -22,8 +22,10 @@ */ import { StateSwitch } from 'state-switch' -import { PuppetHostieServer } from 'wechaty-puppet-hostie' -import { PuppetHostieGrpcServerOptions } from 'wechaty-puppet-hostie/dist/src/grpc/puppet-server' +import { + PuppetHostieServer, + PuppetHostieGrpcServerOptions, +} from 'wechaty-puppet-hostie' import { Message } from './user' From 897b2f73fcbc1ae005934d646a89c2fa7b0be11e Mon Sep 17 00:00:00 2001 From: Huan LI Date: Fri, 13 Mar 2020 18:02:15 +0800 Subject: [PATCH 025/598] code clean --- .github/workflows/npm.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index 41827d12e..7577ba8b2 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -64,7 +64,7 @@ jobs: - name: Is A Publish Branch if: steps.check-branch.outputs.match == 'true' run: | - VERSION=$(npx pkg-jq -r .version package.json) + VERSION=$(npx pkg-jq -r .version) if npx version-exists @chatie/grpc "$VERSION" then "Version $VERSION exists on NPM, skipped." else npm publish From 064ec4b181df5425a0aa01487b7089d0501d6c75 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Fri, 13 Mar 2020 18:14:02 +0800 Subject: [PATCH 026/598] fix name --- .github/workflows/npm.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index 7577ba8b2..a032196b8 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -64,9 +64,10 @@ jobs: - name: Is A Publish Branch if: steps.check-branch.outputs.match == 'true' run: | + NAME=$(npx pkg-jq -r .name) VERSION=$(npx pkg-jq -r .version) - if npx version-exists @chatie/grpc "$VERSION" - then "Version $VERSION exists on NPM, skipped." + if npx version-exists "$NAME" "$VERSION" + then echo "$NAME@$VERSION) exists on NPM, skipped." else npm publish fi env: From 5d9268b6c2b3d5db3e132dd36fc03d324d450b8b Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 14 Mar 2020 16:56:02 +0800 Subject: [PATCH 027/598] Upgrade npm deps --- package.json | 58 ++++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index f030c1c69..d2351b091 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.33.8", + "version": "0.35.0", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", @@ -79,56 +79,56 @@ "node": ">= 10" }, "dependencies": { - "brolog": "^1.8.1", + "brolog": "^1.8.3", "clone-class": "^0.7.3", - "cuid": "^2.1.1", - "hot-import": "^0.2.1", + "cuid": "^2.1.8", + "hot-import": "^0.2.14", "in-gfw": "^1.2.0", "npm-programmatic": "0.0.12", "open-graph": "^0.2.4", "opencollective": "^1.0.3", "opencollective-postinstall": "^2.0.2", - "pkg-dir": "^4.0.0", - "portfinder": "^1.0.17", + "pkg-dir": "^4.2.0", + "portfinder": "^1.0.25", "promise-retry": "^1.1.1", - "raven": "^2.6.2", - "read-pkg-up": "^7.0.0", - "state-switch": "^0.6.2", - "watchdog": "^0.8.1", - "wechaty-puppet": "^0.20.1", - "wechaty-puppet-hostie": "^0.3.19", - "ws": "^7.0.0" + "raven": "^2.6.4", + "read-pkg-up": "^7.0.1", + "state-switch": "^0.6.18", + "watchdog": "^0.8.17", + "wechaty-puppet": "^0.21.12", + "wechaty-puppet-hostie": "^0.3.28", + "ws": "^7.2.3" }, "devDependencies": { - "@babel/core": "^7.0.1", - "@babel/node": "^7.0.0", - "@babel/preset-env": "^7.0.0", + "@babel/core": "^7.8.7", + "@babel/node": "^7.8.7", + "@babel/preset-env": "^7.8.7", "@chatie/eslint-config": "^0.9.1", - "@chatie/git-scripts": "^0.2.3", + "@chatie/git-scripts": "^0.2.5", "@chatie/semver": "^0.4.7", "@chatie/tsconfig": "^0.8.0", "@types/cuid": "^1.3.0", "@types/glob": "^7.1.1", "@types/open-graph": "^0.2.0", "@types/promise-retry": "^1.1.3", - "@types/raven": "^2.1.0", + "@types/raven": "^2.5.3", "@types/retry": "^0.12.0", - "@types/ws": "^7.2.1", - "apiai": "^4.0.0", - "check-node-version": "^4.0.1", - "coveralls": "^3.0.0", - "cross-env": "^7.0.0", + "@types/ws": "^7.2.2", + "apiai": "^4.0.3", + "check-node-version": "^4.0.2", + "coveralls": "^3.0.9", + "cross-env": "^7.0.2", "finis": "^0.4.4", - "glob": "^7.1.0", - "jsdoc-to-markdown": "^5.0.0", + "glob": "^7.1.6", + "jsdoc-to-markdown": "^5.0.3", "markdownlint-cli": "^0.22.0", "nyc": "^15.0.0", "pkg-jq": "^0.2.4", "qrcode-terminal": "^0.12.0", - "shx": "^0.3.0", - "sloc": "^0.2.0", - "tstest": "^0.4.1", - "typedoc": "^0.16.10", + "shx": "^0.3.2", + "sloc": "^0.2.1", + "tstest": "^0.4.10", + "typedoc": "^0.16.11", "wechaty-puppet-mock": "^0.17.4" }, "files_comment__whitelist_npm_publish": "http://stackoverflow.com/a/8617868/1123955", From 3818209562c0705f8dbcd59fae9c2d492fde770e Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 14 Mar 2020 16:56:12 +0800 Subject: [PATCH 028/598] fix log msg --- .github/workflows/npm.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index a032196b8..0d6b54734 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -67,7 +67,7 @@ jobs: NAME=$(npx pkg-jq -r .name) VERSION=$(npx pkg-jq -r .version) if npx version-exists "$NAME" "$VERSION" - then echo "$NAME@$VERSION) exists on NPM, skipped." + then echo "$NAME@$VERSION exists on NPM, skipped." else npm publish fi env: From 4dcd2eb3892b980179b6f93c07a5e43a40984a19 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 14 Mar 2020 16:57:29 +0800 Subject: [PATCH 029/598] Upgrade to using Event Payload (https://github.com/wechaty/wechaty-puppet/issues/85) --- src/io.ts | 6 ++-- src/wechaty.spec.ts | 8 ++--- src/wechaty.ts | 75 +++++++++++++++++++++++---------------------- 3 files changed, 46 insertions(+), 43 deletions(-) diff --git a/src/io.ts b/src/io.ts index b6e48b30f..85df4997c 100644 --- a/src/io.ts +++ b/src/io.ts @@ -24,7 +24,7 @@ import { } from './user' import { - PuppetQRCodeScanEvent, + EventScanPayload, } from 'wechaty-puppet' import { @@ -64,7 +64,7 @@ type IoEventName = keyof typeof IO_EVENT_DICT interface IoEventScan { name : 'scan', - payload : PuppetQRCodeScanEvent, + payload : EventScanPayload, } interface IoEventAny { @@ -90,7 +90,7 @@ export class Io { private onMessage: undefined | AnyFunction - private scanPayload?: PuppetQRCodeScanEvent + private scanPayload?: EventScanPayload constructor ( private options: IoOptions, diff --git a/src/wechaty.spec.ts b/src/wechaty.spec.ts index dc5198767..044756d9c 100755 --- a/src/wechaty.spec.ts +++ b/src/wechaty.spec.ts @@ -190,12 +190,12 @@ test('@event ready', async t => { await wechaty.start() t.true(spy.notCalled, 'should no ready event right start wechaty started') - puppet.emit('ready') + puppet.emit('ready', { data: 'test' }) t.true(spy.calledOnce, 'should fire ready event after puppet ready') await wechaty.stop() await wechaty.start() - puppet.emit('ready') + puppet.emit('ready', { data: 'test' }) t.true(spy.calledTwice, 'should fire ready event second time after stop/start wechaty') @@ -220,7 +220,7 @@ test('ready()', async t => { t.true(spy.notCalled, 'should not ready after right start wechaty') - puppet.emit('ready') + puppet.emit('ready', { data: 'test' }) await new Promise(resolve => setImmediate(resolve)) t.true(spy.calledOnce, 'should ready after puppet ready') @@ -230,7 +230,7 @@ test('ready()', async t => { .then(spy) .catch(e => t.fail('rejection: ' + e)) - puppet.emit('ready') + puppet.emit('ready', { data: 'test' }) await new Promise(resolve => setImmediate(resolve)) t.true(spy.calledTwice, 'should ready again after stop/start wechaty') diff --git a/src/wechaty.ts b/src/wechaty.ts index 8e97de9a4..62f93cb1c 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -88,6 +88,8 @@ import { MiniProgram, } from './user/' +import { timestampToDate } from './helper-functions/pure/timestamp-to-date' + export const WECHATY_EVENT_DICT = { ...CHAT_EVENT_DICT, dong : 'Should be emitted after we call `Wechaty.ding()`', @@ -614,14 +616,14 @@ export class Wechaty extends EventEmitter implements Sayable { switch (eventName) { case 'dong': - puppet.on('dong', data => { - this.emit('dong', data) + puppet.on('dong', payload => { + this.emit('dong', payload.data) }) break case 'error': - puppet.on('error', error => { - this.emit('error', new Error(error)) + puppet.on('error', payload => { + this.emit('error', new Error(payload.data)) }) break @@ -636,8 +638,8 @@ export class Wechaty extends EventEmitter implements Sayable { break case 'friendship': - puppet.on('friendship', async friendshipId => { - const friendship = this.Friendship.load(friendshipId) + puppet.on('friendship', async payload => { + const friendship = this.Friendship.load(payload.friendshipId) await friendship.ready() this.emit('friendship', friendship) friendship.contact().emit('friendship', friendship) @@ -645,24 +647,24 @@ export class Wechaty extends EventEmitter implements Sayable { break case 'login': - puppet.on('login', async contactId => { - const contact = this.ContactSelf.load(contactId) + puppet.on('login', async payload => { + const contact = this.ContactSelf.load(payload.contactId) await contact.ready() this.emit('login', contact) }) break case 'logout': - puppet.on('logout', async (contactId, reason) => { - const contact = this.ContactSelf.load(contactId) + puppet.on('logout', async payload => { + const contact = this.ContactSelf.load(payload.contactId) await contact.ready() - this.emit('logout', contact, reason) + this.emit('logout', contact, payload.data) }) break case 'message': - puppet.on('message', async messageId => { - const msg = this.Message.load(messageId) + puppet.on('message', async payload => { + const msg = this.Message.load(payload.messageId) await msg.ready() this.emit('message', msg) @@ -683,23 +685,23 @@ export class Wechaty extends EventEmitter implements Sayable { break case 'room-invite': - puppet.on('room-invite', async roomInvitationId => { - const roomInvitation = this.RoomInvitation.load(roomInvitationId) + puppet.on('room-invite', async payload => { + const roomInvitation = this.RoomInvitation.load(payload.roomInvitationId) this.emit('room-invite', roomInvitation) }) break case 'room-join': - puppet.on('room-join', async (roomId, inviteeIdList, inviterId, timestamp) => { - const room = this.Room.load(roomId) + puppet.on('room-join', async payload => { + const room = this.Room.load(payload.roomId) await room.sync() - const inviteeList = inviteeIdList.map(id => this.Contact.load(id)) + const inviteeList = payload.inviteeIdList.map(id => this.Contact.load(id)) await Promise.all(inviteeList.map(c => c.ready())) - const inviter = this.Contact.load(inviterId) + const inviter = this.Contact.load(payload.inviterId) await inviter.ready() - const date = new Date(timestamp) + const date = timestampToDate(payload.timestamp) this.emit('room-join', room, inviteeList, inviter, date) room.emit('join', inviteeList, inviter, date) @@ -707,50 +709,51 @@ export class Wechaty extends EventEmitter implements Sayable { break case 'room-leave': - puppet.on('room-leave', async (roomId, leaverIdList, removerId, timestamp) => { - const room = this.Room.load(roomId) + puppet.on('room-leave', async payload => { + const room = this.Room.load(payload.roomId) /** * See: https://github.com/wechaty/wechaty/pull/1833 */ await room.sync() - const leaverList = leaverIdList.map(id => this.Contact.load(id)) + const leaverList = payload.removeeIdList.map(id => this.Contact.load(id)) await Promise.all(leaverList.map(c => c.ready())) - const remover = this.Contact.load(removerId) + const remover = this.Contact.load(payload.removerId) await remover.ready() - const date = new Date(timestamp) + const date = timestampToDate(payload.timestamp) this.emit('room-leave', room, leaverList, remover, date) room.emit('leave', leaverList, remover, date) // issue #254 - if (leaverIdList.includes(this.puppet.selfId())) { - await this.puppet.roomPayloadDirty(roomId) - await this.puppet.roomMemberPayloadDirty(roomId) + const selfId = this.puppet.selfId() + if (selfId && payload.removeeIdList.includes(selfId)) { + await this.puppet.roomPayloadDirty(payload.roomId) + await this.puppet.roomMemberPayloadDirty(payload.roomId) } }) break case 'room-topic': - puppet.on('room-topic', async (roomId, newTopic, oldTopic, changerId, timestamp) => { - const room = this.Room.load(roomId) + puppet.on('room-topic', async payload => { + const room = this.Room.load(payload.roomId) await room.sync() - const changer = this.Contact.load(changerId) + const changer = this.Contact.load(payload.changerId) await changer.ready() - const date = new Date(timestamp) + const date = timestampToDate(payload.timestamp) - this.emit('room-topic', room, newTopic, oldTopic, changer, date) - room.emit('topic', newTopic, oldTopic, changer, date) + this.emit('room-topic', room, payload.newTopic, payload.oldTopic, changer, date) + room.emit('topic', payload.newTopic, payload.oldTopic, changer, date) }) break case 'scan': - puppet.on('scan', async (qrcode, status, data) => { - this.emit('scan', qrcode, status, data) + puppet.on('scan', async payload => { + this.emit('scan', payload.qrcode || '', payload.status, payload.data) }) break From b234bb740800c5a38a8bea0d7663850b5ec15020 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 14 Mar 2020 16:58:07 +0800 Subject: [PATCH 030/598] Upgrade hostie --- src/io-client.ts | 22 +++++++++++----------- src/puppet-config.ts | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/io-client.ts b/src/io-client.ts index ca1f44af3..65135663a 100644 --- a/src/io-client.ts +++ b/src/io-client.ts @@ -23,9 +23,9 @@ import { StateSwitch } from 'state-switch' import { - PuppetHostieServer, - PuppetHostieGrpcServerOptions, -} from 'wechaty-puppet-hostie' + PuppetServer, + PuppetServerOptions, +} from 'wechaty-puppet-hostie' import { Message } from './user' @@ -47,7 +47,7 @@ export class IoClient { * Huan(202002): make it optional. */ private io?: Io - private hostieServer?: PuppetHostieServer + private puppetServer?: PuppetServer private state: StateSwitch @@ -64,28 +64,28 @@ export class IoClient { private async startHostie () { log.verbose('IoClient', 'startHostie()') - if (this.hostieServer) { + if (this.puppetServer) { throw new Error('hostie server exists') } - const options: PuppetHostieGrpcServerOptions = { + const options: PuppetServerOptions = { endpoint : '0.0.0.0:8788', puppet : this.options.wechaty.puppet, token : this.options.token, } - this.hostieServer = new PuppetHostieServer(options) - await this.hostieServer.start() + this.puppetServer = new PuppetServer(options) + await this.puppetServer.start() } private async stopHostie () { log.verbose('IoClient', 'stopHostie()') - if (!this.hostieServer) { + if (!this.puppetServer) { throw new Error('hostie server does not exist') } - await this.hostieServer.stop() - this.hostieServer = undefined + await this.puppetServer.stop() + this.puppetServer = undefined } public async start (): Promise { diff --git a/src/puppet-config.ts b/src/puppet-config.ts index ef6e20e57..caf4ee5bc 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -11,8 +11,8 @@ export const PUPPET_DEPENDENCIES = { * DEPRECATED by Huan(202002): The Above is Alias for the following full NPM module names * *******************************************************************************************/ - 'wechaty-puppet-hostie' : '^0.3.21', // https://www.npmjs.com/package/wechaty-puppet-hostie - 'wechaty-puppet-mock' : '^0.17.5', // https://www.npmjs.com/package/wechaty-puppet-mock + 'wechaty-puppet-hostie' : '^0.3.28', // https://www.npmjs.com/package/wechaty-puppet-hostie + 'wechaty-puppet-mock' : '^0.19.0', // https://www.npmjs.com/package/wechaty-puppet-mock // 'wechaty-puppet-dll' : '^0.3.1', // https://www.npmjs.com/package/wechaty-puppet-dll // 'wechaty-puppet-ioscat' : '^0.5.22', // https://www.npmjs.com/package/wechaty-puppet-ioscat From 1ae964224d66ef0a70cde4e9a90b0391dc960df3 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 14 Mar 2020 17:05:51 +0800 Subject: [PATCH 031/598] update mock --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d2351b091..c367d16dc 100644 --- a/package.json +++ b/package.json @@ -129,7 +129,7 @@ "sloc": "^0.2.1", "tstest": "^0.4.10", "typedoc": "^0.16.11", - "wechaty-puppet-mock": "^0.17.4" + "wechaty-puppet-mock": "^0.19.0" }, "files_comment__whitelist_npm_publish": "http://stackoverflow.com/a/8617868/1123955", "files": [ From d83d7ca54410def895e673ec01fefbbd0c14232a Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 14 Mar 2020 17:06:07 +0800 Subject: [PATCH 032/598] 0.35.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c367d16dc..7837aea37 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.35.0", + "version": "0.35.1", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 995fcb5668f896ecb33198ffdb0e6374127b7319 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Sun, 15 Mar 2020 13:02:11 +0100 Subject: [PATCH 033/598] fix: upgrade state-switch from 0.6.18 to 0.7.2 (#1928) Snyk has created this PR to upgrade state-switch from 0.6.18 to 0.7.2. See this package in NPM: https://www.npmjs.com/package/state-switch See this project in Snyk: https://app.snyk.io/org/zixia/project/df4e8eb8-9fc1-492e-900d-59a1cf481a96?utm_source=github&utm_medium=upgrade-pr --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7837aea37..86c8c52ba 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "promise-retry": "^1.1.1", "raven": "^2.6.4", "read-pkg-up": "^7.0.1", - "state-switch": "^0.6.18", + "state-switch": "^0.7.2", "watchdog": "^0.8.17", "wechaty-puppet": "^0.21.12", "wechaty-puppet-hostie": "^0.3.28", From e96d6b13eb275c43c083e3a11cac2c15229780ea Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 18 Mar 2020 13:33:43 +0800 Subject: [PATCH 034/598] upgrade puppet hostie --- package.json | 2 +- src/puppet-config.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 7837aea37..78bab327d 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,7 @@ "state-switch": "^0.6.18", "watchdog": "^0.8.17", "wechaty-puppet": "^0.21.12", - "wechaty-puppet-hostie": "^0.3.28", + "wechaty-puppet-hostie": "^0.3.29", "ws": "^7.2.3" }, "devDependencies": { diff --git a/src/puppet-config.ts b/src/puppet-config.ts index caf4ee5bc..bff6a3c2d 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -11,7 +11,7 @@ export const PUPPET_DEPENDENCIES = { * DEPRECATED by Huan(202002): The Above is Alias for the following full NPM module names * *******************************************************************************************/ - 'wechaty-puppet-hostie' : '^0.3.28', // https://www.npmjs.com/package/wechaty-puppet-hostie + 'wechaty-puppet-hostie' : '^0.3.29', // https://www.npmjs.com/package/wechaty-puppet-hostie 'wechaty-puppet-mock' : '^0.19.0', // https://www.npmjs.com/package/wechaty-puppet-mock // 'wechaty-puppet-dll' : '^0.3.1', // https://www.npmjs.com/package/wechaty-puppet-dll From 522ff5f324f4cc76d197093eb91095815c43db21 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 18 Mar 2020 13:33:59 +0800 Subject: [PATCH 035/598] 0.35.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 78bab327d..16d144b13 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.35.1", + "version": "0.35.2", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 3fa5c0d39d5ffb24bd3ea819ac688f30636dd2bc Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 18 Mar 2020 13:34:28 +0800 Subject: [PATCH 036/598] 0.35.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a21a0da48..435b5bd8f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.35.2", + "version": "0.35.3", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 5fbc1cd3744b11e51e16affb7f772fab2778a712 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 18 Mar 2020 13:45:01 +0800 Subject: [PATCH 037/598] 0.35.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 435b5bd8f..1aa50647a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.35.3", + "version": "0.35.4", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From c42a37f669de106a76a8e7611da330ca13df0983 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 18 Mar 2020 22:02:30 +0800 Subject: [PATCH 038/598] upgrade puppet providers to the latest versions --- src/puppet-config.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index bff6a3c2d..62ef371e5 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -17,10 +17,10 @@ export const PUPPET_DEPENDENCIES = { // 'wechaty-puppet-dll' : '^0.3.1', // https://www.npmjs.com/package/wechaty-puppet-dll // 'wechaty-puppet-ioscat' : '^0.5.22', // https://www.npmjs.com/package/wechaty-puppet-ioscat // 'wechaty-puppet-padchat' : '^0.19.3', // https://www.npmjs.com/package/wechaty-puppet-padchat - 'wechaty-puppet-padplus' : '^0.5.13', // https://www.npmjs.com/package/wechaty-puppet-padplus + 'wechaty-puppet-padplus' : '^0.5.24', // https://www.npmjs.com/package/wechaty-puppet-padplus // 'wechaty-puppet-padpro' : '^0.3.21', // https://www.npmjs.com/package/wechaty-puppet-padpro - 'wechaty-puppet-puppeteer' : '^0.19.5', // https://www.npmjs.com/package/wechaty-puppet-puppeteer - 'wechaty-puppet-wechat4u' : '^0.16.3', // https://www.npmjs.com/package/wechaty-puppet-wechat4u + 'wechaty-puppet-puppeteer' : '^0.21.2', // https://www.npmjs.com/package/wechaty-puppet-puppeteer + 'wechaty-puppet-wechat4u' : '^0.17.2', // https://www.npmjs.com/package/wechaty-puppet-wechat4u } export type PuppetModuleName = keyof typeof PUPPET_DEPENDENCIES From 2f1b8a3721915cf54be38369102b64f4cbe6f557 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 18 Mar 2020 22:02:47 +0800 Subject: [PATCH 039/598] 0.35.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1aa50647a..d99b19445 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.35.4", + "version": "0.35.5", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 722df5f1ccaa30e1e0a3cb26a028e3d7425e3a00 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 18 Mar 2020 23:51:51 +0800 Subject: [PATCH 040/598] log clean --- src/wechaty.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/wechaty.ts b/src/wechaty.ts index 62f93cb1c..df057bc59 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -612,7 +612,11 @@ export class Wechaty extends EventEmitter implements Sayable { const eventNameList: PuppetEventName[] = Object.keys(PUPPET_EVENT_DICT) as PuppetEventName[] for (const eventName of eventNameList) { - log.verbose('Wechaty', 'initPuppetEventBridge() puppet.on(%s) registered', eventName) + log.verbose('Wechaty', + 'initPuppetEventBridge() puppet.on(%s) (listenerCount:%s) registering...', + eventName, + puppet.listenerCount(eventName), + ) switch (eventName) { case 'dong': @@ -814,9 +818,7 @@ export class Wechaty extends EventEmitter implements Sayable { this.options.name || '', this.version(), ) - log.verbose('Wechaty', 'puppet: %s', this.options.puppet) - log.verbose('Wechaty', 'name: %s', this.options.name) - log.verbose('Wechaty', 'id: %s', this.id) + log.verbose('Wechaty', 'id: %s', this.id) if (this.state.on()) { log.silly('Wechaty', 'start() on a starting/started instance') From a1747b69109a9cd5a2163da40471711c2f8eb74f Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 18 Mar 2020 23:54:23 +0800 Subject: [PATCH 041/598] 0.35.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d99b19445..cedf79325 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.35.5", + "version": "0.35.6", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From dbe23c5f053c2aef9edb40516f0826421b7c05d0 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Thu, 19 Mar 2020 19:38:22 +0800 Subject: [PATCH 042/598] clean --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index cedf79325..1a894075f 100644 --- a/package.json +++ b/package.json @@ -66,9 +66,9 @@ "微信控" ], "author": { - "name": "Huan LI", + "name": "Huan LI (李卓桓)", "email": "zixia@zixia.net", - "url": "https://www.zixia.net" + "url": "https://linkedin.com/in/zixia/" }, "license": "Apache-2.0", "bugs": { From c428b2205cafe3bc3479e72660c2b8adfd16c310 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Fri, 20 Mar 2020 00:05:01 +0800 Subject: [PATCH 043/598] check duplicated wechaty-puppet module installed (#1930) --- src/puppet-manager.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/puppet-manager.ts b/src/puppet-manager.ts index 963a5aadf..14a20fbe8 100644 --- a/src/puppet-manager.ts +++ b/src/puppet-manager.ts @@ -48,6 +48,14 @@ export class PuppetManager { */ if (options.puppet instanceof Puppet) { puppetInstance = await this.resolveInstance(options.puppet) + } else if (typeof options.puppet !== 'string') { + log.error('PuppetManager', 'resolve() %s', + ` + Wechaty Framework must keep only one Puppet instance #1930 + See: https://github.com/wechaty/wechaty/issues/1930 + `, + ) + throw new Error('Wechaty Framework must keep only one Puppet instance #1930') } else { const MyPuppet = await this.resolveName(options.puppet) /** From 6347e3c26637208ca51e36e183720530b1c5c8c1 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Thu, 19 Mar 2020 18:05:17 +0200 Subject: [PATCH 044/598] fix: upgrade brolog from 0.3.11 to 0.4.3 (#1925) Snyk has created this PR to upgrade brolog from 0.3.11 to 0.4.3. See this package in NPM: https://www.npmjs.com/package/brolog See this project in Snyk: https://app.snyk.io/org/zixia/project/7dbf39d6-a3aa-4cb2-9ec2-23c8b09e855b?utm_source=github&utm_medium=upgrade-pr --- tests/fixtures/docker/with-package-json/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fixtures/docker/with-package-json/package.json b/tests/fixtures/docker/with-package-json/package.json index 77e3ef8aa..c6a83d721 100644 --- a/tests/fixtures/docker/with-package-json/package.json +++ b/tests/fixtures/docker/with-package-json/package.json @@ -4,7 +4,7 @@ "description": "", "main": "with-require-error.js", "dependencies": { - "brolog": "^0.3.11" + "brolog": "^0.4.3" }, "devDependencies": {}, "scripts": { From da855b6e62f131fb689669fba3087e71af353935 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Fri, 20 Mar 2020 00:05:19 +0800 Subject: [PATCH 045/598] 0.35.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1a894075f..4f6a64b8b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.35.6", + "version": "0.35.7", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 32f9e0839c0d6dbc81ecbfbe3fd7dad377bdf761 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Fri, 20 Mar 2020 00:08:24 +0800 Subject: [PATCH 046/598] 0.35.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4f6a64b8b..5ad53762f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.35.7", + "version": "0.35.8", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From d26f69c0ff8e3e5ef8a34f06f8415d052124295c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 20 Mar 2020 23:17:08 +0800 Subject: [PATCH 047/598] Remove MessageUserQueryFilter (#1931) * remove MessageUserQueryFilter (#1929) * restore * 0.35.7 * 0.35.8 * ci * 0.35.12 * restore * 0.35.13 * 0.35.14 --- package.json | 2 +- src/user/message.ts | 40 ++++++++++------------------------------ 2 files changed, 11 insertions(+), 31 deletions(-) diff --git a/package.json b/package.json index 5ad53762f..49057e9d1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.35.8", + "version": "0.35.14", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", diff --git a/src/user/message.ts b/src/user/message.ts index 98c7e8832..08306c463 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -57,14 +57,6 @@ import { } from './mini-program' import { Image } from './image' -export interface MessageUserQueryFilter { - from? : Contact, - text? : string | RegExp - room? : Room - type? : MessageType - to? : Contact -} - /** * All wechat messages will be encapsulated as a Message. * @@ -87,16 +79,16 @@ export class Message extends Accessory implements Sayable { * Find message in cache */ public static async find ( - this : T, - userQuery : string | MessageUserQueryFilter, + this : T, + query : string | MessageQueryFilter, ): Promise { - log.verbose('Message', 'find(%s)', JSON.stringify(userQuery)) + log.verbose('Message', 'find(%s)', JSON.stringify(query)) - if (typeof userQuery === 'string') { - userQuery = { text: userQuery } + if (typeof query === 'string') { + query = { text: query } } - const messageList = await this.findAll(userQuery) + const messageList = await this.findAll(query) if (messageList.length < 1) { return null } @@ -112,27 +104,15 @@ export class Message extends Accessory implements Sayable { * Find messages in cache */ public static async findAll ( - this : T, - userQuery? : MessageUserQueryFilter, + this : T, + query? : MessageQueryFilter, ): Promise> { - log.verbose('Message', 'findAll(%s)', JSON.stringify(userQuery) || '') - - let puppetQuery: undefined | MessageQueryFilter - - if (userQuery) { - puppetQuery = { - fromId : userQuery.from && userQuery.from.id, - roomId : userQuery.room && userQuery.room.id, - text : userQuery.text, - toId : userQuery.to && userQuery.to.id, - type : userQuery.type, - } - } + log.verbose('Message', 'findAll(%s)', JSON.stringify(query) || '') const invalidDict: { [id: string]: true } = {} try { - const MessageIdList = await this.puppet.messageSearch(puppetQuery) + const MessageIdList = await this.puppet.messageSearch(query) const messageList = MessageIdList.map(id => this.load(id)) await Promise.all( messageList.map( From d4f991c823e99bcaf8637bb449c8f513602ed504 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 21 Mar 2020 10:18:38 +0800 Subject: [PATCH 048/598] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 068107cd2..37ada6b99 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,6 @@ [![GitHub stars](https://img.shields.io/github/stars/wechaty/wechaty.svg?label=github%20stars)](https://github.com/wechaty/wechaty) [![Docker Pulls](https://img.shields.io/docker/pulls/zixia/wechaty.svg?maxAge=2592000)](https://hub.docker.com/r/zixia/wechaty/) [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-blue.svg)](https://www.typescriptlang.org/) -[![Greenkeeper badge](https://badges.greenkeeper.io/wechaty/wechaty.svg)](https://greenkeeper.io/) [![Gitter](https://badges.gitter.im/Chatie/wechaty.svg)](https://gitter.im/Chatie/wechaty?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) ## Connecting Chatbots From 20b2b58647067eb2b87035fd2155ac84e5cf57e9 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 21 Mar 2020 13:33:46 +0800 Subject: [PATCH 049/598] upgrade @chatie/git-scripts@0.5 to compatible windows --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5ad53762f..bda8cd6a2 100644 --- a/package.json +++ b/package.json @@ -104,7 +104,7 @@ "@babel/node": "^7.8.7", "@babel/preset-env": "^7.8.7", "@chatie/eslint-config": "^0.9.1", - "@chatie/git-scripts": "^0.2.5", + "@chatie/git-scripts": "^0.5.2", "@chatie/semver": "^0.4.7", "@chatie/tsconfig": "^0.8.0", "@types/cuid": "^1.3.0", From cb1364eb877250430f1cd4fa3d23ede5baa418c4 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 21 Mar 2020 13:34:02 +0800 Subject: [PATCH 050/598] 0.35.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bda8cd6a2..27fe5f563 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.35.8", + "version": "0.35.9", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From cb93f9e80855e0e78155221cd6ae73f1d205d66b Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 21 Mar 2020 13:34:42 +0800 Subject: [PATCH 051/598] 0.35.15 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 34db50bae..2d1c5e81a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.35.14", + "version": "0.35.15", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From d03a96f97731af386cd58266a1110edae48641cd Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 21 Mar 2020 16:35:09 +0800 Subject: [PATCH 052/598] fix hostie room member id --- package.json | 2 +- src/puppet-config.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2d1c5e81a..64723413b 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,7 @@ "state-switch": "^0.7.2", "watchdog": "^0.8.17", "wechaty-puppet": "^0.21.12", - "wechaty-puppet-hostie": "^0.3.29", + "wechaty-puppet-hostie": "^0.3.32", "ws": "^7.2.3" }, "devDependencies": { diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 62ef371e5..3fbd570ac 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -11,7 +11,7 @@ export const PUPPET_DEPENDENCIES = { * DEPRECATED by Huan(202002): The Above is Alias for the following full NPM module names * *******************************************************************************************/ - 'wechaty-puppet-hostie' : '^0.3.29', // https://www.npmjs.com/package/wechaty-puppet-hostie + 'wechaty-puppet-hostie' : '^0.3.32', // https://www.npmjs.com/package/wechaty-puppet-hostie 'wechaty-puppet-mock' : '^0.19.0', // https://www.npmjs.com/package/wechaty-puppet-mock // 'wechaty-puppet-dll' : '^0.3.1', // https://www.npmjs.com/package/wechaty-puppet-dll From 4d189c6e427439ab3212d4733a361a2a570b7805 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 21 Mar 2020 16:40:27 +0800 Subject: [PATCH 053/598] 0.35.16 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 64723413b..28882b1db 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.35.15", + "version": "0.35.16", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 8cd6bf9cba584576d4203b06809e5b0b6853954c Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 21 Mar 2020 17:02:51 +0800 Subject: [PATCH 054/598] fix UrlLink Response for Hostie --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 28882b1db..3b2ecf0ea 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,7 @@ "state-switch": "^0.7.2", "watchdog": "^0.8.17", "wechaty-puppet": "^0.21.12", - "wechaty-puppet-hostie": "^0.3.32", + "wechaty-puppet-hostie": "^0.3.33", "ws": "^7.2.3" }, "devDependencies": { From 19ec3ed637404f57b4802057f458b72fe2d4edc0 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 21 Mar 2020 17:07:42 +0800 Subject: [PATCH 055/598] 0.35.17 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3b2ecf0ea..459f84bbc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.35.16", + "version": "0.35.17", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From cae02d70083132478cc4dbc650a9c4a7dbe041ff Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sun, 22 Mar 2020 11:43:16 +0800 Subject: [PATCH 056/598] fix hostie connection --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 459f84bbc..55d8da04c 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,7 @@ "state-switch": "^0.7.2", "watchdog": "^0.8.17", "wechaty-puppet": "^0.21.12", - "wechaty-puppet-hostie": "^0.3.33", + "wechaty-puppet-hostie": "^0.3.35", "ws": "^7.2.3" }, "devDependencies": { From ca7f80a8800e854acf359f0b306581e041cd5161 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sun, 22 Mar 2020 11:47:00 +0800 Subject: [PATCH 057/598] clean puppet config --- src/puppet-config.ts | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 3fbd570ac..617aa53ab 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -2,23 +2,23 @@ * Wechaty Official Puppet Implementations List */ export const PUPPET_DEPENDENCIES = { - // 'default' : '0.0.0', // will be replaced with PUPPET_DEFAULT - // 'mock' : '0.0.0', // compatible with v0.18, will be replaced with wechaty-puppet-padchat - // 'padchat' : '0.0.0', // compatible with v0.18, will be replaced with wechaty-puppet-padchat - // 'padpro' : '0.0.0', - - /****************************************************************************************** - * DEPRECATED by Huan(202002): The Above is Alias for the following full NPM module names * - *******************************************************************************************/ + /** + * The following puppets were DEPRECATED + */ + // 'wechaty-puppet-ioscat' : '^0.5.22', // https://www.npmjs.com/package/wechaty-puppet-ioscat + // 'wechaty-puppet-padchat' : '^0.19.3', // https://www.npmjs.com/package/wechaty-puppet-padchat + // 'wechaty-puppet-padpro' : '^0.3.21', // https://www.npmjs.com/package/wechaty-puppet-padpro - 'wechaty-puppet-hostie' : '^0.3.32', // https://www.npmjs.com/package/wechaty-puppet-hostie + /** + * Wechaty Internal Puppets + */ + 'wechaty-puppet-hostie' : '^0.3.35', // https://www.npmjs.com/package/wechaty-puppet-hostie 'wechaty-puppet-mock' : '^0.19.0', // https://www.npmjs.com/package/wechaty-puppet-mock - // 'wechaty-puppet-dll' : '^0.3.1', // https://www.npmjs.com/package/wechaty-puppet-dll - // 'wechaty-puppet-ioscat' : '^0.5.22', // https://www.npmjs.com/package/wechaty-puppet-ioscat - // 'wechaty-puppet-padchat' : '^0.19.3', // https://www.npmjs.com/package/wechaty-puppet-padchat + /** + * Wechaty External Puppets + */ 'wechaty-puppet-padplus' : '^0.5.24', // https://www.npmjs.com/package/wechaty-puppet-padplus - // 'wechaty-puppet-padpro' : '^0.3.21', // https://www.npmjs.com/package/wechaty-puppet-padpro 'wechaty-puppet-puppeteer' : '^0.21.2', // https://www.npmjs.com/package/wechaty-puppet-puppeteer 'wechaty-puppet-wechat4u' : '^0.17.2', // https://www.npmjs.com/package/wechaty-puppet-wechat4u } From eff174c9bc20d6f3dbe619b90f2b666abf7bac3d Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sun, 22 Mar 2020 11:47:16 +0800 Subject: [PATCH 058/598] 0.35.18 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 55d8da04c..565bd7c80 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.35.17", + "version": "0.35.18", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 14e7b7aa492181bcd1178ff7791de52dc7425265 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Mon, 23 Mar 2020 09:19:17 +0800 Subject: [PATCH 059/598] remove deprecated `friend` event listener support --- src/wechaty.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/wechaty.ts b/src/wechaty.ts index df057bc59..dcc1e7d2c 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -513,18 +513,6 @@ export class Wechaty extends EventEmitter implements Sayable { : typeof listener, ) - // DEPRECATED for 'friend' event - if (event as any === 'friend') { - log.warn('Wechaty', "on('friend', contact, friendRequest) is DEPRECATED. use on('friendship', friendship) instead") - if (typeof listener === 'function') { - const oldListener = listener - listener = (...args: any[]) => { - log.warn('Wechaty', "on('friend', contact, friendRequest) is DEPRECATED. use on('friendship', friendship) instead") - oldListener.apply(this, args) - } - } - } - if (typeof listener === 'function') { this.addListenerFunction(event, listener) } else { From dfd3736784fcbdfe0c2c6be58e4e8179397744fc Mon Sep 17 00:00:00 2001 From: Huan LI Date: Mon, 23 Mar 2020 09:55:50 +0800 Subject: [PATCH 060/598] add `super.on()` doc --- src/wechaty.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/wechaty.ts b/src/wechaty.ts index dcc1e7d2c..9f16d42ad 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -553,6 +553,9 @@ export class Wechaty extends EventEmitter implements Sayable { private addListenerFunction (event: WechatyEventName, listener: AnyFunction): void { log.verbose('Wechaty', 'addListenerFunction(%s)', event) + /** + * We use `super.on()` at here to prevent loop + */ super.on(event, (...args: any[]) => { try { listener.apply(this, args) From 6ae7d3e979407ba872258788a6ff8661c70fd565 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Mon, 23 Mar 2020 13:28:16 +0800 Subject: [PATCH 061/598] Upgrade hostie & wechaty-puppet --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 565bd7c80..cabe9522c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.35.18", + "version": "0.37.0", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", @@ -95,8 +95,8 @@ "read-pkg-up": "^7.0.1", "state-switch": "^0.7.2", "watchdog": "^0.8.17", - "wechaty-puppet": "^0.21.12", - "wechaty-puppet-hostie": "^0.3.35", + "wechaty-puppet": "^0.23.2", + "wechaty-puppet-hostie": "^0.5.1", "ws": "^7.2.3" }, "devDependencies": { From 2326f8ad9df3cd22ea47080926f83cf250e8403c Mon Sep 17 00:00:00 2001 From: Huan LI Date: Mon, 23 Mar 2020 13:28:33 +0800 Subject: [PATCH 062/598] 0.37.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cabe9522c..f5b1ab4cc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.37.0", + "version": "0.37.1", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 14bc117250a8a944c6137e1344f333c9a9bc5932 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Mon, 23 Mar 2020 13:31:29 +0800 Subject: [PATCH 063/598] clean --- src/wechaty.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/wechaty.ts b/src/wechaty.ts index 9f16d42ad..946dd3ebf 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -622,13 +622,13 @@ export class Wechaty extends EventEmitter implements Sayable { }) break - case 'watchdog': - puppet.on('watchdog', data => { + case 'heartbeat': + puppet.on('heartbeat', payload => { /** * Use `watchdog` event from Puppet to `heartbeat` Wechaty. */ // TODO: use a throttle queue to prevent beat too fast. - this.emit('heartbeat', data) + this.emit('heartbeat', payload.data) }) break @@ -756,6 +756,9 @@ export class Wechaty extends EventEmitter implements Sayable { break default: + /** + * Check: The eventName here should have the type `never` + */ throw new Error('eventName ' + eventName + ' unsupported!') } From 0c4368cb87a7bc94ec78d05707e19f1761ac54a0 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Mon, 23 Mar 2020 13:31:45 +0800 Subject: [PATCH 064/598] 0.37.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f5b1ab4cc..dcc469cac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.37.1", + "version": "0.37.2", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From e460ecfe0e6e9e597f1fb5c36c46ecf620ba10db Mon Sep 17 00:00:00 2001 From: Huan LI Date: Mon, 23 Mar 2020 13:35:25 +0800 Subject: [PATCH 065/598] only test under latest version of node --- .github/workflows/npm.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index 0d6b54734..33bd0f0b2 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: os: [macos-latest, windows-latest, ubuntu-latest] - node: [12, 13] + node: [13] runs-on: ${{ matrix.os }} steps: From 557ab45615cc95a8e7bc03d3755a9f3217f34d62 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Mon, 23 Mar 2020 13:35:41 +0800 Subject: [PATCH 066/598] 0.37.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dcc469cac..c3469bc65 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.37.2", + "version": "0.37.3", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 3276bf6721779d036ecdc063d4d63fb212661c7f Mon Sep 17 00:00:00 2001 From: Huan LI Date: Mon, 23 Mar 2020 13:43:01 +0800 Subject: [PATCH 067/598] upgrade hostie to 0.5 --- src/puppet-config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 617aa53ab..ef4707428 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -10,9 +10,9 @@ export const PUPPET_DEPENDENCIES = { // 'wechaty-puppet-padpro' : '^0.3.21', // https://www.npmjs.com/package/wechaty-puppet-padpro /** - * Wechaty Internal Puppets + * Wechaty Internal Puppets: dependenced by package.json */ - 'wechaty-puppet-hostie' : '^0.3.35', // https://www.npmjs.com/package/wechaty-puppet-hostie + 'wechaty-puppet-hostie' : '^0.5.1', // https://www.npmjs.com/package/wechaty-puppet-hostie 'wechaty-puppet-mock' : '^0.19.0', // https://www.npmjs.com/package/wechaty-puppet-mock /** From 2c5bb86c9550d9812334b2841c68aea5d92cf24b Mon Sep 17 00:00:00 2001 From: Huan LI Date: Mon, 23 Mar 2020 13:43:17 +0800 Subject: [PATCH 068/598] 0.37.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c3469bc65..e57d770c6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.37.3", + "version": "0.37.4", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From e5fc8e02f1f523cd7d4ef9803bf6f40eeb06a1d7 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 25 Mar 2020 01:06:42 +0800 Subject: [PATCH 069/598] add room.avatar() doc (#1923) --- src/user/room.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/user/room.ts b/src/user/room.ts index dc2c2e92a..5f92e1192 100644 --- a/src/user/room.ts +++ b/src/user/room.ts @@ -1185,6 +1185,14 @@ export class Room extends Accessory implements Sayable { return owner } + /** + * Get avatar from the room. + * @returns {FileBox} + * @example + * const fileBox = await room.avatar() + * const name = fileBox.name + * fileBox.toFile(name) + */ public async avatar (): Promise { log.verbose('Room', 'avatar()') From e7d784df776f451006fb5338e5a700fb9280690e Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 25 Mar 2020 01:08:27 +0800 Subject: [PATCH 070/598] add room.avatar() doc (#1923) --- docs/index.md | 200 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 188 insertions(+), 12 deletions(-) diff --git a/docs/index.md b/docs/index.md index 0e03a9896..fe87a1b8c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -# Wechaty v0.29.21 Documentation +# Wechaty v0.37.4 Documentation - Blog - - Docs - @@ -117,6 +117,7 @@ See more: * [Wechaty](#Wechaty) * [new Wechaty([options])](#new_Wechaty_new) * _instance_ + * [.name()](#Wechaty+name) * [.on(event, listener)](#Wechaty+on) ⇒ [Wechaty](#Wechaty) * [.start()](#Wechaty+start) ⇒ Promise.<void> * [.stop()](#Wechaty+stop) ⇒ Promise.<void> @@ -146,6 +147,13 @@ bot.on('login', user => console.log(`User ${user} logined`)) bot.on('message', message => console.log(`Message: ${message}`)) bot.start() ``` + + +### wechaty.name() +Wechaty bot name set by `optoins.name` +default: `wechaty` + +**Kind**: instance method of [Wechaty](#Wechaty) ### wechaty.on(event, listener) ⇒ [Wechaty](#Wechaty) @@ -431,6 +439,7 @@ All wechat rooms(groups) will be encapsulated as a Room. * [.memberAll([query])](#Room+memberAll) ⇒ Promise.<Array.<Contact>> * [.member(queryArg)](#Room+member) ⇒ Promise.<(null\|Contact)> * [.owner()](#Room+owner) ⇒ [Contact](#Contact) \| null + * [.avatar()](#Room+avatar) ⇒ FileBox * _static_ * [.create(contactList, [topic])](#Room.create) ⇒ [Promise.<Room>](#Room) * [.findAll([query])](#Room.findAll) ⇒ Promise.<Array.<Room>> @@ -557,6 +566,18 @@ if (room) { }) } ``` +**Example** *(Event:message )* +```js +const bot = new Wechaty() +await bot.start() +// after logged in... +const room = await bot.Room.find({topic: 'topic of your room'}) // change `event-room` to any room topic in your wechat +if (room) { + room.on('message', (message) => { + console.log(`Room received new message: ${message}`) + }) +} +``` **Example** *(Event:topic )* ```js const bot = new Wechaty() @@ -865,6 +886,18 @@ This function is depending on the Puppet Implementation, see [puppet-compatible- ```js const owner = room.owner() ``` + + +### room.avatar() ⇒ FileBox +Get avatar from the room. + +**Kind**: instance method of [Room](#Room) +**Example** +```js +const fileBox = await room.avatar() +const name = fileBox.name +fileBox.toFile(name) +``` ### Room.create(contactList, [topic]) ⇒ [Promise.<Room>](#Room) @@ -952,11 +985,13 @@ All wechat contacts(friend) will be encapsulated as a Contact. * [.province()](#Contact+province) ⇒ string \| null * [.city()](#Contact+city) ⇒ string \| null * [.avatar()](#Contact+avatar) ⇒ Promise.<FileBox> + * [.tags()](#Contact+tags) ⇒ Promise.<Array.<Tag>> * [.sync()](#Contact+sync) ⇒ Promise.<this> * [.self()](#Contact+self) ⇒ boolean * _static_ * [.find(query)](#Contact.find) ⇒ Promise.<(Contact\|null)> * [.findAll([queryArg])](#Contact.findAll) ⇒ Promise.<Array.<Contact>> + * [.tags()](#Contact.tags) ⇒ Promise.<Array.<Tag>> @@ -1145,6 +1180,16 @@ const name = file.name await file.toFile(name, true) console.log(`Contact: ${contact.name()} with avatar file: ${name}`) ``` + + +### contact.tags() ⇒ Promise.<Array.<Tag>> +Get all tags of contact + +**Kind**: instance method of [Contact](#Contact) +**Example** +```js +const tags = await contact.tags() +``` ### contact.sync() ⇒ Promise.<this> @@ -1212,6 +1257,16 @@ const contactList = await bot.Contact.findAll() // get the const contactList = await bot.Contact.findAll({ name: 'ruirui' }) // find allof the contacts whose name is 'ruirui' const contactList = await bot.Contact.findAll({ alias: 'lijiarui' }) // find all of the contacts whose alias is 'lijiarui' ``` + + +### Contact.tags() ⇒ Promise.<Array.<Tag>> +Get tags for all contact + +**Kind**: static method of [Contact](#Contact) +**Example** +```js +const tags = await wechaty.Contact.tags() +``` ## ContactSelf @@ -1316,9 +1371,12 @@ Send, receive friend request, and friend confirmation events. * [.hello()](#Friendship+hello) ⇒ string * [.contact()](#Friendship+contact) ⇒ [Contact](#Contact) * [.type()](#Friendship+type) ⇒ FriendshipType + * [.toJSON()](#Friendship+toJSON) ⇒ FriendshipPayload * _static_ + * [.search(condition)](#Friendship.search) ⇒ [Promise.<Contact>](#Contact) * ~~[.send()](#Friendship.send)~~ * [.add(contact, hello)](#Friendship.add) ⇒ Promise.<void> + * [.fromJSON()](#Friendship.fromJSON) @@ -1414,6 +1472,47 @@ bot.on('friendship', async friendship => { } .start() ``` + + +### friendship.toJSON() ⇒ FriendshipPayload +get friendShipPayload Json + +**Kind**: instance method of [Friendship](#Friendship) +**Example** +```js +const bot = new Wechaty() +bot.on('friendship', async friendship => { + try { + // JSON.stringify(friendship) as well. + const payload = await friendship.toJSON() + } catch (e) { + console.error(e) + } +} +.start() +``` + + +### Friendship.search(condition) ⇒ [Promise.<Contact>](#Contact) +Search a Friend by phone or weixin. + +The best practice is to search friend request once per minute. +Remeber not to do this too frequently, or your account may be blocked. + +**Kind**: static method of [Friendship](#Friendship) + +| Param | Type | Description | +| --- | --- | --- | +| condition | FriendshipSearchCondition | Search friend by phone or weixin. | + +**Example** +```js +const friend_phone = await bot.Friendship.search({phone: '13112341234'}) +const friend_weixin = await bot.Friendship.search({weixin: 'weixin_account'}) + +console.log(`This is the new friend info searched by phone : ${friend_phone}`) +await bot.Friendship.add(friend_phone, 'hello') +``` ### ~~Friendship.send()~~ @@ -1444,6 +1543,21 @@ for (let i = 0; i < memberList.length; i++) { await bot.Friendship.add(member, 'Nice to meet you! I am wechaty bot!') } ``` + + +### Friendship.fromJSON() +create friendShip by friendshipJson + +**Kind**: static method of [Friendship](#Friendship) +**Example** +```js +const bot = new Wechaty() +bot.start() + +const payload = '{...}' // your saved JSON payload +const friendship = bot.FriendShip.fromJSON(friendshipFromDisk) +await friendship.accept() +``` ## Message @@ -1462,6 +1576,7 @@ All wechat messages will be encapsulated as a Message. * [.text()](#Message+text) ⇒ string * [.toRecalled()](#Message+toRecalled) * [.say(textOrContactOrFile, [mention])](#Message+say) ⇒ Promise.<(void\|Message)> + * [.recall()](#Message+recall) ⇒ Promise.<boolean> * [.type()](#Message+type) ⇒ MessageType * [.self()](#Message+self) ⇒ boolean * [.mentionList()](#Message+mentionList) ⇒ Promise.<Array.<Contact>> @@ -1471,6 +1586,7 @@ All wechat messages will be encapsulated as a Message. * [.age()](#Message+age) ⇒ number * ~~[.file()](#Message+file)~~ * [.toFileBox()](#Message+toFileBox) ⇒ Promise.<FileBox> + * [.toImage()](#Message+toImage) ⇒ Image * [.toContact()](#Message+toContact) ⇒ [Promise.<Contact>](#Contact) * _static_ * [.find()](#Message.find) @@ -1659,6 +1775,24 @@ bot }) .start() ``` + + +### message.recall() ⇒ Promise.<boolean> +Recall a message. +> Tips: + +**Kind**: instance method of [Message](#Message) +**Example** +```js +const bot = new Wechaty() +bot +.on('message', async m => { + const recallMessage = await msg.say('123') + if (recallMessage) { + const isSuccess = await recallMessage.recall() + } +}) +``` ### message.type() ⇒ MessageType @@ -1791,6 +1925,21 @@ const fileBox = await message.toFileBox() const fileName = fileBox.name fileBox.toFile(fileName) ``` + + +### message.toImage() ⇒ Image +Extract the Image File from the Message, so that we can use different image sizes. +> Tips: +This function is depending on the Puppet Implementation, see [puppet-compatible-table](https://github.com/wechaty/wechaty/wiki/Puppet#3-puppet-compatible-table) + +**Kind**: instance method of [Message](#Message) +**Example** *(Save image file from a message)* +```js +const image = message.toImage() +const fileBox = await image.artwork() +const fileName = fileBox.name +fileBox.toFile(fileName) +``` ### message.toContact() ⇒ [Promise.<Contact>](#Contact) @@ -1820,12 +1969,15 @@ accept room invitation **Kind**: global class * [RoomInvitation](#RoomInvitation) - * [.accept()](#RoomInvitation+accept) ⇒ Promise.<void> - * [.inviter()](#RoomInvitation+inviter) ⇒ [Contact](#Contact) - * [.topic()](#RoomInvitation+topic) ⇒ [Contact](#Contact) - * [.roomTopic()](#RoomInvitation+roomTopic) - * [.date()](#RoomInvitation+date) ⇒ Promise.<Date> - * [.age()](#RoomInvitation+age) ⇒ number + * _instance_ + * [.accept()](#RoomInvitation+accept) ⇒ Promise.<void> + * [.inviter()](#RoomInvitation+inviter) ⇒ [Contact](#Contact) + * [.topic()](#RoomInvitation+topic) ⇒ [Contact](#Contact) + * [.date()](#RoomInvitation+date) ⇒ Promise.<Date> + * [.age()](#RoomInvitation+age) ⇒ number + * [.toJSON()](#RoomInvitation+toJSON) ⇒ string + * _static_ + * [.fromJSON()](#RoomInvitation.fromJSON) ⇒ [RoomInvitation](#RoomInvitation) @@ -1877,11 +2029,6 @@ bot.on('room-invite', async roomInvitation => { } .start() ``` - - -### roomInvitation.roomTopic() -**Kind**: instance method of [RoomInvitation](#RoomInvitation) -**Deprecated:**: use topic() instead ### roomInvitation.date() ⇒ Promise.<Date> @@ -1898,6 +2045,35 @@ and when we received it in Wechaty, the time is `8:43:15`, then the age() will return `8:43:15 - 8:43:01 = 14 (seconds)` **Kind**: instance method of [RoomInvitation](#RoomInvitation) + + +### roomInvitation.toJSON() ⇒ string +Get the room invitation info when listened on room-invite event + +**Kind**: instance method of [RoomInvitation](#RoomInvitation) +**Example** +```js +const bot = new Wechaty() +bot.on('room-invite', async roomInvitation => { + const roomInvitation = bot.RoomInvitation.load(roomInvitation.id) + const jsonData = await roomInvitation.toJSON(roomInvitation.id) + // save the json data to disk, and we can use it by RoomInvitation.fromJSON() +} +.start() +``` + + +### RoomInvitation.fromJSON() ⇒ [RoomInvitation](#RoomInvitation) +Load the room invitation info from disk + +**Kind**: static method of [RoomInvitation](#RoomInvitation) +**Example** +```js +const bot = new Wechaty() +const dataFromDisk // get the room invitation info data from disk +const roomInvitation = await bot.RoomInvitation.fromJSON(dataFromDisk) +await roomInvitation.accept() +``` ## PuppetModuleName From ca96b14718233cfe428c90f37a76f429e3abb59c Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 25 Mar 2020 01:08:43 +0800 Subject: [PATCH 071/598] 0.37.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e57d770c6..44e9028bc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.37.4", + "version": "0.37.5", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 220a98f0b31bc58a2466c73aabb8aac84703a6ae Mon Sep 17 00:00:00 2001 From: Huan LI Date: Fri, 27 Mar 2020 02:13:21 +0800 Subject: [PATCH 072/598] ci from blue to green --- README.md | 2 +- docs/images/bot-qr-code.png | Bin 150356 -> 132169 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 37ada6b99..496a3da16 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Wechaty [![NPM Version](https://badge.fury.io/js/wechaty.svg)](https://www.npmjs.com/package/wechaty) [![NPM](https://github.com/wechaty/wechaty/workflows/NPM/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ANPM) [![Docker](https://github.com/wechaty/wechaty/workflows/Docker/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ADocker) -[![Wechaty](https://wechaty.github.io/wechaty/images/wechaty-logo-en.png)](https://github.com/wechaty/wechaty) +[![Wechaty](https://wechaty.github.io/wechaty/images/wechaty-logo-green-en.png)](https://github.com/wechaty/wechaty) [![Downloads](https://img.shields.io/npm/dm/wechaty.svg?style=flat-square)](https://www.npmjs.com/package/wechaty) [![GitHub stars](https://img.shields.io/github/stars/wechaty/wechaty.svg?label=github%20stars)](https://github.com/wechaty/wechaty) diff --git a/docs/images/bot-qr-code.png b/docs/images/bot-qr-code.png index a2afcc724ff3dea32c1473691be82646ae401060..4983427041bd9ba44088920f7cc7bc2159a79b34 100644 GIT binary patch literal 132169 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/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ⅈLLle69zFS} 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 _o+<=sTzX}TSi)Z_azE5&2s5l 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�VBVujr4W3nKV5!LFB9xag2Tp^xop$=XHHt5l0n^ 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

ybI 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 WvEp7l2>MI$x_Hj{Z1I^}5C1=pLR`oI From fbaec071d3e996f704ec0ea9721d83d3421d21d9 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Fri, 27 Mar 2020 02:13:37 +0800 Subject: [PATCH 073/598] 0.37.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 44e9028bc..45a519174 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.37.5", + "version": "0.37.6", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From fe9b53117a0ea772e82748f25ff16cd1400fccd9 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sun, 29 Mar 2020 00:06:55 +0800 Subject: [PATCH 074/598] add gitter chat badge --- docs/index.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/index.md b/docs/index.md index fe87a1b8c..9b8df6e43 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2222,3 +2222,9 @@ The way to search Contact | name | string | The name-string set by user-self, should be called name | | alias | string | The name-string set by bot for others, should be called alias [More Detail](https://github.com/wechaty/wechaty/issues/365) | + + From 4d48647c9b8bfb80baf0b547e056f0653ea279fa Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sun, 29 Mar 2020 00:07:11 +0800 Subject: [PATCH 075/598] 0.37.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 45a519174..ab920f5cf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.37.6", + "version": "0.37.7", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From b70ff20b5c36080466ce2732350d48bc3b9c8c7e Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sun, 29 Mar 2020 00:14:37 +0800 Subject: [PATCH 076/598] add Gitter.im Sidecar --- docs/index.md | 5 ++--- scripts/generate-docs.sh | 29 +++++++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/docs/index.md b/docs/index.md index 9b8df6e43..76295494e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,8 +1,7 @@ -# Wechaty v0.37.4 Documentation +# Wechaty v0.37.7 Documentation - Blog - -- Docs - - +- Docs - ## Classes diff --git a/scripts/generate-docs.sh b/scripts/generate-docs.sh index 53f55aa09..ea9a6dec7 100755 --- a/scripts/generate-docs.sh +++ b/scripts/generate-docs.sh @@ -17,5 +17,30 @@ fi echo "Generating docs ..." npm run dist -echo -e '# Wechaty v'"$(jq -r .version package.json)"' Documentation\n\n- Blog - \n- Docs - \n\n' > docs/index.md -jsdoc2md dist/src/wechaty.js dist/src/user/{room,contact,contact-self,friendship,message,room-invitation}.js >> docs/index.md + +DOCS_INDEX_MD=docs/index.md + +cat <<_EOF_ > "$DOCS_INDEX_MD" +# Wechaty v$(jq -r .version package.json) Documentation + +- Blog - +- Docs - + +_EOF_ + +jsdoc2md \ + dist/src/wechaty.js \ + dist/src/user/{room,contact,contact-self,friendship,message,room-invitation}.js \ + >> "$DOCS_INDEX_MD" + +# +# https://sidecar.gitter.im/ +# +cat <<_EOF_ >> "$DOCS_INDEX_MD" + + +_EOF_ From 731a1e7b03de4aca89ed4c5443f8d9e2eeeaf670 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sun, 29 Mar 2020 00:14:53 +0800 Subject: [PATCH 077/598] 0.37.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ab920f5cf..8144da2aa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.37.7", + "version": "0.37.8", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 235407c06bde4bd449c0d5f3b7beb87dc161a8ec Mon Sep 17 00:00:00 2001 From: Huan LI Date: Thu, 2 Apr 2020 12:37:21 +0800 Subject: [PATCH 078/598] add npm funding --- package.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/package.json b/package.json index 8144da2aa..39cbf714b 100644 --- a/package.json +++ b/package.json @@ -74,6 +74,10 @@ "bugs": { "url": "https://github.com/wechaty/wechaty/issues" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/wechaty" + }, "homepage": "https://github.com/wechaty/", "engines": { "node": ">= 10" From 97b8a8d13efe46a41585634056ecd4c5da58173c Mon Sep 17 00:00:00 2001 From: Huan LI Date: Thu, 2 Apr 2020 12:37:37 +0800 Subject: [PATCH 079/598] 0.37.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 39cbf714b..a12a205bc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.37.8", + "version": "0.37.9", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From bb1943ebeea15b781b1a540198bdbb933931529c Mon Sep 17 00:00:00 2001 From: Huan LI Date: Thu, 2 Apr 2020 12:38:17 +0800 Subject: [PATCH 080/598] Upgrade puppet abstraction --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a12a205bc..22c6781b4 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "read-pkg-up": "^7.0.1", "state-switch": "^0.7.2", "watchdog": "^0.8.17", - "wechaty-puppet": "^0.23.2", + "wechaty-puppet": "^0.23.6", "wechaty-puppet-hostie": "^0.5.1", "ws": "^7.2.3" }, From ef7ac7b4375b1c89fa6d2b2f139df17a0d64f38a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 4 Apr 2020 21:34:10 +0800 Subject: [PATCH 081/598] BotOrange -> Juzi.BOT --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 496a3da16..1f8967a7b 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Wechaty is a Bot SDK for Wechat **Individual** Account which can help you create > — @Jarvis, Baidu Engineer > > "Wechaty让运营人员更多的时间思考如何进行活动策划、留存用户,商业变现" [link](http://mp.weixin.qq.com/s/dWHAj8XtiKG-1fIS5Og79g) -> — @lijiarui, CEO of BotOrange. +> — @lijiarui, CEO of Juzi.BOT. > > "If you know js ... try Wechaty, it's easy to use." > — @Urinx Uri Lee, Author of [WeixinBot(Python)](https://github.com/Urinx/WeixinBot) From 20133b2d712d8f597e1871e74fb875cb233dcece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 4 Apr 2020 21:36:39 +0800 Subject: [PATCH 082/598] Tencent TVP of Chatbot --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1f8967a7b..0543cefbe 100644 --- a/README.md +++ b/README.md @@ -407,7 +407,7 @@ Support this project by becoming a sponsor. Your logo will show up here with a l ## Author -1. [Huan](https://github.com/huan) [(李卓桓)](http://linkedin.com/in/zixia) \ +1. [Huan](https://github.com/huan) [(李卓桓)](http://linkedin.com/in/zixia) [Tencent TVP of Chatbot](https://cloud.tencent.com/tvp/138) \ 1. [Rui (李佳芮)](https://pre-angel.com/peoples/jiarui-li/) [![Profile of Huan LI (李卓桓) on StackOverflow](https://stackoverflow.com/users/flair/1123955.png)](https://stackoverflow.com/users/1123955/huan) From 21249b09a13d9a37e4d8f8804b8af2259484e9e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 4 Apr 2020 21:46:34 +0800 Subject: [PATCH 083/598] improve readability --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0543cefbe..3fcfea634 100644 --- a/README.md +++ b/README.md @@ -407,7 +407,7 @@ Support this project by becoming a sponsor. Your logo will show up here with a l ## Author -1. [Huan](https://github.com/huan) [(李卓桓)](http://linkedin.com/in/zixia) [Tencent TVP of Chatbot](https://cloud.tencent.com/tvp/138) \ +1. [Huan](https://github.com/huan) [(李卓桓)](http://linkedin.com/in/zixia), [Tencent TVP of Chatbot](https://cloud.tencent.com/tvp/138), \ 1. [Rui (李佳芮)](https://pre-angel.com/peoples/jiarui-li/) [![Profile of Huan LI (李卓桓) on StackOverflow](https://stackoverflow.com/users/flair/1123955.png)](https://stackoverflow.com/users/1123955/huan) From 12c1e2eb5b8eee6fdf81fa2cf4977f784133ff47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 4 Apr 2020 21:57:48 +0800 Subject: [PATCH 084/598] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3fcfea634..450654b1a 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Wechaty is a Bot SDK for Wechat **Individual** Account which can help you create > — @Jarvis, Baidu Engineer > > "Wechaty让运营人员更多的时间思考如何进行活动策划、留存用户,商业变现" [link](http://mp.weixin.qq.com/s/dWHAj8XtiKG-1fIS5Og79g) -> — @lijiarui, CEO of Juzi.BOT. +> — @lijiarui, Founder & CEO of Juzi.BOT. > > "If you know js ... try Wechaty, it's easy to use." > — @Urinx Uri Lee, Author of [WeixinBot(Python)](https://github.com/Urinx/WeixinBot) From d44fe4cc1a53aa994ffd861f301b81be8d106c3d Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sun, 5 Apr 2020 02:39:24 +0800 Subject: [PATCH 085/598] add talker() and conversation() to Message class --- src/user/message.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/user/message.ts b/src/user/message.ts index 08306c463..bdd13f6e3 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -241,6 +241,18 @@ export class Message extends Accessory implements Sayable { return msgStrList.join('') } + public talker (): Contact { + return this.from()! + } + + public conversation (): Contact | Room { + if (this.room()) { + return this.room()! + } else { + return this.from()! + } + } + /** * Get the sender from a message. * @returns {Contact} From a6bd0047fd98681a9073c8e473dd70d262f76f1d Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sun, 5 Apr 2020 02:39:40 +0800 Subject: [PATCH 086/598] 0.37.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 22c6781b4..4e69605f9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.37.9", + "version": "0.37.10", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 5e81c06fac283299af8f4ebd6dc800cb9bb39c68 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sun, 5 Apr 2020 02:40:09 +0800 Subject: [PATCH 087/598] 0.37.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4e69605f9..27e2f0608 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.37.10", + "version": "0.37.11", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From d2b12262184a4a281f9b31d8f7f0f4ca60a4cbff Mon Sep 17 00:00:00 2001 From: Huan LI Date: Mon, 6 Apr 2020 20:45:42 +0800 Subject: [PATCH 088/598] fix wechat4u --- src/puppet-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index ef4707428..07cfd5bf3 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -20,7 +20,7 @@ export const PUPPET_DEPENDENCIES = { */ 'wechaty-puppet-padplus' : '^0.5.24', // https://www.npmjs.com/package/wechaty-puppet-padplus 'wechaty-puppet-puppeteer' : '^0.21.2', // https://www.npmjs.com/package/wechaty-puppet-puppeteer - 'wechaty-puppet-wechat4u' : '^0.17.2', // https://www.npmjs.com/package/wechaty-puppet-wechat4u + 'wechaty-puppet-wechat4u' : '^0.17.4', // https://www.npmjs.com/package/wechaty-puppet-wechat4u } export type PuppetModuleName = keyof typeof PUPPET_DEPENDENCIES From 5601d33b77c986004c4c6fba78c2405c19c036e0 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Mon, 6 Apr 2020 20:45:59 +0800 Subject: [PATCH 089/598] 0.37.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 27e2f0608..f8720a108 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.37.11", + "version": "0.37.12", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From c36e8f32764ce4b486b9f251f7645f1c9f61a273 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Mon, 6 Apr 2020 21:21:21 +0800 Subject: [PATCH 090/598] 0.37.13 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f8720a108..73f1c8209 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.37.12", + "version": "0.37.13", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 77aada3b26f9a68e8f3fb3c06360ebaecdcff977 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Tue, 7 Apr 2020 18:02:33 +0800 Subject: [PATCH 091/598] expose state from puppet --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 73f1c8209..e0764ad60 100644 --- a/package.json +++ b/package.json @@ -99,8 +99,8 @@ "read-pkg-up": "^7.0.1", "state-switch": "^0.7.2", "watchdog": "^0.8.17", - "wechaty-puppet": "^0.23.6", - "wechaty-puppet-hostie": "^0.5.1", + "wechaty-puppet": "^0.23.9", + "wechaty-puppet-hostie": "^0.5.7", "ws": "^7.2.3" }, "devDependencies": { From ec18167a0fa3d50c8214057477a0eefe97d71e79 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 8 Apr 2020 00:45:15 +0800 Subject: [PATCH 092/598] Auto reconnect for hostie --- package.json | 2 +- src/puppet-config.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index e0764ad60..b68cd5bb8 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "state-switch": "^0.7.2", "watchdog": "^0.8.17", "wechaty-puppet": "^0.23.9", - "wechaty-puppet-hostie": "^0.5.7", + "wechaty-puppet-hostie": "^0.5.10", "ws": "^7.2.3" }, "devDependencies": { diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 07cfd5bf3..f9b89ad78 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -12,7 +12,7 @@ export const PUPPET_DEPENDENCIES = { /** * Wechaty Internal Puppets: dependenced by package.json */ - 'wechaty-puppet-hostie' : '^0.5.1', // https://www.npmjs.com/package/wechaty-puppet-hostie + 'wechaty-puppet-hostie' : '^0.5.10', // https://www.npmjs.com/package/wechaty-puppet-hostie 'wechaty-puppet-mock' : '^0.19.0', // https://www.npmjs.com/package/wechaty-puppet-mock /** From 67fe813bf85074123ea2a46fbf266197e5215a47 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 8 Apr 2020 00:45:32 +0800 Subject: [PATCH 093/598] 0.37.14 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b68cd5bb8..b0d4d21fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.37.13", + "version": "0.37.14", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 659ed6acead6892cf6d3c5348b909d9ca2ce289e Mon Sep 17 00:00:00 2001 From: SuperChang Date: Wed, 8 Apr 2020 17:48:15 +0800 Subject: [PATCH 094/598] 0.38.0 (#1936) * 0.38.0 * modify: bump wechaty-puppet to even version --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b0d4d21fb..b35bd599c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.37.14", + "version": "0.38.0", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", @@ -99,7 +99,7 @@ "read-pkg-up": "^7.0.1", "state-switch": "^0.7.2", "watchdog": "^0.8.17", - "wechaty-puppet": "^0.23.9", + "wechaty-puppet": "^0.24.0", "wechaty-puppet-hostie": "^0.5.10", "ws": "^7.2.3" }, From 01d6841b76020cdb31535ad9541131df1b52c8ab Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 8 Apr 2020 21:58:28 +0800 Subject: [PATCH 095/598] upgrade state-switch to support rxjs --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b35bd599c..734c7572e 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "promise-retry": "^1.1.1", "raven": "^2.6.4", "read-pkg-up": "^7.0.1", - "state-switch": "^0.7.2", + "state-switch": "^0.9.9", "watchdog": "^0.8.17", "wechaty-puppet": "^0.24.0", "wechaty-puppet-hostie": "^0.5.10", From df37cf31b4c9ed7f6ae0e60c269596dffc85490b Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 8 Apr 2020 21:58:46 +0800 Subject: [PATCH 096/598] 0.38.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 734c7572e..2ae279172 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.38.0", + "version": "0.38.1", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From b6f624eb587e4fa408a69b21a788f3667e613a54 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 8 Apr 2020 23:01:54 +0800 Subject: [PATCH 097/598] 0.20.2 for mock --- package.json | 4 ++-- src/io-client.ts | 10 +++++----- src/io.ts | 2 +- src/puppet-config.ts | 4 ++-- src/wechaty.ts | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 2ae279172..6150333ea 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "state-switch": "^0.9.9", "watchdog": "^0.8.17", "wechaty-puppet": "^0.24.0", - "wechaty-puppet-hostie": "^0.5.10", + "wechaty-puppet-hostie": "^0.6.1", "ws": "^7.2.3" }, "devDependencies": { @@ -133,7 +133,7 @@ "sloc": "^0.2.1", "tstest": "^0.4.10", "typedoc": "^0.16.11", - "wechaty-puppet-mock": "^0.19.0" + "wechaty-puppet-mock": "^0.20.2" }, "files_comment__whitelist_npm_publish": "http://stackoverflow.com/a/8617868/1123955", "files": [ diff --git a/src/io-client.ts b/src/io-client.ts index 65135663a..940c6b02f 100644 --- a/src/io-client.ts +++ b/src/io-client.ts @@ -58,7 +58,7 @@ export class IoClient { options.token ) - this.state = new StateSwitch('IoClient', log) + this.state = new StateSwitch('IoClient', { log }) } private async startHostie () { @@ -91,10 +91,10 @@ export class IoClient { public async start (): Promise { log.verbose('IoClient', 'start()') - if (this.state.pending()) { - log.warn('IoClient', 'start() with a pending state, not the time') - const e = new Error('state.pending() when start()') - throw e + if (this.state.on()) { + log.warn('IoClient', 'start() with a on state, wait and return') + await this.state.ready('on') + return } this.state.on('pending') diff --git a/src/io.ts b/src/io.ts index 85df4997c..758a9bf5f 100644 --- a/src/io.ts +++ b/src/io.ts @@ -81,7 +81,7 @@ export class Io { private eventBuffer : IoEvent[] = [] private ws : undefined | WebSocket - private readonly state = new StateSwitch('Io', log) + private readonly state = new StateSwitch('Io', { log }) private reconnectTimer? : NodeJS.Timer private reconnectTimeout? : number diff --git a/src/puppet-config.ts b/src/puppet-config.ts index f9b89ad78..4e14a8cd7 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -12,8 +12,8 @@ export const PUPPET_DEPENDENCIES = { /** * Wechaty Internal Puppets: dependenced by package.json */ - 'wechaty-puppet-hostie' : '^0.5.10', // https://www.npmjs.com/package/wechaty-puppet-hostie - 'wechaty-puppet-mock' : '^0.19.0', // https://www.npmjs.com/package/wechaty-puppet-mock + 'wechaty-puppet-hostie' : '^0.6.1', // https://www.npmjs.com/package/wechaty-puppet-hostie + 'wechaty-puppet-mock' : '^0.20.2', // https://www.npmjs.com/package/wechaty-puppet-mock /** * Wechaty External Puppets diff --git a/src/wechaty.ts b/src/wechaty.ts index 946dd3ebf..08b6eef85 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -258,8 +258,8 @@ export class Wechaty extends EventEmitter implements Sayable { this.id = cuid() - this.state = new StateSwitch('Wechaty', log) - this.readyState = new StateSwitch('WechatyReady', log) + this.state = new StateSwitch('Wechaty', { log }) + this.readyState = new StateSwitch('WechatyReady', { log }) /** * @ignore From a7ae6059e9bb6bfe442803f67fa41eb194568350 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 8 Apr 2020 23:13:41 +0800 Subject: [PATCH 098/598] upgrade puppets --- package.json | 2 +- src/puppet-config.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 6150333ea..03c797243 100644 --- a/package.json +++ b/package.json @@ -133,7 +133,7 @@ "sloc": "^0.2.1", "tstest": "^0.4.10", "typedoc": "^0.16.11", - "wechaty-puppet-mock": "^0.20.2" + "wechaty-puppet-mock": "^0.20.4" }, "files_comment__whitelist_npm_publish": "http://stackoverflow.com/a/8617868/1123955", "files": [ diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 4e14a8cd7..b4cc23169 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -13,7 +13,7 @@ export const PUPPET_DEPENDENCIES = { * Wechaty Internal Puppets: dependenced by package.json */ 'wechaty-puppet-hostie' : '^0.6.1', // https://www.npmjs.com/package/wechaty-puppet-hostie - 'wechaty-puppet-mock' : '^0.20.2', // https://www.npmjs.com/package/wechaty-puppet-mock + 'wechaty-puppet-mock' : '^0.20.4', // https://www.npmjs.com/package/wechaty-puppet-mock /** * Wechaty External Puppets From 9a539ff4834b892382b9d1295207d5cb0fbe5ae2 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 8 Apr 2020 23:15:00 +0800 Subject: [PATCH 099/598] 0.38.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 03c797243..0e1b9cfdc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.38.1", + "version": "0.38.2", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From dec7b0c1002507b1556bf18b18899c59e90ef5c1 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Thu, 9 Apr 2020 03:29:19 +0800 Subject: [PATCH 100/598] stable padplus --- src/puppet-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index b4cc23169..b3a2097d2 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -18,7 +18,7 @@ export const PUPPET_DEPENDENCIES = { /** * Wechaty External Puppets */ - 'wechaty-puppet-padplus' : '^0.5.24', // https://www.npmjs.com/package/wechaty-puppet-padplus + 'wechaty-puppet-padplus' : '^0.6.1', // https://www.npmjs.com/package/wechaty-puppet-padplus 'wechaty-puppet-puppeteer' : '^0.21.2', // https://www.npmjs.com/package/wechaty-puppet-puppeteer 'wechaty-puppet-wechat4u' : '^0.17.4', // https://www.npmjs.com/package/wechaty-puppet-wechat4u } From 5495115a5b59c30be9261dcbb6680501f9689f4e Mon Sep 17 00:00:00 2001 From: Huan LI Date: Thu, 9 Apr 2020 03:29:35 +0800 Subject: [PATCH 101/598] 0.38.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0e1b9cfdc..bc0f21380 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.38.2", + "version": "0.38.3", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From ce6ed39cc60086f922ef138547da340a7e9e8a8b Mon Sep 17 00:00:00 2001 From: Huan LI Date: Thu, 9 Apr 2020 03:43:36 +0800 Subject: [PATCH 102/598] Downgrade to node v10 (#https://github.com/wechaty/wechaty-puppet-padplus/pull/200) --- .github/workflows/npm.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index 33bd0f0b2..1f758de51 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: os: [macos-latest, windows-latest, ubuntu-latest] - node: [13] + node: [10] runs-on: ${{ matrix.os }} steps: @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-node@v1 with: - node-version: 13 + node-version: 10 - run: npm install - run: ./scripts/generate-version.sh - run: ./scripts/npm-pack-testing.sh @@ -48,7 +48,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-node@v1 with: - node-version: 13 + node-version: 10 registry-url: https://registry.npmjs.org/ - run: npm install - run: ./scripts/generate-version.sh From a63049e0816ec1a8977520793e05f0239af414a9 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Thu, 9 Apr 2020 03:43:52 +0800 Subject: [PATCH 103/598] 0.38.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bc0f21380..5196d8233 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.38.3", + "version": "0.38.4", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From f99eae5f5ce12eb258796e380462e545eec469ec Mon Sep 17 00:00:00 2001 From: Huan LI Date: Fri, 10 Apr 2020 13:56:05 +0800 Subject: [PATCH 104/598] add copyright doc --- scripts/sort-contributiveness.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/scripts/sort-contributiveness.ts b/scripts/sort-contributiveness.ts index 6726a5ad5..2dfa639d1 100755 --- a/scripts/sort-contributiveness.ts +++ b/scripts/sort-contributiveness.ts @@ -1,5 +1,22 @@ #!/usr/bin/env ts-node - +/** + * Wechaty - https://github.com/wechaty/wechaty + * + * @copyright 2016-now Huan LI + * + * 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. + * + */ import * as readline from 'readline' const contributeMap: { From 4a0a5572da7c0462f36f3ef2b7617949c9bddd67 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Fri, 10 Apr 2020 16:31:51 +0800 Subject: [PATCH 105/598] upgrade wechaty-puppet@0.25 & hostie / mock to next version --- package.json | 4 ++-- src/puppet-config.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 5196d8233..26dee340a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.38.4", + "version": "0.39.0", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", @@ -99,7 +99,7 @@ "read-pkg-up": "^7.0.1", "state-switch": "^0.9.9", "watchdog": "^0.8.17", - "wechaty-puppet": "^0.24.0", + "wechaty-puppet": "^0.25.1", "wechaty-puppet-hostie": "^0.6.1", "ws": "^7.2.3" }, diff --git a/src/puppet-config.ts b/src/puppet-config.ts index b3a2097d2..d97f1ac09 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -12,8 +12,8 @@ export const PUPPET_DEPENDENCIES = { /** * Wechaty Internal Puppets: dependenced by package.json */ - 'wechaty-puppet-hostie' : '^0.6.1', // https://www.npmjs.com/package/wechaty-puppet-hostie - 'wechaty-puppet-mock' : '^0.20.4', // https://www.npmjs.com/package/wechaty-puppet-mock + 'wechaty-puppet-hostie' : '^0.7.1', // https://www.npmjs.com/package/wechaty-puppet-hostie + 'wechaty-puppet-mock' : '^0.21.1', // https://www.npmjs.com/package/wechaty-puppet-mock /** * Wechaty External Puppets From 4447b988edfdf9db401c6e085d25f461b21d39ae Mon Sep 17 00:00:00 2001 From: Huan LI Date: Fri, 10 Apr 2020 16:32:20 +0800 Subject: [PATCH 106/598] 0.39.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 26dee340a..1c9c8a6bf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.0", + "version": "0.39.1", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 38438255b479966172b92376e42637c7234b7591 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Mon, 13 Apr 2020 01:18:38 +0800 Subject: [PATCH 107/598] doc --- src/wechaty.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/wechaty.ts b/src/wechaty.ts index 08b6eef85..59631f2cc 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -753,6 +753,7 @@ export class Wechaty extends EventEmitter implements Sayable { break case 'reset': + // Do not propagation `reset` event from puppet break default: From 87262c394fb0e4c2b8955bbe451a11966e995a42 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 15 Apr 2020 17:50:11 +0800 Subject: [PATCH 108/598] add support for wechaty-puppet-donut for alpha testing (#1941) --- src/puppet-config.ts | 5 +++++ src/puppet-manager.ts | 11 +++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index d97f1ac09..f10d71366 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -9,6 +9,11 @@ export const PUPPET_DEPENDENCIES = { // 'wechaty-puppet-padchat' : '^0.19.3', // https://www.npmjs.com/package/wechaty-puppet-padchat // 'wechaty-puppet-padpro' : '^0.3.21', // https://www.npmjs.com/package/wechaty-puppet-padpro + /** + * Scoped puppets + */ + '@juzibot/wechaty-puppet-donut': '^0.0.23', // https://www.npmjs.com/package/wechaty-puppet-donut (to be published) + /** * Wechaty Internal Puppets: dependenced by package.json */ diff --git a/src/puppet-manager.ts b/src/puppet-manager.ts index 14a20fbe8..9a175dc2c 100644 --- a/src/puppet-manager.ts +++ b/src/puppet-manager.ts @@ -233,13 +233,20 @@ export class PuppetManager { public static async installAll (): Promise { log.info('PuppetManager', 'installAll() please wait ...') + const skipList = [ + '@juzibot/wechaty-puppet-donut', // windows puppet + ] + const moduleList: string[] = [] for (const puppetModuleName of Object.keys(PUPPET_DEPENDENCIES)) { const version = PUPPET_DEPENDENCIES[puppetModuleName as PuppetModuleName] - if (version !== '0.0.0') { - moduleList.push(`${puppetModuleName}@${version}`) + + if (version === '0.0.0' || skipList.includes(puppetModuleName)) { + continue } + + moduleList.push(`${puppetModuleName}@${version}`) } await npm.install( From 0feebe2e06570cb5e3dd3aee6ba3becccb09c734 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 15 Apr 2020 17:58:48 +0800 Subject: [PATCH 109/598] 0.39.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1c9c8a6bf..fc1ad90dd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.1", + "version": "0.39.2", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From a820c7ac798fd40bef1075c561583a80051fa205 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 15 Apr 2020 18:04:07 +0800 Subject: [PATCH 110/598] update version for puppets --- package.json | 4 ++-- src/puppet-config.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index fc1ad90dd..88f8b83bf 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "state-switch": "^0.9.9", "watchdog": "^0.8.17", "wechaty-puppet": "^0.25.1", - "wechaty-puppet-hostie": "^0.6.1", + "wechaty-puppet-hostie": "^0.7.1", "ws": "^7.2.3" }, "devDependencies": { @@ -133,7 +133,7 @@ "sloc": "^0.2.1", "tstest": "^0.4.10", "typedoc": "^0.16.11", - "wechaty-puppet-mock": "^0.20.4" + "wechaty-puppet-mock": "^0.21.2" }, "files_comment__whitelist_npm_publish": "http://stackoverflow.com/a/8617868/1123955", "files": [ diff --git a/src/puppet-config.ts b/src/puppet-config.ts index f10d71366..5c3584b67 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -18,7 +18,7 @@ export const PUPPET_DEPENDENCIES = { * Wechaty Internal Puppets: dependenced by package.json */ 'wechaty-puppet-hostie' : '^0.7.1', // https://www.npmjs.com/package/wechaty-puppet-hostie - 'wechaty-puppet-mock' : '^0.21.1', // https://www.npmjs.com/package/wechaty-puppet-mock + 'wechaty-puppet-mock' : '^0.21.2', // https://www.npmjs.com/package/wechaty-puppet-mock /** * Wechaty External Puppets From 64c7147f5fb6e4d63e6bbf045c508bbc50b322bf Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 15 Apr 2020 18:04:23 +0800 Subject: [PATCH 111/598] 0.39.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 88f8b83bf..835f20137 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.2", + "version": "0.39.3", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From f8345e1f6a6e55aa5d425d7a60c105f5a4cc5011 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 15 Apr 2020 18:23:34 +0800 Subject: [PATCH 112/598] use Node 10 for compatible with padplus --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 124d8c79d..e7ec9916a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,7 +37,7 @@ RUN apt-get update \ && apt-get purge --auto-remove \ && rm -rf /tmp/* /var/lib/apt/lists/* -RUN curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - \ +RUN curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash - \ && apt-get update && apt-get install -y --no-install-recommends nodejs \ && apt-get purge --auto-remove \ && rm -rf /tmp/* /var/lib/apt/lists/* From e47953931b97a9fc5ac61b9d0145cf1c91fe0dab Mon Sep 17 00:00:00 2001 From: Huan LI Date: Wed, 15 Apr 2020 18:23:51 +0800 Subject: [PATCH 113/598] 0.39.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 835f20137..5cd0aa966 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.3", + "version": "0.39.4", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 75dce0aa13a0c180389292c50115bb279bdcd62d Mon Sep 17 00:00:00 2001 From: Huan LI Date: Thu, 16 Apr 2020 00:23:37 +0800 Subject: [PATCH 114/598] fix windows --- src/puppet-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 5c3584b67..9a818402d 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -12,7 +12,7 @@ export const PUPPET_DEPENDENCIES = { /** * Scoped puppets */ - '@juzibot/wechaty-puppet-donut': '^0.0.23', // https://www.npmjs.com/package/wechaty-puppet-donut (to be published) + '@juzibot/wechaty-puppet-donut': '^0.0.21', // https://www.npmjs.com/package/wechaty-puppet-donut (to be published) /** * Wechaty Internal Puppets: dependenced by package.json From 19ea3d964a4e27ec6eb3256b28793afcc5bb7e44 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Thu, 16 Apr 2020 00:23:54 +0800 Subject: [PATCH 115/598] 0.39.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5cd0aa966..c83c870d3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.4", + "version": "0.39.5", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 138712c605d6b9c94d6d5b7dda6c221a4fa669f0 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 18 Apr 2020 12:58:29 +0800 Subject: [PATCH 116/598] upgrade to latest donut with new flash-store with stable leveldb --- src/puppet-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 9a818402d..cd0c58ac6 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -12,7 +12,7 @@ export const PUPPET_DEPENDENCIES = { /** * Scoped puppets */ - '@juzibot/wechaty-puppet-donut': '^0.0.21', // https://www.npmjs.com/package/wechaty-puppet-donut (to be published) + '@juzibot/wechaty-puppet-donut': '^0.0.26', // https://www.npmjs.com/package/wechaty-puppet-donut (to be published) /** * Wechaty Internal Puppets: dependenced by package.json From 7c283437b1ccd3e3b998379605d9bbf4ac0b7803 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 18 Apr 2020 12:59:53 +0800 Subject: [PATCH 117/598] rename zixia to huan --- AUTHORS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index ac177a78f..912d5639a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,2 +1,2 @@ -Huan https://github.com/zixia +Huan https://github.com/huan Rui https://github.com/lijiarui From 9bcce0067e4ec020a8188efc0dc1549652edc6dc Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 18 Apr 2020 13:01:02 +0800 Subject: [PATCH 118/598] rename zixia to huan --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 54d42d33e..47a59208c 100644 --- a/.gitignore +++ b/.gitignore @@ -57,7 +57,7 @@ yarn.lock .yarn-cache/ .v8flags.* -# why? forgot... 2017-05-18 by zixia +# why? forgot... 2017-05-18 by huan /tests/fixtures/docker/package.json tags From 95cf35e44cdc09783c6e077bcc0a9619b1309ec8 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 18 Apr 2020 13:01:24 +0800 Subject: [PATCH 119/598] 0.39.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c83c870d3..c3a9e0db5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.5", + "version": "0.39.6", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 2199309cb4ee021479952e2603aafce0957a05ec Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 18 Apr 2020 13:11:45 +0800 Subject: [PATCH 120/598] use separate action to cover all node versions --- .github/workflows/node.js.yml | 30 ++++++++++++++++++++++++++++++ .github/workflows/npm.yml | 15 +++++---------- 2 files changed, 35 insertions(+), 10 deletions(-) create mode 100644 .github/workflows/node.js.yml diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml new file mode 100644 index 000000000..b7357b001 --- /dev/null +++ b/.github/workflows/node.js.yml @@ -0,0 +1,30 @@ +# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions + +name: Node.js CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + strategy: + matrix: + os: [macos-latest, windows-latest, ubuntu-latest] + node-version: [10.x, 11.x, 12.x, 13.x] + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - run: npm install + - run: npm run build --if-present + - run: npm test + env: + CI: true diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index 1f758de51..ad958f485 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -5,18 +5,13 @@ on: [push, pull_request] jobs: build: name: Build - strategy: - matrix: - os: [macos-latest, windows-latest, ubuntu-latest] - node: [10] - - runs-on: ${{ matrix.os }} + runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: Use Node.js ${{ matrix.node-version }} + - name: Use Node.js 12 uses: actions/setup-node@v1 with: - node-version: ${{ matrix.node-version }} + node-version: 12 - name: Install Dependencies run: npm install @@ -32,7 +27,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-node@v1 with: - node-version: 10 + node-version: 12 - run: npm install - run: ./scripts/generate-version.sh - run: ./scripts/npm-pack-testing.sh @@ -48,7 +43,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-node@v1 with: - node-version: 10 + node-version: 12 registry-url: https://registry.npmjs.org/ - run: npm install - run: ./scripts/generate-version.sh From a505e148ad42228150c2c3ace49fc4a04344f9be Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 18 Apr 2020 13:12:58 +0800 Subject: [PATCH 121/598] 0.39.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c3a9e0db5..a0884edf3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.6", + "version": "0.39.7", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 9500c2ecb1c3649829af217ba41ccab425610c63 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 18 Apr 2020 13:16:55 +0800 Subject: [PATCH 122/598] 0.39.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a0884edf3..d13a32da5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.7", + "version": "0.39.8", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 3dc8eb7b55b40c40a34393743a71ee6af1d823d1 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 18 Apr 2020 13:50:13 +0800 Subject: [PATCH 123/598] clean badge for npm version --- README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 450654b1a..72821a44f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,8 @@ -# Wechaty [![NPM Version](https://badge.fury.io/js/wechaty.svg)](https://www.npmjs.com/package/wechaty) [![NPM](https://github.com/wechaty/wechaty/workflows/NPM/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ANPM) [![Docker](https://github.com/wechaty/wechaty/workflows/Docker/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ADocker) +# Wechaty [![NPM Version](https://img.shields.io/npm/v/wechaty?color=brightgreen&label=wechaty%40latest)](https://www.npmjs.com/package/wechaty) + +[![NPM](https://github.com/wechaty/wechaty/workflows/NPM/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ANPM) +[![Docker](https://github.com/wechaty/wechaty/workflows/Docker/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ADocker) +[![Node.js CI](https://github.com/wechaty/wechaty/workflows/Node.js%20CI/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3A%22Node.js+CI%22) [![Wechaty](https://wechaty.github.io/wechaty/images/wechaty-logo-green-en.png)](https://github.com/wechaty/wechaty) @@ -82,8 +86,10 @@ Otherwise, please saved the above _The World's Shortest ChatBot Code: 6 lines of ### 1. Npm -[![NPM Version](https://badge.fury.io/js/wechaty.svg)](https://www.npmjs.com/package/wechaty) -[![npm (tag)](https://img.shields.io/npm/v/wechaty/next.svg)](https://www.npmjs.com/package/wechaty?activeTab=versions) +[![NPM Version](https://img.shields.io/npm/v/wechaty?color=brightgreen&label=wechaty%40latest)](https://www.npmjs.com/package/wechaty) +[![npm (tag)](https://img.shields.io/npm/v/wechaty/next?color=yellow&label=wechaty%40next)](https://www.npmjs.com/package/wechaty?activeTab=versions) + + [![Downloads](https://img.shields.io/npm/dm/wechaty.svg?style=flat-square)](https://www.npmjs.com/package/wechaty) [![install size](https://packagephobia.now.sh/badge?p=wechaty)](https://packagephobia.now.sh/result?p=wechaty) From fc69769f50ca03a7407b1e073324a4eb530a5be8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 20 Apr 2020 05:51:21 +0000 Subject: [PATCH 124/598] CHANGELOG v0.38 --- CHANGELOG.md | 64 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5beb3165..d216c7836 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +5,10 @@ ### Active Contributors 1. @[lijiarui](https://github.com/lijiarui): [\#1876](https://github.com/wechaty/wechaty/pull/1876) [\#1875](https://github.com/wechaty/wechaty/pull/1875) [\#1859](https://github.com/wechaty/wechaty/pull/1859) [\#1702](https://github.com/wechaty/wechaty/pull/1702) [\#1700](https://github.com/wechaty/wechaty/pull/1700) [\#1692](https://github.com/wechaty/wechaty/pull/1692) [\#1633](https://github.com/wechaty/wechaty/pull/1633) [\#1631](https://github.com/wechaty/wechaty/pull/1631) [\#1615](https://github.com/wechaty/wechaty/pull/1615) [\#1614](https://github.com/wechaty/wechaty/pull/1614) [\#1533](https://github.com/wechaty/wechaty/pull/1533) [\#1514](https://github.com/wechaty/wechaty/pull/1514) [\#1510](https://github.com/wechaty/wechaty/pull/1510) [\#1502](https://github.com/wechaty/wechaty/pull/1502) [\#1498](https://github.com/wechaty/wechaty/pull/1498) [\#1497](https://github.com/wechaty/wechaty/pull/1497) [\#1486](https://github.com/wechaty/wechaty/pull/1486) [\#1482](https://github.com/wechaty/wechaty/pull/1482) [\#1481](https://github.com/wechaty/wechaty/pull/1481) [\#1477](https://github.com/wechaty/wechaty/pull/1477) [\#1408](https://github.com/wechaty/wechaty/pull/1408) [\#1407](https://github.com/wechaty/wechaty/pull/1407) [\#1405](https://github.com/wechaty/wechaty/pull/1405) [\#1402](https://github.com/wechaty/wechaty/pull/1402) [\#1375](https://github.com/wechaty/wechaty/pull/1375) [\#1374](https://github.com/wechaty/wechaty/pull/1374) [\#1373](https://github.com/wechaty/wechaty/pull/1373) [\#1352](https://github.com/wechaty/wechaty/pull/1352) [\#1351](https://github.com/wechaty/wechaty/pull/1351) [\#1348](https://github.com/wechaty/wechaty/pull/1348) [\#1347](https://github.com/wechaty/wechaty/pull/1347) [\#1344](https://github.com/wechaty/wechaty/pull/1344) [\#1341](https://github.com/wechaty/wechaty/pull/1341) [\#1338](https://github.com/wechaty/wechaty/pull/1338) [\#1333](https://github.com/wechaty/wechaty/pull/1333) [\#1331](https://github.com/wechaty/wechaty/pull/1331) [\#1325](https://github.com/wechaty/wechaty/pull/1325) [\#1116](https://github.com/wechaty/wechaty/pull/1116) [\#1086](https://github.com/wechaty/wechaty/pull/1086) [\#816](https://github.com/wechaty/wechaty/pull/816) [\#812](https://github.com/wechaty/wechaty/pull/812) [\#805](https://github.com/wechaty/wechaty/pull/805) [\#798](https://github.com/wechaty/wechaty/pull/798) [\#757](https://github.com/wechaty/wechaty/pull/757) [\#725](https://github.com/wechaty/wechaty/pull/725) [\#440](https://github.com/wechaty/wechaty/pull/440) [\#370](https://github.com/wechaty/wechaty/pull/370) [\#364](https://github.com/wechaty/wechaty/pull/364) [\#362](https://github.com/wechaty/wechaty/pull/362) [\#328](https://github.com/wechaty/wechaty/pull/328) [\#324](https://github.com/wechaty/wechaty/pull/324) [\#323](https://github.com/wechaty/wechaty/pull/323) [\#321](https://github.com/wechaty/wechaty/pull/321) [\#318](https://github.com/wechaty/wechaty/pull/318) [\#303](https://github.com/wechaty/wechaty/pull/303) [\#292](https://github.com/wechaty/wechaty/pull/292) [\#139](https://github.com/wechaty/wechaty/pull/139) [\#112](https://github.com/wechaty/wechaty/pull/112) [\#110](https://github.com/wechaty/wechaty/pull/110) [\#38](https://github.com/wechaty/wechaty/pull/38) -1. @[huan](https://github.com/huan): [\#1888](https://github.com/wechaty/wechaty/pull/1888) [\#1870](https://github.com/wechaty/wechaty/pull/1870) [\#1782](https://github.com/wechaty/wechaty/pull/1782) [\#1597](https://github.com/wechaty/wechaty/pull/1597) [\#1143](https://github.com/wechaty/wechaty/pull/1143) [\#1131](https://github.com/wechaty/wechaty/pull/1131) [\#1083](https://github.com/wechaty/wechaty/pull/1083) [\#1075](https://github.com/wechaty/wechaty/pull/1075) [\#1074](https://github.com/wechaty/wechaty/pull/1074) [\#1073](https://github.com/wechaty/wechaty/pull/1073) [\#1072](https://github.com/wechaty/wechaty/pull/1072) [\#1071](https://github.com/wechaty/wechaty/pull/1071) [\#860](https://github.com/wechaty/wechaty/pull/860) [\#854](https://github.com/wechaty/wechaty/pull/854) [\#841](https://github.com/wechaty/wechaty/pull/841) [\#831](https://github.com/wechaty/wechaty/pull/831) [\#810](https://github.com/wechaty/wechaty/pull/810) [\#469](https://github.com/wechaty/wechaty/pull/469) [\#462](https://github.com/wechaty/wechaty/pull/462) [\#455](https://github.com/wechaty/wechaty/pull/455) [\#449](https://github.com/wechaty/wechaty/pull/449) [\#396](https://github.com/wechaty/wechaty/pull/396) [\#351](https://github.com/wechaty/wechaty/pull/351) [\#317](https://github.com/wechaty/wechaty/pull/317) [\#316](https://github.com/wechaty/wechaty/pull/316) [\#315](https://github.com/wechaty/wechaty/pull/315) [\#314](https://github.com/wechaty/wechaty/pull/314) [\#313](https://github.com/wechaty/wechaty/pull/313) [\#312](https://github.com/wechaty/wechaty/pull/312) [\#311](https://github.com/wechaty/wechaty/pull/311) [\#168](https://github.com/wechaty/wechaty/pull/168) [\#158](https://github.com/wechaty/wechaty/pull/158) [\#149](https://github.com/wechaty/wechaty/pull/149) [\#146](https://github.com/wechaty/wechaty/pull/146) [\#143](https://github.com/wechaty/wechaty/pull/143) [\#142](https://github.com/wechaty/wechaty/pull/142) [\#141](https://github.com/wechaty/wechaty/pull/141) [\#25](https://github.com/wechaty/wechaty/pull/25) +1. @[huan](https://github.com/huan): [\#1931](https://github.com/wechaty/wechaty/pull/1931) [\#1888](https://github.com/wechaty/wechaty/pull/1888) [\#1870](https://github.com/wechaty/wechaty/pull/1870) [\#1782](https://github.com/wechaty/wechaty/pull/1782) [\#1597](https://github.com/wechaty/wechaty/pull/1597) [\#1143](https://github.com/wechaty/wechaty/pull/1143) [\#1131](https://github.com/wechaty/wechaty/pull/1131) [\#1083](https://github.com/wechaty/wechaty/pull/1083) [\#1075](https://github.com/wechaty/wechaty/pull/1075) [\#1074](https://github.com/wechaty/wechaty/pull/1074) [\#1073](https://github.com/wechaty/wechaty/pull/1073) [\#1072](https://github.com/wechaty/wechaty/pull/1072) [\#1071](https://github.com/wechaty/wechaty/pull/1071) [\#860](https://github.com/wechaty/wechaty/pull/860) [\#854](https://github.com/wechaty/wechaty/pull/854) [\#841](https://github.com/wechaty/wechaty/pull/841) [\#831](https://github.com/wechaty/wechaty/pull/831) [\#810](https://github.com/wechaty/wechaty/pull/810) [\#469](https://github.com/wechaty/wechaty/pull/469) [\#462](https://github.com/wechaty/wechaty/pull/462) [\#455](https://github.com/wechaty/wechaty/pull/455) [\#449](https://github.com/wechaty/wechaty/pull/449) [\#396](https://github.com/wechaty/wechaty/pull/396) [\#351](https://github.com/wechaty/wechaty/pull/351) [\#317](https://github.com/wechaty/wechaty/pull/317) [\#316](https://github.com/wechaty/wechaty/pull/316) [\#315](https://github.com/wechaty/wechaty/pull/315) [\#314](https://github.com/wechaty/wechaty/pull/314) [\#313](https://github.com/wechaty/wechaty/pull/313) [\#312](https://github.com/wechaty/wechaty/pull/312) [\#311](https://github.com/wechaty/wechaty/pull/311) [\#168](https://github.com/wechaty/wechaty/pull/168) [\#158](https://github.com/wechaty/wechaty/pull/158) [\#149](https://github.com/wechaty/wechaty/pull/149) [\#146](https://github.com/wechaty/wechaty/pull/146) [\#143](https://github.com/wechaty/wechaty/pull/143) [\#142](https://github.com/wechaty/wechaty/pull/142) [\#141](https://github.com/wechaty/wechaty/pull/141) [\#25](https://github.com/wechaty/wechaty/pull/25) 1. @[windmemory](https://github.com/windmemory): [\#1832](https://github.com/wechaty/wechaty/pull/1832) [\#1770](https://github.com/wechaty/wechaty/pull/1770) [\#1735](https://github.com/wechaty/wechaty/pull/1735) [\#1729](https://github.com/wechaty/wechaty/pull/1729) [\#1662](https://github.com/wechaty/wechaty/pull/1662) [\#1660](https://github.com/wechaty/wechaty/pull/1660) [\#1643](https://github.com/wechaty/wechaty/pull/1643) [\#1630](https://github.com/wechaty/wechaty/pull/1630) [\#1577](https://github.com/wechaty/wechaty/pull/1577) [\#1571](https://github.com/wechaty/wechaty/pull/1571) [\#1557](https://github.com/wechaty/wechaty/pull/1557) [\#1550](https://github.com/wechaty/wechaty/pull/1550) [\#1538](https://github.com/wechaty/wechaty/pull/1538) [\#1526](https://github.com/wechaty/wechaty/pull/1526) [\#1503](https://github.com/wechaty/wechaty/pull/1503) [\#1457](https://github.com/wechaty/wechaty/pull/1457) +1. @[su-chang](https://github.com/su-chang): [\#1936](https://github.com/wechaty/wechaty/pull/1936) [\#1921](https://github.com/wechaty/wechaty/pull/1921) [\#1915](https://github.com/wechaty/wechaty/pull/1915) [\#1913](https://github.com/wechaty/wechaty/pull/1913) [\#1910](https://github.com/wechaty/wechaty/pull/1910) [\#1900](https://github.com/wechaty/wechaty/pull/1900) [\#1895](https://github.com/wechaty/wechaty/pull/1895) [\#1883](https://github.com/wechaty/wechaty/pull/1883) [\#1868](https://github.com/wechaty/wechaty/pull/1868) [\#1866](https://github.com/wechaty/wechaty/pull/1866) [\#1864](https://github.com/wechaty/wechaty/pull/1864) [\#1861](https://github.com/wechaty/wechaty/pull/1861) [\#1833](https://github.com/wechaty/wechaty/pull/1833) 1. @[mukaiu](https://github.com/mukaiu): [\#1089](https://github.com/wechaty/wechaty/pull/1089) [\#337](https://github.com/wechaty/wechaty/pull/337) [\#470](https://github.com/wechaty/wechaty/pull/470) [\#438](https://github.com/wechaty/wechaty/pull/438) [\#421](https://github.com/wechaty/wechaty/pull/421) [\#420](https://github.com/wechaty/wechaty/pull/420) [\#415](https://github.com/wechaty/wechaty/pull/415) [\#376](https://github.com/wechaty/wechaty/pull/376) -1. @[su-chang](https://github.com/su-chang): [\#1900](https://github.com/wechaty/wechaty/pull/1900) [\#1895](https://github.com/wechaty/wechaty/pull/1895) [\#1883](https://github.com/wechaty/wechaty/pull/1883) [\#1868](https://github.com/wechaty/wechaty/pull/1868) [\#1866](https://github.com/wechaty/wechaty/pull/1866) [\#1864](https://github.com/wechaty/wechaty/pull/1864) [\#1861](https://github.com/wechaty/wechaty/pull/1861) [\#1833](https://github.com/wechaty/wechaty/pull/1833) 1. @[JasLin](https://github.com/JasLin): [\#404](https://github.com/wechaty/wechaty/pull/404) [\#358](https://github.com/wechaty/wechaty/pull/358) [\#105](https://github.com/wechaty/wechaty/pull/105) [\#100](https://github.com/wechaty/wechaty/pull/100) [\#78](https://github.com/wechaty/wechaty/pull/78) [\#76](https://github.com/wechaty/wechaty/pull/76) 1. @[xinbenlv](https://github.com/xinbenlv): [\#1814](https://github.com/wechaty/wechaty/pull/1814) [\#1017](https://github.com/wechaty/wechaty/pull/1017) [\#935](https://github.com/wechaty/wechaty/pull/935) [\#388](https://github.com/wechaty/wechaty/pull/388) [\#361](https://github.com/wechaty/wechaty/pull/361) 1. @[binsee](https://github.com/binsee): [\#844](https://github.com/wechaty/wechaty/pull/844) [\#811](https://github.com/wechaty/wechaty/pull/811) [\#771](https://github.com/wechaty/wechaty/pull/771) [\#744](https://github.com/wechaty/wechaty/pull/744) [\#727](https://github.com/wechaty/wechaty/pull/727) @@ -17,30 +17,75 @@ 1. @[TbhT](https://github.com/TbhT): [\#1713](https://github.com/wechaty/wechaty/pull/1713) [\#1583](https://github.com/wechaty/wechaty/pull/1583) [\#1582](https://github.com/wechaty/wechaty/pull/1582) 1. @[suntong](https://github.com/suntong): [\#1677](https://github.com/wechaty/wechaty/pull/1677) [\#1129](https://github.com/wechaty/wechaty/pull/1129) [\#1123](https://github.com/wechaty/wechaty/pull/1123) 1. @[Gcaufy](https://github.com/Gcaufy): [\#1625](https://github.com/wechaty/wechaty/pull/1625) [\#1620](https://github.com/wechaty/wechaty/pull/1620) [\#310](https://github.com/wechaty/wechaty/pull/310) +1. @[snyk-bot](https://github.com/snyk-bot): [\#1928](https://github.com/wechaty/wechaty/pull/1928) [\#1925](https://github.com/wechaty/wechaty/pull/1925) 1. @[LinuxSuRen](https://github.com/LinuxSuRen): [\#1838](https://github.com/wechaty/wechaty/pull/1838) [\#1836](https://github.com/wechaty/wechaty/pull/1836) 1. @[SilentQianyi](https://github.com/SilentQianyi): [\#1891](https://github.com/wechaty/wechaty/pull/1891) [\#1886](https://github.com/wechaty/wechaty/pull/1886) ### Contributors 1. @[IdiosApps](https://github.com/IdiosApps): [\#1087](https://github.com/wechaty/wechaty/pull/1087) -1. @[rikakomoe](https://github.com/rikakomoe): [\#1904](https://github.com/wechaty/wechaty/pull/1904) +1. @[gengchen528](https://github.com/gengchen528): [\#1818](https://github.com/wechaty/wechaty/pull/1818) 1. @[lhr0909](https://github.com/lhr0909): [\#1666](https://github.com/wechaty/wechaty/pull/1666) 1. @[jzj1993](https://github.com/jzj1993): [\#1661](https://github.com/wechaty/wechaty/pull/1661) -1. @[zhaoic](https://github.com/zhaoic): [\#1822](https://github.com/wechaty/wechaty/pull/1822) +1. @[LanceZhu](https://github.com/LanceZhu): [\#1854](https://github.com/wechaty/wechaty/pull/1854) 1. @[bitwater](https://github.com/bitwater): [\#1532](https://github.com/wechaty/wechaty/pull/1532) +1. @[coderwhocode](https://github.com/coderwhocode): [\#1819](https://github.com/wechaty/wechaty/pull/1819) 1. @[monkeywithacupcake](https://github.com/monkeywithacupcake): [\#1759](https://github.com/wechaty/wechaty/pull/1759) -1. @[gengchen528](https://github.com/gengchen528): [\#1818](https://github.com/wechaty/wechaty/pull/1818) 1. @[hiwanz](https://github.com/hiwanz): [\#1036](https://github.com/wechaty/wechaty/pull/1036) 1. @[htoooth](https://github.com/htoooth): [\#1014](https://github.com/wechaty/wechaty/pull/1014) 1. @[zhenyong](https://github.com/zhenyong): [\#770](https://github.com/wechaty/wechaty/pull/770) -1. @[LanceZhu](https://github.com/LanceZhu): [\#1854](https://github.com/wechaty/wechaty/pull/1854) +1. @[rikakomoe](https://github.com/rikakomoe): [\#1904](https://github.com/wechaty/wechaty/pull/1904) 1. @[xjchengo](https://github.com/xjchengo): [\#416](https://github.com/wechaty/wechaty/pull/416) -1. @[coderwhocode](https://github.com/coderwhocode): [\#1819](https://github.com/wechaty/wechaty/pull/1819) +1. @[zhaoic](https://github.com/zhaoic): [\#1822](https://github.com/wechaty/wechaty/pull/1822) 1. @[ax4](https://github.com/ax4): [\#380](https://github.com/wechaty/wechaty/pull/380) 1. @[cherry-geqi](https://github.com/cherry-geqi): [\#97](https://github.com/wechaty/wechaty/pull/97) # Changelog +## [Unreleased](https://github.com/wechaty/wechaty/tree/HEAD) + +[Full Changelog](https://github.com/wechaty/wechaty/compare/v0.38...HEAD) + +**Closed issues:** + +- Is that you? [\#1942](https://github.com/wechaty/wechaty/issues/1942) + +## [v0.38](https://github.com/wechaty/wechaty/tree/v0.38) (2020-04-08) + +[Full Changelog](https://github.com/wechaty/wechaty/compare/v0.30...v0.38) + +**Implemented enhancements:** + +- BREAKING CHANGE: Remove `MessageUserQueryFilter` [\#1929](https://github.com/wechaty/wechaty/issues/1929) +- Simplify the Accessory class logic [\#1924](https://github.com/wechaty/wechaty/issues/1924) +- Update Docker Base Image form Ubuntu:18 to Ubuntu:19 [\#1920](https://github.com/wechaty/wechaty/issues/1920) +- wechaty dependency modules deep cleaning [\#1917](https://github.com/wechaty/wechaty/issues/1917) +- FileBox version incompatible across wechaty wechaty-puppet and wechaty-puppet-x [\#1914](https://github.com/wechaty/wechaty/issues/1914) +- Publish Wechaty Document Site to https://wechaty.js.org [\#1912](https://github.com/wechaty/wechaty/issues/1912) +- Support Encode & Decode QR Code functions from file-box@0.10 [\#1907](https://github.com/wechaty/wechaty/issues/1907) +- Design an new `Image` class for receive images with different sizes. [\#1871](https://github.com/wechaty/wechaty/issues/1871) +- Integrate Wechat with Matrix with the power of Wechaty [\#1737](https://github.com/wechaty/wechaty/issues/1737) + +**Fixed bugs:** + +- Can not create Image class. [\#1922](https://github.com/wechaty/wechaty/issues/1922) + +**Closed issues:** + +- 微信退出登录后,重新登录不了ipad [\#1839](https://github.com/wechaty/wechaty/issues/1839) +- 基于padpro协议不能发送微信小程序 [\#1837](https://github.com/wechaty/wechaty/issues/1837) + +**Merged pull requests:** + +- 0.38.0 [\#1936](https://github.com/wechaty/wechaty/pull/1936) ([su-chang](https://github.com/su-chang)) +- Remove MessageUserQueryFilter [\#1931](https://github.com/wechaty/wechaty/pull/1931) ([huan](https://github.com/huan)) +- \[Snyk\] Upgrade state-switch from 0.6.18 to 0.7.2 [\#1928](https://github.com/wechaty/wechaty/pull/1928) ([snyk-bot](https://github.com/snyk-bot)) +- \[Snyk\] Upgrade brolog from 0.3.11 to 0.4.3 [\#1925](https://github.com/wechaty/wechaty/pull/1925) ([snyk-bot](https://github.com/snyk-bot)) +- Image bug [\#1921](https://github.com/wechaty/wechaty/pull/1921) ([su-chang](https://github.com/su-chang)) +- File box [\#1915](https://github.com/wechaty/wechaty/pull/1915) ([su-chang](https://github.com/su-chang)) +- Support message.toImage\(\) method. [\#1913](https://github.com/wechaty/wechaty/pull/1913) ([su-chang](https://github.com/su-chang)) +- Support delay to accept room invitation [\#1910](https://github.com/wechaty/wechaty/pull/1910) ([su-chang](https://github.com/su-chang)) + ## [v0.30](https://github.com/wechaty/wechaty/tree/v0.30) (2020-02-08) [Full Changelog](https://github.com/wechaty/wechaty/compare/v0.28...v0.30) @@ -55,7 +100,6 @@ - 主动撤回消息 [\#1885](https://github.com/wechaty/wechaty/issues/1885) - Implement Label in Wechaty [\#1856](https://github.com/wechaty/wechaty/issues/1856) - Would like to have the timestamp on the room/friendship events [\#1829](https://github.com/wechaty/wechaty/issues/1829) -- Would like to have receiver, serialize and deserialize functions on RoomInvitation [\#1823](https://github.com/wechaty/wechaty/issues/1823) - Wechaty v0.26 iosBird Testing, an iOS hook puppet implementation! [\#1775](https://github.com/wechaty/wechaty/issues/1775) - Missing example code [\#1756](https://github.com/wechaty/wechaty/issues/1756) - BREAKING CHANGE v0.25 Room.say\(text: string, mention: Contact\[\]\) deprecated [\#1730](https://github.com/wechaty/wechaty/issues/1730) @@ -71,9 +115,7 @@ **Closed issues:** -- Use docker to run, QR code address prompt "unrecognized QR code" [\#1905](https://github.com/wechaty/wechaty/issues/1905) - room.announce\(\)中当参数为空字符串时, 调用获取群公告而不是设置群公告为空 [\#1902](https://github.com/wechaty/wechaty/issues/1902) -- 启动官方学习项目报错 [\#1898](https://github.com/wechaty/wechaty/issues/1898) - 延期通过好友 [\#1890](https://github.com/wechaty/wechaty/issues/1890) - I want wechaty puppet padpro token to create a wechat bot [\#1882](https://github.com/wechaty/wechaty/issues/1882) - msg.mentionSelf\(\)方法不对,始终返回false [\#1877](https://github.com/wechaty/wechaty/issues/1877) @@ -83,7 +125,6 @@ - wechaty-puppet can not install in electron [\#1851](https://github.com/wechaty/wechaty/issues/1851) - wechaty-puppet-macpro alpha test [\#1846](https://github.com/wechaty/wechaty/issues/1846) - Action required: Greenkeeper could not be activated 🚨 [\#1781](https://github.com/wechaty/wechaty/issues/1781) -- 登陆二维码无法识别 [\#1753](https://github.com/wechaty/wechaty/issues/1753) - 经常报以下warning [\#1634](https://github.com/wechaty/wechaty/issues/1634) - Doesn't work with UK Android account/device [\#1556](https://github.com/wechaty/wechaty/issues/1556) @@ -133,7 +174,6 @@ **Closed issues:** -- 登录不了,有办法解决吗? [\#1842](https://github.com/wechaty/wechaty/issues/1842) - 登录不了一个错误报告 [\#1841](https://github.com/wechaty/wechaty/issues/1841) - 想获取微信消息列表,Message.findAll\(\)返回为空? [\#1825](https://github.com/wechaty/wechaty/issues/1825) - 用了一个月itchat相安无事,用了2小时wechaty... [\#1815](https://github.com/wechaty/wechaty/issues/1815) From 8f581178f6a90752a4f639ed905d63b5a1b00830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 20 Apr 2020 14:04:20 +0800 Subject: [PATCH 125/598] filter out Snyk in CHANGELOG --- CHANGELOG.md | 2 -- package.json | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d216c7836..18bb6650a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -79,8 +79,6 @@ - 0.38.0 [\#1936](https://github.com/wechaty/wechaty/pull/1936) ([su-chang](https://github.com/su-chang)) - Remove MessageUserQueryFilter [\#1931](https://github.com/wechaty/wechaty/pull/1931) ([huan](https://github.com/huan)) -- \[Snyk\] Upgrade state-switch from 0.6.18 to 0.7.2 [\#1928](https://github.com/wechaty/wechaty/pull/1928) ([snyk-bot](https://github.com/snyk-bot)) -- \[Snyk\] Upgrade brolog from 0.3.11 to 0.4.3 [\#1925](https://github.com/wechaty/wechaty/pull/1925) ([snyk-bot](https://github.com/snyk-bot)) - Image bug [\#1921](https://github.com/wechaty/wechaty/pull/1921) ([su-chang](https://github.com/su-chang)) - File box [\#1915](https://github.com/wechaty/wechaty/pull/1915) ([su-chang](https://github.com/su-chang)) - Support message.toImage\(\) method. [\#1913](https://github.com/wechaty/wechaty/pull/1913) ([su-chang](https://github.com/su-chang)) diff --git a/package.json b/package.json index d13a32da5..f3e2698fc 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "pack": "npm pack", "docs": "bash -x scripts/generate-docs.sh", "coverage": "nyc report --reporter=text-lcov | coveralls", - "changelog": "github_changelog_generator -u wechaty -p wechaty && sed -i'.bak' /greenkeeper/d CHANGELOG.md && sed -i'.bak' '/An in-range update of/d' CHANGELOG.md && ts-node scripts/sort-contributiveness.ts < CHANGELOG.md > CHANGELOG.new.md 2>/dev/null && cat CHANGELOG.md >> CHANGELOG.new.md && mv CHANGELOG.new.md CHANGELOG.md", + "changelog": "github_changelog_generator -u wechaty -p wechaty && sed -i'.bak' /greenkeeper/d CHANGELOG.md && sed -i'.bak' /Snyk/d CHANGELOG.md && sed -i'.bak' '/An in-range update of/d' CHANGELOG.md && ts-node scripts/sort-contributiveness.ts < CHANGELOG.md > CHANGELOG.new.md 2>/dev/null && cat CHANGELOG.md >> CHANGELOG.new.md && mv CHANGELOG.new.md CHANGELOG.md", "doctor": "npm run check-node-version && ts-node bin/doctor", "check-node-version": "check-node-version --node \">= 10\"", "lint": "npm run check-node-version && npm run lint:es && npm run lint:ts && npm run lint:sh && npm run lint:md", From 885a9385de398c1f0b52432375f78f9cc4a3be90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 20 Apr 2020 14:04:36 +0800 Subject: [PATCH 126/598] 0.39.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f3e2698fc..2d6e8d62e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.8", + "version": "0.39.9", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 3be8923e8fe6c9e67804d896923ef4a60fcb37bc Mon Sep 17 00:00:00 2001 From: SuperChang Date: Mon, 20 Apr 2020 15:24:28 +0800 Subject: [PATCH 127/598] Update wechaty-puppet-hostie version to 0.7.2 (#1949) * modify: update wechaty-puppet-hostie version to 0.7.2 * 0.39.10 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2d6e8d62e..6b32f8d68 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.9", + "version": "0.39.10", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", @@ -100,7 +100,7 @@ "state-switch": "^0.9.9", "watchdog": "^0.8.17", "wechaty-puppet": "^0.25.1", - "wechaty-puppet-hostie": "^0.7.1", + "wechaty-puppet-hostie": "^0.7.2", "ws": "^7.2.3" }, "devDependencies": { From cd9f6d2a52e2ab9f2f74ac4bbd7944d0f0a9939a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 21 Apr 2020 14:25:26 +0800 Subject: [PATCH 128/598] Upgrade donut to v0.2 --- src/puppet-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index cd0c58ac6..817db4de6 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -12,7 +12,7 @@ export const PUPPET_DEPENDENCIES = { /** * Scoped puppets */ - '@juzibot/wechaty-puppet-donut': '^0.0.26', // https://www.npmjs.com/package/wechaty-puppet-donut (to be published) + '@juzibot/wechaty-puppet-donut': '^0.2', // https://www.npmjs.com/package/wechaty-puppet-donut (to be published) /** * Wechaty Internal Puppets: dependenced by package.json From 1893b872ae6d9765aff164ffd303a5a5a213e236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 21 Apr 2020 14:25:42 +0800 Subject: [PATCH 129/598] 0.39.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2d6e8d62e..61202a675 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.9", + "version": "0.39.10", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From f1acb30aa53bec4a1a6a1f42e70e6cd2d2139501 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 21 Apr 2020 14:26:26 +0800 Subject: [PATCH 130/598] 0.39.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6b32f8d68..a6181451d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.10", + "version": "0.39.11", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 4b0e23b2652915c45604b0f82ab9d704dd67eb82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 21 Apr 2020 23:12:53 +0800 Subject: [PATCH 131/598] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 450654b1a..da962566a 100644 --- a/README.md +++ b/README.md @@ -407,7 +407,7 @@ Support this project by becoming a sponsor. Your logo will show up here with a l ## Author -1. [Huan](https://github.com/huan) [(李卓桓)](http://linkedin.com/in/zixia), [Tencent TVP of Chatbot](https://cloud.tencent.com/tvp/138), \ +1. [Huan](https://github.com/huan) [(李卓桓)](http://linkedin.com/in/zixia), Tencent TVP of Chatbot, \ 1. [Rui (李佳芮)](https://pre-angel.com/peoples/jiarui-li/) [![Profile of Huan LI (李卓桓) on StackOverflow](https://stackoverflow.com/users/flair/1123955.png)](https://stackoverflow.com/users/1123955/huan) From b136e60aa16c4b6f38373c610c05dafabb4f10fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 23 Apr 2020 22:40:45 +0800 Subject: [PATCH 132/598] Use v0.3 of donut --- src/puppet-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 817db4de6..5895216bc 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -12,7 +12,7 @@ export const PUPPET_DEPENDENCIES = { /** * Scoped puppets */ - '@juzibot/wechaty-puppet-donut': '^0.2', // https://www.npmjs.com/package/wechaty-puppet-donut (to be published) + '@juzibot/wechaty-puppet-donut': '^0.3', // https://www.npmjs.com/package/wechaty-puppet-donut (to be published) /** * Wechaty Internal Puppets: dependenced by package.json From 9eba0e6599eeaf243644e5c0a36aea91911f9aae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 23 Apr 2020 22:41:03 +0800 Subject: [PATCH 133/598] 0.39.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a6181451d..6027a7e33 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.11", + "version": "0.39.12", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From b3a5f3eeda21b668bd3333efa1cfcf112ce2d378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 23 Apr 2020 22:41:33 +0800 Subject: [PATCH 134/598] 0.39.13 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6027a7e33..3376d3290 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.12", + "version": "0.39.13", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From d050847f8565f9aeffc28a2a6ed2cf44deebe0e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 25 Apr 2020 12:04:01 +0800 Subject: [PATCH 135/598] docs for escapeRegexp --- src/helper-functions/pure/escape-regexp.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/helper-functions/pure/escape-regexp.ts b/src/helper-functions/pure/escape-regexp.ts index b08a7d078..1eb295b48 100644 --- a/src/helper-functions/pure/escape-regexp.ts +++ b/src/helper-functions/pure/escape-regexp.ts @@ -1,4 +1,7 @@ -// https://stackoverflow.com/a/3561711/1123955 +/** + * Is there a RegExp.escape function in Javascript? + * https://stackoverflow.com/a/3561711/1123955 + */ export function escapeRegExp (text: string) { return text.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&') } From 0f4ba0bec3cd3de420328192d5cd383e4dc5f9ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 25 Apr 2020 14:57:45 +0800 Subject: [PATCH 136/598] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index da962566a..5b91f7b68 100644 --- a/README.md +++ b/README.md @@ -407,7 +407,7 @@ Support this project by becoming a sponsor. Your logo will show up here with a l ## Author -1. [Huan](https://github.com/huan) [(李卓桓)](http://linkedin.com/in/zixia), Tencent TVP of Chatbot, \ +1. [Huan](https://github.com/huan) [(李卓桓)](http://linkedin.com/in/zixia), Tencent TVP of Chatbot 1. [Rui (李佳芮)](https://pre-angel.com/peoples/jiarui-li/) [![Profile of Huan LI (李卓桓) on StackOverflow](https://stackoverflow.com/users/flair/1123955.png)](https://stackoverflow.com/users/1123955/huan) From 76362dc707c359870f9192932d282ef344649874 Mon Sep 17 00:00:00 2001 From: Gcaufy Date: Sat, 25 Apr 2020 22:13:03 +0800 Subject: [PATCH 137/598] fix: fixed missing dependence & added coverage test (#1952) --- .nycrc | 3 +++ package.json | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 .nycrc diff --git a/.nycrc b/.nycrc new file mode 100644 index 000000000..618c05384 --- /dev/null +++ b/.nycrc @@ -0,0 +1,3 @@ +{ + "reporter": ["lcov", "text-summary"] +} diff --git a/package.json b/package.json index 3376d3290..0f3465bb3 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "puppet-install": "ts-node bin/puppet-install.ts", "sloc": "sloc bin examples scripts src tests --details --format cli-table --keys total,source,comment && sloc bin examples scripts src tests", "ts-node": "ts-node", - "test": "npm run lint && npm run test:unit && npm run sloc", + "test": "npm run lint && nyc npm run test:unit && npm run sloc", "test:pack": "bash -x scripts/npm-pack-testing.sh", "test:shell": "shellcheck bin/*.sh scripts/*.sh", "test:unit": "blue-tape -r ts-node/register \"src/**/*.spec.ts\" \"src/*.spec.ts\" \"tests/*.spec.ts\" \"tests/**/*.spec.ts\"", @@ -119,6 +119,7 @@ "@types/retry": "^0.12.0", "@types/ws": "^7.2.2", "apiai": "^4.0.3", + "blue-tape": "^1.0.0", "check-node-version": "^4.0.2", "coveralls": "^3.0.9", "cross-env": "^7.0.2", From 873f04350f6e7b6e875c301106505b784567ac90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 26 Apr 2020 02:09:11 +0800 Subject: [PATCH 138/598] remove unnecessary dep --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 0f3465bb3..0d2ea86f2 100644 --- a/package.json +++ b/package.json @@ -119,7 +119,6 @@ "@types/retry": "^0.12.0", "@types/ws": "^7.2.2", "apiai": "^4.0.3", - "blue-tape": "^1.0.0", "check-node-version": "^4.0.2", "coveralls": "^3.0.9", "cross-env": "^7.0.2", From 2e6e0dba4578297fbe10bbbc2f116426e4dd92f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 26 Apr 2020 02:09:28 +0800 Subject: [PATCH 139/598] 0.39.14 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0d2ea86f2..b225c6f43 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.13", + "version": "0.39.14", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From d2c9826d28fd0bec7a04b69678b3b142b2648564 Mon Sep 17 00:00:00 2001 From: SuperChang Date: Tue, 28 Apr 2020 18:21:28 +0800 Subject: [PATCH 140/598] Friendship contact (#1955) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: sync contact after load in friendship event * 0.39.15 * fix: add await to all friendship.contact() * move ready() inside to prevent breaking changes (#1954) * 0.39.16 * clean * 0.39.17 Co-authored-by: Huan LI (李卓桓) --- package.json | 2 +- src/user/friendship.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index b225c6f43..85aeb2c02 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.14", + "version": "0.39.17", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", diff --git a/src/user/friendship.ts b/src/user/friendship.ts index 9488b7d67..94517ca17 100644 --- a/src/user/friendship.ts +++ b/src/user/friendship.ts @@ -211,6 +211,8 @@ export class Friendship extends Accessory implements Acceptable { if (!this.payload) { throw new Error('no payload') } + + await this.contact().ready() } /** From 6dd731a470a69de4e57089257e7ac2bdf92b525e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 29 Apr 2020 10:56:52 +0800 Subject: [PATCH 141/598] use shield img for npm badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5b91f7b68..61a9919cd 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Wechaty [![NPM Version](https://badge.fury.io/js/wechaty.svg)](https://www.npmjs.com/package/wechaty) [![NPM](https://github.com/wechaty/wechaty/workflows/NPM/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ANPM) [![Docker](https://github.com/wechaty/wechaty/workflows/Docker/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ADocker) +# Wechaty [![NPM Version](https://img.shields.io/npm/v/wechaty?color=brightgreen)](https://www.npmjs.com/package/wechaty) [![NPM](https://github.com/wechaty/wechaty/workflows/NPM/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ANPM) [![Docker](https://github.com/wechaty/wechaty/workflows/Docker/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ADocker) [![Wechaty](https://wechaty.github.io/wechaty/images/wechaty-logo-green-en.png)](https://github.com/wechaty/wechaty) From 09b5de475988245448274911d4ae760b26094601 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 29 Apr 2020 10:57:08 +0800 Subject: [PATCH 142/598] 0.39.15 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b225c6f43..c8adcee27 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.14", + "version": "0.39.15", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 769921d996cd5303a5aee6614d084186aef87921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 29 Apr 2020 10:58:06 +0800 Subject: [PATCH 143/598] 0.39.18 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 85aeb2c02..6aa8b4854 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.17", + "version": "0.39.18", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 2f7b641434a6e2f11053581e96de33c7868f3d33 Mon Sep 17 00:00:00 2001 From: Gcaufy Date: Fri, 1 May 2020 17:15:04 +0800 Subject: [PATCH 144/598] feat: added wechaty plugin (#1946) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: added wechaty plugin * 0.39.14 * fix: remove plugins & change to functional plugin & added test cases * 0.39.15 * fix: varible name changes & no this & Test class extends * fix: varible name changes & no this & Test class extends * fix typo * 0.39.19 Co-authored-by: Huan (李卓桓) --- package.json | 2 +- src/wechaty.spec.ts | 37 +++++++++++++++++++++++++++++++ src/wechaty.ts | 54 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 6aa8b4854..3c6bf5d6b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.18", + "version": "0.39.19", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", diff --git a/src/wechaty.spec.ts b/src/wechaty.spec.ts index 044756d9c..964deed8b 100755 --- a/src/wechaty.spec.ts +++ b/src/wechaty.spec.ts @@ -149,6 +149,43 @@ test('on(event, Function)', async t => { }) +test('use plugin', async (t) => { + + // Do not modify the gloabl Wechaty instance + class MyWechatyTest extends Wechaty {} + + let result = '' + + const myGlobalPlugin = function () { + return function (bot: Wechaty) { + bot.on('message', () => (result += 'FROM_GLOBAL_PLUGIN:')) + } + } + + const myPlugin = function () { + return function (bot: Wechaty) { + bot.on('message', () => (result += 'FROM_MY_PLUGIN:')) + } + } + + MyWechatyTest.use(myGlobalPlugin()) + + const bot = new MyWechatyTest({ + puppet: new PuppetMock(), + }) + + bot.use(myPlugin()) + + bot.on('message', () => (result += 'FROM_BOT')) + + bot.emit('message', {} as any) + + await bot.stop() + + t.ok(result === 'FROM_GLOBAL_PLUGIN:FROM_MY_PLUGIN:FROM_BOT') + +}) + test('initPuppetAccessory()', async t => { const wechatyTest = new WechatyTest() diff --git a/src/wechaty.ts b/src/wechaty.ts index 59631f2cc..9c352145c 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -114,6 +114,10 @@ export interface WechatyOptions { ioToken? : string, // Io TOKEN } +export interface WechatyPlugin { + (bot: Wechaty): void; +} + const PUPPET_MEMORY_NAME = 'puppet' /** @@ -152,6 +156,8 @@ export class Wechaty extends EventEmitter implements Sayable { */ private static globalInstance: Wechaty + private static globalPluginList: WechatyPlugin[] = [] + private memory?: MemoryCard private lifeTimer? : NodeJS.Timer @@ -202,6 +208,31 @@ export class Wechaty extends EventEmitter implements Sayable { return this.globalInstance } + /** + * @param {WechatyPlugin[]} plugins - The plugins you want to use + * + * @return {Wechaty} - this for chaining, + * + * @desc + * For wechaty ecosystem, allow user to define a 3rd party plugin for the all wechaty instances + * + * @example + * // Report all chat message to my server. + * + * function WechatyReportPlugin(options: { url: string }) { + * return function (this: Wechaty) { + * this.on('message', message => http.post(options.url, { data: message })) + * } + * } + * + * bot.use(WechatyReportPlugin({ url: 'http://somewhere.to.report.your.data.com' }) + */ + public static use ( + ...plugins: WechatyPlugin[] + ) { + this.globalPluginList = this.globalPluginList.concat(plugins) + } + /** * The term [Puppet](https://github.com/wechaty/wechaty/wiki/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). @@ -282,6 +313,8 @@ export class Wechaty extends EventEmitter implements Sayable { // No need to set puppet/wechaty, so do not clone this.UrlLink = UrlLink this.MiniProgram = MiniProgram + + this.installGloablPlugin() } /** @@ -521,6 +554,27 @@ export class Wechaty extends EventEmitter implements Sayable { return this } + /** + * @param {WechatyPlugin[]} plugins - The plugins you want to use + * + * @return {Wechaty} - this for chaining, + * + * @desc + * For wechaty ecosystem, allow user to define a 3rd party plugin for the current wechaty instance. + * + * @example + * // The same usage with Wechaty.use(). + * + */ + public use (...plugins: WechatyPlugin[]) { + plugins.forEach(plugin => plugin(this)) + return this + } + + private installGloablPlugin () { + (this.constructor as typeof Wechaty).globalPluginList.forEach(plugin => plugin(this)) + } + private addListenerModuleFile (event: WechatyEventName, modulePath: string): void { const absoluteFilename = callerResolve(modulePath, __filename) log.verbose('Wechaty', 'addListenerModuleFile() hotImport(%s)', absoluteFilename) From d2671cda7ead60cdf8e4898e8fcbd62bc090aa3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 1 May 2020 19:11:50 +0800 Subject: [PATCH 145/598] linting --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 1dc66294a..5d657822b 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,6 @@ Otherwise, please saved the above _The World's Shortest ChatBot Code: 6 lines of [![NPM Version](https://img.shields.io/npm/v/wechaty?color=brightgreen&label=wechaty%40latest)](https://www.npmjs.com/package/wechaty) [![npm (tag)](https://img.shields.io/npm/v/wechaty/next?color=yellow&label=wechaty%40next)](https://www.npmjs.com/package/wechaty?activeTab=versions) - [![Downloads](https://img.shields.io/npm/dm/wechaty.svg?style=flat-square)](https://www.npmjs.com/package/wechaty) [![install size](https://packagephobia.now.sh/badge?p=wechaty)](https://packagephobia.now.sh/result?p=wechaty) From 3342e82b36d33665b8ec95ed3e1086ff199c85dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 1 May 2020 19:12:07 +0800 Subject: [PATCH 146/598] 0.39.20 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3c6bf5d6b..abe39a10c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.19", + "version": "0.39.20", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 7df792b326c0a9dd310a1df6b51b9ac0f7d6937c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 1 May 2020 19:18:48 +0800 Subject: [PATCH 147/598] export WechatyPlugin --- src/index.ts | 1 + src/wechaty.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 6910d2fba..4ac4d0add 100644 --- a/src/index.ts +++ b/src/index.ts @@ -19,6 +19,7 @@ export { export { Wechaty, WechatyOptions, + WechatyPlugin, } from './wechaty' export { diff --git a/src/wechaty.ts b/src/wechaty.ts index 9c352145c..4fb362219 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -115,7 +115,7 @@ export interface WechatyOptions { } export interface WechatyPlugin { - (bot: Wechaty): void; + (bot: Wechaty): void } const PUPPET_MEMORY_NAME = 'puppet' From 718ba8128e2352ebcae021cdf018128458b3ebc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 1 May 2020 19:19:09 +0800 Subject: [PATCH 148/598] 0.39.21 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index abe39a10c..a75f67be2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.20", + "version": "0.39.21", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From b26aa73d2cfe9e150ac4473a38235e266076d477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 2 May 2020 19:00:58 +0800 Subject: [PATCH 149/598] Upgrade padplus to 0.7 --- src/puppet-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 5895216bc..2ab51acd5 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -23,7 +23,7 @@ export const PUPPET_DEPENDENCIES = { /** * Wechaty External Puppets */ - 'wechaty-puppet-padplus' : '^0.6.1', // https://www.npmjs.com/package/wechaty-puppet-padplus + 'wechaty-puppet-padplus' : '^0.7.15', // https://www.npmjs.com/package/wechaty-puppet-padplus 'wechaty-puppet-puppeteer' : '^0.21.2', // https://www.npmjs.com/package/wechaty-puppet-puppeteer 'wechaty-puppet-wechat4u' : '^0.17.4', // https://www.npmjs.com/package/wechaty-puppet-wechat4u } From 2b207bc2b71fd742c0a1a789b328e8c3103bde6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 2 May 2020 19:01:15 +0800 Subject: [PATCH 150/598] 0.39.22 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a75f67be2..f4324b5f9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.21", + "version": "0.39.22", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From b4c121c4843e7a1e802bbf4c1f6c1f7c6ac4236f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 2 May 2020 19:03:21 +0800 Subject: [PATCH 151/598] 0.39.23 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f4324b5f9..3f8c50e3d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.22", + "version": "0.39.23", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 50b25b016fd2de67656ede7d82ac038790077a30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 2 May 2020 20:58:07 +0800 Subject: [PATCH 152/598] log clean --- src/wechaty.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wechaty.ts b/src/wechaty.ts index 4fb362219..1d39d1c85 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -862,7 +862,7 @@ export class Wechaty extends EventEmitter implements Sayable { * // do other stuff with bot here */ public async start (): Promise { - log.info('Wechaty', '<%s>(%s) start() v%s is starting...', + log.verbose('Wechaty', '<%s>(%s) start() v%s is starting...', this.options.puppet || config.systemPuppetName(), this.options.name || '', this.version(), @@ -940,7 +940,7 @@ export class Wechaty extends EventEmitter implements Sayable { * await bot.stop() */ public async stop (): Promise { - log.info('Wechaty', '<%s> stop() v%s is stoping ...', + log.verbose('Wechaty', '<%s> stop() v%s is stoping ...', this.options.puppet || config.systemPuppetName(), this.version(), ) From 79b32cd4c81806d1e4322d5b7aed70e1ae3b67ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 2 May 2020 20:58:41 +0800 Subject: [PATCH 153/598] 0.39.24 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3f8c50e3d..bf602dcc5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.23", + "version": "0.39.24", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From fe78a2ac5c3874fdfbd49cb6ae0fd21a475d2953 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 3 May 2020 17:16:52 +0800 Subject: [PATCH 154/598] enhance sayable --- src/index.ts | 3 +++ src/types.ts | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/index.ts b/src/index.ts index 4ac4d0add..754d12949 100644 --- a/src/index.ts +++ b/src/index.ts @@ -45,3 +45,6 @@ export { } from './deprecated' export { IoClient } from './io-client' +export { + Sayable, +} from './types' diff --git a/src/types.ts b/src/types.ts index 8f4d13400..4f3f13459 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,3 +1,4 @@ +import { Wechaty } from './wechaty' import { Contact, Message, @@ -10,8 +11,10 @@ export interface Sayable { text : string, replyTo? : Contact | Contact[] ): Promise + wechaty: Wechaty, } export interface Acceptable { accept: () => Promise + wechaty: Wechaty } From 7004009f9a9de0f95c57b3d32e324bacaad6d2f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 3 May 2020 17:19:08 +0800 Subject: [PATCH 155/598] new Sayable --- src/wechaty.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/wechaty.ts b/src/wechaty.ts index 1d39d1c85..69f6bfddd 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -149,6 +149,7 @@ export class Wechaty extends EventEmitter implements Sayable { public readonly state : StateSwitch private readonly readyState : StateSwitch + public readonly wechaty : Wechaty /** * singleton globalInstance @@ -292,6 +293,8 @@ export class Wechaty extends EventEmitter implements Sayable { this.state = new StateSwitch('Wechaty', { log }) this.readyState = new StateSwitch('WechatyReady', { log }) + this.wechaty = this + /** * @ignore * Clone Classes for this bot and attach the `puppet` to the Class From 28de177e60684a53a8f7286c9315bf407cdb6c91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 3 May 2020 17:19:24 +0800 Subject: [PATCH 156/598] 0.39.25 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bf602dcc5..e75c95165 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.24", + "version": "0.39.25", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 6b46d4c9fff85930234894552528840d5574fc6d Mon Sep 17 00:00:00 2001 From: Yuan Gao Date: Tue, 5 May 2020 12:30:02 +0800 Subject: [PATCH 157/598] fix: typo in wechaty.ts (#1963) --- src/wechaty.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/wechaty.ts b/src/wechaty.ts index 69f6bfddd..a197aee7e 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -93,8 +93,8 @@ import { timestampToDate } from './helper-functions/pure/timestamp-to-date' export const WECHATY_EVENT_DICT = { ...CHAT_EVENT_DICT, dong : 'Should be emitted after we call `Wechaty.ding()`', - error : "Will be emit when there's an Error occurred.", - heartbeat : 'Will be emited periodly after the Wechaty started. If not, means that the Wechaty had died.', + error : "Will be emitted when there's an Error occurred.", + heartbeat : 'Will be emitted periodically after the Wechaty started. If not, means that the Wechaty had died.', ready : 'All underlined data source are ready for use.', start : 'Will be emitted after the Wechaty had been started.', stop : 'Will be emitted after the Wechaty had been stopped.', @@ -280,10 +280,10 @@ export class Wechaty extends EventEmitter implements Sayable { private options: WechatyOptions = {}, ) { super() - log.verbose('Wechaty', 'contructor()') + log.verbose('Wechaty', 'constructor()') if (!options.name && options.profile) { - log.verbose('Wechaty', 'constuctor() WechatyOptions.profile DEPRECATED. use WechatyOptions.name instead.') + log.verbose('Wechaty', 'constructor() WechatyOptions.profile DEPRECATED. use WechatyOptions.name instead.') options.name = options.profile } this.memory = this.options.memory @@ -317,7 +317,7 @@ export class Wechaty extends EventEmitter implements Sayable { this.UrlLink = UrlLink this.MiniProgram = MiniProgram - this.installGloablPlugin() + this.installGlobalPlugin() } /** @@ -337,7 +337,7 @@ export class Wechaty extends EventEmitter implements Sayable { } /** - * Wechaty bot name set by `optoins.name` + * Wechaty bot name set by `options.name` * default: `wechaty` */ public name () { @@ -420,7 +420,7 @@ export class Wechaty extends EventEmitter implements Sayable { *

* @property {Function} heartbeat -(this: Wechaty, data: any) => void @@ -490,7 +490,7 @@ export class Wechaty extends EventEmitter implements Sayable { * const contact = friendship.contact() * let result = await friendship.accept() * if(result){ - * console.log(`Request from ${contact.name()} is accept succesfully!`) + * console.log(`Request from ${contact.name()} is accept successfully!`) * } else{ * console.log(`Request from ${contact.name()} failed to accept!`) * } @@ -574,7 +574,7 @@ export class Wechaty extends EventEmitter implements Sayable { return this } - private installGloablPlugin () { + private installGlobalPlugin () { (this.constructor as typeof Wechaty).globalPluginList.forEach(plugin => plugin(this)) } @@ -943,7 +943,7 @@ export class Wechaty extends EventEmitter implements Sayable { * await bot.stop() */ public async stop (): Promise { - log.verbose('Wechaty', '<%s> stop() v%s is stoping ...', + log.verbose('Wechaty', '<%s> stop() v%s is stopping ...', this.options.puppet || config.systemPuppetName(), this.version(), ) From fcd499435b492ca535e2a5e8951db764e30c9d72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 5 May 2020 16:02:31 +0800 Subject: [PATCH 158/598] fix lots of the typos (#1963)) --- .vscode/settings.json | 18 +++++ ...qrcode-value.ts => guard-qr-code-value.ts} | 0 src/user/room.ts | 70 +++++++++++-------- src/wechaty.ts | 42 +++++------ 4 files changed, 78 insertions(+), 52 deletions(-) rename src/helper-functions/pure/{guard-qrcode-value.ts => guard-qr-code-value.ts} (100%) diff --git a/.vscode/settings.json b/.vscode/settings.json index 5ba4c1699..172e7c638 100755 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -70,4 +70,22 @@ "javascript", "typescript", ], + "cSpell.words": [ + "Wechaty", + "appid", + "huan", + "ioscat", + "ipad", + "lijiarui", + "logonoff", + "padchat", + "padplus", + "pagepath", + "qrcode", + "removee", + "thumbnailurl", + "wechat", + "weixin", + "zixia" + ], } diff --git a/src/helper-functions/pure/guard-qrcode-value.ts b/src/helper-functions/pure/guard-qr-code-value.ts similarity index 100% rename from src/helper-functions/pure/guard-qrcode-value.ts rename to src/helper-functions/pure/guard-qr-code-value.ts diff --git a/src/user/room.ts b/src/user/room.ts index 5f92e1192..96b09052e 100644 --- a/src/user/room.ts +++ b/src/user/room.ts @@ -37,7 +37,7 @@ import { import { guardQrCodeValue, -} from '../helper-functions/pure/guard-qrcode-value' +} from '../helper-functions/pure/guard-qr-code-value' import { Contact } from './contact' import { MiniProgram } from './mini-program' @@ -61,7 +61,7 @@ export const ROOM_EVENT_DICT = { export type RoomEventName = keyof typeof ROOM_EVENT_DICT /** - * All wechat rooms(groups) will be encapsulated as a Room. + * All WeChat rooms(groups) will be encapsulated as a Room. * * [Examples/Room-Bot]{@link https://github.com/wechaty/wechaty/blob/1523c5e02be46ebe2cc172a744b2fbe53351540e/examples/room-bot.ts} * @@ -77,9 +77,9 @@ export class Room extends Accessory implements Sayable { * @param {Contact[]} contactList * @param {string} [topic] * @returns {Promise} - * @example Creat a room with 'lijiarui' and 'juxiaomi', the room topic is 'ding - created' - * const helperContactA = await Contact.find({ name: 'lijiarui' }) // change 'lijiarui' to any contact in your wechat - * const helperContactB = await Contact.find({ name: 'juxiaomi' }) // change 'juxiaomi' to any contact in your wechat + * @example Creat a room with 'lijiarui' and 'huan', the room topic is 'ding - created' + * const helperContactA = await Contact.find({ name: 'lijiarui' }) // change 'lijiarui' to any contact in your WeChat + * const helperContactB = await Contact.find({ name: 'huan' }) // change 'huan' to any contact in your WeChat * const contactList = [helperContactA, helperContactB] * console.log('Bot', 'contactList: %s', contactList.join(',')) * const room = await Room.create(contactList, 'ding') @@ -282,11 +282,11 @@ export class Room extends Accessory implements Sayable { const MyClass = instanceToClass(this, Room) if (MyClass === Room) { - throw new Error('Room class can not be instanciated directly! See: https://github.com/wechaty/wechaty/issues/1217') + throw new Error('Room class can not be instantiated directly! See: https://github.com/wechaty/wechaty/issues/1217') } if (!this.puppet) { - throw new Error('Room class can not be instanciated without a puppet!') + throw new Error('Room class can not be instantiated without a puppet!') } } @@ -299,7 +299,7 @@ export class Room extends Accessory implements Sayable { return this.constructor.name } - return `Room<${this.payload.topic || 'loadind...'}>` + return `Room<${this.payload.topic || 'loading...'}>` } public async * [Symbol.asyncIterator] (): AsyncIterableIterator { @@ -319,7 +319,7 @@ export class Room extends Accessory implements Sayable { } /** - * Force reload data for Room, Sync data from lowlevel API again. + * Force reload data for Room, Sync data from puppet API again. * * @returns {Promise} * @example @@ -593,7 +593,7 @@ export class Room extends Accessory implements Sayable { textList[0], ) // TODO(huan) 20191222 it seems the following code will not happen, - // becasue it's equal the mentionList.length === 0 situation? + // because it's equal the mentionList.length === 0 situation? // // XXX(huan) 20200101: See issue https://github.com/wechaty/wechaty/issues/1893 // This is an anti-pattern usage. @@ -614,7 +614,7 @@ export class Room extends Accessory implements Sayable { const textListLength = textList.length const varListLength = varList.length if (textListLength - varListLength !== 1) { - throw new Error('Can not say message, invalid Templated String Array.') + throw new Error('Can not say message, invalid Template String Array.') } let finalText = '' @@ -665,7 +665,7 @@ export class Room extends Accessory implements Sayable { * @property {string} join - Emit when anyone join any room. * @property {string} topic - Get topic event, emitted when someone change room topic. * @property {string} leave - Emit when anyone leave the room.
- * If someone leaves the room by themselves, wechat will not notice other people in the room, so the bot will never get the "leave" event. + * If someone leaves the room by themselves, WeChat will not notice other people in the room, so the bot will never get the "leave" event. */ /** @@ -686,7 +686,7 @@ export class Room extends Accessory implements Sayable { * const bot = new Wechaty() * await bot.start() * // after logged in... - * const room = await bot.Room.find({topic: 'topic of your room'}) // change `event-room` to any room topic in your wechat + * const room = await bot.Room.find({topic: 'topic of your room'}) // change `event-room` to any room topic in your WeChat * if (room) { * room.on('join', (room, inviteeList, inviter) => { * const nameList = inviteeList.map(c => c.name()).join(',') @@ -698,7 +698,7 @@ export class Room extends Accessory implements Sayable { * const bot = new Wechaty() * await bot.start() * // after logged in... - * const room = await bot.Room.find({topic: 'topic of your room'}) // change `event-room` to any room topic in your wechat + * const room = await bot.Room.find({topic: 'topic of your room'}) // change `event-room` to any room topic in your WeChat * if (room) { * room.on('leave', (room, leaverList) => { * const nameList = leaverList.map(c => c.name()).join(',') @@ -710,7 +710,7 @@ export class Room extends Accessory implements Sayable { * const bot = new Wechaty() * await bot.start() * // after logged in... - * const room = await bot.Room.find({topic: 'topic of your room'}) // change `event-room` to any room topic in your wechat + * const room = await bot.Room.find({topic: 'topic of your room'}) // change `event-room` to any room topic in your WeChat * if (room) { * room.on('message', (message) => { * console.log(`Room received new message: ${message}`) @@ -721,7 +721,7 @@ export class Room extends Accessory implements Sayable { * const bot = new Wechaty() * await bot.start() * // after logged in... - * const room = await bot.Room.find({topic: 'topic of your room'}) // change `event-room` to any room topic in your wechat + * const room = await bot.Room.find({topic: 'topic of your room'}) // change `event-room` to any room topic in your WeChat * if (room) { * room.on('topic', (room, topic, oldTopic, changer) => { * console.log(`Room topic changed from ${oldTopic} to ${topic} by ${changer.name()}`) @@ -732,7 +732,7 @@ export class Room extends Accessory implements Sayable { * const bot = new Wechaty() * await bot.start() * // after logged in... - * const room = await bot.Room.find({topic: 'topic of your room'}) // change `event-room` to any room topic in your wechat + * const room = await bot.Room.find({topic: 'topic of your room'}) // change `event-room` to any room topic in your WeChat * if (room) { * room.on('invite', roomInvitation => roomInvitation.accept()) * } @@ -759,8 +759,8 @@ export class Room extends Accessory implements Sayable { * const bot = new Wechaty() * await bot.start() * // after logged in... - * const contact = await bot.Contact.find({name: 'lijiarui'}) // change 'lijiarui' to any contact in your wechat - * const room = await bot.Room.find({topic: 'wechat'}) // change 'wechat' to any room topic in your wechat + * const contact = await bot.Contact.find({name: 'lijiarui'}) // change 'lijiarui' to any contact in your WeChat + * const room = await bot.Room.find({topic: 'WeChat'}) // change 'WeChat' to any room topic in your WeChat * if (room) { * try { * await room.add(contact) @@ -789,7 +789,7 @@ export class Room extends Accessory implements Sayable { * const bot = new Wechaty() * await bot.start() * // after logged in... - * const room = await bot.Room.find({topic: 'wechat'}) // change 'wechat' to any room topic in your wechat + * const room = await bot.Room.find({topic: 'WeChat'}) // change 'WeChat' to any room topic in your WeChat * const contact = await bot.Contact.find({name: 'lijiarui'}) // change 'lijiarui' to any room member in the room you just set * if (room) { * try { @@ -948,6 +948,14 @@ export class Room extends Accessory implements Sayable { } } + /** + * @deprecated: use qrCode() instead + */ + public async qrcode () { + log.warn('Room', 'qrcode() is deprecated. use qrCode() instead.') + return this.qrCode() + } + /** * Get QR Code Value of the Room from the room, which can be used as scan and join the room. * > Tips: @@ -955,8 +963,8 @@ export class Room extends Accessory implements Sayable { * 2. The return should be the QR Code Data, instead of the QR Code Image. (the data should be less than 8KB. See: https://stackoverflow.com/a/12764370/1123955 ) * @returns {Promise} */ - public async qrcode (): Promise { - log.verbose('Room', 'qrcode()') + public async qrCode (): Promise { + log.verbose('Room', 'qrCode()') const qrcodeValue = await this.puppet.roomQRCode(this.id) return guardQrCodeValue(qrcodeValue) } @@ -1009,8 +1017,8 @@ export class Room extends Accessory implements Sayable { * const bot = new Wechaty() * await bot.start() * // after logged in... - * const contact = await bot.Contact.find({name: 'lijiarui'}) // change 'lijiarui' to any of contact in your wechat - * const room = await bot.Room.find({topic: 'wechaty'}) // change 'wechaty' to any of the room in your wechat + * const contact = await bot.Contact.find({name: 'lijiarui'}) // change 'lijiarui' to any of contact in your WeChat + * const room = await bot.Room.find({topic: 'wechaty'}) // change 'wechaty' to any of the room in your WeChat * if (contact && room) { * if (await room.has(contact)) { * console.log(`${contact.name()} is in the room wechaty!`) @@ -1039,7 +1047,7 @@ export class Room extends Accessory implements Sayable { * The way to search member by Room.member() * * @typedef RoomMemberQueryFilter - * @property {string} name -Find the contact by wechat name in a room, equal to `Contact.name()`. + * @property {string} name -Find the contact by WeChat name in a room, equal to `Contact.name()`. * @property {string} roomAlias -Find the contact by alias set by the bot for others in a room. * @property {string} contactAlias -Find the contact by alias set by the contact out of a room, equal to `Contact.alias()`. * [More Detail]{@link https://github.com/wechaty/wechaty/issues/365} @@ -1055,10 +1063,10 @@ export class Room extends Accessory implements Sayable { * @param {(RoomMemberQueryFilter | string)} [query] -Optional parameter, When use memberAll(name:string), return all matched members, including name, roomAlias, contactAlias * @returns {Promise} * @example - * const roomList:Conatct[] | null = await room.findAll() + * const roomList:Contact[] | null = await room.findAll() * if(roomList) * console.log(`room all member list: `, roomList) - * const memberContactList: Conatct[] | null =await room.findAll(`abc`) + * const memberContactList: Contact[] | null =await room.findAll(`abc`) * console.log(`contact list with all name, room alias, alias are abc:`, memberContactList) */ public async memberAll ( @@ -1091,9 +1099,9 @@ export class Room extends Accessory implements Sayable { * const bot = new Wechaty() * await bot.start() * // after logged in... - * const room = await bot.Room.find({topic: 'wechaty'}) // change 'wechaty' to any room name in your wechat + * const room = await bot.Room.find({topic: 'wechaty'}) // change 'wechaty' to any room name in your WeChat * if (room) { - * const member = await room.member('lijiarui') // change 'lijiarui' to any room member in your wechat + * const member = await room.member('lijiarui') // change 'lijiarui' to any room member in your WeChat * if (member) { * console.log(`wechaty room got the member: ${member.name()}`) * } else { @@ -1105,9 +1113,9 @@ export class Room extends Accessory implements Sayable { * const bot = new Wechaty() * await bot.start() * // after logged in... - * const room = await bot.Room.find({topic: 'wechaty'}) // change 'wechaty' to any room name in your wechat + * const room = await bot.Room.find({topic: 'wechaty'}) // change 'wechaty' to any room name in your WeChat * if (room) { - * const member = await room.member({name: 'lijiarui'}) // change 'lijiarui' to any room member in your wechat + * const member = await room.member({name: 'lijiarui'}) // change 'lijiarui' to any room member in your WeChat * if (member) { * console.log(`wechaty room got the member: ${member.name()}`) * } else { diff --git a/src/wechaty.ts b/src/wechaty.ts index a197aee7e..36c82334a 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -123,11 +123,11 @@ const PUPPET_MEMORY_NAME = 'puppet' /** * Main bot class. * - * A `Bot` is a wechat client depends on which puppet you use. + * 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 + * - 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/wechaty-getting-started/wiki/FAQ-EN#31-what-is-a-puppet-in-wechaty) @@ -138,8 +138,8 @@ const PUPPET_MEMORY_NAME = 'puppet' * @example The World's Shortest ChatBot Code: 6 lines of JavaScript * const { Wechaty } = require('wechaty') * const bot = new Wechaty() - * bot.on('scan', (qrcode, status) => console.log(['https://api.qrserver.com/v1/create-qr-code/?data=',encodeURIComponent(qrcode),'&size=220x220&margin=20',].join(''))) - * bot.on('login', user => console.log(`User ${user} logined`)) + * bot.on('scan', (qrCode, status) => console.log(['https://api.qrserver.com/v1/create-qr-code/?data=',encodeURIComponent(qrcode),'&size=220x220&margin=20',].join(''))) + * bot.on('login', user => console.log(`User ${user} logged in`)) * bot.on('message', message => console.log(`Message: ${message}`)) * bot.start() */ @@ -193,7 +193,7 @@ export class Wechaty extends EventEmitter implements Sayable { * * Wechaty.instance() // Global instance * .on('scan', (url, status) => console.log(`Scan QR Code to login: ${status}\n${url}`)) - * .on('login', user => console.log(`User ${user} logined`)) + * .on('login', user => console.log(`User ${user} logged in`)) * .on('message', message => console.log(`Message: ${message}`)) * .start() */ @@ -201,7 +201,7 @@ export class Wechaty extends EventEmitter implements Sayable { options?: WechatyOptions, ) { if (options && this.globalInstance) { - throw new Error('instance can be only inited once by options!') + throw new Error('instance can be only initialized once by options!') } if (!this.globalInstance) { this.globalInstance = new Wechaty(options) @@ -236,7 +236,7 @@ export class Wechaty extends EventEmitter implements Sayable { /** * The term [Puppet](https://github.com/wechaty/wechaty/wiki/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 the component that helps Wechaty to control the WeChat(that's the reason we call it puppet). * The plugins are named XXXPuppet, for example: * - [PuppetPuppeteer](https://github.com/wechaty/wechaty-puppet-puppeteer): * - [PuppetPadchat](https://github.com/wechaty/wechaty-puppet-padchat) @@ -247,7 +247,7 @@ export class Wechaty extends EventEmitter implements Sayable { * @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-padchat - * - Using the WebSocket protocol to connect with a Protocol Server for controlling the iPad Wechat program. + * - Using the WebSocket protocol to connect with a Protocol Server for controlling the iPad WeChat program. * @property {string} wechaty-puppet-puppeteer * - 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 @@ -262,8 +262,8 @@ export class Wechaty extends EventEmitter implements Sayable { * When you set this:
* `new Wechaty({name: 'wechaty-name'}) `
* it will generate a file called `wechaty-name.memory-card.json`.
- * This file stores the bot's login information.
- * If the file is valid, the bot can auto login so you don't need to scan the qrcode to login again.
+ * This file stores the login information for bot.
+ * If the file is valid, the bot can auto login so you don't need to scan the qrCode to login again.
* Also, you can set the environment variable for `WECHATY_NAME` to set this value when you start.
* eg: `WECHATY_NAME="your-cute-bot-name" node bot.js` * @property {PuppetModuleName | Puppet} puppet -Puppet name or instance @@ -391,16 +391,16 @@ export class Wechaty extends EventEmitter implements Sayable { * @desc Wechaty Class Event Type * @typedef WechatyEventName * @property {string} error - When the bot get error, there will be a Wechaty error event fired. - * @property {string} login - After the bot login full successful, the event login will be emitted, with a Contact of current logined user. + * @property {string} login - After the bot login full successful, the event login will be emitted, with a Contact of current logged in user. * @property {string} logout - Logout will be emitted when bot detected log out, with a Contact of the current login user. - * @property {string} heartbeat - Get bot's heartbeat. + * @property {string} heartbeat - Get heartbeat of the bot. * @property {string} friendship - When someone sends you a friend request, there will be a Wechaty friendship event fired. * @property {string} message - Emit when there's a new message. * @property {string} ready - Emit when all data has load completed, in wechaty-puppet-padchat, it means it has sync Contact and Room completed * @property {string} room-join - Emit when anyone join any room. * @property {string} room-topic - Get topic event, emitted when someone change room topic. * @property {string} room-leave - Emit when anyone leave the room.
- * - If someone leaves the room by themselves, wechat will not notice other people in the room, so the bot will never get the "leave" event. + * - If someone leaves the room by themselves, WeChat will not notice other people in the room, so the bot will never get the "leave" event. * @property {string} room-invite - Emit when there is a room invitation, see more in {@link RoomInvitation} * @property {string} scan - A scan event will be emitted when the bot needs to show you a QR Code for scanning.
* It is recommend to install qrcode-terminal(run `npm install qrcode-terminal`) in order to show qrcode in the terminal. @@ -626,10 +626,10 @@ export class Wechaty extends EventEmitter implements Sayable { private async initPuppet (): Promise { log.verbose('Wechaty', 'initPuppet() %s', this.options.puppet || '') - const inited = !!this.puppet + const initialized = !!this.puppet - if (inited) { - log.verbose('Wechaty', 'initPuppet(%s) had already been inited, no need to init twice', this.options.puppet) + if (initialized) { + log.verbose('Wechaty', 'initPuppet(%s) had already been initialized, no need to init twice', this.options.puppet) return } @@ -858,7 +858,7 @@ export class Wechaty extends EventEmitter implements Sayable { * * @returns {Promise} * @description - * When you start the bot, bot will begin to login, need you wechat scan qrcode to login + * When you start the bot, bot will begin to login, need you WeChat scan qrcode to login * > Tips: All the bot operation needs to be triggered after start() is done * @example * await bot.start() @@ -1018,9 +1018,9 @@ export class Wechaty extends EventEmitter implements Sayable { * @returns {boolean} * @example * if (bot.logonoff()) { - * console.log('Bot logined') + * console.log('Bot logged in') * } else { - * console.log('Bot not logined') + * console.log('Bot not logged in') * } */ public logonoff (): boolean { From 73faa3d16df20779e16317611142c77a704a09f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 5 May 2020 16:03:36 +0800 Subject: [PATCH 159/598] fix file name --- src/user/contact-self.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/user/contact-self.ts b/src/user/contact-self.ts index c11186221..87dedf454 100644 --- a/src/user/contact-self.ts +++ b/src/user/contact-self.ts @@ -24,7 +24,7 @@ import { import { guardQrCodeValue, -} from '../helper-functions/pure/guard-qrcode-value' +} from '../helper-functions/pure/guard-qr-code-value' import { Contact, From 5aad2d85217859d89ed74ce66e29c694e3faf857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 5 May 2020 16:03:50 +0800 Subject: [PATCH 160/598] 0.39.26 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e75c95165..6b5200d93 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.25", + "version": "0.39.26", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 441b9742dad58308b84a5e7af2d6496558703dae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 9 May 2020 15:34:13 +0800 Subject: [PATCH 161/598] hostie 0.7.9 --- package.json | 2 +- src/puppet-config.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 6b5200d93..42b856c20 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "state-switch": "^0.9.9", "watchdog": "^0.8.17", "wechaty-puppet": "^0.25.1", - "wechaty-puppet-hostie": "^0.7.2", + "wechaty-puppet-hostie": "^0.7.9", "ws": "^7.2.3" }, "devDependencies": { diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 2ab51acd5..453eaf9b9 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -17,7 +17,7 @@ export const PUPPET_DEPENDENCIES = { /** * Wechaty Internal Puppets: dependenced by package.json */ - 'wechaty-puppet-hostie' : '^0.7.1', // https://www.npmjs.com/package/wechaty-puppet-hostie + 'wechaty-puppet-hostie' : '^0.7.9', // https://www.npmjs.com/package/wechaty-puppet-hostie 'wechaty-puppet-mock' : '^0.21.2', // https://www.npmjs.com/package/wechaty-puppet-mock /** From fb492a3ad8c1292efeb8c7d1b9885fb4ea34c393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 9 May 2020 15:49:08 +0800 Subject: [PATCH 162/598] add id to sayable --- src/types.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/types.ts b/src/types.ts index 4f3f13459..5559889eb 100644 --- a/src/types.ts +++ b/src/types.ts @@ -7,11 +7,12 @@ import { export type AnyFunction = (...args: any[]) => any export interface Sayable { + id : string, + wechaty : Wechaty, say ( text : string, replyTo? : Contact | Contact[] ): Promise - wechaty: Wechaty, } export interface Acceptable { From 38b5f505f3cfbff2de91519e1ba643bba1fa080b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 9 May 2020 15:49:24 +0800 Subject: [PATCH 163/598] 0.39.27 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 42b856c20..61da73912 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.26", + "version": "0.39.27", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From c92da878e15633a9c411944aad5def946aebcaab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 9 May 2020 15:50:36 +0800 Subject: [PATCH 164/598] 0.39.28 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 61da73912..41d7f83de 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.27", + "version": "0.39.28", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 43d9fa5fd885fdfb21283689844637127a930407 Mon Sep 17 00:00:00 2001 From: SuperChang Date: Sun, 10 May 2020 16:37:43 +0800 Subject: [PATCH 165/598] Upgrade hostie (#1967) * modify: upgrade wechaty-puppet-hostie to v0.7.10 * 0.39.29 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 41d7f83de..0cae874f4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.28", + "version": "0.39.29", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", @@ -100,7 +100,7 @@ "state-switch": "^0.9.9", "watchdog": "^0.8.17", "wechaty-puppet": "^0.25.1", - "wechaty-puppet-hostie": "^0.7.9", + "wechaty-puppet-hostie": "^0.7.10", "ws": "^7.2.3" }, "devDependencies": { From 7b02db5193feaacd38a937a4383cec32075e0763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 11 May 2020 23:35:09 +0800 Subject: [PATCH 166/598] add puppet event support (private) --- src/wechaty.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/wechaty.ts b/src/wechaty.ts index 36c82334a..831843e61 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -851,6 +851,14 @@ export class Wechaty extends EventEmitter implements Sayable { this.Tag.puppet = puppet this.puppet = puppet + + /** + * Private Event + * emit puppet when set + * + * Huan(202005) + */ + ;(this.emit as any)('puppet', puppet) } /** From 1e5be060cd3ebe0e5b291e84c0b8682a30129cf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 12 May 2020 02:06:10 +0800 Subject: [PATCH 167/598] 0.39.29 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 41d7f83de..ed66241fc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.28", + "version": "0.39.29", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From ef1b1286076185da57f17108ba3720d721ba6573 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 12 May 2020 02:11:14 +0800 Subject: [PATCH 168/598] 0.39.30 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0cae874f4..2416ddfd3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.29", + "version": "0.39.30", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 4472daa0885d216b195cc7457b3da55955d64290 Mon Sep 17 00:00:00 2001 From: SuperChang Date: Thu, 14 May 2020 15:20:37 +0800 Subject: [PATCH 169/598] Upgrade wechaty-puppet-hostie@0.7.11 (#1971) * fix: upgrade wechaty-puppet-hostie to v0.7.11, support grpc message length to 150Mb * 0.39.31 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2416ddfd3..e27e68038 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.30", + "version": "0.39.31", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", @@ -100,7 +100,7 @@ "state-switch": "^0.9.9", "watchdog": "^0.8.17", "wechaty-puppet": "^0.25.1", - "wechaty-puppet-hostie": "^0.7.10", + "wechaty-puppet-hostie": "^0.7.11", "ws": "^7.2.3" }, "devDependencies": { From 24d506ac4ec62148dfaaa066354b5052c7487a9a Mon Sep 17 00:00:00 2001 From: Gcaufy Date: Sat, 16 May 2020 22:45:21 +0800 Subject: [PATCH 170/598] Fix async error handler (#1968) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: fixed to handle async error * 0.39.30 * 0.39.31 * fix: code fix Co-authored-by: Huan (李卓桓) --- src/wechaty.spec.ts | 36 ++++++++++++++++++++++++++++++++++++ src/wechaty.ts | 15 +++++++++++---- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/wechaty.spec.ts b/src/wechaty.spec.ts index 964deed8b..25ffc71a1 100755 --- a/src/wechaty.spec.ts +++ b/src/wechaty.spec.ts @@ -149,6 +149,42 @@ test('on(event, Function)', async t => { }) +test('test async error', async (t) => { + + // Do not modify the gloabl Wechaty instance + class MyWechatyTest extends Wechaty {} + + const EXPECTED_ERROR = new Error('test') + + const bot = new MyWechatyTest({ + puppet: new PuppetMock(), + }) + + const asyncErrorFunction = function () { + return new Promise((resolve, reject) => { + setTimeout(function () { + reject(EXPECTED_ERROR) + }, 100) + // tslint ask resolve must be called, + // so write a fasly value, so that it never called + if (+new Date() < 0) { + resolve() + } + }) + } + + bot.on('message', async () => { + await asyncErrorFunction() + }) + bot.on('error', (e) => { + t.ok(e.message === EXPECTED_ERROR.message) + }) + + bot.emit('message', {} as any) + + await bot.stop() +}) + test('use plugin', async (t) => { // Do not modify the gloabl Wechaty instance diff --git a/src/wechaty.ts b/src/wechaty.ts index 831843e61..c7b2a341c 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -585,7 +585,7 @@ export class Wechaty extends EventEmitter implements Sayable { hotImport(absoluteFilename) .then((func: AnyFunction) => super.on(event, (...args: any[]) => { try { - func.apply(this, args) + return func.apply(this, args) } catch (e) { log.error('Wechaty', 'addListenerModuleFile(%s, %s) listener exception: %s', event, modulePath, e, @@ -610,15 +610,22 @@ export class Wechaty extends EventEmitter implements Sayable { private addListenerFunction (event: WechatyEventName, listener: AnyFunction): void { log.verbose('Wechaty', 'addListenerFunction(%s)', event) + const handleError = (e: Error, type = '') => { + log.error('Wechaty', 'addListenerFunction(%s) listener %sexception: %s', event, type, e) + this.emit('error', e) + } + /** * We use `super.on()` at here to prevent loop */ super.on(event, (...args: any[]) => { try { - listener.apply(this, args) + const result = listener.apply(this, args) + if (result && result.catch && typeof result.catch === 'function') { + result.catch((e: Error) => handleError(e, 'async')) + } } catch (e) { - log.error('Wechaty', 'addListenerFunction(%s) listener exception: %s', event, e) - this.emit('error', e) + handleError(e) } }) } From 4e42abb1df75f1926a4a022a705546b366cf077f Mon Sep 17 00:00:00 2001 From: Yuan Gao Date: Mon, 18 May 2020 18:37:03 +0800 Subject: [PATCH 171/598] Detail error stack (#1976) * add error.stack for unhandled rejection and exception * 0.39.32 --- package.json | 2 +- src/config.ts | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index e27e68038..1fcbddaee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.31", + "version": "0.39.32", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", diff --git a/src/config.ts b/src/config.ts index 7162fc821..dd667796f 100644 --- a/src/config.ts +++ b/src/config.ts @@ -86,9 +86,13 @@ if (logLevel) { if (log.level() === 'verbose' || log.level() === 'silly') { log.info('Config', 'registering process.on("unhandledRejection") for development/debug') - process.on('unhandledRejection', (reason, promise) => { + /** + * Refer to https://nodejs.org/api/process.html#process_event_unhandledrejection + * the reason is in type: Error | any + */ + process.on('unhandledRejection', (reason: Error | any, promise) => { log.error('Config', '###########################') - log.error('Config', 'unhandledRejection: %s %s', reason, promise) + log.error('Config', 'unhandledRejection: %s %s', reason.stack || reason, promise) log.error('Config', '###########################') promise.catch(err => { log.error('Config', 'process.on(unhandledRejection) promise.catch(%s)', err.message) @@ -100,7 +104,7 @@ if (log.level() === 'verbose' || log.level() === 'silly') { const origin = arguments[1] // to compatible with node 12 or below version typings log.error('Config', '###########################') - log.error('Config', 'uncaughtException: %s %s', error, origin) + log.error('Config', 'uncaughtException: %s %s', error.stack, origin) log.error('Config', '###########################') }) } From 58c0d020d8b2edf8b537f0d816e264856ab5b6c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 19 May 2020 10:55:12 +0800 Subject: [PATCH 172/598] add Apache License NOTICE --- LICENSE | 3 ++- NOTICE | 8 ++++++++ scripts/update-license.ts | 5 +++-- 3 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 NOTICE diff --git a/LICENSE b/LICENSE index 9935b1bdc..27f56e940 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,8 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2016-2018 Huan LI (李卓桓) + Copyright 2016 Huan LI (李卓桓) and + Wechaty Contributors . Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/NOTICE b/NOTICE new file mode 100644 index 000000000..cbfd0fdee --- /dev/null +++ b/NOTICE @@ -0,0 +1,8 @@ +Wechaty Chatbot SDK +Copyright 2016 Huan (李卓桓) and Wechaty Contributors. + +This product includes software developed at +The Wechaty Organization (https://github.com/wechaty). + +This software contains code derived from the Stackoverflow, +including various modifications by GitHub. diff --git a/scripts/update-license.ts b/scripts/update-license.ts index 80e3f5fcb..b94954f74 100755 --- a/scripts/update-license.ts +++ b/scripts/update-license.ts @@ -16,9 +16,10 @@ import { promisify } from 'util' import * as globCallback from 'glob' const LICENSE = `/** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From e83a3802b93f6f1d76283ca9a378aae357cd5351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 19 May 2020 10:58:27 +0800 Subject: [PATCH 173/598] Update Apache License header for adding all contributors --- bin/doctor.ts | 5 +++-- bin/io-client.ts | 5 +++-- bin/puppet-install.ts | 19 ++++++++++++++++ bin/version.ts | 5 +++-- examples/ding-dong-bot.ts | 5 +++-- scripts/retry-unit-tests.ts | 22 ++++++++++++++----- scripts/sort-contributiveness.ts | 5 +++-- scripts/update-license.ts | 21 +++++++++++++++++- src/accessory.spec.ts | 5 +++-- src/accessory.ts | 19 ++++++++++++++++ src/config.spec.ts | 5 +++-- src/config.ts | 5 +++-- src/deprecated.ts | 19 ++++++++++++++++ src/doctor.ts | 5 +++-- src/helper-functions/impure/generate-token.ts | 19 ++++++++++++++++ src/helper-functions/impure/get-port.spec.ts | 5 +++-- src/helper-functions/impure/get-port.ts | 19 ++++++++++++++++ src/helper-functions/impure/open-graph.ts | 19 ++++++++++++++++ src/helper-functions/index.ts | 19 ++++++++++++++++ src/helper-functions/pure/escape-regexp.ts | 19 ++++++++++++++-- .../pure/guard-qrcode-value.ts | 21 +++++++++++++++--- .../pure/timestamp-to-date.spec.ts | 19 ++++++++++++++++ .../pure/timestamp-to-date.ts | 19 +++++++++++++--- src/helper-functions/pure/try-wait.spec.ts | 5 +++-- src/helper-functions/pure/try-wait.ts | 19 ++++++++++++++++ src/helper-functions/pure/xml.spec.ts | 5 +++-- src/helper-functions/pure/xml.ts | 19 ++++++++++++++++ src/index.ts | 19 ++++++++++++++++ src/io-client.ts | 5 +++-- src/io.spec.ts | 19 ++++++++++++++++ src/io.ts | 5 +++-- src/puppet-config.ts | 18 ++++++++++++++- src/puppet-manager.spec.ts | 5 +++-- src/puppet-manager.ts | 19 ++++++++++++++++ src/types.ts | 19 ++++++++++++++++ src/typings.d.ts | 19 ++++++++++++++++ src/user/contact-self.ts | 6 ++--- src/user/contact.accessory.spec.ts | 19 ++++++++++++++++ src/user/contact.spec.ts | 5 +++-- src/user/contact.ts | 6 ++--- src/user/favorite.ts | 19 ++++++++++++++++ src/user/friendship.ts | 6 ++--- src/user/image.ts | 19 ++++++++++++++++ src/user/index.ts | 19 ++++++++++++++++ src/user/message.spec.ts | 5 +++-- src/user/message.ts | 7 +++--- src/user/mini-program.ts | 19 ++++++++++++++++ src/user/moment.ts | 19 ++++++++++++++++ src/user/money.ts | 19 ++++++++++++++++ src/user/room-invitation.ts | 6 ++--- src/user/room.spec.ts | 5 +++-- src/user/room.ts | 6 ++--- src/user/tag.ts | 19 ++++++++++++++++ src/user/url-link.ts | 19 ++++++++++++++++ src/version.spec.ts | 19 ++++++++++++++++ src/version.ts | 19 ++++++++++++++-- src/wechaty.spec.ts | 5 +++-- src/wechaty.ts | 6 ++--- tests/electron.spec.ts | 5 +++-- tests/fixtures/docker/import-require.ts | 5 +++-- tests/fixtures/docker/ts-bot.ts | 5 +++-- tests/fixtures/docker/type-error.ts | 5 +++-- .../with-package-json/with-import-error.ts | 5 +++-- .../docker/with-package-json/with-import.ts | 5 +++-- tests/fixtures/smoke-testing.ts | 19 ++++++++++++++++ tests/node.spec.ts | 5 +++-- 66 files changed, 716 insertions(+), 90 deletions(-) mode change 100755 => 100644 bin/puppet-install.ts mode change 100755 => 100644 scripts/retry-unit-tests.ts mode change 100755 => 100644 scripts/sort-contributiveness.ts mode change 100755 => 100644 scripts/update-license.ts mode change 100755 => 100644 src/accessory.spec.ts mode change 100755 => 100644 src/config.spec.ts mode change 100755 => 100644 src/helper-functions/impure/get-port.spec.ts mode change 100755 => 100644 src/helper-functions/pure/try-wait.spec.ts mode change 100755 => 100644 src/helper-functions/pure/xml.spec.ts mode change 100755 => 100644 src/io.spec.ts mode change 100755 => 100644 src/puppet-manager.spec.ts mode change 100755 => 100644 src/user/contact.accessory.spec.ts mode change 100755 => 100644 src/user/contact.spec.ts mode change 100755 => 100644 src/user/message.spec.ts mode change 100755 => 100644 src/user/room.spec.ts mode change 100755 => 100644 src/version.spec.ts mode change 100755 => 100644 src/wechaty.spec.ts mode change 100755 => 100644 tests/electron.spec.ts mode change 100755 => 100644 tests/node.spec.ts diff --git a/bin/doctor.ts b/bin/doctor.ts index c70e35f31..85a3311ef 100644 --- a/bin/doctor.ts +++ b/bin/doctor.ts @@ -1,8 +1,9 @@ #!/usr/bin/env node /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/bin/io-client.ts b/bin/io-client.ts index a85020c86..6312a755d 100644 --- a/bin/io-client.ts +++ b/bin/io-client.ts @@ -1,8 +1,9 @@ #!/usr/bin/env node /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/bin/puppet-install.ts b/bin/puppet-install.ts old mode 100755 new mode 100644 index 23240ef20..3a6f86976 --- a/bin/puppet-install.ts +++ b/bin/puppet-install.ts @@ -1,5 +1,24 @@ #!/usr/bin/env ts-node +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ import { PuppetManager } from '../src/puppet-manager' PuppetManager.installAll() diff --git a/bin/version.ts b/bin/version.ts index 6f741d815..82c560806 100644 --- a/bin/version.ts +++ b/bin/version.ts @@ -1,8 +1,9 @@ #!/usr/bin/env node /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/examples/ding-dong-bot.ts b/examples/ding-dong-bot.ts index 4efba04b0..4bdfe8e98 100644 --- a/examples/ding-dong-bot.ts +++ b/examples/ding-dong-bot.ts @@ -1,7 +1,8 @@ /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/scripts/retry-unit-tests.ts b/scripts/retry-unit-tests.ts old mode 100755 new mode 100644 index ceaac95c4..fc6437c28 --- a/scripts/retry-unit-tests.ts +++ b/scripts/retry-unit-tests.ts @@ -1,10 +1,22 @@ #!/usr/bin/env ts-node /** - * https://github.com/wechaty/wechaty/issues/1084 - * WebDriver / Puppeteer sometimes will fail(i.e. timeout) with no reason. - * That will cause the unit tests fail randomly. - * So we need to retry again when unit tests fail, - * and treat it's really fail after MAX_RETRY_NUM times. + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * */ import { spawn } from 'child_process' diff --git a/scripts/sort-contributiveness.ts b/scripts/sort-contributiveness.ts old mode 100755 new mode 100644 index 2dfa639d1..53ba34688 --- a/scripts/sort-contributiveness.ts +++ b/scripts/sort-contributiveness.ts @@ -1,8 +1,9 @@ #!/usr/bin/env ts-node /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-now Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/scripts/update-license.ts b/scripts/update-license.ts old mode 100755 new mode 100644 index b94954f74..4d0b92388 --- a/scripts/update-license.ts +++ b/scripts/update-license.ts @@ -1,5 +1,24 @@ #!/usr/bin/env ts-node +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ import { createReadStream, createWriteStream, @@ -13,7 +32,7 @@ import { } from 'stream' import { promisify } from 'util' -import * as globCallback from 'glob' +import globCallback from 'glob' const LICENSE = `/** * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty diff --git a/src/accessory.spec.ts b/src/accessory.spec.ts old mode 100755 new mode 100644 index ee6d576bc..f4c2cfbc6 --- a/src/accessory.spec.ts +++ b/src/accessory.spec.ts @@ -1,8 +1,9 @@ #!/usr/bin/env ts-node /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/accessory.ts b/src/accessory.ts index c5ae28587..4ecf47c2c 100644 --- a/src/accessory.ts +++ b/src/accessory.ts @@ -1,3 +1,22 @@ +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ import { EventEmitter } from 'events' import { instanceToClass } from 'clone-class' diff --git a/src/config.spec.ts b/src/config.spec.ts old mode 100755 new mode 100644 index 0b52ae978..d4e2b938a --- a/src/config.spec.ts +++ b/src/config.spec.ts @@ -1,8 +1,9 @@ #!/usr/bin/env ts-node /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/config.ts b/src/config.ts index 7162fc821..f8316b0a0 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,7 +1,8 @@ /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/deprecated.ts b/src/deprecated.ts index fe98e79ff..2432e5327 100644 --- a/src/deprecated.ts +++ b/src/deprecated.ts @@ -1 +1,20 @@ +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ export const WECHATY_DEPRECATED_HOLDER = 42 diff --git a/src/doctor.ts b/src/doctor.ts index 3178192b4..6015683b5 100644 --- a/src/doctor.ts +++ b/src/doctor.ts @@ -1,7 +1,8 @@ /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/helper-functions/impure/generate-token.ts b/src/helper-functions/impure/generate-token.ts index acc891d50..860ce9335 100644 --- a/src/helper-functions/impure/generate-token.ts +++ b/src/helper-functions/impure/generate-token.ts @@ -1,3 +1,22 @@ +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ import cuid from 'cuid' export function generateToken () { diff --git a/src/helper-functions/impure/get-port.spec.ts b/src/helper-functions/impure/get-port.spec.ts old mode 100755 new mode 100644 index b524d8bcf..d44df4114 --- a/src/helper-functions/impure/get-port.spec.ts +++ b/src/helper-functions/impure/get-port.spec.ts @@ -1,8 +1,9 @@ #!/usr/bin/env ts-node /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/helper-functions/impure/get-port.ts b/src/helper-functions/impure/get-port.ts index 727dac6e4..f7339109b 100644 --- a/src/helper-functions/impure/get-port.ts +++ b/src/helper-functions/impure/get-port.ts @@ -1,3 +1,22 @@ +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ import portfinder from 'portfinder' /** diff --git a/src/helper-functions/impure/open-graph.ts b/src/helper-functions/impure/open-graph.ts index 4e9282416..30e0dcfa9 100644 --- a/src/helper-functions/impure/open-graph.ts +++ b/src/helper-functions/impure/open-graph.ts @@ -1,3 +1,22 @@ +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ import og from 'open-graph' export async function openGraph (url: string): Promise { diff --git a/src/helper-functions/index.ts b/src/helper-functions/index.ts index 630015f44..8cd1496d8 100644 --- a/src/helper-functions/index.ts +++ b/src/helper-functions/index.ts @@ -1,3 +1,22 @@ +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ export { getPort } from './impure/get-port' export { generateToken } from './impure/generate-token' diff --git a/src/helper-functions/pure/escape-regexp.ts b/src/helper-functions/pure/escape-regexp.ts index 1eb295b48..d7f39b0f6 100644 --- a/src/helper-functions/pure/escape-regexp.ts +++ b/src/helper-functions/pure/escape-regexp.ts @@ -1,6 +1,21 @@ /** - * Is there a RegExp.escape function in Javascript? - * https://stackoverflow.com/a/3561711/1123955 + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * */ export function escapeRegExp (text: string) { return text.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&') diff --git a/src/helper-functions/pure/guard-qrcode-value.ts b/src/helper-functions/pure/guard-qrcode-value.ts index 9a3514ab0..aebf75545 100644 --- a/src/helper-functions/pure/guard-qrcode-value.ts +++ b/src/helper-functions/pure/guard-qrcode-value.ts @@ -1,7 +1,22 @@ /** - * QR CODE max char length: 7,089 - * https://stackoverflow.com/a/12764370/1123955 - */ + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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 MAX_LEN = 7089 export function guardQrCodeValue (value: string): string { diff --git a/src/helper-functions/pure/timestamp-to-date.spec.ts b/src/helper-functions/pure/timestamp-to-date.spec.ts index 953749029..472e8399e 100644 --- a/src/helper-functions/pure/timestamp-to-date.spec.ts +++ b/src/helper-functions/pure/timestamp-to-date.spec.ts @@ -1,3 +1,22 @@ +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ import { test } from 'tstest' import { timestampToDate } from './timestamp-to-date' diff --git a/src/helper-functions/pure/timestamp-to-date.ts b/src/helper-functions/pure/timestamp-to-date.ts index dbb582e4e..afbc026f1 100644 --- a/src/helper-functions/pure/timestamp-to-date.ts +++ b/src/helper-functions/pure/timestamp-to-date.ts @@ -1,8 +1,21 @@ /** - * Huan(202001): support both seconds & milliseconds + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. * - * How to test if a given time-stamp is in seconds or milliseconds? - * https://stackoverflow.com/a/23982005/1123955 */ export function timestampToDate (timestamp: number): Date { /** diff --git a/src/helper-functions/pure/try-wait.spec.ts b/src/helper-functions/pure/try-wait.spec.ts old mode 100755 new mode 100644 index a64f79cb5..62b06324d --- a/src/helper-functions/pure/try-wait.spec.ts +++ b/src/helper-functions/pure/try-wait.spec.ts @@ -1,8 +1,9 @@ #!/usr/bin/env ts-node /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/helper-functions/pure/try-wait.ts b/src/helper-functions/pure/try-wait.ts index 87e0d5ba7..91aff9797 100644 --- a/src/helper-functions/pure/try-wait.ts +++ b/src/helper-functions/pure/try-wait.ts @@ -1,3 +1,22 @@ +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ import promiseRetry from 'promise-retry' import { OperationOptions } from 'retry' diff --git a/src/helper-functions/pure/xml.spec.ts b/src/helper-functions/pure/xml.spec.ts old mode 100755 new mode 100644 index 23bf329f2..e4c35b590 --- a/src/helper-functions/pure/xml.spec.ts +++ b/src/helper-functions/pure/xml.spec.ts @@ -1,8 +1,9 @@ #!/usr/bin/env ts-node /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/helper-functions/pure/xml.ts b/src/helper-functions/pure/xml.ts index 3391c4585..53b9e0a8d 100644 --- a/src/helper-functions/pure/xml.ts +++ b/src/helper-functions/pure/xml.ts @@ -1,3 +1,22 @@ +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ export function stripHtml (html?: string): string { if (!html) { return '' diff --git a/src/index.ts b/src/index.ts index 754d12949..2b92d2c5b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,22 @@ +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ export { ScanStatus, UrlLinkPayload, diff --git a/src/io-client.ts b/src/io-client.ts index 940c6b02f..31c3ec3d4 100644 --- a/src/io-client.ts +++ b/src/io-client.ts @@ -1,7 +1,8 @@ /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/io.spec.ts b/src/io.spec.ts old mode 100755 new mode 100644 index 64db358d3..e6daf0185 --- a/src/io.spec.ts +++ b/src/io.spec.ts @@ -1,5 +1,24 @@ #!/usr/bin/env ts-node +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ import test from 'blue-tape' import { Io } from './io' diff --git a/src/io.ts b/src/io.ts index 758a9bf5f..dbbdae9df 100644 --- a/src/io.ts +++ b/src/io.ts @@ -1,7 +1,8 @@ /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 2ab51acd5..26b1126fd 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -1,5 +1,21 @@ /** - * Wechaty Official Puppet Implementations List + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * */ export const PUPPET_DEPENDENCIES = { /** diff --git a/src/puppet-manager.spec.ts b/src/puppet-manager.spec.ts old mode 100755 new mode 100644 index 2d8d8c37a..6a241c9ce --- a/src/puppet-manager.spec.ts +++ b/src/puppet-manager.spec.ts @@ -1,9 +1,10 @@ #!/usr/bin/env ts-node /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/puppet-manager.ts b/src/puppet-manager.ts index 9a175dc2c..9e7f91f85 100644 --- a/src/puppet-manager.ts +++ b/src/puppet-manager.ts @@ -1,3 +1,22 @@ +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ import path from 'path' import readPkgUp from 'read-pkg-up' diff --git a/src/types.ts b/src/types.ts index 4f3f13459..e9338959a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,3 +1,22 @@ +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ import { Wechaty } from './wechaty' import { Contact, diff --git a/src/typings.d.ts b/src/typings.d.ts index eed8d3a65..3229dffff 100644 --- a/src/typings.d.ts +++ b/src/typings.d.ts @@ -1,3 +1,22 @@ +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ declare module 'bl' declare module 'qrcode-terminal' declare module 'json-rpc-peer' diff --git a/src/user/contact-self.ts b/src/user/contact-self.ts index c11186221..45279c652 100644 --- a/src/user/contact-self.ts +++ b/src/user/contact-self.ts @@ -1,7 +1,8 @@ /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +16,6 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * @ignore */ import { FileBox, diff --git a/src/user/contact.accessory.spec.ts b/src/user/contact.accessory.spec.ts old mode 100755 new mode 100644 index fe87845c9..f64a2c186 --- a/src/user/contact.accessory.spec.ts +++ b/src/user/contact.accessory.spec.ts @@ -1,4 +1,23 @@ #!/usr/bin/env ts-node +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ import test from 'blue-tape' // import sinon from 'sinon' diff --git a/src/user/contact.spec.ts b/src/user/contact.spec.ts old mode 100755 new mode 100644 index 650289dce..a9af4b1c5 --- a/src/user/contact.spec.ts +++ b/src/user/contact.spec.ts @@ -1,8 +1,9 @@ #!/usr/bin/env ts-node /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/user/contact.ts b/src/user/contact.ts index c991e507a..2ee187891 100644 --- a/src/user/contact.ts +++ b/src/user/contact.ts @@ -1,7 +1,8 @@ /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +16,6 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * @ignore */ import { instanceToClass } from 'clone-class' diff --git a/src/user/favorite.ts b/src/user/favorite.ts index 2cf24d6bb..9c0a2f751 100644 --- a/src/user/favorite.ts +++ b/src/user/favorite.ts @@ -1,3 +1,22 @@ +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ import { Tag } from './tag' import { Accessory } from '../accessory' diff --git a/src/user/friendship.ts b/src/user/friendship.ts index 94517ca17..182cfc679 100644 --- a/src/user/friendship.ts +++ b/src/user/friendship.ts @@ -1,7 +1,8 @@ /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +15,6 @@ * 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. - * @ignore * */ diff --git a/src/user/image.ts b/src/user/image.ts index 7fbe230a9..4429cd19c 100644 --- a/src/user/image.ts +++ b/src/user/image.ts @@ -1,3 +1,22 @@ +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ import { instanceToClass } from 'clone-class' import { diff --git a/src/user/index.ts b/src/user/index.ts index effb78b01..78117cc3a 100644 --- a/src/user/index.ts +++ b/src/user/index.ts @@ -1,3 +1,22 @@ +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ export * from './contact' export * from './tag' export * from './contact-self' diff --git a/src/user/message.spec.ts b/src/user/message.spec.ts old mode 100755 new mode 100644 index 16ec3fa11..baed42cb0 --- a/src/user/message.spec.ts +++ b/src/user/message.spec.ts @@ -1,8 +1,9 @@ #!/usr/bin/env ts-node /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/user/message.ts b/src/user/message.ts index bdd13f6e3..141ff0249 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -1,7 +1,8 @@ /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +15,7 @@ * 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. - * @ignore + * */ import { instanceToClass, diff --git a/src/user/mini-program.ts b/src/user/mini-program.ts index ddbf75d17..595181204 100644 --- a/src/user/mini-program.ts +++ b/src/user/mini-program.ts @@ -1,3 +1,22 @@ +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ import { MiniProgramPayload, } from 'wechaty-puppet' diff --git a/src/user/moment.ts b/src/user/moment.ts index 21b7bcb6f..9a749d4a4 100644 --- a/src/user/moment.ts +++ b/src/user/moment.ts @@ -1,3 +1,22 @@ +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ import { Contact } from './contact' export class Moment { diff --git a/src/user/money.ts b/src/user/money.ts index ec7d60652..0d3c80817 100644 --- a/src/user/money.ts +++ b/src/user/money.ts @@ -1,3 +1,22 @@ +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ export class Money { /* diff --git a/src/user/room-invitation.ts b/src/user/room-invitation.ts index 47c58724c..760842af3 100644 --- a/src/user/room-invitation.ts +++ b/src/user/room-invitation.ts @@ -1,7 +1,8 @@ /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +15,6 @@ * 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. - * @ignore * */ import { diff --git a/src/user/room.spec.ts b/src/user/room.spec.ts old mode 100755 new mode 100644 index 138d5a5b8..380a07a3b --- a/src/user/room.spec.ts +++ b/src/user/room.spec.ts @@ -1,8 +1,9 @@ #!/usr/bin/env ts-node /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/user/room.ts b/src/user/room.ts index 5f92e1192..e6896633a 100644 --- a/src/user/room.ts +++ b/src/user/room.ts @@ -1,7 +1,8 @@ /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +16,6 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * @ignore */ import { instanceToClass, diff --git a/src/user/tag.ts b/src/user/tag.ts index 438c4c9ea..08afce987 100644 --- a/src/user/tag.ts +++ b/src/user/tag.ts @@ -1,3 +1,22 @@ +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ import { instanceToClass } from 'clone-class' import { log } from '../config' diff --git a/src/user/url-link.ts b/src/user/url-link.ts index b4fdc4010..456ae9589 100644 --- a/src/user/url-link.ts +++ b/src/user/url-link.ts @@ -1,3 +1,22 @@ +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ import Url from 'url' import { diff --git a/src/version.spec.ts b/src/version.spec.ts old mode 100755 new mode 100644 index 8d72118bf..1a0942718 --- a/src/version.spec.ts +++ b/src/version.spec.ts @@ -1,5 +1,24 @@ #!/usr/bin/env ts-node +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ import test from 'blue-tape' import { diff --git a/src/version.ts b/src/version.ts index 9bab8ee24..ed2b2da4c 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1,6 +1,21 @@ /** - * This file will be overwrite when we publish NPM module - * by scripts/generate_version.sh + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * */ export const VERSION = '0.0.0' diff --git a/src/wechaty.spec.ts b/src/wechaty.spec.ts old mode 100755 new mode 100644 index 964deed8b..8ba467fd5 --- a/src/wechaty.spec.ts +++ b/src/wechaty.spec.ts @@ -1,9 +1,10 @@ #!/usr/bin/env ts-node /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/wechaty.ts b/src/wechaty.ts index 69f6bfddd..9bad681a6 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -1,7 +1,8 @@ /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +16,6 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * @ignore */ import cuid from 'cuid' import { EventEmitter } from 'events' diff --git a/tests/electron.spec.ts b/tests/electron.spec.ts old mode 100755 new mode 100644 index c95ef1be0..9bbe04c62 --- a/tests/electron.spec.ts +++ b/tests/electron.spec.ts @@ -1,9 +1,10 @@ #!/usr/bin/env ts-node /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/tests/fixtures/docker/import-require.ts b/tests/fixtures/docker/import-require.ts index 35adaaf2b..929b4dffa 100644 --- a/tests/fixtures/docker/import-require.ts +++ b/tests/fixtures/docker/import-require.ts @@ -1,7 +1,8 @@ /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/tests/fixtures/docker/ts-bot.ts b/tests/fixtures/docker/ts-bot.ts index 69f46d4bb..997fdaad1 100644 --- a/tests/fixtures/docker/ts-bot.ts +++ b/tests/fixtures/docker/ts-bot.ts @@ -1,7 +1,8 @@ /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/tests/fixtures/docker/type-error.ts b/tests/fixtures/docker/type-error.ts index b6604496e..219336de8 100644 --- a/tests/fixtures/docker/type-error.ts +++ b/tests/fixtures/docker/type-error.ts @@ -1,7 +1,8 @@ /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/tests/fixtures/docker/with-package-json/with-import-error.ts b/tests/fixtures/docker/with-package-json/with-import-error.ts index 9deb16f36..1160c5be8 100644 --- a/tests/fixtures/docker/with-package-json/with-import-error.ts +++ b/tests/fixtures/docker/with-package-json/with-import-error.ts @@ -1,7 +1,8 @@ /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/tests/fixtures/docker/with-package-json/with-import.ts b/tests/fixtures/docker/with-package-json/with-import.ts index 0345f77c5..b50c333e7 100644 --- a/tests/fixtures/docker/with-package-json/with-import.ts +++ b/tests/fixtures/docker/with-package-json/with-import.ts @@ -1,7 +1,8 @@ /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/tests/fixtures/smoke-testing.ts b/tests/fixtures/smoke-testing.ts index c30b47071..eb09da28b 100644 --- a/tests/fixtures/smoke-testing.ts +++ b/tests/fixtures/smoke-testing.ts @@ -1,5 +1,24 @@ #!/usr/bin/env ts-node +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ import { Wechaty, VERSION, diff --git a/tests/node.spec.ts b/tests/node.spec.ts old mode 100755 new mode 100644 index 3fa3f5106..422bfdc7c --- a/tests/node.spec.ts +++ b/tests/node.spec.ts @@ -1,9 +1,10 @@ #!/usr/bin/env ts-node /** - * Wechaty - https://github.com/wechaty/wechaty + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * - * @copyright 2016-2018 Huan LI + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 0e5cfd5cff1e88dabd6ea2168927119aafb26a26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 19 May 2020 10:58:46 +0800 Subject: [PATCH 174/598] 0.39.26 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e75c95165..6b5200d93 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.25", + "version": "0.39.26", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From cc336e034cacfe335cea67f4d3191428f965db44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 19 May 2020 10:59:25 +0800 Subject: [PATCH 175/598] 0.39.33 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1fcbddaee..ff5d26205 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.32", + "version": "0.39.33", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 9071e1b4a3bf4c0a04115a1e93cc4f0c2f46cc24 Mon Sep 17 00:00:00 2001 From: SuperChang Date: Tue, 19 May 2020 21:20:23 +0800 Subject: [PATCH 176/598] Upgrade wechaty-puppet@0.25.7 (#1981) * modify: upgrade wechaty-puppet@0.25.7 for new message type GroupNote and new attribute of MiniProgram * 0.39.34 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index ff5d26205..90895268b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.33", + "version": "0.39.34", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", @@ -99,7 +99,7 @@ "read-pkg-up": "^7.0.1", "state-switch": "^0.9.9", "watchdog": "^0.8.17", - "wechaty-puppet": "^0.25.1", + "wechaty-puppet": "^0.25.7", "wechaty-puppet-hostie": "^0.7.11", "ws": "^7.2.3" }, From abb464c1a94e25ee9810a211e3792b6b47e54ee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 23 May 2020 10:13:04 +0800 Subject: [PATCH 177/598] Link to multiple language wechaty --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5d657822b..a4a5f6184 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ ## Connecting Chatbots -Wechaty is a Bot SDK for Wechat **Individual** Account which can help you create a bot in 6 lines of javascript, with cross-platform support including [Linux, Windows, MacOS](https://github.com/wechaty/wechaty/actions?query=workflow%3ANPM), and [Docker](https://github.com/wechaty/wechaty/actions?query=workflow%3ADocker). +Wechaty is a Bot SDK for Wechat **Individual** Account which can help you create a bot in 6 lines of [JavaScript](https://GitHub.com/Wechaty/wechaty), [Python](https://GitHub.com/Wechaty/python-wechaty/), [Go](https://GitHub.com/Wechaty/go-wechaty/), and [Java](https://GitHub.com/Wechaty/java-wechaty/), with cross-platform support including [Linux, Windows, MacOS](https://github.com/wechaty/wechaty/actions?query=workflow%3ANPM), and [Docker](https://github.com/wechaty/wechaty/actions?query=workflow%3ADocker). :octocat: :beetle: @@ -415,6 +415,6 @@ Support this project by becoming a sponsor. Your logo will show up here with a l ## Copyright & License -- Code & Docs © 2016-now Huan LI \ +- Code & Docs © 2016 Huan LI \ - Code released under the Apache-2.0 License - Docs released under Creative Commons From e36f423d11ba140e414750879d12bbe4e0888cdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 24 May 2020 13:21:00 +0800 Subject: [PATCH 178/598] enable WECHATY_PUPPET_PORT (#1984) --- bin/io-client.ts | 17 ++++++++++++++--- src/io-client.ts | 27 +++++++++++++++++++++------ src/io.ts | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 67 insertions(+), 10 deletions(-) diff --git a/bin/io-client.ts b/bin/io-client.ts index 6312a755d..836271549 100644 --- a/bin/io-client.ts +++ b/bin/io-client.ts @@ -24,7 +24,10 @@ import { log, } from '../src/config' -import { IoClient } from '../src/io-client' +import { + IoClient, + IoClientOptions, +} from '../src/io-client' import { Wechaty } from '../src/wechaty' const welcome = ` @@ -56,10 +59,18 @@ async function main () { const wechaty = new Wechaty({ name: token }) - const client = new IoClient({ + const WECHATY_HOSTIE_PORT = 'WECHATY_HOSTIE_PORT' + const port = parseInt(process.env[WECHATY_HOSTIE_PORT] || '0') + + const options: IoClientOptions = { token, wechaty, - }) + } + if (port) { + options.port = port + } + + const client = new IoClient(options) client.start() .catch(onError.bind(client)) diff --git a/src/io-client.ts b/src/io-client.ts index 31c3ec3d4..d004a6d89 100644 --- a/src/io-client.ts +++ b/src/io-client.ts @@ -39,6 +39,11 @@ import { Wechaty } from './wechaty' export interface IoClientOptions { token : string, wechaty : Wechaty, + port?: number +} + +const DEFAULT_IO_CLIENT_OPTIONS: Partial = { + port: 8788, } export class IoClient { @@ -52,13 +57,22 @@ export class IoClient { private state: StateSwitch + protected options: Required + constructor ( - public options: IoClientOptions, + options: IoClientOptions, ) { - log.verbose('IoClient', 'constructor({token: %s})', - options.token + log.verbose('IoClient', 'constructor({%s})', + JSON.stringify(options), ) + const normalizedOptions = { + ...DEFAULT_IO_CLIENT_OPTIONS, + ...options, + } as Required + + this.options = normalizedOptions + this.state = new StateSwitch('IoClient', { log }) } @@ -70,7 +84,7 @@ export class IoClient { } const options: PuppetServerOptions = { - endpoint : '0.0.0.0:8788', + endpoint : '0.0.0.0:' + this.options.port, puppet : this.options.wechaty.puppet, token : this.options.token, } @@ -148,8 +162,9 @@ export class IoClient { } this.io = new Io({ - token : this.options.token, - wechaty : this.options.wechaty, + hostiePort : this.options.port, + token : this.options.token, + wechaty : this.options.wechaty, }) try { diff --git a/src/io.ts b/src/io.ts index dbbdae9df..608d5deb8 100644 --- a/src/io.ts +++ b/src/io.ts @@ -44,6 +44,7 @@ export interface IoOptions { token: string, apihost?: string, protocol?: string, + hostiePort: number, } export const IO_EVENT_DICT = { @@ -53,6 +54,7 @@ export const IO_EVENT_DICT = { login : 'tbw', logout : 'tbw', message : 'tbw', + port : 'tbw', raw : 'tbw', reset : 'tbw', scan : 'tbw', @@ -68,12 +70,20 @@ interface IoEventScan { payload : EventScanPayload, } +interface IoEventPort { + name: 'port', + payload: { + asyncId: string, + port: number, + }, +} + interface IoEventAny { name: IoEventName, payload: any, } -type IoEvent = IoEventScan | IoEventAny +type IoEvent = IoEventScan | IoEventPort | IoEventAny export class Io { @@ -327,6 +337,27 @@ export class Io { await this.options.wechaty.logout() break + case 'port': + log.info('Io', 'on(port): %s', ioEvent.payload) + + try { + const payload = (ioEvent as IoEventPort).payload + const asyncId = payload.asyncId + + const portEvent: IoEventPort = { + name : 'port', + payload : { + asyncId, + port: this.options.hostiePort, + }, + } + await this.send(portEvent) + } catch (e) { + log.error('Io', 'on(hostiePort): %s', e) + } + + break + default: log.warn('Io', 'UNKNOWN on(%s): %s', ioEvent.name, ioEvent.payload) break From 3a159142f34e1e4cb492bb2a62e7a8171e4136df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 24 May 2020 13:26:18 +0800 Subject: [PATCH 179/598] enable WECHATY_PUPPET_PORT (#1984) --- src/io-client.ts | 1 - src/io.ts | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/io-client.ts b/src/io-client.ts index d004a6d89..47d18657c 100644 --- a/src/io-client.ts +++ b/src/io-client.ts @@ -162,7 +162,6 @@ export class IoClient { } this.io = new Io({ - hostiePort : this.options.port, token : this.options.token, wechaty : this.options.wechaty, }) diff --git a/src/io.ts b/src/io.ts index 608d5deb8..2d3f6dc69 100644 --- a/src/io.ts +++ b/src/io.ts @@ -44,7 +44,6 @@ export interface IoOptions { token: string, apihost?: string, protocol?: string, - hostiePort: number, } export const IO_EVENT_DICT = { @@ -348,7 +347,7 @@ export class Io { name : 'port', payload : { asyncId, - port: this.options.hostiePort, + port: parseInt(process.env.WECHATY_HOSTIE_PORT || '0'), }, } await this.send(portEvent) From ce9ce383bb04cbcf2f363099e0cd95b1b1fc57c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 24 May 2020 13:29:13 +0800 Subject: [PATCH 180/598] 0.39.35 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 90895268b..230ffa692 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.34", + "version": "0.39.35", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 2e6c525a3b8f6286ea6648dbc4dbc3100770bc08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 24 May 2020 20:01:43 +0800 Subject: [PATCH 181/598] fix stringify --- package.json | 2 +- src/io-client.ts | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 230ffa692..f8f8397f9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.35", + "version": "0.39.36", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", diff --git a/src/io-client.ts b/src/io-client.ts index 47d18657c..b2d7937ee 100644 --- a/src/io-client.ts +++ b/src/io-client.ts @@ -63,7 +63,11 @@ export class IoClient { options: IoClientOptions, ) { log.verbose('IoClient', 'constructor({%s})', - JSON.stringify(options), + Object.keys(options) + .map(key => { + return `${key}:${(options as any)[key]}` + }) + .reduce((acc, cur) => `${acc}, ${cur}`) ) const normalizedOptions = { From 770894ec4a7485a4085a2f5eccfe3d1d2c7beff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 24 May 2020 20:22:23 +0800 Subject: [PATCH 182/598] update links --- docs/index.md | 5 +++-- scripts/generate-docs.sh | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/index.md b/docs/index.md index 76295494e..d95ade3c4 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,7 +1,8 @@ # Wechaty v0.37.7 Documentation -- Blog - -- Docs - +- Blog - +- API References - +- Docs Site - ## Classes diff --git a/scripts/generate-docs.sh b/scripts/generate-docs.sh index ea9a6dec7..d780d20b5 100755 --- a/scripts/generate-docs.sh +++ b/scripts/generate-docs.sh @@ -23,8 +23,9 @@ DOCS_INDEX_MD=docs/index.md cat <<_EOF_ > "$DOCS_INDEX_MD" # Wechaty v$(jq -r .version package.json) Documentation -- Blog - -- Docs - +- Blog - +- API References - +- Docs Site - _EOF_ From 65ea54218b2b83214aed2ab60b7d2042677f80a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 25 May 2020 19:23:03 +0800 Subject: [PATCH 183/598] add JsonRpc for io (#1984) --- package.json | 1 + src/config.ts | 1 + src/io-client.ts | 1 + src/io-peer/io-peer.spec.ts | 59 +++++++++++++++++++++++++ src/io-peer/io-peer.ts | 78 ++++++++++++++++++++++++++++++++++ src/io-peer/json-rpc-peer.d.ts | 65 ++++++++++++++++++++++++++++ src/io.spec.ts | 1 + src/io.ts | 74 +++++++++++++++++++++++--------- src/typings.d.ts | 1 - 9 files changed, 259 insertions(+), 22 deletions(-) create mode 100755 src/io-peer/io-peer.spec.ts create mode 100644 src/io-peer/io-peer.ts create mode 100644 src/io-peer/json-rpc-peer.d.ts diff --git a/package.json b/package.json index f8f8397f9..ec83517c8 100644 --- a/package.json +++ b/package.json @@ -88,6 +88,7 @@ "cuid": "^2.1.8", "hot-import": "^0.2.14", "in-gfw": "^1.2.0", + "json-rpc-peer": "^0.15.5", "npm-programmatic": "0.0.12", "open-graph": "^0.2.4", "opencollective": "^1.0.3", diff --git a/src/config.ts b/src/config.ts index 7bfd29322..3d20288ef 100644 --- a/src/config.ts +++ b/src/config.ts @@ -18,6 +18,7 @@ * */ /// +/// import os from 'os' diff --git a/src/io-client.ts b/src/io-client.ts index b2d7937ee..f9e385028 100644 --- a/src/io-client.ts +++ b/src/io-client.ts @@ -166,6 +166,7 @@ export class IoClient { } this.io = new Io({ + hostiePort : this.options.port, token : this.options.token, wechaty : this.options.wechaty, }) diff --git a/src/io-peer/io-peer.spec.ts b/src/io-peer/io-peer.spec.ts new file mode 100755 index 000000000..5c3261682 --- /dev/null +++ b/src/io-peer/io-peer.spec.ts @@ -0,0 +1,59 @@ +#!/usr/bin/env ts-node + +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ +import test from 'blue-tape' + +import Peer, { + format, + parse, + JsonRpcPayloadResponse, +} from 'json-rpc-peer' + +import { + getPeer, +} from './io-peer' + +test('getPeer()', async t => { + const EXPECTED_PORT = 8788 + const server = getPeer({ + hostieGrpcPort: EXPECTED_PORT, + }) + const client = new Peer() + + server.pipe(client).pipe(server) + + const port = await client.request('getHostieGrpcPort') + t.equal(port, EXPECTED_PORT, 'should get the right port') +}) + +test('exec()', async t => { + const EXPECTED_PORT = 8788 + const server = getPeer({ + hostieGrpcPort: EXPECTED_PORT, + }) + + const request = format.request(42, 'getHostieGrpcPort') + const response = await server.exec(request) as string + // console.info('response: ', response) + + const obj = parse(response) as JsonRpcPayloadResponse + t.equal(obj.result, EXPECTED_PORT, 'should get the right port from payload') +}) diff --git a/src/io-peer/io-peer.ts b/src/io-peer/io-peer.ts new file mode 100644 index 000000000..4761186ee --- /dev/null +++ b/src/io-peer/io-peer.ts @@ -0,0 +1,78 @@ +import Peer, { + JsonRpcPayload, + JsonRpcPayloadError, + JsonRpcPayloadNotification, + JsonRpcPayloadRequest, + JsonRpcPayloadResponse, + // format, + MethodNotFound, +} from 'json-rpc-peer' + +// // https://stackoverflow.com/a/50375286/1123955 +// type UnionToIntersection = +// (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never + +// type UnknownJsonRpcPayload = Partial> + +const isJsonRpcRequest = (payload: JsonRpcPayload): payload is JsonRpcPayloadRequest => payload.type === 'request' +const isJsonRpcNotification = (payload: JsonRpcPayload): payload is JsonRpcPayloadNotification => payload.type === 'notification' +const isJsonRpcResponse = (payload: JsonRpcPayload): payload is JsonRpcPayloadResponse => payload.type === 'response' +const isJsonRpcError = (payload: JsonRpcPayload): payload is JsonRpcPayloadError => payload.type === 'error' + +interface IoPeerOptions { + hostieGrpcPort: number, +} + +const getPeer = (options: IoPeerOptions) => { + const getHostieGrpcPort = () => options.hostieGrpcPort + + const serviceImpl = { + getHostieGrpcPort, + } + + const onMessage = async (message: JsonRpcPayload): Promise => { + if (isJsonRpcRequest(message)) { + const { + // id, + method, + // params, + } = message + + if (!(method in serviceImpl)) { + console.error('serviceImpl does not contain method: ' + method) + return + } + + const serviceMethodName = method as keyof typeof serviceImpl + switch (serviceMethodName) { + case 'getHostieGrpcPort': + return serviceImpl[serviceMethodName]() + + default: + throw new MethodNotFound(serviceMethodName) + } + } else if (isJsonRpcResponse(message)) { + // NOOP: we are server + } else if (isJsonRpcNotification(message)) { + // NOOP: we are server + } else if (isJsonRpcError(message)) { + // NOOP: we are server + } else { + throw new Error('unknown json-rpc message: ' + JSON.stringify(message)) + } + console.info(JSON.stringify(message)) + } + + const ioPeer = new Peer(onMessage) + + return ioPeer +} + +export { + getPeer, + + isJsonRpcError, + isJsonRpcNotification, + isJsonRpcRequest, + isJsonRpcResponse, +} diff --git a/src/io-peer/json-rpc-peer.d.ts b/src/io-peer/json-rpc-peer.d.ts new file mode 100644 index 000000000..18f9205e4 --- /dev/null +++ b/src/io-peer/json-rpc-peer.d.ts @@ -0,0 +1,65 @@ +declare module 'json-rpc-peer' { + + /// + /// + + import { EventEmitter } from 'events' + import { JsonRpcPayload, JsonRpcParamsSchema } from 'json-rpc-protocol' + + // export as namespace JsonRpcPeer + + export * from 'json-rpc-protocol' + + declare module 'json-rpc-peer' { + export class Peer extends EventEmitter implements NodeJS.WritableStream { + + constructor(onmessage?: (message: JsonRpcPayload, data: any) => Promise) + + public exec( + message: string | object, + data?: any + ): Promise + + /** + * Fails all pending requests. + */ + public failPendingRequests(reason?: string) + + /** + * This function should be called to send a request to the other end. + */ + public request(method: string, params?: JsonRpcParamsSchema): Promise + + /** + * This function should be called to send a notification to the other end. + */ + public notify(method: string, params?: JsonRpcParamsSchema) + + public push(chunk: any, encoding?: string) + + public pipe(writable: T): T + + // NodeJS.WritableStream + + writable: boolean + write( + buffer: Uint8Array | string, + cb?: (err?: Error | null) => void + ): boolean + + write( + str: string, + encoding?: string, + cb?: (err?: Error | null) => void + ): boolean + + end(cb?: () => void): void + end(data: string | Uint8Array, cb?: () => void): void + end(str: string, encoding?: string, cb?: () => void): void + + } + + export default Peer + } + +} diff --git a/src/io.spec.ts b/src/io.spec.ts index e6daf0185..d4635a230 100644 --- a/src/io.spec.ts +++ b/src/io.spec.ts @@ -27,6 +27,7 @@ import { Wechaty } from './wechaty' test('Io restart without problem', async t => { const io = new Io({ // token must not contain any white spaces + hostiePort: 8788, token : 'mock_token_in_wechaty/wechaty/src/io.spec.ts', wechaty : new Wechaty(), }) diff --git a/src/io.ts b/src/io.ts index 2d3f6dc69..b76df2c20 100644 --- a/src/io.ts +++ b/src/io.ts @@ -28,6 +28,12 @@ import { EventScanPayload, } from 'wechaty-puppet' +import Peer, { + JsonRpcPayload, + JsonRpcPayloadResponse, + parse, +} from 'json-rpc-peer' + import { config, log, @@ -39,21 +45,27 @@ import { Wechaty, } from './wechaty' +import { + getPeer, + isJsonRpcRequest, +} from './io-peer/io-peer' + export interface IoOptions { wechaty: Wechaty, token: string, apihost?: string, protocol?: string, + hostiePort?:number, } export const IO_EVENT_DICT = { botie : 'tbw', error : 'tbw', heartbeat : 'tbw', + jsonrpc : 'JSON RPC', login : 'tbw', logout : 'tbw', message : 'tbw', - port : 'tbw', raw : 'tbw', reset : 'tbw', scan : 'tbw', @@ -69,12 +81,9 @@ interface IoEventScan { payload : EventScanPayload, } -interface IoEventPort { - name: 'port', - payload: { - asyncId: string, - port: number, - }, +interface IoEventJsonRpc { + name: 'jsonrpc', + payload: JsonRpcPayload, } interface IoEventAny { @@ -82,7 +91,7 @@ interface IoEventAny { payload: any, } -type IoEvent = IoEventScan | IoEventPort | IoEventAny +type IoEvent = IoEventScan | IoEventJsonRpc | IoEventAny export class Io { @@ -102,6 +111,8 @@ export class Io { private scanPayload?: EventScanPayload + protected jsonRpc?: Peer + constructor ( private options: IoOptions, ) { @@ -117,6 +128,13 @@ export class Io { options.protocol, this.id, ) + + if (options.hostiePort) { + this.jsonRpc = getPeer({ + hostieGrpcPort: this.options.hostiePort!, + }) + } + } public toString () { @@ -336,23 +354,37 @@ export class Io { await this.options.wechaty.logout() break - case 'port': - log.info('Io', 'on(port): %s', ioEvent.payload) + case 'jsonrpc': + log.info('Io', 'on(jsonrpc): %s', ioEvent.payload) try { - const payload = (ioEvent as IoEventPort).payload - const asyncId = payload.asyncId - - const portEvent: IoEventPort = { - name : 'port', - payload : { - asyncId, - port: parseInt(process.env.WECHATY_HOSTIE_PORT || '0'), - }, + const request = (ioEvent as IoEventJsonRpc).payload + if (!isJsonRpcRequest(request)) { + log.warn('Io', 'on(jsonrpc) payload is not a jsonrpc request: %s', JSON.stringify(request)) + return } - await this.send(portEvent) + + if (!this.jsonRpc) { + throw new Error('jsonRpc not initialized!') + } + + const response = await this.jsonRpc.exec(request) + if (!response) { + log.warn('Io', 'on(jsonrpc) response is undefined.') + return + } + const payload = parse(response) as JsonRpcPayloadResponse + + const jsonrpcEvent: IoEventJsonRpc = { + name: 'jsonrpc', + payload, + } + + log.verbose('Io', 'on(jsonrpc) send(%s)', response) + await this.send(jsonrpcEvent) + } catch (e) { - log.error('Io', 'on(hostiePort): %s', e) + log.error('Io', 'on(jsonrpc): %s', e) } break diff --git a/src/typings.d.ts b/src/typings.d.ts index 3229dffff..c5e63a5a8 100644 --- a/src/typings.d.ts +++ b/src/typings.d.ts @@ -19,6 +19,5 @@ */ declare module 'bl' declare module 'qrcode-terminal' -declare module 'json-rpc-peer' declare module 'npm-programmatic' declare module 'in-gfw' From f54227a6126fd6c00ce904a29a03492a406a203d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 25 May 2020 19:23:21 +0800 Subject: [PATCH 184/598] 0.39.37 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ec83517c8..4602bd036 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.36", + "version": "0.39.37", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 9ea075f1d8dd77a5dd96516a7f5dea5a5749c9e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 25 May 2020 23:25:06 +0800 Subject: [PATCH 185/598] use Node.js 12 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index e7ec9916a..124d8c79d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,7 +37,7 @@ RUN apt-get update \ && apt-get purge --auto-remove \ && rm -rf /tmp/* /var/lib/apt/lists/* -RUN curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash - \ +RUN curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - \ && apt-get update && apt-get install -y --no-install-recommends nodejs \ && apt-get purge --auto-remove \ && rm -rf /tmp/* /var/lib/apt/lists/* From a27dc6b7a360a65406e5bd29d396123226a43782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 25 May 2020 23:25:19 +0800 Subject: [PATCH 186/598] 0.39.38 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4602bd036..7b4230883 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.37", + "version": "0.39.38", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 39bc35bee1b7e8cb809dc6088a03498764c30256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 26 May 2020 00:21:42 +0800 Subject: [PATCH 187/598] fix type guard for json rpc peer (#1984) --- src/io-peer/io-peer.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/io-peer/io-peer.ts b/src/io-peer/io-peer.ts index 4761186ee..bacc94601 100644 --- a/src/io-peer/io-peer.ts +++ b/src/io-peer/io-peer.ts @@ -14,10 +14,10 @@ import Peer, { // type UnknownJsonRpcPayload = Partial> -const isJsonRpcRequest = (payload: JsonRpcPayload): payload is JsonRpcPayloadRequest => payload.type === 'request' -const isJsonRpcNotification = (payload: JsonRpcPayload): payload is JsonRpcPayloadNotification => payload.type === 'notification' -const isJsonRpcResponse = (payload: JsonRpcPayload): payload is JsonRpcPayloadResponse => payload.type === 'response' -const isJsonRpcError = (payload: JsonRpcPayload): payload is JsonRpcPayloadError => payload.type === 'error' +const isJsonRpcRequest = (payload: JsonRpcPayload): payload is JsonRpcPayloadRequest => ('method' in payload) +const isJsonRpcNotification = (payload: JsonRpcPayload): payload is JsonRpcPayloadNotification => isJsonRpcRequest(payload) && (!('id' in payload)) +const isJsonRpcResponse = (payload: JsonRpcPayload): payload is JsonRpcPayloadResponse => ('result' in payload) +const isJsonRpcError = (payload: JsonRpcPayload): payload is JsonRpcPayloadError => ('error' in payload) interface IoPeerOptions { hostieGrpcPort: number, From b71cb0e6e0d2f0c3a15534a57618036c5e91cd39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 26 May 2020 00:21:54 +0800 Subject: [PATCH 188/598] 0.39.39 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7b4230883..66c243303 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.38", + "version": "0.39.39", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From d0082dbc430e6b38f86f340446ff5f431e1ff9a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 26 May 2020 01:50:44 +0800 Subject: [PATCH 189/598] update hostie --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 66c243303..29c9a3cd0 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "state-switch": "^0.9.9", "watchdog": "^0.8.17", "wechaty-puppet": "^0.25.7", - "wechaty-puppet-hostie": "^0.7.11", + "wechaty-puppet-hostie": "^0.7.12", "ws": "^7.2.3" }, "devDependencies": { From 20fd5a0ddc11ebaf74760ef7e9eac62eb39d3d1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 26 May 2020 01:50:57 +0800 Subject: [PATCH 190/598] 0.39.40 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 29c9a3cd0..a39f2441d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.39", + "version": "0.39.40", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From f54857d83bbcac9181a7531ce3df89bc044c58e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 26 May 2020 20:08:21 +0800 Subject: [PATCH 191/598] add how to create a minimal reproduciable example link to stackoverflow --- .github/ISSUE_TEMPLATE/wechaty-bug-report.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/wechaty-bug-report.md b/.github/ISSUE_TEMPLATE/wechaty-bug-report.md index 6b6aa8a80..ac6c29f49 100644 --- a/.github/ISSUE_TEMPLATE/wechaty-bug-report.md +++ b/.github/ISSUE_TEMPLATE/wechaty-bug-report.md @@ -40,8 +40,11 @@ Answer: Give a clear and concise description of what the bug is. ## 3. To Reproduce + This part is very important: if you can not provide any reproduce steps, then the problem will be very hard to be recognized. +**[How to create a Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example)** + Steps to reproduce the behavior: 1. run '...' 2. ... From d4e3d0ea275e375ddb5b1fcb74adde7020551825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 29 May 2020 02:39:18 +0800 Subject: [PATCH 192/598] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a4a5f6184..8a7eb694a 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ ## Connecting Chatbots -Wechaty is a Bot SDK for Wechat **Individual** Account which can help you create a bot in 6 lines of [JavaScript](https://GitHub.com/Wechaty/wechaty), [Python](https://GitHub.com/Wechaty/python-wechaty/), [Go](https://GitHub.com/Wechaty/go-wechaty/), and [Java](https://GitHub.com/Wechaty/java-wechaty/), with cross-platform support including [Linux, Windows, MacOS](https://github.com/wechaty/wechaty/actions?query=workflow%3ANPM), and [Docker](https://github.com/wechaty/wechaty/actions?query=workflow%3ADocker). +Wechaty is a Conversational AI RPA Chatbot SDK for Wechat **Individual** Account which can help you create a bot in 6 lines of [JavaScript](https://GitHub.com/Wechaty/wechaty), [Python](https://GitHub.com/Wechaty/python-wechaty/), [Go](https://GitHub.com/Wechaty/go-wechaty/), and [Java](https://GitHub.com/Wechaty/java-wechaty/), with cross-platform support including [Linux, Windows, MacOS](https://github.com/wechaty/wechaty/actions?query=workflow%3ANPM), and [Docker](https://github.com/wechaty/wechaty/actions?query=workflow%3ADocker). :octocat: :beetle: From 19050daf6c4a226bb894e44c8233e8ba5fec96d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 29 May 2020 15:46:16 +0800 Subject: [PATCH 193/598] add voice from developers: @mrwhh --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 8a7eb694a..9f3bb40b2 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,9 @@ Wechaty is a Conversational AI RPA Chatbot SDK for Wechat **Individual** Account > > "If you know js ... try Wechaty, it's easy to use." > — @Urinx Uri Lee, Author of [WeixinBot(Python)](https://github.com/Urinx/WeixinBot) +> +> "Wechaty is a good project, I hope it can continue! Therefore, I became a contributors in open collective." +> — [@Simple](https://github.com/mrwhh) See more at [Wiki:Voice Of Developer](https://github.com/Wechaty/wechaty/wiki/Voice%20Of%20Developer) From 2629147c9516786033346528952ac63c3f670345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 2 Jun 2020 04:08:53 +0800 Subject: [PATCH 194/598] 0.40.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a39f2441d..d8220601e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.39.40", + "version": "0.40.0", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 98a48e8a79a5b39bd6718339901568a16f49277d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 2 Jun 2020 04:09:07 +0800 Subject: [PATCH 195/598] 0.40.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d8220601e..24412bdae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.40.0", + "version": "0.40.1", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 86dd9440de1c8d05b890a526a64d89c56ee1cf82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 2 Jun 2020 15:49:50 +0800 Subject: [PATCH 196/598] Delete TODO.md --- TODO.md | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 TODO.md diff --git a/TODO.md b/TODO.md deleted file mode 100644 index ce6d190f2..000000000 --- a/TODO.md +++ /dev/null @@ -1,4 +0,0 @@ -# TODO - -- [x] Puppet -- [ ] PuppetHostie From ce34b75b4ee7bf7891ef32360d8fa0b8cef0671d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 2 Jun 2020 15:50:27 +0800 Subject: [PATCH 197/598] Update NOTICE --- NOTICE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NOTICE b/NOTICE index cbfd0fdee..6ac5759ff 100644 --- a/NOTICE +++ b/NOTICE @@ -1,4 +1,4 @@ -Wechaty Chatbot SDK +Wechaty Conversational AI RPA SDK for Chatbot Copyright 2016 Huan (李卓桓) and Wechaty Contributors. This product includes software developed at From d9d01a735eb10139660e01a8f332fbb1309067ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 2 Jun 2020 15:51:04 +0800 Subject: [PATCH 198/598] Update NOTICE --- NOTICE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NOTICE b/NOTICE index 6ac5759ff..e664fae43 100644 --- a/NOTICE +++ b/NOTICE @@ -1,4 +1,4 @@ -Wechaty Conversational AI RPA SDK for Chatbot +Wechaty, a Conversational AI RPA SDK for Chatbot Copyright 2016 Huan (李卓桓) and Wechaty Contributors. This product includes software developed at From 991f3ad86914dd704c4631b1032062700207f9bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 3 Jun 2020 15:03:38 +0800 Subject: [PATCH 199/598] upgrade wechaty-puppet-hostie@0.8 --- .vscode/settings.json | 1 + package.json | 4 ++-- src/puppet-config.ts | 6 +++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 172e7c638..717600a1d 100755 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -80,6 +80,7 @@ "logonoff", "padchat", "padplus", + "padpro", "pagepath", "qrcode", "removee", diff --git a/package.json b/package.json index 24412bdae..1a8dfce7e 100644 --- a/package.json +++ b/package.json @@ -100,8 +100,8 @@ "read-pkg-up": "^7.0.1", "state-switch": "^0.9.9", "watchdog": "^0.8.17", - "wechaty-puppet": "^0.25.7", - "wechaty-puppet-hostie": "^0.7.12", + "wechaty-puppet": "^0.26.1", + "wechaty-puppet-hostie": "^0.8.3", "ws": "^7.2.3" }, "devDependencies": { diff --git a/src/puppet-config.ts b/src/puppet-config.ts index f4ff939c7..7821184b5 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -31,15 +31,15 @@ export const PUPPET_DEPENDENCIES = { '@juzibot/wechaty-puppet-donut': '^0.3', // https://www.npmjs.com/package/wechaty-puppet-donut (to be published) /** - * Wechaty Internal Puppets: dependenced by package.json + * Wechaty Internal Puppets: dependence by package.json */ - 'wechaty-puppet-hostie' : '^0.7.9', // https://www.npmjs.com/package/wechaty-puppet-hostie + 'wechaty-puppet-hostie' : '^0.8.3', // https://www.npmjs.com/package/wechaty-puppet-hostie 'wechaty-puppet-mock' : '^0.21.2', // https://www.npmjs.com/package/wechaty-puppet-mock /** * Wechaty External Puppets */ - 'wechaty-puppet-padplus' : '^0.7.15', // https://www.npmjs.com/package/wechaty-puppet-padplus + 'wechaty-puppet-padplus' : '^0.7.18', // https://www.npmjs.com/package/wechaty-puppet-padplus 'wechaty-puppet-puppeteer' : '^0.21.2', // https://www.npmjs.com/package/wechaty-puppet-puppeteer 'wechaty-puppet-wechat4u' : '^0.17.4', // https://www.npmjs.com/package/wechaty-puppet-wechat4u } From 1157c5bb30c9adc52b9f6cc9746a2de8a9858b46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 3 Jun 2020 15:04:05 +0800 Subject: [PATCH 200/598] 0.40.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1a8dfce7e..d1106cb3e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.40.1", + "version": "0.40.2", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 7a97b58673c3d7d4c3342a1a62973843d43637ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 4 Jun 2020 22:20:18 +0800 Subject: [PATCH 201/598] add Scala Wechaty --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 9f3bb40b2..8e10bfd7a 100644 --- a/README.md +++ b/README.md @@ -409,6 +409,14 @@ Support this project by becoming a sponsor. Your logo will show up here with a l [![Wechaty Sponsor](https://opencollective.com/wechaty/sponsor.svg?width=890)](https://opencollective.com/wechaty/#sponsor) +## Multi-language Wechaty + +- [Wechaty](https://github.com/wechaty/wechaty) - Conversatioanl AI Chatot SDK for Wechaty Individual Accounts (TypeScript) +- [Python Wechaty](https://github.com/wechaty/python-wechaty) - Python WeChaty Conversational AI Chatbot SDK for Wechat Individual Accounts (Python) +- [Go Wechaty](https://github.com/wechaty/go-wechaty) - Go WeChaty Conversational AI Chatbot SDK for Wechat Individual Accounts (Go) +- [Java Wechaty](https://github.com/wechaty/java-wechaty) - Java WeChaty Conversational AI Chatbot SDK for Wechat Individual Accounts (Java) +- [Scala Wechaty](https://github.com/wechaty/scala-wechaty) - Scala WeChaty Conversational AI Chatbot SDK for WechatyIndividual Accounts (Scala) + ## Author 1. [Huan](https://github.com/huan) [(李卓桓)](http://linkedin.com/in/zixia), Tencent TVP of Chatbot From a31d63a456e8de9803dc80c0fffefbd040868a9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 4 Jun 2020 22:20:25 +0800 Subject: [PATCH 202/598] upgrade mock to support mocker! --- package.json | 2 +- src/puppet-config.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 24412bdae..6a75de90e 100644 --- a/package.json +++ b/package.json @@ -134,7 +134,7 @@ "sloc": "^0.2.1", "tstest": "^0.4.10", "typedoc": "^0.16.11", - "wechaty-puppet-mock": "^0.21.2" + "wechaty-puppet-mock": "^0.22.2" }, "files_comment__whitelist_npm_publish": "http://stackoverflow.com/a/8617868/1123955", "files": [ diff --git a/src/puppet-config.ts b/src/puppet-config.ts index f4ff939c7..b77c9c439 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -34,7 +34,7 @@ export const PUPPET_DEPENDENCIES = { * Wechaty Internal Puppets: dependenced by package.json */ 'wechaty-puppet-hostie' : '^0.7.9', // https://www.npmjs.com/package/wechaty-puppet-hostie - 'wechaty-puppet-mock' : '^0.21.2', // https://www.npmjs.com/package/wechaty-puppet-mock + 'wechaty-puppet-mock' : '^0.22.3', // https://www.npmjs.com/package/wechaty-puppet-mock /** * Wechaty External Puppets From 3360b615107d096909f2b4ea9970040207d68dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 4 Jun 2020 22:20:38 +0800 Subject: [PATCH 203/598] 0.40.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6a75de90e..81e10b80a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.40.1", + "version": "0.40.2", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From abbf6808bd8ce98304d516652a67374e7b0700b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 4 Jun 2020 22:21:35 +0800 Subject: [PATCH 204/598] 0.40.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9ed83f3bf..c8c5e9e13 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.40.2", + "version": "0.40.3", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 8c8c092e027168987c3d058ac09195ffa363aa45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 5 Jun 2020 01:48:12 +0800 Subject: [PATCH 205/598] fix mentionIdList typing --- src/user/message.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/user/message.ts b/src/user/message.ts index 141ff0249..2f8999f50 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -670,13 +670,13 @@ export class Message extends Accessory implements Sayable { * Use mention list if mention list is available * otherwise, process the message and get the mention list */ - if (this.payload && this.payload.mentionIdList) { + if (this.payload && 'mentionIdList' in this.payload) { const idToContact = async (id: string) => { const contact = this.wechaty.Contact.load(id) await contact.ready() return contact } - return Promise.all(this.payload.mentionIdList.map(idToContact)) + return Promise.all(this.payload.mentionIdList?.map(idToContact) ?? []) } /** From 93474ddde33eba19ca1d36531292e6149640acd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 5 Jun 2020 01:48:24 +0800 Subject: [PATCH 206/598] 0.40.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c8c5e9e13..e89a51164 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.40.3", + "version": "0.40.4", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 4db7a7f60ce6ee25f1c61a3b71bdad1a5b83c41a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 6 Jun 2020 23:01:57 +0800 Subject: [PATCH 207/598] import log from puppet --- src/config.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/config.ts b/src/config.ts index 3d20288ef..274a97fb2 100644 --- a/src/config.ts +++ b/src/config.ts @@ -25,11 +25,10 @@ import os from 'os' import Raven from 'raven' import readPkgUp from 'read-pkg-up' -import { log } from 'brolog' - import { FileBox, MemoryCard, + log, } from 'wechaty-puppet' import { @@ -76,12 +75,6 @@ Raven.context(function () { }) */ -const logLevel = process.env.WECHATY_LOG -if (logLevel) { - log.level(logLevel.toLowerCase() as any) - log.silly('Config', 'WECHATY_LOG set level to %s', logLevel) -} - /** * to handle unhandled exceptions */ From 1ef3de4e4b51fd06b21da7c36e99fcdea53609b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 6 Jun 2020 23:02:06 +0800 Subject: [PATCH 208/598] fix typo --- .vscode/settings.json | 1 + src/user/contact.ts | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 717600a1d..9bf0a5585 100755 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -84,6 +84,7 @@ "pagepath", "qrcode", "removee", + "ruirui", "thumbnailurl", "wechat", "weixin", diff --git a/src/user/contact.ts b/src/user/contact.ts index 2ee187891..b9d0c10a3 100644 --- a/src/user/contact.ts +++ b/src/user/contact.ts @@ -100,7 +100,7 @@ export class Contact extends Accessory implements Sayable { } if (this === Contact) { throw new Error( - 'The lgobal Contact class can not be used directly!' + 'The global Contact class can not be used directly!' + 'See: https://github.com/wechaty/wechaty/issues/1217', ) } @@ -203,7 +203,7 @@ export class Contact extends Accessory implements Sayable { * const bot = new Wechaty() * await bot.start() * const contactList = await bot.Contact.findAll() // get the contact list of the bot - * const contactList = await bot.Contact.findAll({ name: 'ruirui' }) // find allof the contacts whose name is 'ruirui' + * const contactList = await bot.Contact.findAll({ name: 'ruirui' }) // find all of the contacts whose name is 'ruirui' * const contactList = await bot.Contact.findAll({ alias: 'lijiarui' }) // find all of the contacts whose alias is 'lijiarui' */ public static async findAll ( @@ -294,13 +294,13 @@ export class Contact extends Accessory implements Sayable { if (MyClass === Contact) { throw new Error( - 'Contact class can not be instanciated directly!' + 'Contact class can not be instantiated directly!' + 'See: https://github.com/wechaty/wechaty/issues/1217', ) } if (!this.puppet) { - throw new Error('Contact class can not be instanciated without a puppet!') + throw new Error('Contact class can not be instantiated without a puppet!') } } @@ -562,7 +562,7 @@ export class Contact extends Accessory implements Sayable { */ /** * @description - * Check if it's a offical account, should use {@link Contact#type} instead + * Check if it's a official account, should use {@link Contact#type} instead * @deprecated * @ignore */ @@ -718,7 +718,7 @@ export class Contact extends Accessory implements Sayable { } /** - * Force reload data for Contact, Sync data from lowlevel API again. + * Force reload data for Contact, Sync data from low-level API again. * * @returns {Promise} * @example @@ -732,7 +732,7 @@ export class Contact extends Accessory implements Sayable { * `ready()` is For FrameWork ONLY! * * Please not to use `ready()` at the user land. - * If you want to sync data, uyse `sync()` instead. + * If you want to sync data, use `sync()` instead. * * @ignore */ From ae61df819dc0f9e61d270e552c59e13a657cf5c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 6 Jun 2020 23:02:23 +0800 Subject: [PATCH 209/598] 0.40.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d1106cb3e..00c46de92 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.40.2", + "version": "0.40.3", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From a913ef11b1861206f48d35b3a6eb073f5f4d3371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 6 Jun 2020 23:03:41 +0800 Subject: [PATCH 210/598] 0.40.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e89a51164..9111a6c39 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.40.4", + "version": "0.40.5", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 0753a68f0fdd2e2ffb6c88b50ec07e04c788f388 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 7 Jun 2020 18:21:14 +0800 Subject: [PATCH 211/598] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8e10bfd7a..d6a3f534a 100644 --- a/README.md +++ b/README.md @@ -417,7 +417,7 @@ Support this project by becoming a sponsor. Your logo will show up here with a l - [Java Wechaty](https://github.com/wechaty/java-wechaty) - Java WeChaty Conversational AI Chatbot SDK for Wechat Individual Accounts (Java) - [Scala Wechaty](https://github.com/wechaty/scala-wechaty) - Scala WeChaty Conversational AI Chatbot SDK for WechatyIndividual Accounts (Scala) -## Author +## Authors 1. [Huan](https://github.com/huan) [(李卓桓)](http://linkedin.com/in/zixia), Tencent TVP of Chatbot 1. [Rui (李佳芮)](https://pre-angel.com/peoples/jiarui-li/) @@ -426,6 +426,6 @@ Support this project by becoming a sponsor. Your logo will show up here with a l ## Copyright & License -- Code & Docs © 2016 Huan LI \ +- Code & Docs © 2016 Huan, Rui, and Wechaty Contributors - Code released under the Apache-2.0 License - Docs released under Creative Commons From 202414b24c181706badace7e9bdf9133bfde2ed9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 8 Jun 2020 12:34:37 +0800 Subject: [PATCH 212/598] Minimum requires Node.js v12 --- README.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8e10bfd7a..f8b574ae9 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ Wechaty.instance() // Global Instance .start() ``` -> **Notice: Wechaty requires Node.js version >= 10** +> **Notice: Wechaty requires Node.js version >= 12** This bot can log all messages to the console after login by scan. @@ -68,7 +68,7 @@ You can find more examples from [Wiki](https://github.com/Wechaty/wechaty/wiki/E ## Requirements -1. Node.js v10 +1. Node.js v12 1. `sudo apt-get install build-essential && sudo snap install shellcheck` ## Getting Started diff --git a/package.json b/package.json index e89a51164..3e7dbe2fb 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "coverage": "nyc report --reporter=text-lcov | coveralls", "changelog": "github_changelog_generator -u wechaty -p wechaty && sed -i'.bak' /greenkeeper/d CHANGELOG.md && sed -i'.bak' /Snyk/d CHANGELOG.md && sed -i'.bak' '/An in-range update of/d' CHANGELOG.md && ts-node scripts/sort-contributiveness.ts < CHANGELOG.md > CHANGELOG.new.md 2>/dev/null && cat CHANGELOG.md >> CHANGELOG.new.md && mv CHANGELOG.new.md CHANGELOG.md", "doctor": "npm run check-node-version && ts-node bin/doctor", - "check-node-version": "check-node-version --node \">= 10\"", + "check-node-version": "check-node-version --node \">= 12\"", "lint": "npm run check-node-version && npm run lint:es && npm run lint:ts && npm run lint:sh && npm run lint:md", "lint:es": "eslint --ignore-pattern node_modules/ --ignore-pattern fixtures/ \"{bin,examples,src,scripts,tests}/**/*.ts\"", "lint:md": "markdownlint README.md", From 7719b631d97c408d79c045dbc6a780b3896ec8d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 8 Jun 2020 12:34:49 +0800 Subject: [PATCH 213/598] 0.40.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3e7dbe2fb..7f8913003 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.40.4", + "version": "0.40.5", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From b77471db2856f8b0ec1de5f03090bfa816eddd8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 8 Jun 2020 13:04:38 +0800 Subject: [PATCH 214/598] 0.40.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7f8913003..41b9d5808 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.40.5", + "version": "0.40.6", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From d9518ccb0b1635964dba27944246b48b78083f9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 9 Jun 2020 18:33:46 +0800 Subject: [PATCH 215/598] add uninstaller for plugin interface (#1939) --- src/wechaty.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wechaty.ts b/src/wechaty.ts index e0d5c5097..32cfb5cbf 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -114,8 +114,9 @@ export interface WechatyOptions { ioToken? : string, // Io TOKEN } +type WechatyPluginUninstaller = () => void export interface WechatyPlugin { - (bot: Wechaty): void + (bot: Wechaty): void | WechatyPluginUninstaller } const PUPPET_MEMORY_NAME = 'puppet' From 367c231cc122b440bcaef57510739e81c90ded4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 9 Jun 2020 18:34:29 +0800 Subject: [PATCH 216/598] 0.40.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9111a6c39..021196901 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.40.5", + "version": "0.40.6", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 9aa25a4f01fc746b3408fb51ba86382ac62a35c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 9 Jun 2020 18:35:01 +0800 Subject: [PATCH 217/598] 0.40.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 41b9d5808..a73f339e3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.40.6", + "version": "0.40.7", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 608bbd2f2b6594a7725e1cec21ba6c120cacffa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 9 Jun 2020 18:36:32 +0800 Subject: [PATCH 218/598] require node v12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a73f339e3..2df28cb69 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ }, "homepage": "https://github.com/wechaty/", "engines": { - "node": ">= 10" + "node": ">= 12" }, "dependencies": { "brolog": "^1.8.3", From e0b02a6fec67dd379ab7be1ac80bba22997099a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 9 Jun 2020 18:36:49 +0800 Subject: [PATCH 219/598] 0.40.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2df28cb69..dbe842602 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.40.7", + "version": "0.40.8", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 245c6e0bbe0e2614037354930e0880f0f496ea6d Mon Sep 17 00:00:00 2001 From: Zihua Wu Date: Wed, 10 Jun 2020 02:33:21 +0800 Subject: [PATCH 220/598] fix: typo in README.md (#1989) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a1d4d258c..b4b820cd2 100644 --- a/README.md +++ b/README.md @@ -160,13 +160,13 @@ A `Bot` is a Wechaty instance that control a specific [wechaty-puppet](https://g - `new Wechaty(options?: WechatyOptions)` 1. `options.name?: string` the name of this bot(optional) - 2. `optoins.puppet?: string` select which puppet provider we want to use. must be one of the: + 2. `options.puppet?: string` select which puppet provider we want to use. must be one of the: 1. [wechaty-puppet-puppeteer](https://github.com/Wechaty/wechaty-puppet-puppeteer) - Angular Hook for Web Wechat <- This is the DEFAULT 2. [wechaty-puppet-wechat4u](https://github.com/Wechaty/wechaty-puppet-wechat4u) - HTTP API for Web Wechat 3. [wechaty-puppet-padpro](https://github.com/botorange/wechaty-puppet-padpro) - iPad App Protocol 4. [wechaty-puppet-ioscat](https://github.com/linyimin-bupt/wechaty-puppet-ioscat) - iPhone App Hook 5. [wechaty-puppet-mock](https://github.com/Wechaty/wechaty-puppet-mock) - Mock for Testing - 3. `optoins.puppetOptions?: PuppetOptions` options for the puppet provider. + 3. `options.puppetOptions?: PuppetOptions` options for the puppet provider. | Wechaty | API | Description | | :--- | :--- | :--- | From 7db0ca9f1077d69fa03fb8a21bdd2d0f560c1146 Mon Sep 17 00:00:00 2001 From: William Chen Date: Tue, 9 Jun 2020 11:46:56 -0700 Subject: [PATCH 221/598] test: update workflows for node ^12 (#1993) --- .circleci/config.yml | 2 +- .github/workflows/node.js.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 498423d99..046002666 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -13,7 +13,7 @@ jobs: - run: name: Install Node.js command: | - curl --silent --location https://rpm.nodesource.com/setup_10.x | sudo bash - + curl --silent --location https://rpm.nodesource.com/setup_12.x | sudo bash - sudo yum -y install nodejs - run: diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index b7357b001..47a56e730 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -14,7 +14,7 @@ jobs: strategy: matrix: os: [macos-latest, windows-latest, ubuntu-latest] - node-version: [10.x, 11.x, 12.x, 13.x] + node-version: [12.x, 13.x] runs-on: ${{ matrix.os }} steps: From 215ec727df8ca4d23c189e575fe85819466f33f0 Mon Sep 17 00:00:00 2001 From: ax4 Date: Wed, 10 Jun 2020 11:27:27 +0800 Subject: [PATCH 222/598] fix: fix the broken URLs links to /bot-qr-code.png (#1994) given expired links to the picture file --- docs/index.md | 10 +++++----- src/user/contact-self.ts | 2 +- src/user/contact.ts | 2 +- src/user/message.ts | 2 +- src/user/room.ts | 2 +- src/wechaty.ts | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/index.md b/docs/index.md index d95ade3c4..a27022074 100644 --- a/docs/index.md +++ b/docs/index.md @@ -359,7 +359,7 @@ await bot.say(contact) // 3. send Image to bot itself from remote url import { FileBox } from 'wechaty' -const fileBox = FileBox.fromUrl('https://chatie.io/wechaty/images/bot-qr-code.png') +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 @@ -483,7 +483,7 @@ const msg = await room.say('Hello world!') // only supported by puppet-padplus // 2. Send media file inside Room import { FileBox } from 'wechaty' -const fileBox1 = FileBox.fromUrl('https://chatie.io/wechaty/images/bot-qr-code.png') +const fileBox1 = FileBox.fromUrl('https://wechaty.github.io/wechaty/images/bot-qr-code.png') const fileBox2 = FileBox.fromLocal('/tmp/text.txt') await room.say(fileBox1) const msg1 = await room.say(fileBox1) // only supported by puppet-padplus @@ -1019,7 +1019,7 @@ const msg = await contact.say('welcome to wechaty!') // only supported by puppet // 2. send media file to contact import { FileBox } from 'wechaty' -const fileBox1 = FileBox.fromUrl('https://chatie.io/wechaty/images/bot-qr-code.png') +const fileBox1 = FileBox.fromUrl('https://wechaty.github.io/wechaty/images/bot-qr-code.png') const fileBox2 = FileBox.fromFile('/tmp/text.txt') await contact.say(fileBox1) const msg1 = await contact.say(fileBox1) // only supported by puppet-padplus @@ -1309,7 +1309,7 @@ bot.on('login', (user: ContactSelf) => { import { FileBox } from 'wechaty' bot.on('login', (user: ContactSelf) => { console.log(`user ${user} login`) - const fileBox = FileBox.fromUrl('https://chatie.io/wechaty/images/bot-qr-code.png') + const fileBox = FileBox.fromUrl('https://wechaty.github.io/wechaty/images/bot-qr-code.png') await user.avatar(fileBox) console.log(`Change bot avatar successfully!`) }) @@ -1720,7 +1720,7 @@ bot // 1. send Image if (/^ding$/i.test(m.text())) { - const fileBox = FileBox.fromUrl('https://chatie.io/wechaty/images/bot-qr-code.png') + const fileBox = FileBox.fromUrl('https://wechaty.github.io/wechaty/images/bot-qr-code.png') await msg.say(fileBox) const message = await msg.say(fileBox) // only supported by puppet-padplus } diff --git a/src/user/contact-self.ts b/src/user/contact-self.ts index 2b995db29..d11bc98a0 100644 --- a/src/user/contact-self.ts +++ b/src/user/contact-self.ts @@ -73,7 +73,7 @@ export class ContactSelf extends Contact { * import { FileBox } from 'wechaty' * bot.on('login', (user: ContactSelf) => { * console.log(`user ${user} login`) - * const fileBox = FileBox.fromUrl('https://chatie.io/wechaty/images/bot-qr-code.png') + * const fileBox = FileBox.fromUrl('https://wechaty.github.io/wechaty/images/bot-qr-code.png') * await user.avatar(fileBox) * console.log(`Change bot avatar successfully!`) * }) diff --git a/src/user/contact.ts b/src/user/contact.ts index b9d0c10a3..3c2b22f76 100644 --- a/src/user/contact.ts +++ b/src/user/contact.ts @@ -347,7 +347,7 @@ export class Contact extends Accessory implements Sayable { * // 2. send media file to contact * * import { FileBox } from 'wechaty' - * const fileBox1 = FileBox.fromUrl('https://chatie.io/wechaty/images/bot-qr-code.png') + * const fileBox1 = FileBox.fromUrl('https://wechaty.github.io/wechaty/images/bot-qr-code.png') * const fileBox2 = FileBox.fromFile('/tmp/text.txt') * await contact.say(fileBox1) * const msg1 = await contact.say(fileBox1) // only supported by puppet-padplus diff --git a/src/user/message.ts b/src/user/message.ts index 2f8999f50..3413429f2 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -445,7 +445,7 @@ export class Message extends Accessory implements Sayable { * // 1. send Image * * if (/^ding$/i.test(m.text())) { - * const fileBox = FileBox.fromUrl('https://chatie.io/wechaty/images/bot-qr-code.png') + * const fileBox = FileBox.fromUrl('https://wechaty.github.io/wechaty/images/bot-qr-code.png') * await msg.say(fileBox) * const message = await msg.say(fileBox) // only supported by puppet-padplus * } diff --git a/src/user/room.ts b/src/user/room.ts index 22ce1e7d6..3ade52eae 100644 --- a/src/user/room.ts +++ b/src/user/room.ts @@ -409,7 +409,7 @@ export class Room extends Accessory implements Sayable { * * // 2. Send media file inside Room * import { FileBox } from 'wechaty' - * const fileBox1 = FileBox.fromUrl('https://chatie.io/wechaty/images/bot-qr-code.png') + * const fileBox1 = FileBox.fromUrl('https://wechaty.github.io/wechaty/images/bot-qr-code.png') * const fileBox2 = FileBox.fromLocal('/tmp/text.txt') * await room.say(fileBox1) * const msg1 = await room.say(fileBox1) // only supported by puppet-padplus diff --git a/src/wechaty.ts b/src/wechaty.ts index 32cfb5cbf..0dd2121fe 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -1106,7 +1106,7 @@ export class Wechaty extends EventEmitter implements Sayable { * * // 3. send Image to bot itself from remote url * import { FileBox } from 'wechaty' - * const fileBox = FileBox.fromUrl('https://chatie.io/wechaty/images/bot-qr-code.png') + * 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 From be069085300858505f9000c9410fde781578c822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 10 Jun 2020 16:13:01 +0800 Subject: [PATCH 223/598] add contact for room.say --- src/user/room.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/user/room.ts b/src/user/room.ts index 3ade52eae..ddd0647d6 100644 --- a/src/user/room.ts +++ b/src/user/room.ts @@ -383,6 +383,7 @@ export class Room extends Accessory implements Sayable { public say (file: FileBox) : Promise public say (url: UrlLink) : Promise public say (mini: MiniProgram) : Promise + public say (contact: Contact) : Promise public say (...args: never[]): never From 8d0be48752079695a33dd8e8de8b82a109c99dc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 10 Jun 2020 16:13:18 +0800 Subject: [PATCH 224/598] 0.40.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dbe842602..7438633dd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.40.8", + "version": "0.40.9", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 7c3360ff4e95bf781b8b64127d02713ab506833d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 11 Jun 2020 14:19:34 +0800 Subject: [PATCH 225/598] Support say(message) --- src/user/contact.ts | 17 ++++++++++++----- src/user/message.ts | 32 ++++++++++++++++++++++++-------- src/user/room.ts | 12 +++++++++++- 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/user/contact.ts b/src/user/contact.ts index 3c2b22f76..0c34421a5 100644 --- a/src/user/contact.ts +++ b/src/user/contact.ts @@ -320,11 +320,12 @@ export class Contact extends Accessory implements Sayable { return `Contact<${identity}>` } - public async say (text: string) : Promise - public async say (contact: Contact) : Promise - public async say (file: FileBox) : Promise - public async say (mini: MiniProgram) : Promise - public async say (url: UrlLink) : Promise + public say (text: string) : Promise + public say (message: Message) : Promise + public say (contact: Contact) : Promise + public say (file: FileBox) : Promise + public say (mini: MiniProgram) : Promise + public say (url: UrlLink) : Promise /** * > Tips: @@ -385,12 +386,18 @@ export class Contact extends Accessory implements Sayable { */ public async say ( something: string + | Message | Contact | FileBox | MiniProgram | UrlLink ): Promise { log.verbose('Contact', 'say(%s)', something) + + if (something instanceof Message) { + return something.forward(this) + } + let msgId: string | void if (typeof something === 'string') { /** diff --git a/src/user/message.ts b/src/user/message.ts index 3413429f2..e6bade322 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -416,13 +416,14 @@ export class Message extends Accessory implements Sayable { } } - public async say (text: string, mention?: Contact | Contact[]) : Promise - public async say (contact: Contact) : Promise - public async say (file: FileBox) : Promise - public async say (url: UrlLink) : Promise - public async say (mini: MiniProgram) : Promise - - public async say (...args: never[]): Promise + public say (text: string, mention?: Contact | Contact[]) : Promise + public say (message: Message) : Promise + public say (contact: Contact) : Promise + public say (file: FileBox) : Promise + public say (url: UrlLink) : Promise + public say (mini: MiniProgram) : Promise + + public say (...args: never[]): Promise /** * Reply a Text or Media File message to the sender. * > Tips: @@ -501,7 +502,12 @@ export class Message extends Accessory implements Sayable { * .start() */ public async say ( - textOrContactOrFileOrUrlOrMini : string | Contact | FileBox | UrlLink | MiniProgram, + textOrContactOrFileOrUrlOrMini : string + | Message + | Contact + | FileBox + | UrlLink + | MiniProgram, ): Promise { log.verbose('Message', 'say(%s)', textOrContactOrFileOrUrlOrMini) @@ -511,14 +517,24 @@ export class Message extends Accessory implements Sayable { const room = this.room() let conversationId: string + let conversation if (room) { + conversation = room conversationId = room.id } else if (from) { + conversation = from conversationId = from.id } else { throw new Error('neither room nor from?') } + /** + * Support say a existing message: just forward it. + */ + if (textOrContactOrFileOrUrlOrMini instanceof Message) { + return textOrContactOrFileOrUrlOrMini.forward(conversation) + } + let msgId: void | string if (typeof textOrContactOrFileOrUrlOrMini === 'string') { /** diff --git a/src/user/room.ts b/src/user/room.ts index ddd0647d6..28f9ddf51 100644 --- a/src/user/room.ts +++ b/src/user/room.ts @@ -378,6 +378,7 @@ export class Room extends Accessory implements Sayable { } public say (text: string) : Promise + public say (message: Message) : Promise public say (text: string, ...mentionList: Contact[]) : Promise public say (textList: TemplateStringsArray, ...varList: any[]) : Promise public say (file: FileBox) : Promise @@ -458,6 +459,7 @@ export class Room extends Accessory implements Sayable { */ public async say ( something : string + | Message | Contact | FileBox | MiniProgram @@ -474,12 +476,20 @@ export class Room extends Accessory implements Sayable { let text: string let msgId: string | void + if (something instanceof Message) { + return something.forward(this) + } + + function isTemplateStringArray (tsa: any): tsa is TemplateStringsArray { + return tsa instanceof Array + } + /** * * 0. TemplateStringArray * */ - if (something instanceof Array) { + if (isTemplateStringArray(something)) { const msgId = await this.sayTemplateStringsArray( something as TemplateStringsArray, ...varList, From ffdd883e02c0d4243fa2810645b7b1599137d26b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 11 Jun 2020 14:19:49 +0800 Subject: [PATCH 226/598] 0.40.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7438633dd..a0d22e3bc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.40.9", + "version": "0.40.10", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 8f66a6547040571c714d3fe522c1f0198b12f22b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 12 Jun 2020 23:21:29 +0800 Subject: [PATCH 227/598] remove hot import support (#1997) --- package.json | 3 +- src/wechaty.ts | 159 ++++++++++++++++++++----------------------------- 2 files changed, 64 insertions(+), 98 deletions(-) diff --git a/package.json b/package.json index a0d22e3bc..db83725a0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.40.10", + "version": "0.41.0", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", @@ -86,7 +86,6 @@ "brolog": "^1.8.3", "clone-class": "^0.7.3", "cuid": "^2.1.8", - "hot-import": "^0.2.14", "in-gfw": "^1.2.0", "json-rpc-peer": "^0.15.5", "npm-programmatic": "0.0.12", diff --git a/src/wechaty.ts b/src/wechaty.ts index 0dd2121fe..2f4650a57 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -22,14 +22,8 @@ import { EventEmitter } from 'events' import os from 'os' import { - // Constructor, cloneClass, - // instanceToClass, } from 'clone-class' -import { - callerResolve, - hotImport, -} from 'hot-import' import { StateSwitch, } from 'state-switch' @@ -51,7 +45,6 @@ import { Raven, config, - isProduction, log, } from './config' @@ -61,7 +54,6 @@ import { } from './version' import { - AnyFunction, Sayable, } from './types' @@ -102,6 +94,24 @@ export const WECHATY_EVENT_DICT = { export type WechatyEventName = keyof typeof WECHATY_EVENT_DICT +/** + * Wechaty Event Listener Interfaces + */ +export type WechatyDongEventListener = (this: Wechaty, data?: string) => void +export type WechatyErrorEventListener = (this: Wechaty, error: Error) => void +export type WechatyFriendshipEventListener = (this: Wechaty, friendship: Friendship) => void +export type WechatyHeartbeatEventListener = (this: Wechaty, data: any) => void +export type WechatyLoginEventListener = (this: Wechaty, user: ContactSelf) => void +export type WechatyLogoutEventListener = (this: Wechaty, user: ContactSelf, reason?: string) => void +export type WechatyMessageEventListener = (this: Wechaty, message: Message) => void +export type WechatyReadyEventListener = (this: Wechaty) => void +export type WechatyRoomInviteEventListener = (this: Wechaty, roomInvitation: RoomInvitation) => void +export type WechatyRoomJoinEventListener = (this: Wechaty, room: Room, inviteeList: Contact[], inviter: Contact, date?: Date) => void +export type WechatyRoomLeaveEventListener = (this: Wechaty, room: Room, leaverList: Contact[], remover?: Contact, date?: Date) => void +export type WechatyRoomTopicEventListener = (this: Wechaty, room: Room, newTopic: string, oldTopic: string, changer: Contact, date?: Date) => void +export type WechatyScanEventListener = (this: Wechaty, qrcode: string, status: ScanStatus, data?: string) => void +export type WechatyStartStopEventListener = (this: Wechaty) => void + export interface WechatyOptions { memory? : MemoryCard, name? : string, // Wechaty Name @@ -345,20 +355,20 @@ export class Wechaty extends EventEmitter implements Sayable { return this.options.name || 'wechaty' } - public emit (event: 'dong', data?: string) : boolean - public emit (event: 'error', error: Error) : boolean - public emit (event: 'friendship', friendship: Friendship) : boolean - public emit (event: 'heartbeat', data: any) : boolean - public emit (event: 'login', user: ContactSelf) : boolean - public emit (event: 'logout', user: ContactSelf, reason?: string) : boolean - public emit (event: 'message', message: Message) : boolean - public emit (event: 'ready') : boolean - public emit (event: 'room-invite', roomInvitation: RoomInvitation) : boolean + public emit (event: 'dong', data?: string) : boolean + public emit (event: 'error', error: Error) : boolean + public emit (event: 'friendship', friendship: Friendship) : boolean + public emit (event: 'heartbeat', data: any) : boolean + public emit (event: 'login', user: ContactSelf) : boolean + public emit (event: 'logout', user: ContactSelf, reason?: string) : boolean + public emit (event: 'message', message: Message) : boolean + public emit (event: 'ready') : boolean + public emit (event: 'room-invite', roomInvitation: RoomInvitation) : boolean public emit (event: 'room-join', room: Room, inviteeList : Contact[], inviter : Contact, date: Date) : boolean public emit (event: 'room-leave', room: Room, leaverList : Contact[], remover : Contact, date: Date) : boolean public emit (event: 'room-topic', room: Room, newTopic: string, oldTopic: string, changer: Contact, date: Date) : boolean - public emit (event: 'scan', qrcode: string, status: ScanStatus, data?: string) : boolean - public emit (event: 'start' | 'stop') : boolean + public emit (event: 'scan', qrcode: string, status: ScanStatus, data?: string) : boolean + public emit (event: 'start' | 'stop') : boolean // guard for the above event: make sure it includes all the possible values public emit (event: never, listener: never): never @@ -370,20 +380,20 @@ export class Wechaty extends EventEmitter implements Sayable { return super.emit(event, ...args) } - public on (event: 'dong', listener: string | ((this: Wechaty, data?: string) => void)) : this - public on (event: 'error', listener: string | ((this: Wechaty, error: Error) => void)) : this - public on (event: 'friendship', listener: string | ((this: Wechaty, friendship: Friendship) => void)) : this - public on (event: 'heartbeat', listener: string | ((this: Wechaty, data: any) => void)) : this - public on (event: 'login', listener: string | ((this: Wechaty, user: ContactSelf) => void)) : this - public on (event: 'logout', listener: string | ((this: Wechaty, user: ContactSelf, reason?: string) => void)) : this - public on (event: 'message', listener: string | ((this: Wechaty, message: Message) => void)) : this - public on (event: 'ready', listener: string | ((this: Wechaty) => void)) : this - public on (event: 'room-invite', listener: string | ((this: Wechaty, roomInvitation: RoomInvitation) => void)) : this - public on (event: 'room-join', listener: string | ((this: Wechaty, room: Room, inviteeList: Contact[], inviter: Contact, date?: Date) => void)) : this - public on (event: 'room-leave', listener: string | ((this: Wechaty, room: Room, leaverList: Contact[], remover?: Contact, date?: Date) => void)) : this - public on (event: 'room-topic', listener: string | ((this: Wechaty, room: Room, newTopic: string, oldTopic: string, changer: Contact, date?: Date) => void)) : this - public on (event: 'scan', listener: string | ((this: Wechaty, qrcode: string, status: ScanStatus, data?: string) => void)) : this - public on (event: 'start' | 'stop', listener: string | ((this: Wechaty) => void)) : this + public on (event: 'dong', listener: WechatyDongEventListener) : this + public on (event: 'error', listener: WechatyErrorEventListener) : this + public on (event: 'friendship', listener: WechatyFriendshipEventListener) : this + public on (event: 'heartbeat', listener: WechatyHeartbeatEventListener) : this + public on (event: 'login', listener: WechatyLoginEventListener) : this + public on (event: 'logout', listener: WechatyLogoutEventListener) : this + public on (event: 'message', listener: WechatyMessageEventListener) : this + public on (event: 'ready', listener: WechatyReadyEventListener) : this + public on (event: 'room-invite', listener: WechatyRoomInviteEventListener) : this + public on (event: 'room-join', listener: WechatyRoomJoinEventListener) : this + public on (event: 'room-leave', listener: WechatyRoomLeaveEventListener) : this + public on (event: 'room-topic', listener: WechatyRoomTopicEventListener) : this + public on (event: 'scan', listener: WechatyScanEventListener) : this + public on (event: 'start' | 'stop', listener: WechatyStartStopEventListener) : this // guard for the above event: make sure it includes all the possible values public on (event: never, listener: never): never @@ -542,19 +552,28 @@ export class Wechaty extends EventEmitter implements Sayable { * console.error(error) * }) */ - public on (event: WechatyEventName, listener: string | ((...args: any[]) => any)): this { - log.verbose('Wechaty', 'on(%s, %s) registered', - event, - typeof listener === 'string' - ? listener - : typeof listener, - ) + public on (event: WechatyEventName, listener: (...args: any[]) => any): this { + log.verbose('Wechaty', 'on(%s, listener) registered', event) - if (typeof listener === 'function') { - this.addListenerFunction(event, listener) - } else { - this.addListenerModuleFile(event, listener) + const handleError = (e: Error, type = '') => { + log.error('Wechaty', 'addListenerFunction(%s) listener %s exception: %s', event, type, e) + this.emit('error', e) } + + /** + * We use `super.on()` at here to prevent loop + */ + super.on(event, (...args: any[]) => { + try { + const result = listener.apply(this, args) + if (result && result.catch && typeof result.catch === 'function') { + result.catch((e: Error) => handleError(e, 'async')) + } + } catch (e) { + handleError(e) + } + }) + return this } @@ -579,58 +598,6 @@ export class Wechaty extends EventEmitter implements Sayable { (this.constructor as typeof Wechaty).globalPluginList.forEach(plugin => plugin(this)) } - private addListenerModuleFile (event: WechatyEventName, modulePath: string): void { - const absoluteFilename = callerResolve(modulePath, __filename) - log.verbose('Wechaty', 'addListenerModuleFile() hotImport(%s)', absoluteFilename) - - hotImport(absoluteFilename) - .then((func: AnyFunction) => super.on(event, (...args: any[]) => { - try { - return func.apply(this, args) - } catch (e) { - log.error('Wechaty', 'addListenerModuleFile(%s, %s) listener exception: %s', - event, modulePath, e, - ) - this.emit('error', e) - } - })) - .catch(e => { - log.error('Wechaty', 'addListenerModuleFile(%s, %s) hotImport() exception: %s', - event, modulePath, e, - ) - this.emit('error', e) - }) - - if (isProduction()) { - log.verbose('Wechaty', 'addListenerModuleFile() disable watch for hotImport because NODE_ENV is production.') - hotImport(absoluteFilename, false) - .catch(e => log.error('Wechaty', 'addListenerModuleFile() hotImport() rejection: %s', e)) - } - } - - private addListenerFunction (event: WechatyEventName, listener: AnyFunction): void { - log.verbose('Wechaty', 'addListenerFunction(%s)', event) - - const handleError = (e: Error, type = '') => { - log.error('Wechaty', 'addListenerFunction(%s) listener %sexception: %s', event, type, e) - this.emit('error', e) - } - - /** - * We use `super.on()` at here to prevent loop - */ - super.on(event, (...args: any[]) => { - try { - const result = listener.apply(this, args) - if (result && result.catch && typeof result.catch === 'function') { - result.catch((e: Error) => handleError(e, 'async')) - } - } catch (e) { - handleError(e) - } - }) - } - private async initPuppet (): Promise { log.verbose('Wechaty', 'initPuppet() %s', this.options.puppet || '') From 046eee72268d84d542023e5a9e386f34930c6f0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 12 Jun 2020 23:23:07 +0800 Subject: [PATCH 228/598] 0.41.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index db83725a0..fdabfd948 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.0", + "version": "0.41.1", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 879d63d553c0d968604dae9bbb1b37ed332bb043 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 13 Jun 2020 00:11:37 +0800 Subject: [PATCH 229/598] add words --- .vscode/settings.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.vscode/settings.json b/.vscode/settings.json index 9bf0a5585..5e96c515f 100755 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -76,12 +76,14 @@ "huan", "ioscat", "ipad", + "lcov", "lijiarui", "logonoff", "padchat", "padplus", "padpro", "pagepath", + "portfinder", "qrcode", "removee", "ruirui", From bb169910dfe70e41a97a76be5fdf791132b66e40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 13 Jun 2020 00:11:50 +0800 Subject: [PATCH 230/598] 0.41.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fdabfd948..2e64e16fd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.1", + "version": "0.41.2", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 09c137a409612342bdf51b70934ae735208c643d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 13 Jun 2020 19:27:46 +0800 Subject: [PATCH 231/598] add multi-language badges --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index b4b820cd2..dfe3fde62 100644 --- a/README.md +++ b/README.md @@ -411,6 +411,11 @@ Support this project by becoming a sponsor. Your logo will show up here with a l ## Multi-language Wechaty +[![Wechaty in Python](https://img.shields.io/badge/Wechaty-Python-blue)](https://github.com/wechaty/python-wechaty) +[![Wechaty in Kotlin](https://img.shields.io/badge/Wechaty-Kotlin-orange)](https://github.com/wechaty/java-wechaty) +[![Wechaty in Go](https://img.shields.io/badge/Wechaty-Go-7de)](https://github.com/wechaty/go-wechaty) +[![Wechaty in Scala](https://img.shields.io/badge/Wechaty-Scala-890)](https://github.com/wechaty/scala-wechaty) + - [Wechaty](https://github.com/wechaty/wechaty) - Conversatioanl AI Chatot SDK for Wechaty Individual Accounts (TypeScript) - [Python Wechaty](https://github.com/wechaty/python-wechaty) - Python WeChaty Conversational AI Chatbot SDK for Wechat Individual Accounts (Python) - [Go Wechaty](https://github.com/wechaty/go-wechaty) - Go WeChaty Conversational AI Chatbot SDK for Wechat Individual Accounts (Go) From d3587739c2055f9f17a004a4f8e087ee86eba68a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 13 Jun 2020 19:27:59 +0800 Subject: [PATCH 232/598] 0.41.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2e64e16fd..fd1ecbab2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.2", + "version": "0.41.3", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From f3a18c04e4414df28a1928c04c462dae14d40e83 Mon Sep 17 00:00:00 2001 From: lijiarui Date: Sun, 14 Jun 2020 22:38:49 +0800 Subject: [PATCH 233/598] Update README.md (#1998) add video and blog link --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index dfe3fde62..4e53a2c5d 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,12 @@ Wechaty is used in many ChatBot projects by thousands of developers. If you want Scan now, because other Wechaty developers want to talk with you too! (secret code: _wechaty_) +### Video playlist + +Wechaty already held lots of talk in the past 4 yeare, you can click [Youtube Playlist](https://www.youtube.com/playlist?list=PL8hd9KDTdarDXf_Rxtr8meKhxtgcXMInh) to find all wechaty wonderful talk on youtube! + +You can also click [blog](https://wechaty.github.io/) to find all of the blog written by wechaty contributors. + ## The World's Shortest ChatBot Code: 6 lines of JavaScript ```javascript From 021c2819428cff1ca19170e35310ce12830e4ec8 Mon Sep 17 00:00:00 2001 From: "Zhongxiang.Wang" Date: Mon, 15 Jun 2020 15:58:27 +0800 Subject: [PATCH 234/598] docs: fixed table format flaw for `Contact.say` in README.md. (#1999) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4e53a2c5d..724ad7c33 100644 --- a/README.md +++ b/README.md @@ -203,7 +203,7 @@ All wechat contacts(friends/non-friends) will be encapsulated as a Contact. | static | [`load(query: string): Contact`](https://wechaty.github.io/wechaty/#Contact.load) | get contact by id | | property | `id: readonly string` | get contact id | | method | [`sync(): Promise`](https://wechaty.github.io/wechaty/#Contact+sync) | force reload data for contact , sync data from lowlevel API again| -| method | [`say(text: string): Promise`](https://wechaty.github.io/wechaty/#Contact+say) | send text, Contact, or file to contact, return the message which the bot sent (only `puppet-padplus` supported). | +| method | [`say(text: string): Promise`](https://wechaty.github.io/wechaty/#Contact+say) | send text, Contact, or file to contact, return the message which the bot sent (only `puppet-padplus` supported). | | method | [`self(): boolean`](https://wechaty.github.io/wechaty/#Contact+self) | check if contact is self | | method | [`name(): string`](https://wechaty.github.io/wechaty/#Contact+name) | get the name from a contact | | method | [`alias(): Promise`](https://wechaty.github.io/wechaty/#Contact+alias) | get the alias for a contact | From 3df59c5d4791b04cb326af3a256e15cacadfd2a0 Mon Sep 17 00:00:00 2001 From: lijiarui Date: Mon, 15 Jun 2020 18:33:11 +0800 Subject: [PATCH 235/598] Update README.md (#2001) - Add emoji for fun - Add resources link --- README.md | 55 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 724ad7c33..95c48359a 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-blue.svg)](https://www.typescriptlang.org/) [![Gitter](https://badges.gitter.im/Chatie/wechaty.svg)](https://gitter.im/Chatie/wechaty?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) -## Connecting Chatbots +## :hearts: Connecting Chatbots Wechaty is a Conversational AI RPA Chatbot SDK for Wechat **Individual** Account which can help you create a bot in 6 lines of [JavaScript](https://GitHub.com/Wechaty/wechaty), [Python](https://GitHub.com/Wechaty/python-wechaty/), [Go](https://GitHub.com/Wechaty/go-wechaty/), and [Java](https://GitHub.com/Wechaty/java-wechaty/), with cross-platform support including [Linux, Windows, MacOS](https://github.com/wechaty/wechaty/actions?query=workflow%3ANPM), and [Docker](https://github.com/wechaty/wechaty/actions?query=workflow%3ADocker). @@ -17,7 +17,7 @@ Wechaty is a Conversational AI RPA Chatbot SDK for Wechat **Individual** Account :book: :whale: -## Voice of Developers +## :yum: Voice of Developers > "Wechaty is a great solution, I believe there would be much more users recognize it." [link](https://github.com/Wechaty/wechaty/pull/310#issuecomment-285574472) > — @Gcaufy, Tencent Engineer, Author of [WePY](https://github.com/Tencent/wepy) @@ -39,7 +39,7 @@ Wechaty is a Conversational AI RPA Chatbot SDK for Wechat **Individual** Account See more at [Wiki:Voice Of Developer](https://github.com/Wechaty/wechaty/wiki/Voice%20Of%20Developer) -### Join Us +### :raising_hand: Join Us Wechaty is used in many ChatBot projects by thousands of developers. If you want to talk with other developers, just scan the following QR Code in WeChat with secret code _wechaty_, join our **Wechaty Developers' Home**. @@ -47,13 +47,18 @@ Wechaty is used in many ChatBot projects by thousands of developers. If you want Scan now, because other Wechaty developers want to talk with you too! (secret code: _wechaty_) -### Video playlist +### :book: Resource -Wechaty already held lots of talk in the past 4 yeare, you can click [Youtube Playlist](https://www.youtube.com/playlist?list=PL8hd9KDTdarDXf_Rxtr8meKhxtgcXMInh) to find all wechaty wonderful talk on youtube! +Wechaty already held lots of talk and got a lot of blogs in the past 4 years, here is all of the wechaty resouces: -You can also click [blog](https://wechaty.github.io/) to find all of the blog written by wechaty contributors. +- :video_camera: [Youtube Playlist: Watch all of talk video related with Wechaty](https://www.youtube.com/playlist?list=PL8hd9KDTdarDXf_Rxtr8meKhxtgcXMInh) +- :page_with_curl: [Full Docs](https://wechaty.js.org/) +- :bulb: [Blog: See how developers use wechaty building fantastic project!](https://wechaty.github.io/) +- :beginner: [Wechaty-Getting-Started:Wechaty Starter Project Template that Works Out-of-the-Box](https://github.com/wechaty/wechaty-getting-started) +- :tada: [Wechaty Contributor List: Thanks for their contribution!](https://github.com/wechaty/wechaty/wiki/Contributors) +- :gift: [Juzibot Support Wechaty: Know everything about Wechaty](https://github.com/juzibot/Welcome/wiki/Everything-about-Wechaty) -## The World's Shortest ChatBot Code: 6 lines of JavaScript +## :rocket: The World's Shortest ChatBot Code: 6 lines of JavaScript ```javascript @@ -72,12 +77,12 @@ This bot can log all messages to the console after login by scan. You can find more examples from [Wiki](https://github.com/Wechaty/wechaty/wiki/Examples) and [Example Directory](https://github.com/Wechaty/wechaty/blob/master/examples/). -## Requirements +## :checkered_flag: Requirements 1. Node.js v12 1. `sudo apt-get install build-essential && sudo snap install shellcheck` -## Getting Started +## :triangular_flag_on_post: Getting Started [![node](https://img.shields.io/node/v/wechaty.svg?maxAge=604800)](https://nodejs.org/) @@ -154,7 +159,7 @@ Learn more about Wechaty Puppet from the Puppet Wiki: 1. Puppet Directory: 1. Puppet Compatibility: -## API +## :guitar: API Read the Full Documentation at [Wechaty Official API Reference](https://wechaty.github.io/wechaty/) @@ -304,7 +309,7 @@ Accept room invitation | method | [`date(): Promise`](https://wechaty.github.io/wechaty/#RoomInvitation+date) | the time it was created | | method | `age(): Promise` | the number of seconds since it has been created | -## TEST +## :eyeglasses: TEST [![NPM](https://github.com/wechaty/wechaty/workflows/NPM/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ANPM) [![Docker](https://github.com/wechaty/wechaty/workflows/Docker/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ADocker) @@ -321,20 +326,20 @@ npm test Get to know more about the tests from [Wiki:Tests](https://github.com/Wechaty/wechaty/wiki/Tests) -## RELEASE NOTES +## :pencil: RELEASE NOTES - [Latest Release](https://github.com/Wechaty/wechaty/releases/latest)(All releases [here](https://github.com/Wechaty/wechaty/releases)) - [Changelog](https://github.com/Wechaty/wechaty/blob/master/CHANGELOG.md) -### Views Since Feb 15, 2019 +### :saxophone: Views Since Feb 15, 2019 [![HitCount](http://hits.dwyl.io/wechaty/wechaty.svg)](http://hits.dwyl.io/wechaty/wechaty) -## POWERED BY WECHATY +## :sparkling_heart: POWERED BY WECHATY [![Powered by Wechaty](https://img.shields.io/badge/Powered%20By-Wechaty-brightgreen.svg)](https://github.com/Wechaty/wechaty) -### Wechaty Badge +### :sparkles: Wechaty Badge ```markdown [![Powered by Wechaty](https://img.shields.io/badge/Powered%20By-Wechaty-brightgreen.svg)](https://github.com/Wechaty/wechaty) @@ -342,7 +347,7 @@ Get to know more about the tests from [Wiki:Tests](https://github.com/Wechaty/we Get more embed html/markdown code from [Wiki:PoweredByWechaty](https://github.com/Wechaty/wechaty/wiki/PoweredByWechaty) -### Projects Using Wechaty +### :star2: Projects Using Wechaty 1. [一个用CNN深度神经网络给图片评分的wechaty项目](https://github.com/huyingxi/wechaty_selfie) 2. [Relay between Telegram and WeChat](https://github.com/Firaenix/TeleChatRelay) @@ -357,7 +362,7 @@ Pull Request is welcome to add yours! Learn more about Projects Using Wechaty at [Wiki:PoweredByWechaty](https://github.com/Wechaty/wechaty/wiki/PoweredByWechaty) -## Find a Good Server +## :innocent: Find a Good Server The best practice for running Wechaty Docker/NPM is using a VPS(Virtual Private Server) outside of China, which can save you hours of time because `npm install` and `docker pull` will run smoothly without any problem. @@ -370,11 +375,11 @@ The following VPS providers are used by the Wechaty team, and they worked perfec | Korea | $10 | 1GB | Alipay, Paypal | [Netdedi](https://www.netdedi.com/?affid=35) | | Singapore | $3.5 | 512MB | Alipay, Wechat | [Vultr](https://www.vultr.com/?ref=6986613) | -## See Also +## :notes: See Also - [RelatedProject](https://github.com/Wechaty/wechaty/wiki/RelatedProject) -## The Story +## :poop: The Story In 2017 ... @@ -389,7 +394,7 @@ So a tireless bot working for me 24x7 on wechat, monitoring/filtering the most i At last, It's built for huan's personal study purpose of Automatically Testing. -## Contributors +## :two_hearts: Contributors [![GitHub issues](https://img.shields.io/github/issues/wechaty/wechaty.svg)](https://github.com/Wechaty/wechaty/issues) [![GitHub pull requests](https://img.shields.io/github/issues-pr/wechaty/wechaty.svg)](https://github.com/Wechaty/wechaty/pulls) @@ -399,7 +404,7 @@ At last, It's built for huan's personal study purpose of Automatically Testing. This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. [![Contribute](https://opencollective.com/wechaty/contributors.svg?width=890&button=false)](https://github.com/Wechaty/wechaty/graphs/contributors) -## Backers +## :sunglasses: Backers [![Backers on Open Collective](https://opencollective.com/wechaty/backers/badge.svg)](#backers) @@ -407,7 +412,7 @@ Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com [![Open Collective Wechaty](https://opencollective.com/wechaty/backers.svg?width=890)](https://opencollective.com/wechaty#backers) -## Sponsors +## :smirk: Sponsors [![Sponsors on Open Collective](https://opencollective.com/wechaty/sponsors/badge.svg)](#sponsors) @@ -415,7 +420,7 @@ Support this project by becoming a sponsor. Your logo will show up here with a l [![Wechaty Sponsor](https://opencollective.com/wechaty/sponsor.svg?width=890)](https://opencollective.com/wechaty/#sponsor) -## Multi-language Wechaty +## :point_down: Multi-language Wechaty [![Wechaty in Python](https://img.shields.io/badge/Wechaty-Python-blue)](https://github.com/wechaty/python-wechaty) [![Wechaty in Kotlin](https://img.shields.io/badge/Wechaty-Kotlin-orange)](https://github.com/wechaty/java-wechaty) @@ -428,14 +433,14 @@ Support this project by becoming a sponsor. Your logo will show up here with a l - [Java Wechaty](https://github.com/wechaty/java-wechaty) - Java WeChaty Conversational AI Chatbot SDK for Wechat Individual Accounts (Java) - [Scala Wechaty](https://github.com/wechaty/scala-wechaty) - Scala WeChaty Conversational AI Chatbot SDK for WechatyIndividual Accounts (Scala) -## Authors +## :raised_hands: Authors 1. [Huan](https://github.com/huan) [(李卓桓)](http://linkedin.com/in/zixia), Tencent TVP of Chatbot 1. [Rui (李佳芮)](https://pre-angel.com/peoples/jiarui-li/) [![Profile of Huan LI (李卓桓) on StackOverflow](https://stackoverflow.com/users/flair/1123955.png)](https://stackoverflow.com/users/1123955/huan) -## Copyright & License +## :email: Copyright & License - Code & Docs © 2016 Huan, Rui, and Wechaty Contributors - Code released under the Apache-2.0 License From 277269c9ae10822f6bfad93050d5198bcadef170 Mon Sep 17 00:00:00 2001 From: "Zhongxiang.Wang" Date: Mon, 15 Jun 2020 18:34:26 +0800 Subject: [PATCH 236/598] docs: fixed table format flaw of `Message.say` in README.md. (#2000) * docs: fixed table format flaw of `Message.say` in README.md. * docs: added document link to `Message.date()`. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 95c48359a..c0702f203 100644 --- a/README.md +++ b/README.md @@ -254,14 +254,14 @@ All wechat messages will be encapsulated as a Message. | method | [`to(): Contact`](https://wechaty.github.io/wechaty/#Message+to) | get the destination of the message | | method | [`room(): null \| Room`](https://wechaty.github.io/wechaty/#Message+room) | get the room from the message.(If the message is not in a room, then will return `null`) | | method | [`text(): string`](https://wechaty.github.io/wechaty/#Message+text) | get the text content of the message | -| method | [`say(text: string): Promise`](https://wechaty.github.io/wechaty/#Message+say) | reply a Text, Media File , or contact message to the sender, return the message which the bot sent (only `puppet-padplus` supported). | +| method | [`say(text: string): Promise`](https://wechaty.github.io/wechaty/#Message+say) | reply a Text, Media File , or contact message to the sender, return the message which the bot sent (only `puppet-padplus` supported). | | method | [`type(): MessageType`](https://wechaty.github.io/wechaty/#Message+type) | get the type from the message | | method | [`self(): boolean`](https://wechaty.github.io/wechaty/#Message+self) | check if a message is sent by self | | method | [`mention(): Contact[]`](https://wechaty.github.io/wechaty/#Message+mention) | get message mentioned contactList. | | method | [`mentionSelf(): boolean`](https://wechaty.github.io/wechaty/#Message+mentionSelf) | check if a message is mention self | | method | [`forward(to: Contact): Promise`](https://wechaty.github.io/wechaty/#Message+forward) | Forward the received message | | method | [`age(): number`](https://wechaty.github.io/wechaty/#Message+age) | the number of seconds since it has been created | -| method | `date(): Date` | the time it was created | +| method | [`date(): Date`](https://wechaty.github.io/wechaty/#Message+date) | the time it was created | | method | [`toFileBox(): Promise`](https://wechaty.github.io/wechaty/#Message+toFileBox) | extract the Media File from the Message, and put it into the FileBox. | | method | [`toContact(): Promise`](https://wechaty.github.io/wechaty/#Message+toContact) | get Share Card of the Message | @@ -307,7 +307,7 @@ Accept room invitation | method | [`inviter(): Contact`](https://wechaty.github.io/wechaty/#RoomInvitation+inviter) | get the inviter from room invitation | | method | [`roomTopic(): Promise`](https://wechaty.github.io/wechaty/#RoomInvitation+inviter) | get the room topic from room invitation | | method | [`date(): Promise`](https://wechaty.github.io/wechaty/#RoomInvitation+date) | the time it was created | -| method | `age(): Promise` | the number of seconds since it has been created | +| method | [`age(): Promise`](https://wechaty.github.io/wechaty/#RoomInvitation+age) | the number of seconds since it has been created | ## :eyeglasses: TEST From 0c498461597bf83ee81b46fe5a66b027b6171379 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 16 Jun 2020 19:16:45 +0800 Subject: [PATCH 237/598] add doc (#2004) --- src/user/message.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/user/message.ts b/src/user/message.ts index e6bade322..8b4cd2531 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -935,7 +935,8 @@ export class Message extends Accessory implements Sayable { * For example, the message is sent at time `8:43:01`, * and when we received it in Wechaty, the time is `8:43:15`, * then the age() will return `8:43:15 - 8:43:01 = 14 (seconds)` - * @returns {number} + * + * @returns {number} message age in seconds. */ public age (): number { const ageMilliseconds = Date.now() - this.date().getTime() From 89766f73a7d411326749ceaf493a7e25fc99615c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 16 Jun 2020 19:17:03 +0800 Subject: [PATCH 238/598] 0.41.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fd1ecbab2..6381ba70d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.3", + "version": "0.41.4", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 9a51b4970d5126acc1882c6d36905ab8e9c2a5bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 16 Jun 2020 19:17:58 +0800 Subject: [PATCH 239/598] 0.41.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6381ba70d..b8bc0b851 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.4", + "version": "0.41.5", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From ec08e201598945044b8c7b8c8507571d777b0e79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 16 Jun 2020 20:53:42 +0800 Subject: [PATCH 240/598] add plugin doc --- README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/README.md b/README.md index c0702f203..66c4ec09f 100644 --- a/README.md +++ b/README.md @@ -326,6 +326,25 @@ npm test Get to know more about the tests from [Wiki:Tests](https://github.com/Wechaty/wechaty/wiki/Tests) +## CREATING WECHATY PLUGIN + +Creating and publishing a Wechaty Plugin is simple. Simply expose your module as a function that takes 1 parameter: wechaty. When your plugin is imported by Wechaty, it will pass itself in as the argument, and so you are free to add any configuration that Wechaty supports. + +```ts +import { WechatyPlugin } from 'wechaty' + +export default const MyPlugin: WechatyPlugin = (wechaty: Wechaty) => { + // ... +} +``` + +The `config` exist so the user can pass in customizations to your Plugin. In documenting your Wechaty Plugin, you would lay out your supported config for the user. + +See: + +1. [Wechaty Plugin Support with KickOut Example #1939](https://github.com/wechaty/wechaty/issues/1939) +1. [Wechaty Plugins Contrib](https://github.com/wechaty/wechaty-plugin-contrib) + ## :pencil: RELEASE NOTES - [Latest Release](https://github.com/Wechaty/wechaty/releases/latest)(All releases [here](https://github.com/Wechaty/wechaty/releases)) From ceb905d807b2d37ce98f4f4f4cdcaec7a2a49168 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 16 Jun 2020 20:53:57 +0800 Subject: [PATCH 241/598] 0.41.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b8bc0b851..65e0314a5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.5", + "version": "0.41.6", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 42748ef85a66914b5796b3fb7d9d1fe62635e48c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 18 Jun 2020 02:25:07 +0800 Subject: [PATCH 242/598] upgrade wechaty-puppet-puppeteer to v0.23 --- src/puppet-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 834683c08..a9056b752 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -40,7 +40,7 @@ export const PUPPET_DEPENDENCIES = { * Wechaty External Puppets */ 'wechaty-puppet-padplus' : '^0.7.18', // https://www.npmjs.com/package/wechaty-puppet-padplus - 'wechaty-puppet-puppeteer' : '^0.21.2', // https://www.npmjs.com/package/wechaty-puppet-puppeteer + 'wechaty-puppet-puppeteer' : '^0.23.1', // https://www.npmjs.com/package/wechaty-puppet-puppeteer 'wechaty-puppet-wechat4u' : '^0.17.4', // https://www.npmjs.com/package/wechaty-puppet-wechat4u } From f456f4c556d15d00cb274905abef6a53f18a715f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 18 Jun 2020 02:25:19 +0800 Subject: [PATCH 243/598] 0.41.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fd1ecbab2..6381ba70d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.3", + "version": "0.41.4", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 685a1e41efc1938ecfff71a77ed819a2e10ba77e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 18 Jun 2020 02:25:51 +0800 Subject: [PATCH 244/598] 0.41.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index aabafdbe1..89341a0c6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.7", + "version": "0.41.8", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From bdef37e0a0265e6531380e508b7d2ed30e0efd0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 18 Jun 2020 02:31:22 +0800 Subject: [PATCH 245/598] test under node v14 --- .github/workflows/node.js.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 47a56e730..52f3a3c99 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -14,7 +14,7 @@ jobs: strategy: matrix: os: [macos-latest, windows-latest, ubuntu-latest] - node-version: [12.x, 13.x] + node-version: [12, 14] runs-on: ${{ matrix.os }} steps: From 24c90eb0627ad64e13d4aeb693f7f397fda85b2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 18 Jun 2020 02:31:35 +0800 Subject: [PATCH 246/598] 0.41.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 89341a0c6..95617cc0f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.8", + "version": "0.41.9", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 1ec8527683623baf42cd74712fa4747b883c0085 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 18 Jun 2020 14:39:57 +0800 Subject: [PATCH 247/598] add sourcerer-io / hall-of-fame --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 66c4ec09f..a139acb93 100644 --- a/README.md +++ b/README.md @@ -421,6 +421,16 @@ At last, It's built for huan's personal study purpose of Automatically Testing. [![Open Collective Sponsors](https://opencollective.com/wechaty/sponsors/badge.svg?label=open%20collective%20sponsors&color=blue)](https://opencollective.com/wechaty/) This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. + +[![contributor](https://sourcerer.io/fame/huan/wechaty/wechaty/images/0)](https://sourcerer.io/fame/huan/wechaty/wechaty/links/0) +[![contributor](https://sourcerer.io/fame/huan/wechaty/wechaty/images/1)](https://sourcerer.io/fame/huan/wechaty/wechaty/links/1) +[![contributor](https://sourcerer.io/fame/huan/wechaty/wechaty/images/2)](https://sourcerer.io/fame/huan/wechaty/wechaty/links/2) +[![contributor](https://sourcerer.io/fame/huan/wechaty/wechaty/images/3)](https://sourcerer.io/fame/huan/wechaty/wechaty/links/3) +[![contributor](https://sourcerer.io/fame/huan/wechaty/wechaty/images/4)](https://sourcerer.io/fame/huan/wechaty/wechaty/links/4) +[![contributor](https://sourcerer.io/fame/huan/wechaty/wechaty/images/5)](https://sourcerer.io/fame/huan/wechaty/wechaty/links/5) +[![contributor](https://sourcerer.io/fame/huan/wechaty/wechaty/images/6)](https://sourcerer.io/fame/huan/wechaty/wechaty/links/6) +[![contributor](https://sourcerer.io/fame/huan/wechaty/wechaty/images/7)](https://sourcerer.io/fame/huan/wechaty/wechaty/links/7) + [![Contribute](https://opencollective.com/wechaty/contributors.svg?width=890&button=false)](https://github.com/Wechaty/wechaty/graphs/contributors) ## :sunglasses: Backers From ce91ef59b25e8d721365fa4d940c4ec7f0f420e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 18 Jun 2020 14:40:10 +0800 Subject: [PATCH 248/598] 0.41.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 65e0314a5..aabafdbe1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.6", + "version": "0.41.7", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From afeedfa985c85a5c73fc8b4b5f58fb47109189a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 18 Jun 2020 14:42:36 +0800 Subject: [PATCH 249/598] 0.41.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 95617cc0f..d0decd659 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.9", + "version": "0.41.10", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From e172e20cede0ec36486479a9e25d2ff082732c6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 18 Jun 2020 16:33:37 +0800 Subject: [PATCH 250/598] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index a139acb93..123c855e6 100644 --- a/README.md +++ b/README.md @@ -431,6 +431,8 @@ This project exists thanks to all the people who contribute. [[Contribute](CONTR [![contributor](https://sourcerer.io/fame/huan/wechaty/wechaty/images/6)](https://sourcerer.io/fame/huan/wechaty/wechaty/links/6) [![contributor](https://sourcerer.io/fame/huan/wechaty/wechaty/images/7)](https://sourcerer.io/fame/huan/wechaty/wechaty/links/7) +----- + [![Contribute](https://opencollective.com/wechaty/contributors.svg?width=890&button=false)](https://github.com/Wechaty/wechaty/graphs/contributors) ## :sunglasses: Backers From 79e85c627650a0ed2756910473cf80be89aafb64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 18 Jun 2020 22:40:20 +0800 Subject: [PATCH 251/598] enhance the use plugin type --- package.json | 6 +++--- src/wechaty.ts | 10 ++++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index d0decd659..509fcb97e 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,9 @@ "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", + "engines": { + "node": ">= 12" + }, "wechaty": { "DEFAULT_PORT": 8080, "DEFAULT_PROTOCOL": "io|0.0.1", @@ -79,9 +82,6 @@ "url": "https://opencollective.com/wechaty" }, "homepage": "https://github.com/wechaty/", - "engines": { - "node": ">= 12" - }, "dependencies": { "brolog": "^1.8.3", "clone-class": "^0.7.3", diff --git a/src/wechaty.ts b/src/wechaty.ts index 2f4650a57..7361a21da 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -240,9 +240,10 @@ export class Wechaty extends EventEmitter implements Sayable { * bot.use(WechatyReportPlugin({ url: 'http://somewhere.to.report.your.data.com' }) */ public static use ( - ...plugins: WechatyPlugin[] + ...plugins: (WechatyPlugin | WechatyPlugin[])[] ) { - this.globalPluginList = this.globalPluginList.concat(plugins) + const pluginList = plugins.flat() + this.globalPluginList = this.globalPluginList.concat(pluginList) } /** @@ -589,8 +590,9 @@ export class Wechaty extends EventEmitter implements Sayable { * // The same usage with Wechaty.use(). * */ - public use (...plugins: WechatyPlugin[]) { - plugins.forEach(plugin => plugin(this)) + public use (...plugins: (WechatyPlugin | WechatyPlugin[])[]) { + const pluginList = plugins.flat() + pluginList.forEach(plugin => plugin(this)) return this } From 1eede236f6007a0cdbc78da1d68e2ed9cd302a19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 18 Jun 2020 22:40:33 +0800 Subject: [PATCH 252/598] 0.41.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 509fcb97e..a2393911b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.10", + "version": "0.41.11", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 3c1cebb17b381c7d82d8a919ba1a6027e5204b08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 18 Jun 2020 22:41:02 +0800 Subject: [PATCH 253/598] 0.41.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a2393911b..9bc690762 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.11", + "version": "0.41.12", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 94905b4f021ae9efb29a844e8b5f6de318a6d6bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 20 Jun 2020 23:02:40 +0800 Subject: [PATCH 254/598] follow the Deno module naming style --- examples/ding-dong-bot.ts | 2 +- package.json | 4 ++-- src/{index.ts => mod.ts} | 0 src/wechaty.spec.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename src/{index.ts => mod.ts} (100%) diff --git a/examples/ding-dong-bot.ts b/examples/ding-dong-bot.ts index 4bdfe8e98..bb882fdeb 100644 --- a/examples/ding-dong-bot.ts +++ b/examples/ding-dong-bot.ts @@ -23,7 +23,7 @@ import { Message, ScanStatus, Wechaty, -} from '../src/' // from 'wechaty' +} from '../src/mod' // from 'wechaty' import { generate } from 'qrcode-terminal' diff --git a/package.json b/package.json index 95617cc0f..749eb0390 100644 --- a/package.json +++ b/package.json @@ -2,8 +2,8 @@ "name": "wechaty", "version": "0.41.9", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", - "main": "dist/src/index.js", - "typings": "dist/src/index.d.ts", + "main": "dist/src/mod.js", + "typings": "dist/src/mod.d.ts", "wechaty": { "DEFAULT_PORT": 8080, "DEFAULT_PROTOCOL": "io|0.0.1", diff --git a/src/index.ts b/src/mod.ts similarity index 100% rename from src/index.ts rename to src/mod.ts diff --git a/src/wechaty.spec.ts b/src/wechaty.spec.ts index 84bb0a3eb..529d98e2a 100644 --- a/src/wechaty.spec.ts +++ b/src/wechaty.spec.ts @@ -37,7 +37,7 @@ import { Message, Room, -} from './' +} from './mod' import { Puppet, From 7e9a95bc0cd81bef9e522f310c75116f6b18dfef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 20 Jun 2020 23:02:51 +0800 Subject: [PATCH 255/598] 0.41.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 749eb0390..f0113faa7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.9", + "version": "0.41.10", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 2c0676a5637f167f8efad45a7c27758592a26512 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 20 Jun 2020 23:09:44 +0800 Subject: [PATCH 256/598] 0.41.13 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b565a7f09..b12fb2b25 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.12", + "version": "0.41.13", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 882c2b8124156d86e855a99c9c50178a163c6717 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 20 Jun 2020 23:46:00 +0800 Subject: [PATCH 257/598] allow fall down to the defination of say() to get more flexibility. --- src/user/message.ts | 4 +++- src/user/room.ts | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/user/message.ts b/src/user/message.ts index 8b4cd2531..e8eb4b488 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -423,7 +423,9 @@ export class Message extends Accessory implements Sayable { public say (url: UrlLink) : Promise public say (mini: MiniProgram) : Promise - public say (...args: never[]): Promise + // Huan(202006): allow fall down to the defination to get more flexibility. + // public say (...args: never[]): Promise + /** * Reply a Text or Media File message to the sender. * > Tips: diff --git a/src/user/room.ts b/src/user/room.ts index 28f9ddf51..1e3444455 100644 --- a/src/user/room.ts +++ b/src/user/room.ts @@ -386,7 +386,8 @@ export class Room extends Accessory implements Sayable { public say (mini: MiniProgram) : Promise public say (contact: Contact) : Promise - public say (...args: never[]): never + // Huan(202006): allow fall down to the defination to get more flexibility. + // public say (...args: never[]): never /** * Send message inside Room, if set [replyTo], wechaty will mention the contact as well. From 1061aa53ea45558c4c40aecb0a2937a72f9963a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 20 Jun 2020 23:46:12 +0800 Subject: [PATCH 258/598] 0.41.14 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b12fb2b25..082bac3e9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.13", + "version": "0.41.14", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 7a5e4484eecc61e7a4e8edff65bb107949840c05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 20 Jun 2020 23:49:49 +0800 Subject: [PATCH 259/598] fix typing for message.say() --- src/user/message.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/user/message.ts b/src/user/message.ts index e8eb4b488..2d866cb2d 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -416,12 +416,12 @@ export class Message extends Accessory implements Sayable { } } - public say (text: string, mention?: Contact | Contact[]) : Promise - public say (message: Message) : Promise - public say (contact: Contact) : Promise - public say (file: FileBox) : Promise - public say (url: UrlLink) : Promise - public say (mini: MiniProgram) : Promise + public say (text: string) : Promise + public say (message: Message) : Promise + public say (contact: Contact) : Promise + public say (file: FileBox) : Promise + public say (url: UrlLink) : Promise + public say (mini: MiniProgram) : Promise // Huan(202006): allow fall down to the defination to get more flexibility. // public say (...args: never[]): Promise From 266992c1acdf4bd0e9e986000dc40ffffe2f832b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 20 Jun 2020 23:50:00 +0800 Subject: [PATCH 260/598] 0.41.15 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 082bac3e9..7a32d2144 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.14", + "version": "0.41.15", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 74aed223c33f012691691666effb89076743baa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 22 Jun 2020 08:12:38 +0800 Subject: [PATCH 261/598] fix typo --- src/config.ts | 2 +- src/user/message.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/config.ts b/src/config.ts index 274a97fb2..8c6f699ba 100644 --- a/src/config.ts +++ b/src/config.ts @@ -159,7 +159,7 @@ export function qrCodeForChatie (): FileBox { // String.fromCharCode(8197) export const FOUR_PER_EM_SPACE = String.fromCharCode(0x2005) // mobile: \u2005, PC、mac: \u0020 -export const AT_SEPRATOR_REGEX = /[\u2005\u0020]/ +export const AT_SEPARATOR_REGEX = /[\u2005\u0020]/ export function qrcodeValueToImageUrl (qrcodeValue: string): string { return [ diff --git a/src/user/message.ts b/src/user/message.ts index 8b4cd2531..cf378bf88 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -34,7 +34,7 @@ import { Accessory, } from '../accessory' import { - AT_SEPRATOR_REGEX, + AT_SEPARATOR_REGEX, FileBox, log, @@ -697,9 +697,9 @@ export class Message extends Accessory implements Sayable { /** * define magic code `8197` to identify @xxx - * const AT_SEPRATOR = String.fromCharCode(8197) + * const AT_SEPARATOR = String.fromCharCode(8197) */ - const atList = this.text().split(AT_SEPRATOR_REGEX) + const atList = this.text().split(AT_SEPARATOR_REGEX) // console.log('atList: ', atList) if (atList.length === 0) return [] From 163ad6bdcde2beb39d79bb22c1a417645971ce9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 22 Jun 2020 08:12:53 +0800 Subject: [PATCH 262/598] 0.41.13 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9bc690762..f6bf0eb26 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.12", + "version": "0.41.13", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", From 9edb5529a0aaef32e4794b8362965feeea168153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 22 Jun 2020 08:43:49 +0800 Subject: [PATCH 263/598] 0.41.16 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7a32d2144..8defb1b60 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.15", + "version": "0.41.16", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From e49447e36375b6381ce886f9e50591d30a630bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 22 Jun 2020 16:02:05 +0800 Subject: [PATCH 264/598] 0.41.17 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8defb1b60..0a596e465 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.16", + "version": "0.41.17", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 9cc64f8348b1a203d67cffb995cd8ba2b2059746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 23 Jun 2020 16:45:39 +0800 Subject: [PATCH 265/598] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 123c855e6..4190ef57c 100644 --- a/README.md +++ b/README.md @@ -420,8 +420,6 @@ At last, It's built for huan's personal study purpose of Automatically Testing. [![Open Collective Backers](https://opencollective.com/wechaty/backer/badge.svg?label=open%20collective%20backers&color=blue)](https://opencollective.com/wechaty/) [![Open Collective Sponsors](https://opencollective.com/wechaty/sponsors/badge.svg?label=open%20collective%20sponsors&color=blue)](https://opencollective.com/wechaty/) -This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. - [![contributor](https://sourcerer.io/fame/huan/wechaty/wechaty/images/0)](https://sourcerer.io/fame/huan/wechaty/wechaty/links/0) [![contributor](https://sourcerer.io/fame/huan/wechaty/wechaty/images/1)](https://sourcerer.io/fame/huan/wechaty/wechaty/links/1) [![contributor](https://sourcerer.io/fame/huan/wechaty/wechaty/images/2)](https://sourcerer.io/fame/huan/wechaty/wechaty/links/2) @@ -431,6 +429,8 @@ This project exists thanks to all the people who contribute. [[Contribute](CONTR [![contributor](https://sourcerer.io/fame/huan/wechaty/wechaty/images/6)](https://sourcerer.io/fame/huan/wechaty/wechaty/links/6) [![contributor](https://sourcerer.io/fame/huan/wechaty/wechaty/images/7)](https://sourcerer.io/fame/huan/wechaty/wechaty/links/7) +This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. + ----- [![Contribute](https://opencollective.com/wechaty/contributors.svg?width=890&button=false)](https://github.com/Wechaty/wechaty/graphs/contributors) From 15d503810b2fe01f4d8605d048c8dc23ce84902c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 23 Jun 2020 16:46:49 +0800 Subject: [PATCH 266/598] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4190ef57c..294678969 100644 --- a/README.md +++ b/README.md @@ -467,7 +467,7 @@ Support this project by becoming a sponsor. Your logo will show up here with a l ## :raised_hands: Authors 1. [Huan](https://github.com/huan) [(李卓桓)](http://linkedin.com/in/zixia), Tencent TVP of Chatbot -1. [Rui (李佳芮)](https://pre-angel.com/peoples/jiarui-li/) +1. [Rui (李佳芮)](https://pre-angel.com/peoples/jiarui-li/), Microsoft AI MVP [![Profile of Huan LI (李卓桓) on StackOverflow](https://stackoverflow.com/users/flair/1123955.png)](https://stackoverflow.com/users/1123955/huan) From ad623c5b08aab83c72d8ddf2200dd4b78cdb627b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 27 Jun 2020 20:05:18 +0800 Subject: [PATCH 267/598] wechaty-puppet @ 0.27 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0a596e465..4bd366b9f 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "read-pkg-up": "^7.0.1", "state-switch": "^0.9.9", "watchdog": "^0.8.17", - "wechaty-puppet": "^0.26.1", + "wechaty-puppet": "^0.27.1", "wechaty-puppet-hostie": "^0.8.3", "ws": "^7.2.3" }, From f6a5c1f34ac8e2ab22d98ddc75e845740c24cba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 27 Jun 2020 20:10:39 +0800 Subject: [PATCH 268/598] 0.41.18 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4bd366b9f..ff62a1c4f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.17", + "version": "0.41.18", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 70edb1d695c3a03e3b10edbb355f7acc753a8138 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 27 Jun 2020 20:11:21 +0800 Subject: [PATCH 269/598] 0.41.19 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ff62a1c4f..f9d652687 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.18", + "version": "0.41.19", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 5ad688b79da561d0c613b297ea88c5bfd9faaf67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 29 Jun 2020 21:16:18 +0800 Subject: [PATCH 270/598] switch to our wechaty QR Code online api service (https://github.com/wechaty/qrcode/issues/1) --- README.md | 2 +- docs/index.md | 2 +- examples/ding-dong-bot.ts | 4 +--- src/config.ts | 3 +-- src/wechaty.ts | 2 +- 5 files changed, 5 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 294678969..3c926bec7 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ Wechaty already held lots of talk and got a lot of blogs in the past 4 years, he const { Wechaty } = require('wechaty') // import { Wechaty } from 'wechaty' Wechaty.instance() // Global Instance -.on('scan', (qrcode, status) => console.log(`Scan QR Code to login: ${status}\nhttps://api.qrserver.com/v1/create-qr-code/?data=${encodeURIComponent(qrcode)}`)) +.on('scan', (qrcode, status) => console.log(`Scan QR Code to login: ${status}\nhttps://wechaty.github.io/qrcode/${encodeURIComponent(qrcode)}`)) .on('login', user => console.log(`User ${user} logined`)) .on('message', message => console.log(`Message: ${message}`)) .start() diff --git a/docs/index.md b/docs/index.md index a27022074..6c63aded0 100644 --- a/docs/index.md +++ b/docs/index.md @@ -142,7 +142,7 @@ Creates an instance of Wechaty. ```js const { Wechaty } = require('wechaty') const bot = new Wechaty() -bot.on('scan', (qrcode, status) => console.log(['https://api.qrserver.com/v1/create-qr-code/?data=',encodeURIComponent(qrcode),'&size=220x220&margin=20',].join(''))) +bot.on('scan', (qrcode, status) => console.log('https://wechaty.github.io/qrcode/' + encodeURIComponent(qrcode))) bot.on('login', user => console.log(`User ${user} logined`)) bot.on('message', message => console.log(`Message: ${message}`)) bot.start() diff --git a/examples/ding-dong-bot.ts b/examples/ding-dong-bot.ts index bb882fdeb..95ffd2cba 100644 --- a/examples/ding-dong-bot.ts +++ b/examples/ding-dong-bot.ts @@ -76,10 +76,8 @@ function onScan (qrcode: string, status: ScanStatus) { if (status === ScanStatus.Waiting || status === ScanStatus.Timeout) { generate(qrcode) - // Generate a QR Code online via - // http://goqr.me/api/doc/create-qr-code/ const qrcodeImageUrl = [ - 'https://api.qrserver.com/v1/create-qr-code/?data=', + 'https://wechaty.github.io/qrcode/', encodeURIComponent(qrcode), ].join('') diff --git a/src/config.ts b/src/config.ts index 8c6f699ba..ecc01dd4b 100644 --- a/src/config.ts +++ b/src/config.ts @@ -163,9 +163,8 @@ export const AT_SEPARATOR_REGEX = /[\u2005\u0020]/ export function qrcodeValueToImageUrl (qrcodeValue: string): string { return [ - 'https://api.qrserver.com/v1/create-qr-code/?data=', + 'https://wechaty.github.io/qrcode/', encodeURIComponent(qrcodeValue), - '&size=220x220&margin=20', ].join('') } diff --git a/src/wechaty.ts b/src/wechaty.ts index 7361a21da..1edbcdebd 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -149,7 +149,7 @@ const PUPPET_MEMORY_NAME = 'puppet' * @example The World's Shortest ChatBot Code: 6 lines of JavaScript * const { Wechaty } = require('wechaty') * const bot = new Wechaty() - * bot.on('scan', (qrCode, status) => console.log(['https://api.qrserver.com/v1/create-qr-code/?data=',encodeURIComponent(qrcode),'&size=220x220&margin=20',].join(''))) + * bot.on('scan', (qrCode, status) => console.log('https://wechaty.github.io/qrcode/' + encodeURIComponent(qrcode))) * bot.on('login', user => console.log(`User ${user} logged in`)) * bot.on('message', message => console.log(`Message: ${message}`)) * bot.start() From fb9df44d29c49a69e958100186163f898ec8e670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 29 Jun 2020 21:16:33 +0800 Subject: [PATCH 271/598] 0.41.20 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f9d652687..6d921dcfc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.19", + "version": "0.41.20", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From a0246396bad11e29b8151093076561866ef625a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 30 Jun 2020 01:32:39 +0800 Subject: [PATCH 272/598] fix 256x256 icon --- docs/images/wechaty-icon-green.png | Bin 4025 -> 2106 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/images/wechaty-icon-green.png b/docs/images/wechaty-icon-green.png index ac1e1791c459e4df8c203514575b02858704819f..cb1996803fa97ac84e4c1240a802ac87964d05c3 100644 GIT binary patch literal 2106 zcmbuAYdjPBAIE>2%Ulv?M-GOW`Me)|AABFYU!QN9yPK1eg1Q0#KndfF z{sjQY7D9lW)K-L5p7z=bXLnaG2YUv}z6^P(DfCj?h2nSlE20%_6}s=stKcWZ8$DM> z7f1XayU%=^Y96mo?4)MD&ZrtL|7)_to{1{v75K3|>{&>OL}Fi#{DWXQ2>`4LgSPdG z9hn~!#y!wfkrmvQFG?-36m0On1in5+*}rqY1z$Y!9W%V7(Am+ClYIOtvvtV-H!9lO zd^u-iP0-&Y*vV7P^`xJV0-mt!&G5%0#+PtY7W4W(<%UQKEmfT^avKWj)@6jsmYr=Z z^td;~&pvTE-XOPOw}T?7m%Mu2-P+vSoINKL4Zd8c_Ab3KrVx412PEQ>Vk%wC{ml<4 zuGhis@yjCQJguX#1O;&oN_xH##eGzW8+nSG^G1*zv*+CyB?}?Vl_sXpTygPcW9bJD zzt{7sNuf2}3x70D^&;NCZuHjKS(s!SI)|PB6stI$o*tam7fDc{s4$DZH z_w2Zprc9?&bqp5TLZ@brTf}#bsT_Q-S7i>TCaFHU_=la?mg&fC1y`>dAR{aMPzK0_vg800UDtB zrUPcwytUtjGClhb#(d%3VlQ<-R-r2S|)2( zu11K-t(*$6ZzUCFn5MIaB5KGcYhB%~zGwQB(X0@A{9cBepgQqsgh)FrpavBpVUnQYUTyV>4JUL9}}O5H;tvX#U!X03roT(TvC0A_HrKHL|n+Z<20P}1n4|a zYdz-j(DAV7PlBkJsp{=C({lv|)3r!KIPVf<&X=w#`MihSx1mSBYGY>+ zcUI0*V{%l=U;;D${W$}h3AS04%Zj$40NqfpWw%rB%3q-O_ON@$pLg=>L4^Tf6{}zC ztf-k_f@eZVK2Vg?94O;4HwYl8uD4o4+g#Td%u2D^zEXy`aaBuEEi2X&m$(7p;Az9+ zjeAZo(oLW5v|`E=*QFh0KNN%cyIrMUNNa)fthpBZYrR`!@mM2eI~hCh2$G7U=9ga? zwOR3_@8c=`O72$SdH#KX-jh9c*o&?qmjol#83`8yn~XR^Mk^O@N1g-*xnusEa9L8Q zhP`;%@$F|29P&vn0s%=alE8YTPC~{T)`&!s{)y^vv`2oEl$?h5+)NdCULXCQU(xk= z!U1><57`~2`FFvAXUzm|fysZ8M^GDG3;`_RVLif<&To z7}UKd5SGbq1aO3Csqm+Dko$yct6K-o)XG>OlDh|_P~ED)*H@{i5tG6v2!zJBl37df zl4l9@S}vE{th*cvU4c03K}m|fuoIiDCezS5%RKl zKhvhAD2f%2u*R8c3u-T~Ek8`$@_ue@z+nEUh{^_QSZE@l3!T+)EUIbpWb5LX-n=@o z=$jj4og4l#ScZ zyrFzZ420L8{3(OZc+9GXiY0r6$<1Jte29L^f;o8M1lF*NmPc1m7PRazvDD)EzrT7; z%dzy|~DOu?)Kp9emfaM;+teXAd_G-eW-8KsFvpMhd^9H%mvjH_hx4sPHS;fzgOYtACt5Ji`~9_@agZxM#kcgi#V`~IEWR-;CB zdVYVu=f-rygK0cdl6bcDDCaJC)z&_xrIah9v1|&S_(z4kESug-9{wKnBPXH9T)qTE z?by9n-qL0_+fdx-fWN!SZJ)$9%_O+$fO{Cc<*m%#_=`Bq8_TNGBF&Q10Ff>Lv;7dA ze+ofIwFL_sO0*IWf(k6`d>{1fjm>@tg1?iG8e&P+Gq%@AC_o8NlKWU(HdA{|2A+fj zCdM)etX-;bfpzn5%NwhEc5>?K?LHSn;EMk)nG|R_Jbgh$O|w-_Au7QyI55BtN^+9> f_sW0c%(G&t)F!jr7s_t@^Mf%CZs=+|(v|-KU?`^V literal 4025 zcmeHKdr(tX8o$X65JDao2!w~?C5Tcg5{Qt1bh(g#u_{8K3ZhhEh=9l=B8uzU1SG`p zkbqVqsGy)=Q6r$mRy(LXqD_$iG8DC_JXWh+P^hidwtFt@&TMyQcJ`0`XJ?z4%(?l_ z`Ch;8`+n!h(sgD07 zN^pkv>#x5G8hE;meq#_s|6!#tBxd)p1X*ClgcXp)fkwPdz@QRywjK2Q^1lE9?FKeB z;gYH(BUnBM$&FKOK#3&e7*SiLD=4VYdDI&vO^5DvU+=zgqdVjRMk1qoNNnfeBMv08 zjdkgBiKKd=`$j7FN^YF%;6+OB87V|Y14--!1FJT-M;PL((XfS;JxjW7s+^LDqQL{E z`eblm*n+J&p=g9ZTC`=F1wH`*lRpceR=9~ zb!_L4?Tzzg5X1l3P|AEYn7~o2;P&c4fU=yVG@O32coj9L#G( zq>sfIiR$hjk~~SW(JWEtaF;LRU&+0G+f~_Rxny2!+|W>&&C<~K_<|je^rc;Raba7v zac|8qY2ftee%@s4>saf6a~e%Uya=W_Nj}Qt4%WHnF4Ad=Y>rc{5QP zUky7bf<&~8OgG0{Ej6hu=AIg%fwsCWXbKfZv>E&f(eC%4dZ7Y3xgCAn;MLjT8t2%k zB-0_;SSg*w8QNWG{UF07!e821v;WINsojxE)calfv*ZW&%|RoWvw1mdLpCViHq7_+ zUz)J&m^yG{^&04sDr{|AuL^qBKG1`spTlNZ9+wC#qeFI2be^xYGTl(sZwir>DpMBE zmAWErZ59%_|7d0i@qXJdzcu}l8YUs3LPm#+Rd%-yM zLZF|5KX>qhSXSMT1#T?{m6NB`QH&{aCRK_bQIOa?D?b4e&+p^m6!44E&~?i_+_}B; zjz0&Vlo`5^p0LixiI`BT#QmJiK;_LvCMW%lzF=J8ywczn&S-~?cV}q$_BOQ7O5aTG z^}{D7)|~y`ogs6)tJb2;dit}!G3MffLkcKij~NIF(3|e-PIHQ$+rJpMH>gza8)RIw zb#s1?2vA9$r+(WcfvsX+KSgln>Bq)oEa%<@{s4V1>QvCVeQ_Z5ro zT49h+aTAB>_M&v{W59hr#jTvWFb~{?+DhQGAEfG2e3etTZ&pO63eFbJiaI!TIk@N& zQCqTVby|mNR%+zbrGMfKd^6QoB@#D2&hmju1KWQFvh(&JlF_py_KBfL(!l37c!bvK z`%MC0B=Ja}m<~{JQX1U-g@j9IlR>7wu(5WT3&7rEd7w6$N)t@8 z{gJVB|3*V-)z#1hy!_W->kq|aHRSXeCOLn%Cx#EEOlz%X zMu=ZTHNHPy7Z%~_Jx5{cZ52M=JB_u^sjFY&B=Tf|TGC{U(Mf8L1{|8@K@62_lUMBG z2U+2D#;FP;T7Or{@Nf1`dlc$dc;fM;)G?f%Xsc1;HOA-phw?ux^PJ#JM{ju(m^=Fh zVW)mLW9aD#tTehV#|@xx7DAkLXCMoYn=l~^Aec-a(NjVEPBft>37EtG3g8ii!&(Y% z<&;uXfD^h2s|&^HI2pC!MHI3i{7IZB1q|@_lTy;j_GI)VPNmahKTrLWQ3{%2Mw&Gb zp1kP)=*T*$xccgx523mAFV~@2Z&#l!0iFG??!~TnF3XU{S+)&FnxiWV@&5Btg`yIIsV28{thsE zf&Ir2{d;wKK~$m#6#!?E)X4F$0!jA6F_kWO;0HWCp}AW8zWn!)fT02%FSfGv#&rmM NR)$3g&xdZ#`zvi9?w9}o From d06705365d2dad4b9e0e9de8c29674c3dc5cc07f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 30 Jun 2020 01:32:51 +0800 Subject: [PATCH 273/598] 0.41.16 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7a32d2144..8defb1b60 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.15", + "version": "0.41.16", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 2ec0845d6c4ba215412430adea58391b65003c2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 30 Jun 2020 02:00:55 +0800 Subject: [PATCH 274/598] 0.41.21 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6d921dcfc..b9081b9a5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.20", + "version": "0.41.21", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 43ca39b4bba85f48246f497dda03e2a35ea53afa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 30 Jun 2020 15:44:04 +0800 Subject: [PATCH 275/598] upgrade eslint-config --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6d921dcfc..54f0d5f12 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "@babel/core": "^7.8.7", "@babel/node": "^7.8.7", "@babel/preset-env": "^7.8.7", - "@chatie/eslint-config": "^0.9.1", + "@chatie/eslint-config": "^0.11.5", "@chatie/git-scripts": "^0.5.2", "@chatie/semver": "^0.4.7", "@chatie/tsconfig": "^0.8.0", From 19a39d6e72faa41d0b77b3585a63b5eaf3a86cfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 30 Jun 2020 16:04:14 +0800 Subject: [PATCH 276/598] 0.41.22 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 24e1fa167..8b7a98aa3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.21", + "version": "0.41.22", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From d775041e5a6870ebccfc0da982f75415d05e7f21 Mon Sep 17 00:00:00 2001 From: SuperChang Date: Tue, 30 Jun 2020 18:53:02 +0800 Subject: [PATCH 277/598] Upgrade hostie (#2011) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 0.29.3 * Merge master (#18) * update puppeteer puppet * 0.31.18 * upgrade to wechaty-puppet@0.20 * 0.31.19 * upgrade puppet configs * 0.31.20 * dep upgrade & clean (#1917) * 0.31.21 * upgrade eslint-config (https://github.com/wechaty/wechaty/issues/1917) * 0.31.22 * use green version of powered by wechaty badge * 0.31.23 * use NODE_AUTH_TOKEN instead of NPM_TOKEN * 0.31.24 * use bright green for badge * 0.31.25 * restore pkg-jq * 0.31.26 * Upgrade docker base image & node.js (#1920) * 0.32.1 * fix scan status for padplus (https://github.com/wechaty/wechaty-puppet-padplus/issues/161) * 0.32.2 Co-authored-by: Huan (李卓桓) * fix: upgrade hostie@0.8.4 * 0.41.23 Co-authored-by: Huan (李卓桓) --- package.json | 4 ++-- src/puppet-config.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 8b7a98aa3..c9f03a260 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.22", + "version": "0.41.23", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", @@ -100,7 +100,7 @@ "state-switch": "^0.9.9", "watchdog": "^0.8.17", "wechaty-puppet": "^0.27.1", - "wechaty-puppet-hostie": "^0.8.3", + "wechaty-puppet-hostie": "^0.8.4", "ws": "^7.2.3" }, "devDependencies": { diff --git a/src/puppet-config.ts b/src/puppet-config.ts index a9056b752..50b644195 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -33,7 +33,7 @@ export const PUPPET_DEPENDENCIES = { /** * Wechaty Internal Puppets: dependence by package.json */ - 'wechaty-puppet-hostie' : '^0.8.3', // https://www.npmjs.com/package/wechaty-puppet-hostie + 'wechaty-puppet-hostie' : '^0.8.4', // https://www.npmjs.com/package/wechaty-puppet-hostie 'wechaty-puppet-mock' : '^0.22.3', // https://www.npmjs.com/package/wechaty-puppet-mock /** From b95d61eba5324230037c7bc52ff811fcd260811c Mon Sep 17 00:00:00 2001 From: SuperChang Date: Tue, 30 Jun 2020 20:40:03 +0800 Subject: [PATCH 278/598] Upgrade hostie (#2012) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 0.29.3 * Merge master (#18) * update puppeteer puppet * 0.31.18 * upgrade to wechaty-puppet@0.20 * 0.31.19 * upgrade puppet configs * 0.31.20 * dep upgrade & clean (#1917) * 0.31.21 * upgrade eslint-config (https://github.com/wechaty/wechaty/issues/1917) * 0.31.22 * use green version of powered by wechaty badge * 0.31.23 * use NODE_AUTH_TOKEN instead of NPM_TOKEN * 0.31.24 * use bright green for badge * 0.31.25 * restore pkg-jq * 0.31.26 * Upgrade docker base image & node.js (#1920) * 0.32.1 * fix scan status for padplus (https://github.com/wechaty/wechaty-puppet-padplus/issues/161) * 0.32.2 Co-authored-by: Huan (李卓桓) * fix: upgrade hostie@0.8.4 * 0.41.23 * fix: upgrade hostie@0.8.5 * 0.41.24 Co-authored-by: Huan (李卓桓) --- package.json | 4 ++-- src/puppet-config.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index c9f03a260..a91b956e2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.23", + "version": "0.41.24", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", @@ -100,7 +100,7 @@ "state-switch": "^0.9.9", "watchdog": "^0.8.17", "wechaty-puppet": "^0.27.1", - "wechaty-puppet-hostie": "^0.8.4", + "wechaty-puppet-hostie": "^0.8.5", "ws": "^7.2.3" }, "devDependencies": { diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 50b644195..6661dc7cb 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -33,7 +33,7 @@ export const PUPPET_DEPENDENCIES = { /** * Wechaty Internal Puppets: dependence by package.json */ - 'wechaty-puppet-hostie' : '^0.8.4', // https://www.npmjs.com/package/wechaty-puppet-hostie + 'wechaty-puppet-hostie' : '^0.8.5', // https://www.npmjs.com/package/wechaty-puppet-hostie 'wechaty-puppet-mock' : '^0.22.3', // https://www.npmjs.com/package/wechaty-puppet-mock /** From f44c3ea2620d9da823a6e4e20aad11486f01b982 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 5 Jul 2020 16:17:19 +0800 Subject: [PATCH 279/598] use wechaty qr code image generator --- .vscode/settings.json | 1 + src/io-client.ts | 13 +++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 5e96c515f..90886484a 100755 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -73,6 +73,7 @@ "cSpell.words": [ "Wechaty", "appid", + "botie", "huan", "ioscat", "ipad", diff --git a/src/io-client.ts b/src/io-client.ts index f9e385028..a0f909c9f 100644 --- a/src/io-client.ts +++ b/src/io-client.ts @@ -19,7 +19,7 @@ */ /** * DO NOT use `require('../')` here! - * because it will casue a LOOP require ERROR + * because it will cause a LOOP require ERROR */ import { StateSwitch } from 'state-switch' @@ -146,10 +146,15 @@ export class IoClient { } wechaty - .on('login', user => log.info('IoClient', `${user.name()} logined`)) - .on('logout', user => log.info('IoClient', `${user.name()} logouted`)) - .on('scan', (url, code) => log.info('IoClient', `[${code}] ${url}`)) + .on('login', user => log.info('IoClient', `${user.name()} logged in`)) + .on('logout', user => log.info('IoClient', `${user.name()} logged out`)) .on('message', msg => this.onMessage(msg)) + .on('scan', (url, code) => { + log.info('IoClient', [ + `[${code}] ${url}]`, + `Online QR Code Image: https://wechaty.github.io/qrcode/${url}`, + ].join('\n')) + }) } private async startIo (): Promise { From e1e5393599178dc727d21f1463cc7dd8b528753d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 5 Jul 2020 16:17:43 +0800 Subject: [PATCH 280/598] 0.41.23 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8b7a98aa3..667a93ddf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.22", + "version": "0.41.23", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 54e368a295cbb6e0464ebe9e33056f7adcc9966b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 5 Jul 2020 16:19:51 +0800 Subject: [PATCH 281/598] 0.41.25 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a91b956e2..73717b98f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.24", + "version": "0.41.25", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 8bd195eb51c52a0ae9ec54eb3745fd558af54c55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 6 Jul 2020 01:39:02 +0800 Subject: [PATCH 282/598] fix padplus float timestamp bug (#1985) --- src/puppet-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index a9056b752..a835c943d 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -39,7 +39,7 @@ export const PUPPET_DEPENDENCIES = { /** * Wechaty External Puppets */ - 'wechaty-puppet-padplus' : '^0.7.18', // https://www.npmjs.com/package/wechaty-puppet-padplus + 'wechaty-puppet-padplus' : '^0.7.29', // https://www.npmjs.com/package/wechaty-puppet-padplus 'wechaty-puppet-puppeteer' : '^0.23.1', // https://www.npmjs.com/package/wechaty-puppet-puppeteer 'wechaty-puppet-wechat4u' : '^0.17.4', // https://www.npmjs.com/package/wechaty-puppet-wechat4u } From 19e13190783fea7c8f9d65b72f3e0b9e8ba4d049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 6 Jul 2020 01:45:04 +0800 Subject: [PATCH 283/598] 0.41.22 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b9081b9a5..052867111 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.21", + "version": "0.41.22", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From f19a4e8039849b7f74f442e31bb9c7143e3d872a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 6 Jul 2020 01:45:33 +0800 Subject: [PATCH 284/598] 0.41.26 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 73717b98f..f563f2f8d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.25", + "version": "0.41.26", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From c6141c9b0fa9cbdfd6827f9be978a6811307e8b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 6 Jul 2020 01:49:13 +0800 Subject: [PATCH 285/598] upgrade --- src/puppet-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 4b980db3a..af1a97f44 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -33,7 +33,7 @@ export const PUPPET_DEPENDENCIES = { /** * Wechaty Internal Puppets: dependence by package.json */ - 'wechaty-puppet-hostie' : '^0.8.5', // https://www.npmjs.com/package/wechaty-puppet-hostie + 'wechaty-puppet-hostie' : '^0.8.6', // https://www.npmjs.com/package/wechaty-puppet-hostie 'wechaty-puppet-mock' : '^0.22.3', // https://www.npmjs.com/package/wechaty-puppet-mock /** From 53e6dc1babf6b562aae3e2266d60bad456d08a5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 6 Jul 2020 01:49:25 +0800 Subject: [PATCH 286/598] 0.41.27 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f563f2f8d..b8ff775fe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.26", + "version": "0.41.27", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 1ae36231525f970b4f3d4d6d72c2c06e5936069a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 6 Jul 2020 03:04:25 +0800 Subject: [PATCH 287/598] fix padplus puppet start state problem (https://github.com/wechaty/wechaty/issues/1985#issuecomment-653924805) --- src/puppet-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index af1a97f44..24749eb3f 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -39,7 +39,7 @@ export const PUPPET_DEPENDENCIES = { /** * Wechaty External Puppets */ - 'wechaty-puppet-padplus' : '^0.7.29', // https://www.npmjs.com/package/wechaty-puppet-padplus + 'wechaty-puppet-padplus' : '^0.7.30', // https://www.npmjs.com/package/wechaty-puppet-padplus 'wechaty-puppet-puppeteer' : '^0.23.1', // https://www.npmjs.com/package/wechaty-puppet-puppeteer 'wechaty-puppet-wechat4u' : '^0.17.4', // https://www.npmjs.com/package/wechaty-puppet-wechat4u } From fccaceb93b7289f42b93f025b27785bed43a51d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 6 Jul 2020 03:04:45 +0800 Subject: [PATCH 288/598] update --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b8ff775fe..7101222fe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.27", + "version": "0.41.28", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 2627d6a2088095a2eb816191ad1b64ef0d5bc02f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 6 Jul 2020 03:21:09 +0800 Subject: [PATCH 289/598] Deploy Docker Image with GitHub Action --- .github/workflows/docker.yml | 26 +++++++++---------- IMAGE | 1 + scripts/deploy-docker.sh | 48 ++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 15 deletions(-) create mode 100644 IMAGE create mode 100644 scripts/deploy-docker.sh diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 4a3b9f8a6..5961fa8ba 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -21,23 +21,19 @@ jobs: - run: ./scripts/docker.sh build - run: ./scripts/docker.sh test + # https://www.prestonlamb.com/blog/creating-a-docker-image-with-github-actions publish: - if: github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/v')) name: Publish needs: [build] + if: github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/v[0-9]+')) runs-on: ubuntu-latest steps: - - name: Check Branch - id: check-branch - run: | - if [[ ${{ github.ref }} =~ ^refs/heads/(master|v[0-9]+\.[0-9]+.*)$ ]]; then - echo ::set-output name=match::true - fi # See: https://stackoverflow.com/a/58869470/1123955 - - name: Is A Publish Branch - if: steps.check-branch.outputs.match == 'true' - run: curl -X POST -d '{"from":"GitHub Action"}' "$DOCKER_REBUILD_URL" - env: - DOCKER_REBUILD_URL: ${{ secrets.DOCKER_REBUILD_URL }} - - name: Is Not A Publish Branch - if: steps.check-branch.outputs.match != 'true' - run: echo 'Not A Publish Branch' + - uses: actions/checkout@v2 + - name: Install Dependencies + run: make install + - name: Login to DockerHub Registry + run: echo ${{ secrets.DOCKER_PERSONAL_ACCESS_TOKEN }} | docker login -u zixia --password-stdin + - name: Build the Docker image + run: docker build -t artifact_image . + - name: Deploy to Docker Hub + run: bash -x ./scripts/deploy-docker.sh artifact_image diff --git a/IMAGE b/IMAGE new file mode 100644 index 000000000..06e68add6 --- /dev/null +++ b/IMAGE @@ -0,0 +1 @@ +zixia/wechaty diff --git a/scripts/deploy-docker.sh b/scripts/deploy-docker.sh new file mode 100644 index 000000000..e1a3d3c75 --- /dev/null +++ b/scripts/deploy-docker.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash + +set -eo pipefail + +function deployVersion () { + SEMVER_MAJOR=$(node -e "console.log(require('semver').major('$VERSION'))") + SEMVER_MINOR=$(node -e "console.log(require('semver').minor('$VERSION'))") + + TAG="$SEMVER_MAJOR.$SEMVER_MINOR" + + echo "Deploying TAG=$TAG" + docker tag "${ARTIFACT_IMAGE}" "${IMAGE}:${TAG}" + docker push "${IMAGE}:${TAG}" +} + +function deployLatest () { + echo "Deploying IMAGE=$IMAGE latest" + docker tag "${ARTIFACT_IMAGE}" "${IMAGE}:latest" + docker push "${IMAGE}:latest" +} + +function deployNext () { + echo "Deploying IMAGE=$IMAGE next" + docker tag "${ARTIFACT_IMAGE}" "${IMAGE}:next" + docker push "${IMAGE}:next" +} + +function main () { + if [ -z "$1" ]; then + >&2 echo -e "Missing argument.\nUsage: $0 ARTIFACT_IMAGE" + exit 1 + fi + + ARTIFACT_IMAGE=$1 + + IMAGE=$(cat IMAGE) + VERSION=$(cat VERSION) + + deployVersion + + if npx --package @chatie/semver semver-is-prod "$VERSION"; then + deployLatest + else + deployLatest + fi +} + +main "$@" From 42320f763bd4cbf5b1e4ac10494213bdf8a4874e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 6 Jul 2020 03:21:20 +0800 Subject: [PATCH 290/598] 0.41.29 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7101222fe..924fa694d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.28", + "version": "0.41.29", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 75cdfa7da8db7caa38989051e59d2cea5ff83031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 6 Jul 2020 03:51:56 +0800 Subject: [PATCH 291/598] fix docker deployg --- .github/workflows/docker.yml | 8 +- IMAGE | 1 - scripts/deploy-docker.sh | 48 ----------- scripts/docker.sh | 151 +++++++++++++++++++++++------------ 4 files changed, 103 insertions(+), 105 deletions(-) delete mode 100644 IMAGE delete mode 100644 scripts/deploy-docker.sh diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 5961fa8ba..0d3ae2b77 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -30,10 +30,10 @@ jobs: steps: - uses: actions/checkout@v2 - name: Install Dependencies - run: make install + run: npm install + - name: Build the Docker image + run: ./scripts/docker.sh build - name: Login to DockerHub Registry run: echo ${{ secrets.DOCKER_PERSONAL_ACCESS_TOKEN }} | docker login -u zixia --password-stdin - - name: Build the Docker image - run: docker build -t artifact_image . - name: Deploy to Docker Hub - run: bash -x ./scripts/deploy-docker.sh artifact_image + run: ./scripts/docker.sh deploy diff --git a/IMAGE b/IMAGE deleted file mode 100644 index 06e68add6..000000000 --- a/IMAGE +++ /dev/null @@ -1 +0,0 @@ -zixia/wechaty diff --git a/scripts/deploy-docker.sh b/scripts/deploy-docker.sh deleted file mode 100644 index e1a3d3c75..000000000 --- a/scripts/deploy-docker.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash - -set -eo pipefail - -function deployVersion () { - SEMVER_MAJOR=$(node -e "console.log(require('semver').major('$VERSION'))") - SEMVER_MINOR=$(node -e "console.log(require('semver').minor('$VERSION'))") - - TAG="$SEMVER_MAJOR.$SEMVER_MINOR" - - echo "Deploying TAG=$TAG" - docker tag "${ARTIFACT_IMAGE}" "${IMAGE}:${TAG}" - docker push "${IMAGE}:${TAG}" -} - -function deployLatest () { - echo "Deploying IMAGE=$IMAGE latest" - docker tag "${ARTIFACT_IMAGE}" "${IMAGE}:latest" - docker push "${IMAGE}:latest" -} - -function deployNext () { - echo "Deploying IMAGE=$IMAGE next" - docker tag "${ARTIFACT_IMAGE}" "${IMAGE}:next" - docker push "${IMAGE}:next" -} - -function main () { - if [ -z "$1" ]; then - >&2 echo -e "Missing argument.\nUsage: $0 ARTIFACT_IMAGE" - exit 1 - fi - - ARTIFACT_IMAGE=$1 - - IMAGE=$(cat IMAGE) - VERSION=$(cat VERSION) - - deployVersion - - if npx --package @chatie/semver semver-is-prod "$VERSION"; then - deployLatest - else - deployLatest - fi -} - -main "$@" diff --git a/scripts/docker.sh b/scripts/docker.sh index 97d901651..02172a6e2 100755 --- a/scripts/docker.sh +++ b/scripts/docker.sh @@ -1,54 +1,101 @@ #!/bin/bash -# -# 1. CircleCI with `Btrfs volume error` -# https://circleci.com/docs/docker-btrfs-error/ -# -set -e - -imageName='wechaty:test' - -# Shellcheck - https://github.com/koalaman/shellcheck/wiki/SC2086 -options=('--rm') -[ -n "$CIRCLECI" ] && options=('--rm=false') -[ -n "$NO_CACHE" ] && options+=('--no-cache') - -declare -i ret=0 - -case "$1" in - build | '') - echo docker build "${options[@]}" -t "$imageName" . - exec docker build "${options[@]}" -t "$imageName" . - -# echo docker build "${options[@]}" -t "${imageName}:onbuild" -f Dockerfile.onbuild . -# exec docker build "${options[@]}" -t "${imageName}:onbuild" -f Dockerfile.onbuild . - - ret=$? - ;; - - test) - echo "Testing the docker image behaviors to make sure it works as expected..." - echo "bats tests/" - IMAGE_NAME="$imageName" bats tests/ - - echo - echo - echo docker run -i "${options[@]}" -v /dev/shm:/dev/shm "$imageName" test - exec docker run -i "${options[@]}" -v /dev/shm:/dev/shm "$imageName" test - ret=$? - ;; - - clean) - docker ps -a | grep Exited | awk '{print $1}' | xargs docker rm || true - docker images | grep none | awk '{print $3}' | xargs docker rmi - ;; - - *) - echo docker run -ti "${options[@]}" -v /dev/shm:/dev/shm "$imageName" "$@" - exec docker run -ti "${options[@]}" -v /dev/shm:/dev/shm "$imageName" "$@" - ;; -esac - -[ "$ret" -ne 0 ] && { - echo "ERROR: exec return $ret ???" - exit $ret + +set -eo pipefail + +function deployVersion () { + ARTIFACT_IMAGE=$1 + IMAGE=$2 + VERSION=$3 + + SEMVER_MAJOR=$(node -e "console.log(require('semver').major('$VERSION'))") + SEMVER_MINOR=$(node -e "console.log(require('semver').minor('$VERSION'))") + + TAG="$SEMVER_MAJOR.$SEMVER_MINOR" + + echo "Deploying TAG=$TAG" + docker tag "${ARTIFACT_IMAGE}" "${IMAGE}:${TAG}" + docker push "${IMAGE}:${TAG}" +} + +function deployLatest () { + ARTIFACT_IMAGE=$1 + IMAGE=$2 + + echo "Deploying IMAGE=$IMAGE latest" + docker tag "${ARTIFACT_IMAGE}" "${IMAGE}:latest" + docker push "${IMAGE}:latest" +} + +function deployNext () { + ARTIFACT_IMAGE=$1 + IMAGE=$2 + + echo "Deploying IMAGE=$IMAGE next" + docker tag "${ARTIFACT_IMAGE}" "${IMAGE}:next" + docker push "${IMAGE}:next" +} + +function main () { + artifactImage='wechaty:test' + dockerImage='zixia/wechaty' + + # Shellcheck - https://github.com/koalaman/shellcheck/wiki/SC2086 + options=('--rm') + [ -n "$NO_CACHE" ] && options+=('--no-cache') + + declare -i ret=0 + + case "$1" in + build | '') + echo docker build "${options[@]}" -t "$artifactImage" . + exec docker build "${options[@]}" -t "$artifactImage" . + + # echo docker build "${options[@]}" -t "${artifactImage}:onbuild" -f Dockerfile.onbuild . + # exec docker build "${options[@]}" -t "${artifactImage}:onbuild" -f Dockerfile.onbuild . + + ret=$? + ;; + + test) + echo "Testing the docker image behaviors to make sure it works as expected..." + echo "bats tests/" + IMAGE_NAME="$artifactImage" bats tests/ + + echo + echo + echo docker run -i "${options[@]}" -v /dev/shm:/dev/shm "$artifactImage" test + exec docker run -i "${options[@]}" -v /dev/shm:/dev/shm "$artifactImage" test + ret=$? + ;; + + deploy) + version=$(npx pkg-jq -r .version) + + deployVersion "$artifactImage" "$dockerImage" "$version" + + if npx --package @chatie/semver semver-is-prod "$VERSION"; then + deployLatest "$artifactImage" "$dockerImage" + else + deployNext "$artifactImage" "$dockerImage" + fi + ;; + + clean) + docker ps -a | grep Exited | awk '{print $1}' | xargs docker rm || true + docker images | grep none | awk '{print $3}' | xargs docker rmi + ;; + + *) + echo docker run -ti "${options[@]}" -v /dev/shm:/dev/shm "$artifactImage" "$@" + exec docker run -ti "${options[@]}" -v /dev/shm:/dev/shm "$artifactImage" "$@" + ;; + esac + + [ "$ret" -ne 0 ] && { + echo "ERROR: exec return $ret ???" + } + + return $ret } + +main "$@" From 010833fcdf443dfefafabd28e8f70625eceffe66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 6 Jul 2020 03:52:08 +0800 Subject: [PATCH 292/598] 0.41.30 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 924fa694d..91232f77a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.29", + "version": "0.41.30", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 48e9b0ea9d1946db257f2058eb11b4c8c48ba9d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 6 Jul 2020 04:27:27 +0800 Subject: [PATCH 293/598] clean --- .github/workflows/docker.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 0d3ae2b77..04d6452ab 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -29,8 +29,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: Install Dependencies - run: npm install - name: Build the Docker image run: ./scripts/docker.sh build - name: Login to DockerHub Registry From 81590085562981d20b74b3c31721fbcf2a49fe87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 6 Jul 2020 04:27:40 +0800 Subject: [PATCH 294/598] 0.41.31 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 91232f77a..9512f17eb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.30", + "version": "0.41.31", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 99e8d37f5671158c617a580f59da562e42e9d6c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 9 Jul 2020 02:03:05 +0800 Subject: [PATCH 295/598] enable dotenv --- bin/io-client.ts | 3 +++ package.json | 2 ++ 2 files changed, 5 insertions(+) diff --git a/bin/io-client.ts b/bin/io-client.ts index 836271549..e465df925 100644 --- a/bin/io-client.ts +++ b/bin/io-client.ts @@ -19,6 +19,9 @@ * */ +/* eslint-disable import/first */ +require('dotenv').config() + import { config, log, diff --git a/package.json b/package.json index 73717b98f..ec9bb8c63 100644 --- a/package.json +++ b/package.json @@ -86,6 +86,7 @@ "brolog": "^1.8.3", "clone-class": "^0.7.3", "cuid": "^2.1.8", + "dotenv": "^8.2.0", "in-gfw": "^1.2.0", "json-rpc-peer": "^0.15.5", "npm-programmatic": "0.0.12", @@ -112,6 +113,7 @@ "@chatie/semver": "^0.4.7", "@chatie/tsconfig": "^0.8.0", "@types/cuid": "^1.3.0", + "@types/dotenv": "^8.2.0", "@types/glob": "^7.1.1", "@types/open-graph": "^0.2.0", "@types/promise-retry": "^1.1.3", From bd49cbfaa63fd8eb655c344f7fa01c17c16ce0b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 9 Jul 2020 02:04:16 +0800 Subject: [PATCH 296/598] 0.41.32 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7f54fc8fb..a088fd884 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.31", + "version": "0.41.32", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 8e8ca6bcb0e09e52c26ae4a790e409f63f667543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 9 Jul 2020 02:21:59 +0800 Subject: [PATCH 297/598] debug docker --- .vscode/settings.json | 1 + scripts/docker.sh | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 90886484a..d3fc16364 100755 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -91,6 +91,7 @@ "thumbnailurl", "wechat", "weixin", + "zbeekman", "zixia" ], } diff --git a/scripts/docker.sh b/scripts/docker.sh index 02172a6e2..156f4049d 100755 --- a/scripts/docker.sh +++ b/scripts/docker.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -x set -eo pipefail From 235d18b49190c97a532ee7f5ece26b17612ffcba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 9 Jul 2020 02:22:15 +0800 Subject: [PATCH 298/598] 0.41.33 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a088fd884..3185daea3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.32", + "version": "0.41.33", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 6f875c653d3a399fe0fe91f64f51cbf40227ca72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 9 Jul 2020 02:32:45 +0800 Subject: [PATCH 299/598] message.say() mention support --- src/user/message.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/user/message.ts b/src/user/message.ts index e217daba9..d530c0bd9 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -423,7 +423,7 @@ export class Message extends Accessory implements Sayable { public say (url: UrlLink) : Promise public say (mini: MiniProgram) : Promise - // Huan(202006): allow fall down to the defination to get more flexibility. + // Huan(202006): allow fall down to the definition to get more flexibility. // public say (...args: never[]): Promise /** @@ -520,6 +520,7 @@ export class Message extends Accessory implements Sayable { let conversationId: string let conversation + if (room) { conversation = room conversationId = room.id @@ -542,13 +543,15 @@ export class Message extends Accessory implements Sayable { /** * Text Message */ - // msgId = await this.puppet.messageSendText({ - // contactId : (from && from.id) || undefined, - // roomId : (room && room.id) || undefined, - // }, textOrContactOrFileOrUrlOrMini) + let mentionIdList + if (from && await this.mentionSelf()) { + mentionIdList = [from.id] + } + msgId = await this.puppet.messageSendText( conversationId, textOrContactOrFileOrUrlOrMini, + mentionIdList, ) } else if (textOrContactOrFileOrUrlOrMini instanceof Contact) { /** From 0a8ad239281fe830f578cd1a44cab020e2a68906 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 9 Jul 2020 02:44:13 +0800 Subject: [PATCH 300/598] fix semver cut --- scripts/docker.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/docker.sh b/scripts/docker.sh index 156f4049d..928586e70 100755 --- a/scripts/docker.sh +++ b/scripts/docker.sh @@ -7,8 +7,8 @@ function deployVersion () { IMAGE=$2 VERSION=$3 - SEMVER_MAJOR=$(node -e "console.log(require('semver').major('$VERSION'))") - SEMVER_MINOR=$(node -e "console.log(require('semver').minor('$VERSION'))") + SEMVER_MAJOR=$(echo "$VERSION" | cut -d. -f1) + SEMVER_MINOR=$(echo "$VERSION" | cut -d. -f2) TAG="$SEMVER_MAJOR.$SEMVER_MINOR" From 0ef8c7f6099b3bb851d753195ac54b1a690137db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 9 Jul 2020 02:44:31 +0800 Subject: [PATCH 301/598] 0.41.34 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3185daea3..b925013a8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.33", + "version": "0.41.34", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From ac5e11ef71b19c4f00a7417934c4035ebe998b31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 10 Jul 2020 15:28:00 +0800 Subject: [PATCH 302/598] add type SayableMessage --- src/helper-functions/{index.ts => mod.ts} | 0 src/sayable-message.ts | 44 +++++++++++++++++++++++ src/user/{index.ts => mod.ts} | 0 3 files changed, 44 insertions(+) rename src/helper-functions/{index.ts => mod.ts} (100%) create mode 100644 src/sayable-message.ts rename src/user/{index.ts => mod.ts} (100%) diff --git a/src/helper-functions/index.ts b/src/helper-functions/mod.ts similarity index 100% rename from src/helper-functions/index.ts rename to src/helper-functions/mod.ts diff --git a/src/sayable-message.ts b/src/sayable-message.ts new file mode 100644 index 000000000..fb4e58161 --- /dev/null +++ b/src/sayable-message.ts @@ -0,0 +1,44 @@ +import { + FileBox, + Message, + Contact, + UrlLink, + MiniProgram, + log, +} from './mod' + +export type SayableMessage = undefined + | Message + | string + | FileBox + | Contact + | UrlLink + | MiniProgram + +async function toSayableMessage (message: Message): Promise { + const type = message.type() + switch (type) { + case Message.Type.Text: + return message.text() + case Message.Type.Image: + case Message.Type.Attachment: + case Message.Type.Audio: + case Message.Type.Video: + case Message.Type.Emoticon: + return message.toFileBox() + case Message.Type.Contact: + return message.toContact() + case Message.Type.Url: + return message.toUrlLink() + case Message.Type.MiniProgram: + return message.toMiniProgram() + + default: + log.silly('Wechaty', 'toSayableMessage(%s) non-convertible type: %s', message, type) + return undefined + } +} + +export { + toSayableMessage, +} diff --git a/src/user/index.ts b/src/user/mod.ts similarity index 100% rename from src/user/index.ts rename to src/user/mod.ts From 4d2b69717c557e7113a229d6af57631dd9993034 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 10 Jul 2020 15:28:06 +0800 Subject: [PATCH 303/598] rename index -> mod --- src/io-client.ts | 2 +- src/mod.ts | 8 ++++++-- src/types.ts | 2 +- src/wechaty.ts | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/io-client.ts b/src/io-client.ts index a0f909c9f..ad59726c1 100644 --- a/src/io-client.ts +++ b/src/io-client.ts @@ -28,7 +28,7 @@ import { PuppetServerOptions, } from 'wechaty-puppet-hostie' -import { Message } from './user' +import { Message } from './user/mod' import { log, diff --git a/src/mod.ts b/src/mod.ts index 2b92d2c5b..8c434861a 100644 --- a/src/mod.ts +++ b/src/mod.ts @@ -33,7 +33,7 @@ export { /** * We need to put `Wechaty` at the beginning of this file for import - * because we have circluar dependencies between `Puppet` & `Wechaty` + * because we have circular dependencies between `Puppet` & `Wechaty` */ export { Wechaty, @@ -58,7 +58,7 @@ export { RoomInvitation, UrlLink, MiniProgram, -} from './user' +} from './user/mod' export { } from './deprecated' @@ -67,3 +67,7 @@ export { IoClient } from './io-client' export { Sayable, } from './types' +export { + SayableMessage, + toSayableMessage, +} from './sayable-message' diff --git a/src/types.ts b/src/types.ts index 154cc63d6..5805d3bc2 100644 --- a/src/types.ts +++ b/src/types.ts @@ -21,7 +21,7 @@ import { Wechaty } from './wechaty' import { Contact, Message, -} from './user' +} from './user/mod' export type AnyFunction = (...args: any[]) => any diff --git a/src/wechaty.ts b/src/wechaty.ts index 1edbcdebd..7f0fc2297 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -78,7 +78,7 @@ import { RoomInvitation, UrlLink, MiniProgram, -} from './user/' +} from './user/mod' import { timestampToDate } from './helper-functions/pure/timestamp-to-date' From 1b6691263e1e1a717e1101efdc55b6541bfeaaf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 10 Jul 2020 15:29:06 +0800 Subject: [PATCH 304/598] code cleAN --- src/io.ts | 2 +- src/user/friendship.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/io.ts b/src/io.ts index b76df2c20..ce96afa29 100644 --- a/src/io.ts +++ b/src/io.ts @@ -22,7 +22,7 @@ import WebSocket from 'ws' import { Message, -} from './user' +} from './user/mod' import { EventScanPayload, diff --git a/src/user/friendship.ts b/src/user/friendship.ts index 182cfc679..aef53d5d1 100644 --- a/src/user/friendship.ts +++ b/src/user/friendship.ts @@ -30,7 +30,7 @@ import { } from '../config' import { tryWait, -} from '../helper-functions' +} from '../helper-functions/mod' import { FriendshipPayload, From 589021a71ae3a5cb5cf17bf5786e90f35a2cb493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 10 Jul 2020 15:29:24 +0800 Subject: [PATCH 305/598] 0.41.35 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b925013a8..cf5569f04 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.34", + "version": "0.41.35", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 2301a2568a218b6307cf9702bae28308456d45ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 10 Jul 2020 15:46:54 +0800 Subject: [PATCH 306/598] move SayableMessage to plugin-contrib --- src/mod.ts | 4 ---- src/sayable-message.ts | 44 ------------------------------------------ 2 files changed, 48 deletions(-) delete mode 100644 src/sayable-message.ts diff --git a/src/mod.ts b/src/mod.ts index 8c434861a..9d7bf6b31 100644 --- a/src/mod.ts +++ b/src/mod.ts @@ -67,7 +67,3 @@ export { IoClient } from './io-client' export { Sayable, } from './types' -export { - SayableMessage, - toSayableMessage, -} from './sayable-message' diff --git a/src/sayable-message.ts b/src/sayable-message.ts deleted file mode 100644 index fb4e58161..000000000 --- a/src/sayable-message.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { - FileBox, - Message, - Contact, - UrlLink, - MiniProgram, - log, -} from './mod' - -export type SayableMessage = undefined - | Message - | string - | FileBox - | Contact - | UrlLink - | MiniProgram - -async function toSayableMessage (message: Message): Promise { - const type = message.type() - switch (type) { - case Message.Type.Text: - return message.text() - case Message.Type.Image: - case Message.Type.Attachment: - case Message.Type.Audio: - case Message.Type.Video: - case Message.Type.Emoticon: - return message.toFileBox() - case Message.Type.Contact: - return message.toContact() - case Message.Type.Url: - return message.toUrlLink() - case Message.Type.MiniProgram: - return message.toMiniProgram() - - default: - log.silly('Wechaty', 'toSayableMessage(%s) non-convertible type: %s', message, type) - return undefined - } -} - -export { - toSayableMessage, -} From 9844beb30dd44bb528eb720d354e295b224eba06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 10 Jul 2020 15:47:10 +0800 Subject: [PATCH 307/598] 0.41.36 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cf5569f04..ae39cbb45 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.35", + "version": "0.41.36", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 709a2551942349385be95f374569b7f95c6bcc02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 11 Jul 2020 07:49:07 +0800 Subject: [PATCH 308/598] support say number --- src/user/contact.ts | 6 ++++++ src/user/message.ts | 37 ++++++++++++++++++++++--------------- src/user/room.ts | 6 ++++++ 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/user/contact.ts b/src/user/contact.ts index 0c34421a5..af87c28dc 100644 --- a/src/user/contact.ts +++ b/src/user/contact.ts @@ -321,6 +321,7 @@ export class Contact extends Accessory implements Sayable { } public say (text: string) : Promise + public say (num: number) : Promise public say (message: Message) : Promise public say (contact: Contact) : Promise public say (file: FileBox) : Promise @@ -386,6 +387,7 @@ export class Contact extends Accessory implements Sayable { */ public async say ( something: string + | number | Message | Contact | FileBox @@ -398,6 +400,10 @@ export class Contact extends Accessory implements Sayable { return something.forward(this) } + if (typeof something === 'number') { + something = String(something) + } + let msgId: string | void if (typeof something === 'string') { /** diff --git a/src/user/message.ts b/src/user/message.ts index d530c0bd9..77d69c657 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -417,6 +417,7 @@ export class Message extends Accessory implements Sayable { } public say (text: string) : Promise + public say (num: number) : Promise public say (message: Message) : Promise public say (contact: Contact) : Promise public say (file: FileBox) : Promise @@ -504,14 +505,15 @@ export class Message extends Accessory implements Sayable { * .start() */ public async say ( - textOrContactOrFileOrUrlOrMini : string + something : string + | number | Message | Contact | FileBox | UrlLink | MiniProgram, ): Promise { - log.verbose('Message', 'say(%s)', textOrContactOrFileOrUrlOrMini) + log.verbose('Message', 'say(%s)', something) // const user = this.puppet.userSelf() const from = this.from() @@ -534,12 +536,17 @@ export class Message extends Accessory implements Sayable { /** * Support say a existing message: just forward it. */ - if (textOrContactOrFileOrUrlOrMini instanceof Message) { - return textOrContactOrFileOrUrlOrMini.forward(conversation) + if (something instanceof Message) { + return something.forward(conversation) + } + + // Convert number to string + if (typeof something === 'number') { + something = String(something) } let msgId: void | string - if (typeof textOrContactOrFileOrUrlOrMini === 'string') { + if (typeof something === 'string') { /** * Text Message */ @@ -550,43 +557,43 @@ export class Message extends Accessory implements Sayable { msgId = await this.puppet.messageSendText( conversationId, - textOrContactOrFileOrUrlOrMini, + something, mentionIdList, ) - } else if (textOrContactOrFileOrUrlOrMini instanceof Contact) { + } else if (something instanceof Contact) { /** * Contact Card */ msgId = await this.puppet.messageSendContact( conversationId, - textOrContactOrFileOrUrlOrMini.id, + something.id, ) - } else if (textOrContactOrFileOrUrlOrMini instanceof FileBox) { + } else if (something instanceof FileBox) { /** * File Message */ msgId = await this.puppet.messageSendFile( conversationId, - textOrContactOrFileOrUrlOrMini, + something, ) - } else if (textOrContactOrFileOrUrlOrMini instanceof UrlLink) { + } else if (something instanceof UrlLink) { /** * Link Message */ msgId = await this.puppet.messageSendUrl( conversationId, - textOrContactOrFileOrUrlOrMini.payload, + something.payload, ) - } else if (textOrContactOrFileOrUrlOrMini instanceof MiniProgram) { + } else if (something instanceof MiniProgram) { /** * MiniProgram */ msgId = await this.puppet.messageSendMiniProgram( conversationId, - textOrContactOrFileOrUrlOrMini.payload, + something.payload, ) } else { - throw new Error('unknown msg: ' + textOrContactOrFileOrUrlOrMini) + throw new Error('unknown msg: ' + something) } if (msgId) { const msg = this.wechaty.Message.load(msgId) diff --git a/src/user/room.ts b/src/user/room.ts index 1e3444455..bd98afe35 100644 --- a/src/user/room.ts +++ b/src/user/room.ts @@ -378,6 +378,7 @@ export class Room extends Accessory implements Sayable { } public say (text: string) : Promise + public say (num: number) : Promise public say (message: Message) : Promise public say (text: string, ...mentionList: Contact[]) : Promise public say (textList: TemplateStringsArray, ...varList: any[]) : Promise @@ -460,6 +461,7 @@ export class Room extends Accessory implements Sayable { */ public async say ( something : string + | number | Message | Contact | FileBox @@ -510,6 +512,10 @@ export class Room extends Accessory implements Sayable { * Other conditions * */ + if (typeof something === 'number') { + something = String(something) + } + if (typeof something === 'string') { /** * 1. string From 725dbe2f6693eb14f75a1ee79d1c0536f9cf9eba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 11 Jul 2020 08:08:55 +0800 Subject: [PATCH 309/598] 0.41.37 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ae39cbb45..c435d13b8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.36", + "version": "0.41.37", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 0efc106b658382e04b8f8e10399e51ed6cdbe083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 11 Jul 2020 09:11:04 +0800 Subject: [PATCH 310/598] clean --- src/user/message.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/user/message.ts b/src/user/message.ts index 77d69c657..6fa1afc4a 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -593,7 +593,7 @@ export class Message extends Accessory implements Sayable { something.payload, ) } else { - throw new Error('unknown msg: ' + something) + throw new Error('Message.say() received unknown msg: ' + something) } if (msgId) { const msg = this.wechaty.Message.load(msgId) From c9d08affd6c116d32b3fc726193bf3dadb965bca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 11 Jul 2020 09:11:26 +0800 Subject: [PATCH 311/598] 0.41.38 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c435d13b8..e04d0f582 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.37", + "version": "0.41.38", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 1e5d0070176e1a34059a7d7dbb2808b34eecbf26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 12 Jul 2020 15:58:34 +0800 Subject: [PATCH 312/598] code clean --- src/user/message.ts | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/src/user/message.ts b/src/user/message.ts index 6fa1afc4a..dfddab025 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -156,17 +156,6 @@ export class Message extends Accessory implements Sayable { return msg } - /** - * TODO: rename create to load ??? Huan 201806 - * @deprecated: use load() instead - * @ignore - */ - - public static create (id: string): Message { - log.warn('Message', 'static create(%s) DEPRECATED. Use load() instead', id) - return this.load(id) - } - /** * * Instance Properties @@ -190,11 +179,11 @@ export class Message extends Accessory implements Sayable { const MyClass = instanceToClass(this, Message) if (MyClass === Message) { - throw new Error('Message class can not be instanciated directly! See: https://github.com/wechaty/wechaty/issues/1217') + throw new Error('Message class can not be instantiated directly! See: https://github.com/wechaty/wechaty/issues/1217') } if (!this.puppet) { - throw new Error('Message class can not be instanciated without a puppet!') + throw new Error('Message class can not be instantiated without a puppet!') } } @@ -228,15 +217,6 @@ export class Message extends Accessory implements Sayable { if (!this.payload) { throw new Error('no payload') } - // const filename = this.puppet.messagefile payload.filename - // if (!filename) { - // throw new Error( - // 'no file for message id: ' + this.id - // + ' with type: ' + Message.Type[this.payload.type] - // + '(' + this.payload.type + ')', - // ) - // } - // msgStrList.push(`<${filename || 'unknown file name'}>`) } return msgStrList.join('') @@ -457,8 +437,8 @@ export class Message extends Accessory implements Sayable { * // 2. send Text * * if (/^dong$/i.test(m.text())) { - * await msg.say('dingdingding') - * const message = await msg.say('dingdingding') // only supported by puppet-padplus + * await msg.say('ding') + * const message = await msg.say('ding') // only supported by puppet-padplus * } * * // 3. send Contact @@ -758,7 +738,7 @@ export class Message extends Accessory implements Sayable { contactList = contactList.concat.apply([], contactListNested) if (contactList.length === 0) { - log.silly('Message', `message.mentionList() can not found member using room.member() from mentionList, metion string: ${JSON.stringify(mentionNameList)}`) + log.silly('Message', `message.mentionList() can not found member using room.member() from mentionList, mention string: ${JSON.stringify(mentionNameList)}`) } return contactList } From 6653673a13fef95573d79d72909269b12fcb91ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 12 Jul 2020 15:59:31 +0800 Subject: [PATCH 313/598] 0.41.39 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e04d0f582..21e57905f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.38", + "version": "0.41.39", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 6e8cb154e03f01a326baca2f99806a4a9bc68d88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 12 Jul 2020 19:26:09 +0800 Subject: [PATCH 314/598] fix mocker double init bug --- package.json | 2 +- src/accessory.spec.ts | 0 src/config.spec.ts | 0 src/io.spec.ts | 0 src/puppet-config.ts | 2 +- src/puppet-manager.spec.ts | 0 src/version.spec.ts | 0 src/wechaty.spec.ts | 15 +++++++++++++++ 8 files changed, 17 insertions(+), 2 deletions(-) mode change 100644 => 100755 src/accessory.spec.ts mode change 100644 => 100755 src/config.spec.ts mode change 100644 => 100755 src/io.spec.ts mode change 100644 => 100755 src/puppet-manager.spec.ts mode change 100644 => 100755 src/version.spec.ts mode change 100644 => 100755 src/wechaty.spec.ts diff --git a/package.json b/package.json index 21e57905f..95bc6c30e 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "state-switch": "^0.9.9", "watchdog": "^0.8.17", "wechaty-puppet": "^0.27.1", - "wechaty-puppet-hostie": "^0.8.5", + "wechaty-puppet-hostie": "^0.8.13", "ws": "^7.2.3" }, "devDependencies": { diff --git a/src/accessory.spec.ts b/src/accessory.spec.ts old mode 100644 new mode 100755 diff --git a/src/config.spec.ts b/src/config.spec.ts old mode 100644 new mode 100755 diff --git a/src/io.spec.ts b/src/io.spec.ts old mode 100644 new mode 100755 diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 24749eb3f..4c7d4f9f2 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -33,7 +33,7 @@ export const PUPPET_DEPENDENCIES = { /** * Wechaty Internal Puppets: dependence by package.json */ - 'wechaty-puppet-hostie' : '^0.8.6', // https://www.npmjs.com/package/wechaty-puppet-hostie + 'wechaty-puppet-hostie' : '^0.8.13', // https://www.npmjs.com/package/wechaty-puppet-hostie 'wechaty-puppet-mock' : '^0.22.3', // https://www.npmjs.com/package/wechaty-puppet-mock /** diff --git a/src/puppet-manager.spec.ts b/src/puppet-manager.spec.ts old mode 100644 new mode 100755 diff --git a/src/version.spec.ts b/src/version.spec.ts old mode 100644 new mode 100755 diff --git a/src/wechaty.spec.ts b/src/wechaty.spec.ts old mode 100644 new mode 100755 index 529d98e2a..2b8e69b44 --- a/src/wechaty.spec.ts +++ b/src/wechaty.spec.ts @@ -310,3 +310,18 @@ test('ready()', async t => { await wechaty.stop() }) + +test.only('on/off event listener management', async t => { + const puppet = new PuppetMock() + const wechaty = new Wechaty({ puppet }) + + const onMessage = (_: any) => {} + t.equal(wechaty.listenerCount('message'), 0, 'should no listener after initializing') + + wechaty.on('message', onMessage) + t.equal(wechaty.listenerCount('message'), 1, 'should +1 listener after on(message)') + + wechaty.off('message', onMessage) + t.equal(wechaty.listenerCount('message'), 0, 'should -1 listener after off(message)') + +}) From 86db819f11f607e29508024303f8ca7911edd943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 12 Jul 2020 19:26:31 +0800 Subject: [PATCH 315/598] 0.41.40 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 95bc6c30e..9e7759494 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.39", + "version": "0.41.40", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 88075895b011d32b5d684e5c335eb68b652633bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 12 Jul 2020 21:09:34 +0800 Subject: [PATCH 316/598] fix event listener (#2021) --- package.json | 3 +- src/puppet-config.ts | 2 +- src/wechaty.spec.ts | 8 +- src/wechaty.ts | 471 +++++++++++++++++++++++-------------------- 4 files changed, 254 insertions(+), 230 deletions(-) diff --git a/package.json b/package.json index 9e7759494..a1575b7ab 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "state-switch": "^0.9.9", "watchdog": "^0.8.17", "wechaty-puppet": "^0.27.1", - "wechaty-puppet-hostie": "^0.8.13", + "wechaty-puppet-hostie": "^0.9.1", "ws": "^7.2.3" }, "devDependencies": { @@ -133,6 +133,7 @@ "qrcode-terminal": "^0.12.0", "shx": "^0.3.2", "sloc": "^0.2.1", + "typed-emitter": "^1.2.0", "tstest": "^0.4.10", "typedoc": "^0.16.11", "wechaty-puppet-mock": "^0.22.2" diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 4c7d4f9f2..ae26ec0f9 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -33,7 +33,7 @@ export const PUPPET_DEPENDENCIES = { /** * Wechaty Internal Puppets: dependence by package.json */ - 'wechaty-puppet-hostie' : '^0.8.13', // https://www.npmjs.com/package/wechaty-puppet-hostie + 'wechaty-puppet-hostie' : '^0.9.1', // https://www.npmjs.com/package/wechaty-puppet-hostie 'wechaty-puppet-mock' : '^0.22.3', // https://www.npmjs.com/package/wechaty-puppet-mock /** diff --git a/src/wechaty.spec.ts b/src/wechaty.spec.ts index 2b8e69b44..757c01029 100755 --- a/src/wechaty.spec.ts +++ b/src/wechaty.spec.ts @@ -130,13 +130,13 @@ test('event:start/stop', async t => { // console.log(m) // }) -test('on(event, Function)', async t => { +test.skip('SKIP DEALING WITH THE LISTENER EXCEPTIONS. on(event, Function)', async t => { const spy = sinon.spy() const wechaty = Wechaty.instance() const EXPECTED_ERROR = new Error('testing123') wechaty.on('message', () => { throw EXPECTED_ERROR }) - wechaty.on('scan', () => 42) + // wechaty.on('scan', () => 42) wechaty.on('error', spy) const messageFuture = new Promise(resolve => wechaty.once('message', resolve)) @@ -150,7 +150,7 @@ test('on(event, Function)', async t => { }) -test('test async error', async (t) => { +test.skip('SKIP DEALING WITH THE LISTENER EXCEPTIONS. test async error', async (t) => { // Do not modify the gloabl Wechaty instance class MyWechatyTest extends Wechaty {} @@ -311,7 +311,7 @@ test('ready()', async t => { await wechaty.stop() }) -test.only('on/off event listener management', async t => { +test('on/off event listener management', async t => { const puppet = new PuppetMock() const wechaty = new Wechaty({ puppet }) diff --git a/src/wechaty.ts b/src/wechaty.ts index 7f0fc2297..7fe03fa81 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -21,12 +21,9 @@ import cuid from 'cuid' import { EventEmitter } from 'events' import os from 'os' -import { - cloneClass, -} from 'clone-class' -import { - StateSwitch, -} from 'state-switch' +import TypedEventEmitter from 'typed-emitter' +import { cloneClass } from 'clone-class' +import { StateSwitch } from 'state-switch' import { CHAT_EVENT_DICT, @@ -112,6 +109,182 @@ export type WechatyRoomTopicEventListener = (this: Wechaty, room: Room, newTopi export type WechatyScanEventListener = (this: Wechaty, qrcode: string, status: ScanStatus, data?: string) => void export type WechatyStartStopEventListener = (this: Wechaty) => void +/** + * @desc Wechaty Class Event Type + * @typedef WechatyEventName + * @property {string} error - When the bot get error, there will be a Wechaty error event fired. + * @property {string} login - After the bot login full successful, the event login will be emitted, with a Contact of current logged in user. + * @property {string} logout - Logout will be emitted when bot detected log out, with a Contact of the current login user. + * @property {string} heartbeat - Get heartbeat of the bot. + * @property {string} friendship - When someone sends you a friend request, there will be a Wechaty friendship event fired. + * @property {string} message - Emit when there's a new message. + * @property {string} ready - Emit when all data has load completed, in wechaty-puppet-padchat, it means it has sync Contact and Room completed + * @property {string} room-join - Emit when anyone join any room. + * @property {string} room-topic - Get topic event, emitted when someone change room topic. + * @property {string} room-leave - Emit when anyone leave the room.
+ * - If someone leaves the room by themselves, WeChat will not notice other people in the room, so the bot will never get the "leave" event. + * @property {string} room-invite - Emit when there is a room invitation, see more in {@link RoomInvitation} + * @property {string} scan - A scan event will be emitted when the bot needs to show you a QR Code for scanning.
+ * It is recommend to install qrcode-terminal(run `npm install qrcode-terminal`) in order to show qrcode in the terminal. + */ + +/** + * @desc Wechaty Class Event Function + * @typedef WechatyEventFunction + * @property {Function} error -(this: Wechaty, error: Error) => void callback function + * @property {Function} login -(this: Wechaty, user: ContactSelf)=> void + * @property {Function} logout -(this: Wechaty, user: ContactSelf) => void + * @property {Function} scan -(this: Wechaty, url: string, code: number) => void
+ *
    + *
  1. URL: {String} the QR code image URL
  2. + *
  3. code: {Number} the scan status code. some known status of the code list here is:
  4. + *
+ *
    + *
  • 0 initial_
  • + *
  • 200 login confirmed
  • + *
  • 201 scanned, wait for confirm
  • + *
  • 408 waits for scan
  • + *
+ * @property {Function} heartbeat -(this: Wechaty, data: any) => void + * @property {Function} friendship -(this: Wechaty, friendship: Friendship) => void + * @property {Function} message -(this: Wechaty, message: Message) => void + * @property {Function} ready -(this: Wechaty) => void + * @property {Function} room-join -(this: Wechaty, room: Room, inviteeList: Contact[], inviter: Contact) => void + * @property {Function} room-topic -(this: Wechaty, room: Room, newTopic: string, oldTopic: string, changer: Contact) => void + * @property {Function} room-leave -(this: Wechaty, room: Room, leaverList: Contact[]) => void + * @property {Function} room-invite -(this: Wechaty, room: Room, roomInvitation: RoomInvitation) => void
+ * see more in {@link RoomInvitation} + */ + +/** + * @listens Wechaty + * @param {WechatyEventName} event - Emit WechatyEvent + * @param {WechatyEventFunction} listener - Depends on the WechatyEvent + * + * @return {Wechaty} - this for chaining, + * see advanced {@link https://github.com/wechaty/wechaty-getting-started/wiki/FAQ-EN#36-why-wechatyonevent-listener-return-wechaty|chaining usage} + * + * @desc + * When the bot get message, it will emit the following Event. + * + * You can do anything you want when in these events functions. + * The main Event name as follows: + * - **scan**: Emit when the bot needs to show you a QR Code for scanning. After scan the qrcode, you can login + * - **login**: Emit when bot login full successful. + * - **logout**: Emit when bot detected log out. + * - **message**: Emit when there's a new message. + * + * see more in {@link WechatyEventName} + * + * @example Event:scan + * // Scan Event will emit when the bot needs to show you a QR Code for scanning + * + * bot.on('scan', (url, status) => { + * console.log(`[${status}] Scan ${url} to login.` ) + * }) + * + * @example Event:login + * // Login Event will emit when bot login full successful. + * + * bot.on('login', (user) => { + * console.log(`user ${user} login`) + * }) + * + * @example Event:logout + * // Logout Event will emit when bot detected log out. + * + * bot.on('logout', (user) => { + * console.log(`user ${user} logout`) + * }) + * + * @example Event:message + * // Message Event will emit when there's a new message. + * + * wechaty.on('message', (message) => { + * console.log(`message ${message} received`) + * }) + * + * @example Event:friendship + * // Friendship Event will emit when got a new friend request, or friendship is confirmed. + * + * bot.on('friendship', (friendship) => { + * if(friendship.type() === Friendship.Type.Receive){ // 1. receive new friendship request from new contact + * const contact = friendship.contact() + * let result = await friendship.accept() + * if(result){ + * console.log(`Request from ${contact.name()} is accept successfully!`) + * } else{ + * console.log(`Request from ${contact.name()} failed to accept!`) + * } + * } else if (friendship.type() === Friendship.Type.Confirm) { // 2. confirm friendship + * console.log(`new friendship confirmed with ${contact.name()}`) + * } + * }) + * + * @example Event:room-join + * // room-join Event will emit when someone join the room. + * + * bot.on('room-join', (room, inviteeList, inviter) => { + * const nameList = inviteeList.map(c => c.name()).join(',') + * console.log(`Room ${room.topic()} got new member ${nameList}, invited by ${inviter}`) + * }) + * + * @example Event:room-leave + * // room-leave Event will emit when someone leave the room. + * + * bot.on('room-leave', (room, leaverList) => { + * const nameList = leaverList.map(c => c.name()).join(',') + * console.log(`Room ${room.topic()} lost member ${nameList}`) + * }) + * + * @example Event:room-topic + * // room-topic Event will emit when someone change the room's topic. + * + * bot.on('room-topic', (room, topic, oldTopic, changer) => { + * console.log(`Room ${room.topic()} topic changed from ${oldTopic} to ${topic} by ${changer.name()}`) + * }) + * + * @example Event:room-invite, RoomInvitation has been encapsulated as a RoomInvitation Class. + * // room-invite Event will emit when there's an room invitation. + * + * bot.on('room-invite', async roomInvitation => { + * try { + * console.log(`received room-invite event.`) + * await roomInvitation.accept() + * } catch (e) { + * console.error(e) + * } + * } + * + * @example Event:error + * // error Event will emit when there's an error occurred. + * + * bot.on('error', (error) => { + * console.error(error) + * }) + */ +interface Events { + dong : WechatyDongEventListener + error : WechatyErrorEventListener + friendship : WechatyFriendshipEventListener + heartbeat : WechatyHeartbeatEventListener + login : WechatyLoginEventListener + logout : WechatyLogoutEventListener + message : WechatyMessageEventListener + ready : WechatyReadyEventListener + 'room-invite' : WechatyRoomInviteEventListener + 'room-join' : WechatyRoomJoinEventListener + 'room-leave' : WechatyRoomLeaveEventListener + 'room-topic' : WechatyRoomTopicEventListener + scan : WechatyScanEventListener + start : WechatyStartStopEventListener + stop : WechatyStartStopEventListener +} + +const WechatyEventEmitter = EventEmitter as new () => TypedEventEmitter< + Events +> + export interface WechatyOptions { memory? : MemoryCard, name? : string, // Wechaty Name @@ -154,7 +327,7 @@ const PUPPET_MEMORY_NAME = 'puppet' * bot.on('message', message => console.log(`Message: ${message}`)) * bot.start() */ -export class Wechaty extends EventEmitter implements Sayable { +export class Wechaty extends WechatyEventEmitter implements Sayable { public static readonly VERSION = VERSION @@ -356,226 +529,76 @@ export class Wechaty extends EventEmitter implements Sayable { return this.options.name || 'wechaty' } - public emit (event: 'dong', data?: string) : boolean - public emit (event: 'error', error: Error) : boolean - public emit (event: 'friendship', friendship: Friendship) : boolean - public emit (event: 'heartbeat', data: any) : boolean - public emit (event: 'login', user: ContactSelf) : boolean - public emit (event: 'logout', user: ContactSelf, reason?: string) : boolean - public emit (event: 'message', message: Message) : boolean - public emit (event: 'ready') : boolean - public emit (event: 'room-invite', roomInvitation: RoomInvitation) : boolean - public emit (event: 'room-join', room: Room, inviteeList : Contact[], inviter : Contact, date: Date) : boolean - public emit (event: 'room-leave', room: Room, leaverList : Contact[], remover : Contact, date: Date) : boolean - public emit (event: 'room-topic', room: Room, newTopic: string, oldTopic: string, changer: Contact, date: Date) : boolean - public emit (event: 'scan', qrcode: string, status: ScanStatus, data?: string) : boolean - public emit (event: 'start' | 'stop') : boolean - - // guard for the above event: make sure it includes all the possible values - public emit (event: never, listener: never): never - - public emit ( - event: WechatyEventName, - ...args: any[] - ): boolean { - return super.emit(event, ...args) - } - - public on (event: 'dong', listener: WechatyDongEventListener) : this - public on (event: 'error', listener: WechatyErrorEventListener) : this - public on (event: 'friendship', listener: WechatyFriendshipEventListener) : this - public on (event: 'heartbeat', listener: WechatyHeartbeatEventListener) : this - public on (event: 'login', listener: WechatyLoginEventListener) : this - public on (event: 'logout', listener: WechatyLogoutEventListener) : this - public on (event: 'message', listener: WechatyMessageEventListener) : this - public on (event: 'ready', listener: WechatyReadyEventListener) : this - public on (event: 'room-invite', listener: WechatyRoomInviteEventListener) : this - public on (event: 'room-join', listener: WechatyRoomJoinEventListener) : this - public on (event: 'room-leave', listener: WechatyRoomLeaveEventListener) : this - public on (event: 'room-topic', listener: WechatyRoomTopicEventListener) : this - public on (event: 'scan', listener: WechatyScanEventListener) : this - public on (event: 'start' | 'stop', listener: WechatyStartStopEventListener) : this - - // guard for the above event: make sure it includes all the possible values - public on (event: never, listener: never): never - - /** - * @desc Wechaty Class Event Type - * @typedef WechatyEventName - * @property {string} error - When the bot get error, there will be a Wechaty error event fired. - * @property {string} login - After the bot login full successful, the event login will be emitted, with a Contact of current logged in user. - * @property {string} logout - Logout will be emitted when bot detected log out, with a Contact of the current login user. - * @property {string} heartbeat - Get heartbeat of the bot. - * @property {string} friendship - When someone sends you a friend request, there will be a Wechaty friendship event fired. - * @property {string} message - Emit when there's a new message. - * @property {string} ready - Emit when all data has load completed, in wechaty-puppet-padchat, it means it has sync Contact and Room completed - * @property {string} room-join - Emit when anyone join any room. - * @property {string} room-topic - Get topic event, emitted when someone change room topic. - * @property {string} room-leave - Emit when anyone leave the room.
- * - If someone leaves the room by themselves, WeChat will not notice other people in the room, so the bot will never get the "leave" event. - * @property {string} room-invite - Emit when there is a room invitation, see more in {@link RoomInvitation} - * @property {string} scan - A scan event will be emitted when the bot needs to show you a QR Code for scanning.
- * It is recommend to install qrcode-terminal(run `npm install qrcode-terminal`) in order to show qrcode in the terminal. - */ + // public emit (event: 'dong', data?: string) : boolean + // public emit (event: 'error', error: Error) : boolean + // public emit (event: 'friendship', friendship: Friendship) : boolean + // public emit (event: 'heartbeat', data: any) : boolean + // public emit (event: 'login', user: ContactSelf) : boolean + // public emit (event: 'logout', user: ContactSelf, reason?: string) : boolean + // public emit (event: 'message', message: Message) : boolean + // public emit (event: 'ready') : boolean + // public emit (event: 'room-invite', roomInvitation: RoomInvitation) : boolean + // public emit (event: 'room-join', room: Room, inviteeList : Contact[], inviter : Contact, date: Date) : boolean + // public emit (event: 'room-leave', room: Room, leaverList : Contact[], remover : Contact, date: Date) : boolean + // public emit (event: 'room-topic', room: Room, newTopic: string, oldTopic: string, changer: Contact, date: Date) : boolean + // public emit (event: 'scan', qrcode: string, status: ScanStatus, data?: string) : boolean + // public emit (event: 'start' | 'stop') : boolean + + // // guard for the above event: make sure it includes all the possible values + // public emit (event: never, listener: never): never + + // public emit ( + // event: WechatyEventName, + // ...args: any[] + // ): boolean { + // return super.emit(event, ...args) + // } + + // public on (event: 'dong', listener: WechatyDongEventListener) : this + // public on (event: 'error', listener: WechatyErrorEventListener) : this + // public on (event: 'friendship', listener: WechatyFriendshipEventListener) : this + // public on (event: 'heartbeat', listener: WechatyHeartbeatEventListener) : this + // public on (event: 'login', listener: WechatyLoginEventListener) : this + // public on (event: 'logout', listener: WechatyLogoutEventListener) : this + // public on (event: 'message', listener: WechatyMessageEventListener) : this + // public on (event: 'ready', listener: WechatyReadyEventListener) : this + // public on (event: 'room-invite', listener: WechatyRoomInviteEventListener) : this + // public on (event: 'room-join', listener: WechatyRoomJoinEventListener) : this + // public on (event: 'room-leave', listener: WechatyRoomLeaveEventListener) : this + // public on (event: 'room-topic', listener: WechatyRoomTopicEventListener) : this + // public on (event: 'scan', listener: WechatyScanEventListener) : this + // public on (event: 'start' | 'stop', listener: WechatyStartStopEventListener) : this + + // // guard for the above event: make sure it includes all the possible values + // public on (event: never, listener: never): never - /** - * @desc Wechaty Class Event Function - * @typedef WechatyEventFunction - * @property {Function} error -(this: Wechaty, error: Error) => void callback function - * @property {Function} login -(this: Wechaty, user: ContactSelf)=> void - * @property {Function} logout -(this: Wechaty, user: ContactSelf) => void - * @property {Function} scan -(this: Wechaty, url: string, code: number) => void
- *
    - *
  1. URL: {String} the QR code image URL
  2. - *
  3. code: {Number} the scan status code. some known status of the code list here is:
  4. - *
- *
    - *
  • 0 initial_
  • - *
  • 200 login confirmed
  • - *
  • 201 scanned, wait for confirm
  • - *
  • 408 waits for scan
  • - *
- * @property {Function} heartbeat -(this: Wechaty, data: any) => void - * @property {Function} friendship -(this: Wechaty, friendship: Friendship) => void - * @property {Function} message -(this: Wechaty, message: Message) => void - * @property {Function} ready -(this: Wechaty) => void - * @property {Function} room-join -(this: Wechaty, room: Room, inviteeList: Contact[], inviter: Contact) => void - * @property {Function} room-topic -(this: Wechaty, room: Room, newTopic: string, oldTopic: string, changer: Contact) => void - * @property {Function} room-leave -(this: Wechaty, room: Room, leaverList: Contact[]) => void - * @property {Function} room-invite -(this: Wechaty, room: Room, roomInvitation: RoomInvitation) => void
- * see more in {@link RoomInvitation} - */ - - /** - * @listens Wechaty - * @param {WechatyEventName} event - Emit WechatyEvent - * @param {WechatyEventFunction} listener - Depends on the WechatyEvent - * - * @return {Wechaty} - this for chaining, - * see advanced {@link https://github.com/wechaty/wechaty-getting-started/wiki/FAQ-EN#36-why-wechatyonevent-listener-return-wechaty|chaining usage} - * - * @desc - * When the bot get message, it will emit the following Event. - * - * You can do anything you want when in these events functions. - * The main Event name as follows: - * - **scan**: Emit when the bot needs to show you a QR Code for scanning. After scan the qrcode, you can login - * - **login**: Emit when bot login full successful. - * - **logout**: Emit when bot detected log out. - * - **message**: Emit when there's a new message. - * - * see more in {@link WechatyEventName} - * - * @example Event:scan - * // Scan Event will emit when the bot needs to show you a QR Code for scanning - * - * bot.on('scan', (url, status) => { - * console.log(`[${status}] Scan ${url} to login.` ) - * }) - * - * @example Event:login - * // Login Event will emit when bot login full successful. - * - * bot.on('login', (user) => { - * console.log(`user ${user} login`) - * }) - * - * @example Event:logout - * // Logout Event will emit when bot detected log out. - * - * bot.on('logout', (user) => { - * console.log(`user ${user} logout`) - * }) - * - * @example Event:message - * // Message Event will emit when there's a new message. - * - * wechaty.on('message', (message) => { - * console.log(`message ${message} received`) - * }) - * - * @example Event:friendship - * // Friendship Event will emit when got a new friend request, or friendship is confirmed. - * - * bot.on('friendship', (friendship) => { - * if(friendship.type() === Friendship.Type.Receive){ // 1. receive new friendship request from new contact - * const contact = friendship.contact() - * let result = await friendship.accept() - * if(result){ - * console.log(`Request from ${contact.name()} is accept successfully!`) - * } else{ - * console.log(`Request from ${contact.name()} failed to accept!`) - * } - * } else if (friendship.type() === Friendship.Type.Confirm) { // 2. confirm friendship - * console.log(`new friendship confirmed with ${contact.name()}`) - * } - * }) - * - * @example Event:room-join - * // room-join Event will emit when someone join the room. - * - * bot.on('room-join', (room, inviteeList, inviter) => { - * const nameList = inviteeList.map(c => c.name()).join(',') - * console.log(`Room ${room.topic()} got new member ${nameList}, invited by ${inviter}`) - * }) - * - * @example Event:room-leave - * // room-leave Event will emit when someone leave the room. - * - * bot.on('room-leave', (room, leaverList) => { - * const nameList = leaverList.map(c => c.name()).join(',') - * console.log(`Room ${room.topic()} lost member ${nameList}`) - * }) - * - * @example Event:room-topic - * // room-topic Event will emit when someone change the room's topic. - * - * bot.on('room-topic', (room, topic, oldTopic, changer) => { - * console.log(`Room ${room.topic()} topic changed from ${oldTopic} to ${topic} by ${changer.name()}`) - * }) - * - * @example Event:room-invite, RoomInvitation has been encapsulated as a RoomInvitation Class. - * // room-invite Event will emit when there's an room invitation. - * - * bot.on('room-invite', async roomInvitation => { - * try { - * console.log(`received room-invite event.`) - * await roomInvitation.accept() - * } catch (e) { - * console.error(e) - * } - * } - * - * @example Event:error - * // error Event will emit when there's an error occurred. - * - * bot.on('error', (error) => { - * console.error(error) - * }) - */ public on (event: WechatyEventName, listener: (...args: any[]) => any): this { - log.verbose('Wechaty', 'on(%s, listener) registered', event) - - const handleError = (e: Error, type = '') => { - log.error('Wechaty', 'addListenerFunction(%s) listener %s exception: %s', event, type, e) - this.emit('error', e) - } - - /** - * We use `super.on()` at here to prevent loop - */ - super.on(event, (...args: any[]) => { - try { - const result = listener.apply(this, args) - if (result && result.catch && typeof result.catch === 'function') { - result.catch((e: Error) => handleError(e, 'async')) - } - } catch (e) { - handleError(e) - } - }) + log.verbose('Wechaty', 'on(%s, listener) registering... listenerCount: %s', + event, + this.listenerCount(event), + ) - return this + return super.on(event, listener) + + // const handleError = (e: Error, type = '') => { + // log.error('Wechaty', 'addListenerFunction(%s) listener %s exception: %s', event, type, e) + // this.emit('error', e) + // } + + // /** + // * We use `super.on()` at here to prevent loop + // */ + // super.on(event, (...args: any[]) => { + // try { + // const result = listener.apply(this, args) + // if (result && result.catch && typeof result.catch === 'function') { + // result.catch((e: Error) => handleError(e, 'async')) + // } + // } catch (e) { + // handleError(e) + // } + // }) + // return this } /** From 0f02d2a65c87da198771160b9e5f88754b4d728d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 12 Jul 2020 21:09:59 +0800 Subject: [PATCH 317/598] add createFixture (#2022) --- src/create-fixture.spec.ts | 81 +++++++++++++++++++++++++++++++++++++ src/create-fixture.ts | 82 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100755 src/create-fixture.spec.ts create mode 100644 src/create-fixture.ts diff --git a/src/create-fixture.spec.ts b/src/create-fixture.spec.ts new file mode 100755 index 000000000..78cc41c6f --- /dev/null +++ b/src/create-fixture.spec.ts @@ -0,0 +1,81 @@ +#!/usr/bin/env ts-node + +import { + test, + sinon, +} from 'tstest' + +import { MockContact } from 'wechaty-puppet-mock/dist/src/mocker/user/mock-contact' + +import { Message } from './user/message' +import { createFixture } from './create-fixture' + +test('createFixture() initial state', async (t) => { + for await (const fixture of createFixture()) { + t.true(fixture.message instanceof Message, 'should have message instance') + t.equal(fixture.message.type(), Message.Type.Text, 'should have message with text type') + t.equal(typeof fixture.message.text(), 'string', 'should have message with text content') + + t.equal(fixture.moList.length, 0, 'should be empty mo list') + t.equal(fixture.mtList.length, 0, 'should be empty mt list') + + t.true(fixture.mary instanceof MockContact, 'should get mock contact mary') + t.true(fixture.mike instanceof MockContact, 'should get mock contact mike') + } +}) + +test('createFixture() Mobile Originated', async (t) => { + for await (const fixture of createFixture()) { + const spy = sinon.spy() + fixture.wechaty.on('message', spy) + + fixture.user.say().to(fixture.mary) + await new Promise(setImmediate) + + t.true(spy.called, 'should received message event') + t.equal(spy.args[0][0].from().id, fixture.user.id, 'should get user as from') + t.equal(spy.args[0][0].to().id, fixture.mary.id, 'should get mary as to') + + t.equal(fixture.moList.length, 1, 'should be 1 mo') + t.equal(fixture.mtList.length, 0, 'should be empty mt list') + t.equal(fixture.moList[0].id, spy.args[0][0].id, 'should get the same message instance') + } +}) + +test('createFixture() Mobile Terminated', async (t) => { + for await (const fixture of createFixture()) { + const spy = sinon.spy() + fixture.wechaty.on('message', spy) + + fixture.mary.say().to(fixture.user) + await new Promise(setImmediate) + + t.true(spy.called, 'should received message event') + t.equal(spy.args[0][0].to().id, fixture.user.id, 'should get user as to') + t.equal(spy.args[0][0].from().id, fixture.mary.id, 'should get mary as from') + + t.equal(fixture.moList.length, 0, 'should be 0 mo') + t.equal(fixture.mtList.length, 1, 'should be 1 mt') + t.equal(fixture.mtList[0].id, spy.args[0][0].id, 'should get the same message instance') + } +}) + +test('user.say() multiple times with moList', async t => { + for await (const fixture of createFixture()) { + const TEXT_LIST = [ + 'one', + 'two', + 'three', + ] + for (const text of TEXT_LIST) { + await fixture.user.say(text).to(fixture.mary) + } + await new Promise(setImmediate) + + t.equal(fixture.moList.length, TEXT_LIST.length, 'should receive all TEXT_LIST') + for (let i = 0; i < TEXT_LIST.length; i++) { + t.ok(fixture.moList[i], `should exist moList for ${i}`) + t.deepEqual(fixture.moList[i].text(), TEXT_LIST[i], `should get TEXT_LIST[${i}]: ${TEXT_LIST[i]}`) + } + } +}) diff --git a/src/create-fixture.ts b/src/create-fixture.ts new file mode 100644 index 000000000..d9781dac4 --- /dev/null +++ b/src/create-fixture.ts @@ -0,0 +1,82 @@ +/* eslint-disable sort-keys */ +import { + PuppetMock, + Mocker, +} from 'wechaty-puppet-mock' +import { MockContact } from 'wechaty-puppet-mock/dist/src/mocker/user/mock-contact' +import { MockRoom } from 'wechaty-puppet-mock/dist/src/mocker/user/mock-room' + +import { Wechaty } from './wechaty' +import { Message } from './user/message' + +interface Fixture { + wechaty: Wechaty, + mocker: Mocker, + + message: Message, + moList: Message[], + mtList: Message[], + + user: MockContact, + mary: MockContact, + mike: MockContact, + + room: MockRoom, +} + +async function * createFixture (): AsyncGenerator { + const mocker = new Mocker() + const puppet = new PuppetMock({ mocker }) + const wechaty = new Wechaty({ puppet }) + + await wechaty.start() + + const [user, mike, mary] = mocker.createContacts(3) + mocker.login(user) + + const room = mocker.createRoom({ + memberIdList: [ + user.id, + mike.id, + mary.id, + ], + }) + + const messageFuture = new Promise(resolve => wechaty.once('message', resolve)) + mike.say().to(room) + const message = await messageFuture + + // Mobile Terminated + const mtList = [] as Message[] + const recordMobileTerminatedMessage = (message: Message) => { + if (!message.self()) { + mtList.push(message) + } + } + wechaty.on('message', recordMobileTerminatedMessage) + + // Mobile Originated + const moList = [] as Message[] + const recordMobileOriginatedMessage = (message: Message) => { + if (message.self()) { + moList.push(message) + } + } + wechaty.on('message', recordMobileOriginatedMessage) + + yield { + wechaty, + mocker, + message, + moList, + mtList, + user, + mary, + mike, + room, + } + + await wechaty.stop() +} + +export { createFixture } From e8f9d8d2e25386378c460f9dfed7914f10de484c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 12 Jul 2020 21:10:17 +0800 Subject: [PATCH 318/598] export createFixture --- src/mod.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mod.ts b/src/mod.ts index 9d7bf6b31..8441ca8c7 100644 --- a/src/mod.ts +++ b/src/mod.ts @@ -60,6 +60,8 @@ export { MiniProgram, } from './user/mod' +export { createFixture } from './create-fixture' + export { } from './deprecated' From 0b07800e9709f277050e44a8bac0e1c6b2d4d469 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 12 Jul 2020 21:11:03 +0800 Subject: [PATCH 319/598] 0.41.41 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a1575b7ab..26a3b4b4e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.40", + "version": "0.41.41", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 5583dc8ab48b2bb31265f55403127aa53849f119 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 12 Jul 2020 21:12:53 +0800 Subject: [PATCH 320/598] remove createFixture from puppet mock --- package.json | 2 +- src/puppet-config.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 26a3b4b4e..9f3a18e9f 100644 --- a/package.json +++ b/package.json @@ -136,7 +136,7 @@ "typed-emitter": "^1.2.0", "tstest": "^0.4.10", "typedoc": "^0.16.11", - "wechaty-puppet-mock": "^0.22.2" + "wechaty-puppet-mock": "^0.22.39" }, "files_comment__whitelist_npm_publish": "http://stackoverflow.com/a/8617868/1123955", "files": [ diff --git a/src/puppet-config.ts b/src/puppet-config.ts index ae26ec0f9..823eff21d 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -34,7 +34,7 @@ export const PUPPET_DEPENDENCIES = { * Wechaty Internal Puppets: dependence by package.json */ 'wechaty-puppet-hostie' : '^0.9.1', // https://www.npmjs.com/package/wechaty-puppet-hostie - 'wechaty-puppet-mock' : '^0.22.3', // https://www.npmjs.com/package/wechaty-puppet-mock + 'wechaty-puppet-mock' : '^0.22.39', // https://www.npmjs.com/package/wechaty-puppet-mock /** * Wechaty External Puppets From a3a8cc7cbbe140d2ece7d9e933831f38e49b8182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 12 Jul 2020 21:23:14 +0800 Subject: [PATCH 321/598] 0.41.42 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9f3a18e9f..ddfdb80d2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.41", + "version": "0.41.42", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 723ad5783454a341b7cdb4c50577f92472ed386d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 12 Jul 2020 21:33:24 +0800 Subject: [PATCH 322/598] fix pack testing --- scripts/npm-pack-testing.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/npm-pack-testing.sh b/scripts/npm-pack-testing.sh index 60a247689..69733ed97 100755 --- a/scripts/npm-pack-testing.sh +++ b/scripts/npm-pack-testing.sh @@ -15,7 +15,8 @@ npm install --production \ ./*-*.*.*.tgz \ @types/node \ is-pr \ - typescript + typescript \ + "wechaty-puppet-mock@$NPM_TAG" \ ./node_modules/.bin/tsc \ --lib esnext \ From bd53a488abe46e243d7309705567c99f2544870d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 12 Jul 2020 21:33:40 +0800 Subject: [PATCH 323/598] 0.41.43 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ddfdb80d2..2855bd620 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.42", + "version": "0.41.43", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 10ef86c53da742d234b143f5c102238384eb75d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 12 Jul 2020 21:54:24 +0800 Subject: [PATCH 324/598] check typed-emitter in pack testing --- tests/fixtures/smoke-testing.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/fixtures/smoke-testing.ts b/tests/fixtures/smoke-testing.ts index eb09da28b..eff6c8775 100644 --- a/tests/fixtures/smoke-testing.ts +++ b/tests/fixtures/smoke-testing.ts @@ -59,9 +59,10 @@ async function main () { await Promise.all( botList.map(bot => bot.start()), ) - botList.forEach( - bot => console.info(`Wechaty v${bot.version()} smoking test passed.`), - ) + for (const bot of botList) { + console.info(`Wechaty v${bot.version()} smoking test passed.`) + console.info('listenerCount(message) is', bot.listenerCount('message')) + } } catch (e) { console.error(e) // Error! From c72c51ad159e91d2ec8a7ce45f93d9ba6a3aa08c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 12 Jul 2020 21:54:42 +0800 Subject: [PATCH 325/598] 0.41.44 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2855bd620..c562aa6b7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.43", + "version": "0.41.44", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From bbd00e41d6dc139266acc1465beec4b336ef31a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 12 Jul 2020 22:00:07 +0800 Subject: [PATCH 326/598] fix typed emitter --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c562aa6b7..3037e03e6 100644 --- a/package.json +++ b/package.json @@ -99,6 +99,7 @@ "raven": "^2.6.4", "read-pkg-up": "^7.0.1", "state-switch": "^0.9.9", + "typed-emitter": "^1.2.0", "watchdog": "^0.8.17", "wechaty-puppet": "^0.27.1", "wechaty-puppet-hostie": "^0.9.1", @@ -133,7 +134,6 @@ "qrcode-terminal": "^0.12.0", "shx": "^0.3.2", "sloc": "^0.2.1", - "typed-emitter": "^1.2.0", "tstest": "^0.4.10", "typedoc": "^0.16.11", "wechaty-puppet-mock": "^0.22.39" From f60748311c84e2bb926572f8d37072d070658113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 12 Jul 2020 22:00:23 +0800 Subject: [PATCH 327/598] 0.41.45 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3037e03e6..2daadd117 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.44", + "version": "0.41.45", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 1cadbc3947e40bee6f1d94622875690f1ac5ea4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 13 Jul 2020 12:43:09 +0800 Subject: [PATCH 328/598] upgrade to the lastest mock system --- package.json | 4 ++-- src/create-fixture.spec.ts | 9 +++++---- src/create-fixture.ts | 16 +++++++--------- src/puppet-config.ts | 2 +- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 2daadd117..cb972362d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.41.45", + "version": "0.43.0", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", @@ -136,7 +136,7 @@ "sloc": "^0.2.1", "tstest": "^0.4.10", "typedoc": "^0.16.11", - "wechaty-puppet-mock": "^0.22.39" + "wechaty-puppet-mock": "^0.25.1" }, "files_comment__whitelist_npm_publish": "http://stackoverflow.com/a/8617868/1123955", "files": [ diff --git a/src/create-fixture.spec.ts b/src/create-fixture.spec.ts index 78cc41c6f..b520105f1 100755 --- a/src/create-fixture.spec.ts +++ b/src/create-fixture.spec.ts @@ -4,8 +4,9 @@ import { test, sinon, } from 'tstest' - -import { MockContact } from 'wechaty-puppet-mock/dist/src/mocker/user/mock-contact' +import { + mock, +} from 'wechaty-puppet-mock' import { Message } from './user/message' import { createFixture } from './create-fixture' @@ -19,8 +20,8 @@ test('createFixture() initial state', async (t) => { t.equal(fixture.moList.length, 0, 'should be empty mo list') t.equal(fixture.mtList.length, 0, 'should be empty mt list') - t.true(fixture.mary instanceof MockContact, 'should get mock contact mary') - t.true(fixture.mike instanceof MockContact, 'should get mock contact mike') + t.true(fixture.mary instanceof mock.ContactMock, 'should get mock contact mary') + t.true(fixture.mike instanceof mock.ContactMock, 'should get mock contact mike') } }) diff --git a/src/create-fixture.ts b/src/create-fixture.ts index d9781dac4..06b937811 100644 --- a/src/create-fixture.ts +++ b/src/create-fixture.ts @@ -1,31 +1,29 @@ /* eslint-disable sort-keys */ import { PuppetMock, - Mocker, + mock, } from 'wechaty-puppet-mock' -import { MockContact } from 'wechaty-puppet-mock/dist/src/mocker/user/mock-contact' -import { MockRoom } from 'wechaty-puppet-mock/dist/src/mocker/user/mock-room' import { Wechaty } from './wechaty' import { Message } from './user/message' interface Fixture { wechaty: Wechaty, - mocker: Mocker, + mocker: mock.Mocker, message: Message, moList: Message[], mtList: Message[], - user: MockContact, - mary: MockContact, - mike: MockContact, + user: mock.ContactMock, + mary: mock.ContactMock, + mike: mock.ContactMock, - room: MockRoom, + room: mock.RoomMock, } async function * createFixture (): AsyncGenerator { - const mocker = new Mocker() + const mocker = new mock.Mocker() const puppet = new PuppetMock({ mocker }) const wechaty = new Wechaty({ puppet }) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 823eff21d..4e2e81545 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -34,7 +34,7 @@ export const PUPPET_DEPENDENCIES = { * Wechaty Internal Puppets: dependence by package.json */ 'wechaty-puppet-hostie' : '^0.9.1', // https://www.npmjs.com/package/wechaty-puppet-hostie - 'wechaty-puppet-mock' : '^0.22.39', // https://www.npmjs.com/package/wechaty-puppet-mock + 'wechaty-puppet-mock' : '^0.25.1', // https://www.npmjs.com/package/wechaty-puppet-mock /** * Wechaty External Puppets From 59b377c30cf805ba51f2eb19e34cefcf015b04a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 13 Jul 2020 12:43:28 +0800 Subject: [PATCH 329/598] 0.43.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cb972362d..175b8cb89 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.43.0", + "version": "0.43.1", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From f36d4be68a70f685a860070cce89e5c29b963d86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 13 Jul 2020 12:54:06 +0800 Subject: [PATCH 330/598] change the fixture structure & data for convenience --- src/create-fixture.spec.ts | 22 +++++++++++++--------- src/create-fixture.ts | 31 +++++++++++++++---------------- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/src/create-fixture.spec.ts b/src/create-fixture.spec.ts index b520105f1..a58934106 100755 --- a/src/create-fixture.spec.ts +++ b/src/create-fixture.spec.ts @@ -17,11 +17,15 @@ test('createFixture() initial state', async (t) => { t.equal(fixture.message.type(), Message.Type.Text, 'should have message with text type') t.equal(typeof fixture.message.text(), 'string', 'should have message with text content') + t.equal(fixture.message.talker().id, fixture.player.id, 'should get a message send from player') + t.equal(fixture.message.to()!.id, fixture.bot.id, 'should get a message send to bot') + t.false(fixture.message.room(), 'should get a message as direct message') + t.equal(fixture.moList.length, 0, 'should be empty mo list') t.equal(fixture.mtList.length, 0, 'should be empty mt list') - t.true(fixture.mary instanceof mock.ContactMock, 'should get mock contact mary') - t.true(fixture.mike instanceof mock.ContactMock, 'should get mock contact mike') + t.true(fixture.bot instanceof mock.ContactMock, 'should get mock contact mary') + t.true(fixture.player instanceof mock.ContactMock, 'should get mock contact mike') } }) @@ -30,12 +34,12 @@ test('createFixture() Mobile Originated', async (t) => { const spy = sinon.spy() fixture.wechaty.on('message', spy) - fixture.user.say().to(fixture.mary) + fixture.bot.say().to(fixture.player) await new Promise(setImmediate) t.true(spy.called, 'should received message event') - t.equal(spy.args[0][0].from().id, fixture.user.id, 'should get user as from') - t.equal(spy.args[0][0].to().id, fixture.mary.id, 'should get mary as to') + t.equal(spy.args[0][0].from().id, fixture.bot.id, 'should get bot as from') + t.equal(spy.args[0][0].to().id, fixture.player.id, 'should get player as to') t.equal(fixture.moList.length, 1, 'should be 1 mo') t.equal(fixture.mtList.length, 0, 'should be empty mt list') @@ -48,12 +52,12 @@ test('createFixture() Mobile Terminated', async (t) => { const spy = sinon.spy() fixture.wechaty.on('message', spy) - fixture.mary.say().to(fixture.user) + fixture.player.say().to(fixture.bot) await new Promise(setImmediate) t.true(spy.called, 'should received message event') - t.equal(spy.args[0][0].to().id, fixture.user.id, 'should get user as to') - t.equal(spy.args[0][0].from().id, fixture.mary.id, 'should get mary as from') + t.equal(spy.args[0][0].to().id, fixture.bot.id, 'should get bot as to') + t.equal(spy.args[0][0].from().id, fixture.player.id, 'should get player as from') t.equal(fixture.moList.length, 0, 'should be 0 mo') t.equal(fixture.mtList.length, 1, 'should be 1 mt') @@ -69,7 +73,7 @@ test('user.say() multiple times with moList', async t => { 'three', ] for (const text of TEXT_LIST) { - await fixture.user.say(text).to(fixture.mary) + await fixture.bot.say(text).to(fixture.player) } await new Promise(setImmediate) diff --git a/src/create-fixture.ts b/src/create-fixture.ts index 06b937811..4f3c1d624 100644 --- a/src/create-fixture.ts +++ b/src/create-fixture.ts @@ -8,16 +8,15 @@ import { Wechaty } from './wechaty' import { Message } from './user/message' interface Fixture { - wechaty: Wechaty, - mocker: mock.Mocker, + wechaty : Wechaty, + mocker : mock.Mocker, - message: Message, moList: Message[], mtList: Message[], - user: mock.ContactMock, - mary: mock.ContactMock, - mike: mock.ContactMock, + bot : mock.ContactMock, + player : mock.ContactMock, + message : Message, room: mock.RoomMock, } @@ -29,19 +28,18 @@ async function * createFixture (): AsyncGenerator { await wechaty.start() - const [user, mike, mary] = mocker.createContacts(3) - mocker.login(user) + const [bot, player] = mocker.createContacts(3) + mocker.login(bot) const room = mocker.createRoom({ memberIdList: [ - user.id, - mike.id, - mary.id, + bot.id, + player.id, ], }) const messageFuture = new Promise(resolve => wechaty.once('message', resolve)) - mike.say().to(room) + player.say().to(bot) const message = await messageFuture // Mobile Terminated @@ -65,13 +63,14 @@ async function * createFixture (): AsyncGenerator { yield { wechaty, mocker, + + bot, + player, message, + room, + moList, mtList, - user, - mary, - mike, - room, } await wechaty.stop() From 3b13244c2734421bcd721c446970d515c133f4ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 13 Jul 2020 12:54:27 +0800 Subject: [PATCH 331/598] 0.43.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 175b8cb89..fa2ac4479 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.43.1", + "version": "0.43.2", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 8a0685b91340b900812497c800262fc7d86b48f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 13 Jul 2020 13:40:49 +0800 Subject: [PATCH 332/598] set mock user name to bot/player --- src/create-fixture.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/create-fixture.ts b/src/create-fixture.ts index 4f3c1d624..ebca5c520 100644 --- a/src/create-fixture.ts +++ b/src/create-fixture.ts @@ -28,7 +28,8 @@ async function * createFixture (): AsyncGenerator { await wechaty.start() - const [bot, player] = mocker.createContacts(3) + const bot = mocker.createContact({ name: 'Bot' }) + const player = mocker.createContact({ name: 'Player' }) mocker.login(bot) const room = mocker.createRoom({ From cf5506c73b309b28e27c482c6d8ee8b466f5cbb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 13 Jul 2020 13:41:17 +0800 Subject: [PATCH 333/598] 0.43.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fa2ac4479..54c48347f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.43.2", + "version": "0.43.3", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From cda9c95e996eb530230771c8281c4c88444d47cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 13 Jul 2020 16:38:32 +0800 Subject: [PATCH 334/598] move mock from devDep to dep --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 54c48347f..93727ca25 100644 --- a/package.json +++ b/package.json @@ -103,6 +103,7 @@ "watchdog": "^0.8.17", "wechaty-puppet": "^0.27.1", "wechaty-puppet-hostie": "^0.9.1", + "wechaty-puppet-mock": "^0.25.1", "ws": "^7.2.3" }, "devDependencies": { @@ -135,8 +136,7 @@ "shx": "^0.3.2", "sloc": "^0.2.1", "tstest": "^0.4.10", - "typedoc": "^0.16.11", - "wechaty-puppet-mock": "^0.25.1" + "typedoc": "^0.16.11" }, "files_comment__whitelist_npm_publish": "http://stackoverflow.com/a/8617868/1123955", "files": [ From 3ee65a850800cdaa606d2cb28bf7fcfb0b37876a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 13 Jul 2020 16:38:50 +0800 Subject: [PATCH 335/598] 0.43.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 93727ca25..406e41518 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.43.3", + "version": "0.43.4", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 8034e6727eb6841d56b52484c3d81be23c2d0d73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 15 Jul 2020 01:59:13 +0800 Subject: [PATCH 336/598] clean smoke testing --- tests/fixtures/smoke-testing.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/fixtures/smoke-testing.ts b/tests/fixtures/smoke-testing.ts index eff6c8775..d777d256c 100644 --- a/tests/fixtures/smoke-testing.ts +++ b/tests/fixtures/smoke-testing.ts @@ -27,14 +27,14 @@ import { function getBotList (): Wechaty[] { const botList = [ new Wechaty({ puppet: 'wechaty-puppet-mock' }), - new Wechaty({ puppet: 'wechaty-puppet-wechat4u' }), + // new Wechaty({ puppet: 'wechaty-puppet-wechat4u' }), // new Wechaty({ puppet: 'wechaty-puppet-puppeteer' }), ] if (process.env.WECHATY_PUPPET_HOSTIE_TOKEN) { botList.push( new Wechaty({ - puppet: 'wechaty-puppet-padplus', + puppet: 'wechaty-puppet-hostie', }) ) } From d174a71629ef46a0cdc8c72eabc7ea6def9e4932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 15 Jul 2020 02:05:19 +0800 Subject: [PATCH 337/598] 0.43.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 406e41518..4f3a8e2da 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.43.4", + "version": "0.43.5", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From a68bc9c6711b5872eddb28939633540ff78d52d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 15 Jul 2020 13:35:36 +0800 Subject: [PATCH 338/598] fix wiki link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3c926bec7..f37a451f5 100644 --- a/README.md +++ b/README.md @@ -364,7 +364,7 @@ See: [![Powered by Wechaty](https://img.shields.io/badge/Powered%20By-Wechaty-brightgreen.svg)](https://github.com/Wechaty/wechaty) ``` -Get more embed html/markdown code from [Wiki:PoweredByWechaty](https://github.com/Wechaty/wechaty/wiki/PoweredByWechaty) +Get more embed html/markdown code from [Wiki:Projects Using Wechaty](https://github.com/wechaty/wechaty/wiki/Projects-Using-Wechaty) ### :star2: Projects Using Wechaty From cf3ef3078347979bf9c79d4106b6fe6425f7a166 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 15 Jul 2020 13:37:13 +0800 Subject: [PATCH 339/598] fix wiki link --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f37a451f5..5903db5ec 100644 --- a/README.md +++ b/README.md @@ -364,7 +364,7 @@ See: [![Powered by Wechaty](https://img.shields.io/badge/Powered%20By-Wechaty-brightgreen.svg)](https://github.com/Wechaty/wechaty) ``` -Get more embed html/markdown code from [Wiki:Projects Using Wechaty](https://github.com/wechaty/wechaty/wiki/Projects-Using-Wechaty) +Get more embed html/markdown code from [Wiki:PoweredByWechaty](https://github.com/Wechaty/wechaty/wiki/PoweredByWechaty) ### :star2: Projects Using Wechaty @@ -379,7 +379,7 @@ Get more embed html/markdown code from [Wiki:Projects Using Wechaty](https://git Pull Request is welcome to add yours! -Learn more about Projects Using Wechaty at [Wiki:PoweredByWechaty](https://github.com/Wechaty/wechaty/wiki/PoweredByWechaty) +Learn more about Projects Using Wechaty at [Wiki:Projects Using Wechaty](https://github.com/wechaty/wechaty/wiki/Projects-Using-Wechaty) ## :innocent: Find a Good Server From 6ef7748d054649aba908439edf8cff9df1a63846 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 15 Jul 2020 13:38:57 +0800 Subject: [PATCH 340/598] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5903db5ec..3c47f7acd 100644 --- a/README.md +++ b/README.md @@ -364,7 +364,7 @@ See: [![Powered by Wechaty](https://img.shields.io/badge/Powered%20By-Wechaty-brightgreen.svg)](https://github.com/Wechaty/wechaty) ``` -Get more embed html/markdown code from [Wiki:PoweredByWechaty](https://github.com/Wechaty/wechaty/wiki/PoweredByWechaty) +Get more embed html/markdown code from [Wiki:Powered By Wechaty](https://github.com/wechaty/wechaty/wiki/Powered-By-Wechaty) ### :star2: Projects Using Wechaty From 2de1067386dac4fff177325c1c3c94e757e4d54e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 15 Jul 2020 13:40:19 +0800 Subject: [PATCH 341/598] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3c47f7acd..ca0003b19 100644 --- a/README.md +++ b/README.md @@ -364,7 +364,7 @@ See: [![Powered by Wechaty](https://img.shields.io/badge/Powered%20By-Wechaty-brightgreen.svg)](https://github.com/Wechaty/wechaty) ``` -Get more embed html/markdown code from [Wiki:Powered By Wechaty](https://github.com/wechaty/wechaty/wiki/Powered-By-Wechaty) +Get more embed html/markdown code from [Wiki:Badge](https://github.com/wechaty/wechaty/wiki/Badge) ### :star2: Projects Using Wechaty From 122682d4ad0cd1acbdeba837a8800fc94744f9e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 24 Jul 2020 18:50:27 +0800 Subject: [PATCH 342/598] update icon --- docs/images/wechaty-icon.png | Bin 6243 -> 5016 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/images/wechaty-icon.png b/docs/images/wechaty-icon.png index fcdcb4f9b2000c82623e44294cd24f8476ac9655..8bab05dbcb5200f9b2ea62dd5e88e5b9cfbaaab4 100644 GIT binary patch literal 5016 zcmeHJX;c)~623h%KnsI32*^H-dqPA=qO#K<0bCwp7C~hhgct=xP=QfKXcl4ISWb)@ zL)_48iVPAIQ4kOq6cy2cA_@YMF#!Vvkr7#5b%Q3n_>Ski^UnM8!a2jKTUEEduj<~a z+dDix+|*SKR1rez3*B8lM2Jf=KU^6!jp52`5t`(`(8cLv(Y+@R7H@2I*QRRATIxiP zKgpezv(vOOVyTaBQexWi!6NY%4;PI_+WpJuFUtDl8nFHEzyI?J>=DOq6UV{NRtvfG z{Y*ePiZYEjv{7uA*yo1Vr8W$gKQKkEd|AKV0n^{Ce;won_f+%r42+Y%j*{K8GK)$5TI{eDZp&9@w%r8eB{pL(lj!?x6w zAvD51tVl7HD{`Z+RTj_8N{j1qtPU;0aun}fq-uq?V+wjU_*^s@=F_>!Lm44a<$<=DVbgu1YwsAMq&qJ zHMVBgxyzGqjE4&kxUXFtD(cG2Iy8x-5Z~$_{yDzsmR+(Z5nboiw4U1$roii#I&qS3 zH9fAijNg3E1>)JkutTQaK!0e57l`oxRE`YaV^<7(230xfZzK$>S>M4aUx%Rjty zo#!bFh3k;H$CFjLYs7Q5PllT9O?2+So;KAC+xpa}65Pg~e*3G@5eRT4!CHcvlB_2-W-x~<>rzQoq)V3D5sg^ZF&&u{ANTgi1vuD{<=iugF zZx1X#dP!Cw>!0IiU&(K-z`&}WlHX*ap5o?zCqwbrnx7_46I4(q8=Fmr?pHtGI`G1O zS6h>fuu~PC4DVBR*C)?${TAB&q!>vX%-rX{xp=6dX!zLjYT1^)ypW4=MNMh;jWTA@PUE=8<}N?M6?t2F-iDBWFdK* z7Y7=$N3MljscFuelq(nQxAVwuYibqciPH%IfPqjj%V`rcIAnRP( zlLtFQQ85j9j$f`SY>RkQP@`3i^a}=%osrdNX?u!tx;7RcS}Bt?1>Wz-O%t!XRC(h{ zR$$ZbdM?k+J$?ynz~EYt&NB?dT;oQL{Y?80+>MD+S#;>mp}BQ0F3ibEbxMmr@2aOt zkT&OpShdaX8$?0IWnn7!yv{l0#}=J9x6*i<$*Qml!y=QdgN9}(`}_b3HCU8aQE~Fl zJzKu3-SFcFl3Lkdtz|*{<5pr%xLH%M z<`f6v`mj;}Ryj?`sHNz^tTA$6?+g+_D3a&KERnBYc>bWXAUDxjy zY=3yk$dO~4wCmTX@X&&m#5;ljx6Xzz+3v0{6=+Zk`5pY_?UOCZD?7IB%YVPoT(U`9 z%H^O*8ddMv`}bftLDt{))KOFv!s{?wCo!a^-_RAM0Cp$EN8chkSgQwc_Tj7&N2Jh^U)%2ggYp3C&7w4*2_ zEUh|c#@W3ZIz@Mn<^?7^Dol}Nu@{S+-i%=fH%96(W44<)SkeyB_r)qaLV&3G!^&2q z9ql`4$m~i|VF})L85jYiTxHZ~hcr1X2o6=C72(=1*AjvSW#27uCZMAv8mti*v!LAwjFTp_ zMi#~e-X5UKzyKpE=?|E(ove|i%ZBa2*s%Dxu%v^L62L%iqcA|9Ftx~Cvoe~3_-J$1QztR%zHAO;AOxF+f?n0X_l zasB|W@B6LY@k%9XQO;wmOOoycJ0veb#atE3DsxVZF+0xPA)26LXk0)5>2 zhlga96xu0F+a^@l&!z1<6UMm4BVfX0bggB=1p(SCRePDU@z6p`yZ_)JI3)LxI;W77M8qNRuHOWL47q z#SCMw9jNN+r3uc;%vL(A$(SSj)GcSmy>*uhIaZbPOukoif72em_DO(mMr3w8!UXk8 zhU3@IUg=e@&4EkB;R$}KpH{C^F93G&ONKSpb=)pIbDDsYCrE|xtVix?smamz;*uwK zAMJb|;EQc;o2AKj~B#W z>6aM!sV_W{^hNHzfZCXreChtiG)?m1WD8}poGUR8=Yp+-YR_-UjL?R}>44gZ{s9n# zlCr`C>jHIsj1$|F5U~LHTG?T zOGA5f&H{=kaSHfaq;ps=aHrNs4FMS->RDFEVKDFzfYqB}LqhIHwBnT1UiZv{6#?bZ8~Rs)sV#GIqvd-gU}I%}Rex51 zl+j-W$Q`AZwu|kV@1#FDFnYFE#tY2%39A8t#?0j%SC;*IhgY8LvBSCi>DvaPzxnUT z{?8YbggRVuC^l9?qTeDgiFhabVy4h-6ah}C~=iix>35j8ziJ9h7cGUWCmu) zfq{W}<9+w8yWV=gzutO(>~;1&=ezgW>zwcTe&T$1rJ;EDHq&i9JiNQgO7hxxc=*qM zHvj?d4Cq+s8h0RdS2BEyhj;t%cf$u&h@|1+G2By@m(%t8d9dPZk?7smb7XF-C}BU- zIZfK=HATRh#4f#;{jlUg0G}4^L~qR(0N~F%T2I!9N#1>__G76&hO!ouT;w_53L~(& zP5Y#lL!@xwm2kM@Ycn>V_i0*`j z;u8=*@4*8w;NcVgHKcs{&+vf-?keR|yuSkQ3IB@!X9!^UXZpYKe^19FXkyN_3D0I) z&GrbT1PxQB*=Qwcz6u@XAnXgLv@viJbK_;`*w%G|hJN-g`$`c>#;#u+6}RA_0NX_8 zMLA(if4+JDFr0Eo)AV}PG{WjU+b-i-wwkq@C2hvW68==_uuK(y*($cIt_)FpJKc*hahhJ0{ct&g5?MVGxMLxgNiiDFL8Fn~iu!e4Jl-}}*WVKsGK=;TAF-)h#iD}b z24LP?#o0jHxmr>ed>RoZ9gQ97PD17i1Hk%z!G7|N-N-P@Zb>Z+=)YWopj{8XSV(@M zSbYbBnjZl{27Bjg}optLD~>Z-Sk?VLW)iS@0-Wz)eLpLv=VHeOsOA+v>0 z`&?o5QxB)~_?gNXZziPvu+WQ>9barlw=%FB8fF_)WP;iy>9ZpVFxnifP=P?^7*qLV zABFpE3yT`Fz_uq?~V-Bw0S<;UHGzrWNuP^QOUuw`X38 z@;Xo+X2;By?`XmuQK2I?!gcL2dJ={h)SWf~-8AdPApr>1cQfT=g}UQ@seQfTAzCn7 zwQ4rz8jZ;}4&ml2W0LtJ?`Rasn*3{X+a6(lbmVD-jZ(7Zz|VBqNV7$}9}f4sto>DF z9;{I_mz0Rs>n>5?e~W2#WwP5|pl@2a7;chI)#X8lR(uj=%!<91BxQ$*k%Uva1$(u; z&%DHtIW)Ip7+S5gvzq)v;JvbYX|Y7kO)d8Ew&r5&gD1&FE=uulXFH?>wE%)od97Dg z?pF6l>ht!2Onec*%jIGB&8QQBR8wFz>!n5b0P^By%9N?Q2PR^wpZn##qKa$^WEN{J zHw-Zi6d<`2@2387*m+;LLr2why6Vl5ni7GiTa-?z^VHhd2%^qccY{?$i30rARYlpM z(Rq3Y-1_+aWfWa^)>IEqfJ&VOnOe5IcjfuYRI!tN?Y}MmdhK?x{h}zX3KvVR!^jwra&fNSV zwC+QHQD#1SC`W}|@Pax)ec0uXN3K_0x=YU7U*|IVyB=2$b=qA9Mn<*pU)O}ur`wtH zb?TdCPF<4^<(ZRpp6s*j7A)S_XK{1Q)W84Mc>FWClTdcl{=%k=UV6DhinV)H@1j&Y z1b$$Msh|7y=KRojK4n6K&aeB2R5txgLTKiQUcTcx^&R4w_S`LR^+Ta;YZ?9G%WKi~ zo{CS^-NW5j^C34(4f2xX%2QQ4p(FXDd3>kLk-hFqo0StqGG+{~KUbAPc$?@k%bStm zAP18m2u3D$dDfiME5ymw@%$0ed?IC((`9aA(FZdN!IcBC7Gs%0{|7$aXA%&Gge~hBuenxj{;`3{Uv$6nD6jsZ(H7 z>Nrdsmqpn1XBCg;!?wqMA?;_NjUibvzrag3DgM+^XjWpz0nBqVsy16Hje>|zT!_7Y zizd}NQIwumUq+S_H6yZ8@5rU2Vf!WbBBi7*;f#A1)s|n!c+Oc?TfrUU2&U*-%@>1-fNy;kK|%RM!5dT%~cMmbhOYN*VdlBiA>A3Akm;%4};)?hB7-CdL`tmf4jJ~+w zDnN4B+Hx-{Dx@279ndlvJvqo2TSOL-+>4)Kdc|K1_Nh6_^f-W+RWU)nAFWpF@1;Vw zW!Hz(ULtq9-0Mn?oVGPp?vnrb&gnu23QA&;`qlM=908+?+kMwep&|V?Jzcp+-E*VW z_46B7pkW^ZoT?L&IkZ%Jb8bT%ay;-sJhe*1hSZpNKwi-c;Ab_&Do`4dUp-~7UB2Z_ zJY&E-DT6V!V*7Nt3(htX8Hrm*1e5uQY};nB%mW|Jx~!~D;=mw4qFV|xF74Yf0uxy| z?EPGPGAb?kM@xHYxzn9E@{e>f4>@v{+IE_k01wuds^=tH__L<+CYP(sd>ywYge%`V z(JNf41xp}2l^Z892Xy8at;41G!Az}c0Ct!`nfj4R=x)rue4^G^2)t((uDN~vw4_kD zaX2I+ls%mC-rK(ooBSm5vc9PM^6td?8B=d3|!;TnGU!{T5aZ{QqTDM zGq*skTK~KBCS^gF1FUyekU(w$^Hx-N>wLg@V#mEYCWZLW%;EFKgNT>vD-saga$Q|W zE6!yXsV=S%^D4$A&Q;gW!{x68gOyY){f-HxW{8twpJ(Yzfs(xx?PP&q|Fqh+{LcXp zl4v28+1N@cl~G5|iG@z1O1l=of+cyZ`kasZ;j{!4W44{Q0h>W@m-+@M61mn2y`1NT z%tKyoZ=>PG7~XQ2#%`+H<@!c{NAw*keB*&462!ztc&#=UnSX}>znLfhgCLG8{U>ttFPZw^@2gMzG97rs^wLJCcN`x?01N**0*`yP(z+Y z#u`tQCmpBLt1!3_C`3ycl^&k>2r;OgpOSxXlT@lqAY<1~1oJfpDUw9wzt6i_z3G}b z!z#gH9N}rWT-q>^8z>XdOfoB_0+r|7Y za{lrB|5%CYDQ+R<^cSF*xfONDV|`}kgE#ffI=Fi$ zn*aoFhSQE7?!X#Hw>TpIB@=C=KEhG3;0W6Y2MtNe;74-u|QQW~6dw3d0 z|M1Mb%*Fl!sHv88p$iyux|hAf#<&ApM_6c{^9qd}#HO~Z3shH@lw4UKe0bq+(Dj4C zuZ48seuc)o%aTq~`a1UT`V9)Kxnc@IRKfOWsKY7ACd|#dE??iE;kn{-f+T>~34`L| zt1BF9U9v>ZqsyiJt-Q@HGoDH zGpwi^WesF}-d~+Hx95-0(8spk8CAY*-O<8UHl`7&<^1aESY)gnjiuC#%%sh8zyg6r zEb@NUCg80TE^DYkF|1VJN)uWAy@rmekAkfn>EEIKPeklpau4OsBY9|9>KzFc^7o1f z2e_Tcg=k|pDM5s0r|ws)z1dOAYzmz&q5|7>2-A*e^NF;LVfGhuJv*{cyN?6VdRQLQ#lTbYOL;)u(sG%^PL+1aQ$*6wn${Q==G~E1Wsr zr114qsqV3dW`7VQ9>^j3m0A1g}!bWK!4iJP7Dax zy{ZIKrV*6`YOQmNOJZ;o!YywJRIvGFL#|sayt8F{`lsU%$ssrQ7$Yl&ST#r zvp)({Hfzm&R&$-XjYMCby7Clu=(|}%mtqV4I7o@Id`-C2>MwzG*xXD<_zYW9g8=BQ z@rtm6nPYyrnZcn6i zP9kRm+si=f_*k2d&C#r&^urSmA-;Xp9#s9dRG=rda67m%X{!#STuQ{}f8qr_GoG+_ zdq*g8U@h(3jIVi)=n>rY>AEi?CY~Jn*g>Pl2cbHww&BD7LsLhjk_2CMtj2MB)*}mh z55!3WH5ww!PsAlX-AiE0<=q2 zIdI|2+P;zv3Skhw7t0&cD2Bh3mu0w;p54NcKXv-;(*%*TQ(*Uz5e11Y7vlT4Uh?M+ zJI&qx#Gsz&yda&#j`R%sw%s8wsBBv_c$wZISJNK*i(l)F>zGnn;mvYGMVL$2*y0B_ zrHJ%I1THe>oyb01LU;7EnC=myh-qwA+b+eA>aycVz zsOJZ8<410;#6@DKfv3s=t78ufpB>^-Lrv)QUfT~ zAr41jh@6#QjBHb2w1)aY@IT{^f|g4-Eu!~U1=0*7=0tV}9uYL9bxC8=we8iRMqH&? zBB})V?QJFdwzdrFoX0g_$41QP-D1)Of)s_T*2SsOZcoOjjRH9y^Sf?vu13E#O_ciu z?ALI)anrpmR)N6cqGN~TL^aOxl37WKCjnmP_ds4BAcG33$6IFQ^VxjBa`Au-*!ZOC z?Fc?WeP)&~dl_rni*jYV@VQ&9Qbu1dKvoad=*HqtU+o2-&RbJ+CjMP?pqP{MGd(P$ z-}_+nL_G*lds0EU(cYUa+=hOVOubMl$e@n>>Dh%NvUjmY0{xoFxDdG*I&#gs$k}I5 zRrX#3d@JNJC3-+KnB(3npv$^0#^beN5|!HCWzPEsO^+T zgO2K;h5evONsqG#gL5_XwxQB2M~P&nWXMZP0F~RtlWFt ziF{untJDadEL@C60jq_PfrE*vGlLB1w~Ki?4d*ZW7JsgzE-I(^lqy#A|HJ>-6iwL&DVZ{F`+R4=dgMeMUCr_mNSHU_X=pybKuJ$KN$ zrk||4zKPozBDQE=R)l3Le>@9rzP232u{zuo>Fm(VJ*e7; z&iB*yBG*?}WGSY$S{{06Z}1Yd+NiVk+ddm#``B>(xzaWe7_a-Cw8hj}mhBJijK=j6 zo7BB#i=nDcmktWlS@(od@anOV|4jsZdf{UiS9s{S=*SoC(nmgnV})$@YX>c_3@?>? zO`bI>IPr;k4ZA8!RWvpd6NqMl_*3UdLZd&H%jnG+Ijqa>x6bOH!xu`+IefBer~3qG z^?%-QWJ1Srgmni|l`>jLduWc`jX9(1x-2Po|WQuM^=lT^}cW8)Ts_bdmv z;*h>{DjU7mPsGzg#}iZbIV_M#Dh~UPAq$5deBv|TQ3DErw*#f9o`2~Uf$F4FZYuZq zOq4|}-@eT|3v2Q(u)X!#13`Q#uFA27D{^rLgoWqQ9@0A370vF7L!ws;KDs5DXLL|O z5EGYsSE+1SxMToDh}DZjKPk@rL5NfD5?9p-wM-$&e3lUXwCB+lR=Rco_WYFcODo zLp*$_iT2vt#kju9dayLgz2KInmyF~q$>Vh;Zs{scD&_;_9@~9SrTIXz=}0}}wJ%3F zn8Ed(ZBoA5qyzxH-qlBMb#d!grkHo=D)$^%B`WY6*EZOZG3Wf+sIzp?G+z2HCC1$t zq59hg*;rgDyr^MvIZLJ@XzHVBQt3J#H#-4kyag>o_P!e5|7a*A`O+njEsFg150l)b zzy#yB6XcRVw`#B-_;JX;aMsB8_=QFC8@-VtbtQ)2ub^f>gPH2aCe4daSKpk`!46qT z(YD@fjyn!wVzRW~#AX}wLm@n^z}&@-J!Vt(u#AjbzQ|D^`h1RzpGgl@Yb+b|*3}cX z#2Z&adpr~=f9saLGiqSa_|bsFsQE$TNpap%Hqd(aM@u{w?pLjgy}uGfaGk}`JnAkSk>-WqmC=9`C}#!|JCc%onb@sxYq7Ji)* zQnd2>`fNyYzu_$_yW?aUL$v&;J#xtR14PKdLUNYJf9qZ634bcpVYVrMRo%QBLqxck zzRU3eX_H?j0Y*fP{(0GdmRrBQXjkso`UDc Date: Fri, 24 Jul 2020 18:50:43 +0800 Subject: [PATCH 343/598] 0.43.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 406e41518..4f3a8e2da 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.43.4", + "version": "0.43.5", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From e65d9fe7bc06d3389bd0aa66f77429d056a52ca4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 24 Jul 2020 18:51:18 +0800 Subject: [PATCH 344/598] 0.43.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4f3a8e2da..c4b6e519f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.43.5", + "version": "0.43.6", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 8ce2278067b72aef50b99c5b16593b18dba07532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 25 Jul 2020 18:19:22 +0800 Subject: [PATCH 345/598] code clean & add support to emit on userSelf --- src/wechaty.ts | 65 ++------------------------------------------------ 1 file changed, 2 insertions(+), 63 deletions(-) diff --git a/src/wechaty.ts b/src/wechaty.ts index 7fe03fa81..3fb890041 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -529,49 +529,6 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { return this.options.name || 'wechaty' } - // public emit (event: 'dong', data?: string) : boolean - // public emit (event: 'error', error: Error) : boolean - // public emit (event: 'friendship', friendship: Friendship) : boolean - // public emit (event: 'heartbeat', data: any) : boolean - // public emit (event: 'login', user: ContactSelf) : boolean - // public emit (event: 'logout', user: ContactSelf, reason?: string) : boolean - // public emit (event: 'message', message: Message) : boolean - // public emit (event: 'ready') : boolean - // public emit (event: 'room-invite', roomInvitation: RoomInvitation) : boolean - // public emit (event: 'room-join', room: Room, inviteeList : Contact[], inviter : Contact, date: Date) : boolean - // public emit (event: 'room-leave', room: Room, leaverList : Contact[], remover : Contact, date: Date) : boolean - // public emit (event: 'room-topic', room: Room, newTopic: string, oldTopic: string, changer: Contact, date: Date) : boolean - // public emit (event: 'scan', qrcode: string, status: ScanStatus, data?: string) : boolean - // public emit (event: 'start' | 'stop') : boolean - - // // guard for the above event: make sure it includes all the possible values - // public emit (event: never, listener: never): never - - // public emit ( - // event: WechatyEventName, - // ...args: any[] - // ): boolean { - // return super.emit(event, ...args) - // } - - // public on (event: 'dong', listener: WechatyDongEventListener) : this - // public on (event: 'error', listener: WechatyErrorEventListener) : this - // public on (event: 'friendship', listener: WechatyFriendshipEventListener) : this - // public on (event: 'heartbeat', listener: WechatyHeartbeatEventListener) : this - // public on (event: 'login', listener: WechatyLoginEventListener) : this - // public on (event: 'logout', listener: WechatyLogoutEventListener) : this - // public on (event: 'message', listener: WechatyMessageEventListener) : this - // public on (event: 'ready', listener: WechatyReadyEventListener) : this - // public on (event: 'room-invite', listener: WechatyRoomInviteEventListener) : this - // public on (event: 'room-join', listener: WechatyRoomJoinEventListener) : this - // public on (event: 'room-leave', listener: WechatyRoomLeaveEventListener) : this - // public on (event: 'room-topic', listener: WechatyRoomTopicEventListener) : this - // public on (event: 'scan', listener: WechatyScanEventListener) : this - // public on (event: 'start' | 'stop', listener: WechatyStartStopEventListener) : this - - // // guard for the above event: make sure it includes all the possible values - // public on (event: never, listener: never): never - public on (event: WechatyEventName, listener: (...args: any[]) => any): this { log.verbose('Wechaty', 'on(%s, listener) registering... listenerCount: %s', event, @@ -579,26 +536,6 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { ) return super.on(event, listener) - - // const handleError = (e: Error, type = '') => { - // log.error('Wechaty', 'addListenerFunction(%s) listener %s exception: %s', event, type, e) - // this.emit('error', e) - // } - - // /** - // * We use `super.on()` at here to prevent loop - // */ - // super.on(event, (...args: any[]) => { - // try { - // const result = listener.apply(this, args) - // if (result && result.catch && typeof result.catch === 'function') { - // result.catch((e: Error) => handleError(e, 'async')) - // } - // } catch (e) { - // handleError(e) - // } - // }) - // return this } /** @@ -723,6 +660,8 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { const room = msg.room() if (room) { room.emit('message', msg) + } else { + this.userSelf().emit('message', msg) } }) break From 02e932415af11607781eed58255af0accfa698a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 25 Jul 2020 18:19:39 +0800 Subject: [PATCH 346/598] 0.43.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c4b6e519f..e4eab20e4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.43.6", + "version": "0.43.7", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 8be971cf23ef5a2c2c4674f3be4766be37c1c553 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 26 Jul 2020 03:25:42 +0800 Subject: [PATCH 347/598] upgrade puppet mock --- package.json | 2 +- src/create-fixture.spec.ts | 86 -------------------------------------- src/create-fixture.ts | 80 ----------------------------------- src/deprecated.ts | 20 --------- src/mod.ts | 5 --- src/puppet-config.ts | 4 +- 6 files changed, 3 insertions(+), 194 deletions(-) delete mode 100755 src/create-fixture.spec.ts delete mode 100644 src/create-fixture.ts delete mode 100644 src/deprecated.ts diff --git a/package.json b/package.json index e4eab20e4..1ebf21cd3 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,7 @@ "watchdog": "^0.8.17", "wechaty-puppet": "^0.27.1", "wechaty-puppet-hostie": "^0.9.1", - "wechaty-puppet-mock": "^0.25.1", + "wechaty-puppet-mock": "^0.25.3", "ws": "^7.2.3" }, "devDependencies": { diff --git a/src/create-fixture.spec.ts b/src/create-fixture.spec.ts deleted file mode 100755 index a58934106..000000000 --- a/src/create-fixture.spec.ts +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env ts-node - -import { - test, - sinon, -} from 'tstest' -import { - mock, -} from 'wechaty-puppet-mock' - -import { Message } from './user/message' -import { createFixture } from './create-fixture' - -test('createFixture() initial state', async (t) => { - for await (const fixture of createFixture()) { - t.true(fixture.message instanceof Message, 'should have message instance') - t.equal(fixture.message.type(), Message.Type.Text, 'should have message with text type') - t.equal(typeof fixture.message.text(), 'string', 'should have message with text content') - - t.equal(fixture.message.talker().id, fixture.player.id, 'should get a message send from player') - t.equal(fixture.message.to()!.id, fixture.bot.id, 'should get a message send to bot') - t.false(fixture.message.room(), 'should get a message as direct message') - - t.equal(fixture.moList.length, 0, 'should be empty mo list') - t.equal(fixture.mtList.length, 0, 'should be empty mt list') - - t.true(fixture.bot instanceof mock.ContactMock, 'should get mock contact mary') - t.true(fixture.player instanceof mock.ContactMock, 'should get mock contact mike') - } -}) - -test('createFixture() Mobile Originated', async (t) => { - for await (const fixture of createFixture()) { - const spy = sinon.spy() - fixture.wechaty.on('message', spy) - - fixture.bot.say().to(fixture.player) - await new Promise(setImmediate) - - t.true(spy.called, 'should received message event') - t.equal(spy.args[0][0].from().id, fixture.bot.id, 'should get bot as from') - t.equal(spy.args[0][0].to().id, fixture.player.id, 'should get player as to') - - t.equal(fixture.moList.length, 1, 'should be 1 mo') - t.equal(fixture.mtList.length, 0, 'should be empty mt list') - t.equal(fixture.moList[0].id, spy.args[0][0].id, 'should get the same message instance') - } -}) - -test('createFixture() Mobile Terminated', async (t) => { - for await (const fixture of createFixture()) { - const spy = sinon.spy() - fixture.wechaty.on('message', spy) - - fixture.player.say().to(fixture.bot) - await new Promise(setImmediate) - - t.true(spy.called, 'should received message event') - t.equal(spy.args[0][0].to().id, fixture.bot.id, 'should get bot as to') - t.equal(spy.args[0][0].from().id, fixture.player.id, 'should get player as from') - - t.equal(fixture.moList.length, 0, 'should be 0 mo') - t.equal(fixture.mtList.length, 1, 'should be 1 mt') - t.equal(fixture.mtList[0].id, spy.args[0][0].id, 'should get the same message instance') - } -}) - -test('user.say() multiple times with moList', async t => { - for await (const fixture of createFixture()) { - const TEXT_LIST = [ - 'one', - 'two', - 'three', - ] - for (const text of TEXT_LIST) { - await fixture.bot.say(text).to(fixture.player) - } - await new Promise(setImmediate) - - t.equal(fixture.moList.length, TEXT_LIST.length, 'should receive all TEXT_LIST') - for (let i = 0; i < TEXT_LIST.length; i++) { - t.ok(fixture.moList[i], `should exist moList for ${i}`) - t.deepEqual(fixture.moList[i].text(), TEXT_LIST[i], `should get TEXT_LIST[${i}]: ${TEXT_LIST[i]}`) - } - } -}) diff --git a/src/create-fixture.ts b/src/create-fixture.ts deleted file mode 100644 index ebca5c520..000000000 --- a/src/create-fixture.ts +++ /dev/null @@ -1,80 +0,0 @@ -/* eslint-disable sort-keys */ -import { - PuppetMock, - mock, -} from 'wechaty-puppet-mock' - -import { Wechaty } from './wechaty' -import { Message } from './user/message' - -interface Fixture { - wechaty : Wechaty, - mocker : mock.Mocker, - - moList: Message[], - mtList: Message[], - - bot : mock.ContactMock, - player : mock.ContactMock, - message : Message, - - room: mock.RoomMock, -} - -async function * createFixture (): AsyncGenerator { - const mocker = new mock.Mocker() - const puppet = new PuppetMock({ mocker }) - const wechaty = new Wechaty({ puppet }) - - await wechaty.start() - - const bot = mocker.createContact({ name: 'Bot' }) - const player = mocker.createContact({ name: 'Player' }) - mocker.login(bot) - - const room = mocker.createRoom({ - memberIdList: [ - bot.id, - player.id, - ], - }) - - const messageFuture = new Promise(resolve => wechaty.once('message', resolve)) - player.say().to(bot) - const message = await messageFuture - - // Mobile Terminated - const mtList = [] as Message[] - const recordMobileTerminatedMessage = (message: Message) => { - if (!message.self()) { - mtList.push(message) - } - } - wechaty.on('message', recordMobileTerminatedMessage) - - // Mobile Originated - const moList = [] as Message[] - const recordMobileOriginatedMessage = (message: Message) => { - if (message.self()) { - moList.push(message) - } - } - wechaty.on('message', recordMobileOriginatedMessage) - - yield { - wechaty, - mocker, - - bot, - player, - message, - room, - - moList, - mtList, - } - - await wechaty.stop() -} - -export { createFixture } diff --git a/src/deprecated.ts b/src/deprecated.ts deleted file mode 100644 index 2432e5327..000000000 --- a/src/deprecated.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty - * - * @copyright 2016 Huan LI (李卓桓) , and - * Wechaty Contributors . - * - * 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. - * - */ -export const WECHATY_DEPRECATED_HOLDER = 42 diff --git a/src/mod.ts b/src/mod.ts index 8441ca8c7..cbcfc613a 100644 --- a/src/mod.ts +++ b/src/mod.ts @@ -60,11 +60,6 @@ export { MiniProgram, } from './user/mod' -export { createFixture } from './create-fixture' - -export { -} from './deprecated' - export { IoClient } from './io-client' export { Sayable, diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 4e2e81545..4002d3f3b 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -33,8 +33,8 @@ export const PUPPET_DEPENDENCIES = { /** * Wechaty Internal Puppets: dependence by package.json */ - 'wechaty-puppet-hostie' : '^0.9.1', // https://www.npmjs.com/package/wechaty-puppet-hostie - 'wechaty-puppet-mock' : '^0.25.1', // https://www.npmjs.com/package/wechaty-puppet-mock + 'wechaty-puppet-hostie' : '*', // https://www.npmjs.com/package/wechaty-puppet-hostie + 'wechaty-puppet-mock' : '*', // https://www.npmjs.com/package/wechaty-puppet-mock /** * Wechaty External Puppets From 0990055fb2eaf7d34f4fb8e27eb158bd5ab73ea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 26 Jul 2020 04:02:48 +0800 Subject: [PATCH 348/598] fix puppet mock dependency --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1ebf21cd3..e94f609b1 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,7 @@ "watchdog": "^0.8.17", "wechaty-puppet": "^0.27.1", "wechaty-puppet-hostie": "^0.9.1", - "wechaty-puppet-mock": "^0.25.3", + "wechaty-puppet-mock": "^0.27.2", "ws": "^7.2.3" }, "devDependencies": { From 2af07909d31cf7f164a2a2491386c79ef16b8df4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 26 Jul 2020 04:03:01 +0800 Subject: [PATCH 349/598] 0.43.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e94f609b1..5e43f9e53 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.43.7", + "version": "0.43.8", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From ed60a313f4f3b925700e1f7696c0f79e714520b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 26 Jul 2020 04:03:52 +0800 Subject: [PATCH 350/598] add npmignore --- .npmignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .npmignore diff --git a/.npmignore b/.npmignore new file mode 100644 index 000000000..77f12ae2e --- /dev/null +++ b/.npmignore @@ -0,0 +1 @@ +docs/ From a658c7d4d701c61510c463c6f2bb9089f0519c2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 26 Jul 2020 14:54:10 +0800 Subject: [PATCH 351/598] 0.43.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5e43f9e53..7f2aa1562 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.43.8", + "version": "0.43.9", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 9775f5cba5cdc6f38fcd7573940fd2e937e5827f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 26 Jul 2020 14:57:28 +0800 Subject: [PATCH 352/598] add tarnsparent banner image --- .../wechaty-logo-green-en-transparent.png | Bin 0 -> 23972 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/wechaty-logo-green-en-transparent.png diff --git a/docs/images/wechaty-logo-green-en-transparent.png b/docs/images/wechaty-logo-green-en-transparent.png new file mode 100644 index 0000000000000000000000000000000000000000..a3b096ab2f88021266755eee706ae3c678d984d6 GIT binary patch literal 23972 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 Date: Sun, 26 Jul 2020 14:57:53 +0800 Subject: [PATCH 353/598] 0.43.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7f2aa1562..4ac3694d6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.43.9", + "version": "0.43.10", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From e7c04b74f5881935eff91449d1fa0e942d47b0b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 27 Jul 2020 01:27:29 +0800 Subject: [PATCH 354/598] remove Accessories by wechatify user classes (#2028) --- package.json | 2 +- src/accessory.spec.ts | 80 -------- src/accessory.ts | 198 ------------------ src/user/contact-self.ts | 40 +++- src/user/contact.accessory.spec.ts | 20 -- src/user/contact.ts | 76 ++++--- src/user/favorite.ts | 27 ++- src/user/friendship.ts | 45 ++-- src/user/image.ts | 34 +++- src/user/message.ts | 66 +++--- src/user/mini-program.ts | 24 ++- src/user/moment.ts | 25 ++- src/user/room-invitation.ts | 48 +++-- src/user/room.ts | 96 +++++---- src/user/tag.ts | 40 +++- src/user/url-link.ts | 13 +- src/wechaty-events.ts | 223 ++++++++++++++++++++ src/wechaty.ts | 316 ++++++----------------------- 18 files changed, 672 insertions(+), 701 deletions(-) delete mode 100755 src/accessory.spec.ts delete mode 100644 src/accessory.ts create mode 100644 src/wechaty-events.ts diff --git a/package.json b/package.json index 4ac3694d6..ec91df338 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.43.10", + "version": "0.45.0", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", diff --git a/src/accessory.spec.ts b/src/accessory.spec.ts deleted file mode 100755 index f4c2cfbc6..000000000 --- a/src/accessory.spec.ts +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env ts-node -/** - * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty - * - * @copyright 2016 Huan LI (李卓桓) , and - * Wechaty Contributors . - * - * 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. - * - */ -import test from 'blue-tape' -// import sinon from 'sinon' - -import { - cloneClass, -} from 'clone-class' - -import { - Accessory, -} from './accessory' - -import { Puppet } from 'wechaty-puppet' - -const EXPECTED_PUPPET1 = { p: 1 } as any as Puppet -const EXPECTED_PUPPET2 = { p: 2 } as any as Puppet - -test('Accessory smoke testing', async t => { - - class FixtureClass extends Accessory {} - - t.throws(() => FixtureClass.puppet, 'should throw if read static puppet before initialize') - - const c = new FixtureClass() - t.throws(() => c.puppet, 'should throw if read instance puppet before initialization') - - FixtureClass.puppet = EXPECTED_PUPPET1 - t.equal(FixtureClass.puppet, EXPECTED_PUPPET1, 'should get EXPECTED_PUPPET1 from static puppet after set static puppet') - t.equal(c.puppet, EXPECTED_PUPPET1, 'should get EXPECTED_PUPPET1 from instance puppet after set static puppet') - - // c.puppet = EXPECTED_PUPPET2 - // t.equal(FixtureClass.puppet, EXPECTED_PUPPET1, 'should get EXPECTED_PUPPET1 from static puppet after set instance puppet to EXPECTED_PUPPET2') - // t.equal(c.puppet, EXPECTED_PUPPET2, 'should get EXPECTED_PUPPET2 from instance puppet after set instance puppet to EXPECTED_PUPPET2') -}) - -test('Two clone-ed classes have different static puppet value', async t => { - - class FixtureClass extends Accessory {} - - const ClonedClass1 = cloneClass(FixtureClass) - const ClonedClass2 = cloneClass(FixtureClass) - - ClonedClass1.puppet = EXPECTED_PUPPET1 - ClonedClass2.puppet = EXPECTED_PUPPET2 - - const c1 = new ClonedClass1() - const c2 = new ClonedClass2() - - t.equal(c1.puppet, EXPECTED_PUPPET1, 'should get the puppet as 1 from 1st cloned class') - t.equal(c2.puppet, EXPECTED_PUPPET2, 'should get the puppet as 2 from 2nd cloned class') -}) - -test('Throw error when set the value again', async t => { - class FixtureClass extends Accessory {} - - t.doesNotThrow(() => { FixtureClass.wechaty = {} as any }, 'instance: should not throw when set wechaty at 1st time') - t.throws(() => { FixtureClass.wechaty = {} as any }, 'instance: should throw when set wechaty at 2nd time') - - t.doesNotThrow(() => { FixtureClass.puppet = {} as any }, 'static: should not throw when set puppet at 1st time') - t.throws(() => { FixtureClass.puppet = {} as any }, 'static: should throw when set puppet at 2nd time') -}) diff --git a/src/accessory.ts b/src/accessory.ts deleted file mode 100644 index 4ecf47c2c..000000000 --- a/src/accessory.ts +++ /dev/null @@ -1,198 +0,0 @@ -/** - * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty - * - * @copyright 2016 Huan LI (李卓桓) , and - * Wechaty Contributors . - * - * 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. - * - */ -import { EventEmitter } from 'events' - -import { instanceToClass } from 'clone-class' -import { Puppet } from 'wechaty-puppet' - -import { log } from './config' -import { Wechaty } from './wechaty' - -// use Symbol to prevent conflicting with the child class properties -// This symbol must be exported (for now). -// See: https://github.com/Microsoft/TypeScript/issues/20080 -const SYMBOL_NAME = Symbol('name') -const SYMBOL_COUNTER = Symbol('counter') - -let COUNTER = 0 - -export abstract class Accessory extends EventEmitter { - - // Not work??? - // private static readonly PUPPET_ACCESSORY_NAME = Symbol('name') - - private [SYMBOL_NAME] : string - private [SYMBOL_COUNTER] : number - - /** - * - * 1. Static Properties & Methods - * - */ - private static _puppet? : Puppet - private static _wechaty? : Wechaty - - /** - * @ignore - */ - public static set puppet (puppet: Puppet) { - log.silly('Accessory', '<%s> static set puppet = "%s"', - this.name, - puppet, - ) - - if (this._puppet) { - throw new Error('puppet can not be set twice') - } - this._puppet = puppet - } - - /** - * @ignore - */ - public static get puppet (): Puppet { - // log.silly('Accessory', '<%s> static get puppet()', - // this.name, - // ) - - if (this._puppet) { - return this._puppet - } - - throw new Error([ - 'static puppet not found for ', - this.name, - ', ', - 'please see issue #1217: https://github.com/wechaty/wechaty/issues/1217', - ].join('')) - } - - /** - * @ignore - */ - public static set wechaty (wechaty: Wechaty) { - log.silly('Accessory', '<%s> static set wechaty = "%s"', - this.name, - wechaty, - ) - if (this._wechaty) { - throw new Error('wechaty can not be set twice') - } - this._wechaty = wechaty - } - - /** - * @ignore - */ - public static get wechaty (): Wechaty { - // log.silly('Accessory', '<%s> static get wechaty()', - // this.name, - // ) - - if (this._wechaty) { - return this._wechaty - } - - throw new Error('static wechaty not found for ' + this.name) - } - - /** - * - * 2. Instance Properties & Methods - * - * DEPRECATED: The ability of set different `puppet` to the instance is required. - * For example: the Wechaty instances have to have different `puppet`. - * - * Huan(202003): simplify the logic: do not use Accessory to - * set different puppet for different instances - */ - - /** - * @ignore - * - * instance.puppet - * - * Huan(202003) - * DEPRECATED: Needs to support different `puppet` between instances. - * For example: every Wechaty instance needs its own `puppet` - * So: that's the reason that there's no `private _wechaty: Wechaty` for the instance. - * - */ - public get puppet (): Puppet { - // log.silly('Accessory', '#%d<%s> get puppet()', - // this[SYMBOL_COUNTER], - // this[SYMBOL_NAME] || this, - // ) - - // Huan(202003): DEPRECATED - // if (this._puppet) { - // return this._puppet - // } - - /** - * Get `puppet` from Class Static puppet property - * note: use `instanceToClass` at here is because - * we might have many copy/child of `Accessory` Classes - */ - return instanceToClass(this, Accessory).puppet - } - - /** - * @ignore - * - * instance.wechaty is for: - * Contact.wechaty - * FriendRequest.wechaty - * Message.wechaty - * Room.wechaty - * ... etc - * - * So it only need one `wechaty` for all the instances - */ - public get wechaty (): Wechaty { - // log.silly('Accessory', '#%d<%s> get wechaty()', - // this[SYMBOL_COUNTER], - // this[SYMBOL_NAME] || this, - // ) - - /** - * Get `wechaty` from Class Static puppet property - * note: use `instanceToClass` at here is because - * we might have many copy/child of `Accessory` Classes - */ - return instanceToClass(this, Accessory).wechaty - } - - constructor ( - name?: string, - ) { - super() - - this[SYMBOL_NAME] = name || this.toString() - this[SYMBOL_COUNTER] = COUNTER++ - - log.silly('Accessory', '#%d<%s> constructor(%s)', - this[SYMBOL_COUNTER], - this[SYMBOL_NAME], - name || '', - ) - } - -} diff --git a/src/user/contact-self.ts b/src/user/contact-self.ts index d11bc98a0..404d827f0 100644 --- a/src/user/contact-self.ts +++ b/src/user/contact-self.ts @@ -20,12 +20,14 @@ import { FileBox, log, -} from '../config' +} from 'wechaty-puppet' import { guardQrCodeValue, } from '../helper-functions/pure/guard-qr-code-value' +import { Wechaty } from '../wechaty' + import { Contact, } from './contact' @@ -41,7 +43,7 @@ import { * console.log(`user ${user} login`) * }) */ -export class ContactSelf extends Contact { +class ContactSelf extends Contact { // constructor ( // id: string, @@ -87,11 +89,11 @@ export class ContactSelf extends Contact { return filebox } - if (this.id !== this.puppet.selfId()) { + if (this.id !== this.wechaty.puppet.selfId()) { throw new Error('set avatar only available for user self') } - await this.puppet.contactAvatar(this.id, file) + await this.wechaty.puppet.contactAvatar(this.id, file) } /** @@ -112,7 +114,7 @@ export class ContactSelf extends Contact { log.verbose('Contact', 'qrcode()') let puppetId: string try { - puppetId = this.puppet.selfId() + puppetId = this.wechaty.puppet.selfId() } catch (e) { throw Error('Can not get qrcode, user might be either not logged in or already logged out') } @@ -120,7 +122,7 @@ export class ContactSelf extends Contact { throw new Error('only can get qrcode for the login userself') } - const qrcodeValue = await this.puppet.contactSelfQRCode() + const qrcodeValue = await this.wechaty.puppet.contactSelfQRCode() return guardQrCodeValue(qrcodeValue) } @@ -152,7 +154,7 @@ export class ContactSelf extends Contact { let puppetId: string try { - puppetId = this.puppet.selfId() + puppetId = this.wechaty.puppet.selfId() } catch (e) { throw Error('Can not set name for user self, user might be either not logged in or already logged out') } @@ -161,7 +163,7 @@ export class ContactSelf extends Contact { throw new Error('only can set name for user self') } - return this.puppet.contactSelfName(name).then(this.sync.bind(this)) + return this.wechaty.puppet.contactSelfName(name).then(this.sync.bind(this)) } /** @@ -184,7 +186,7 @@ export class ContactSelf extends Contact { let puppetId: string try { - puppetId = this.puppet.selfId() + puppetId = this.wechaty.puppet.selfId() } catch (e) { throw Error('Can not set signature for user self, user might be either not logged in or already logged out') } @@ -193,7 +195,25 @@ export class ContactSelf extends Contact { throw new Error('only can change signature for user self') } - return this.puppet.contactSelfSignature(signature).then(this.sync.bind(this)) + return this.wechaty.puppet.contactSelfSignature(signature).then(this.sync.bind(this)) } } + +function wechatifyContactSelf (wechaty: Wechaty): typeof ContactSelf { + + class WechatifiedContactSelf extends ContactSelf { + + static get wechaty () { return wechaty } + get wechaty () { return wechaty } + + } + + return WechatifiedContactSelf + +} + +export { + ContactSelf, + wechatifyContactSelf, +} diff --git a/src/user/contact.accessory.spec.ts b/src/user/contact.accessory.spec.ts index f64a2c186..6c877b171 100644 --- a/src/user/contact.accessory.spec.ts +++ b/src/user/contact.accessory.spec.ts @@ -25,9 +25,6 @@ import { cloneClass, } from 'clone-class' -import { - PuppetMock, -} from 'wechaty-puppet-mock' import { Contact as GlobalContact, } from './contact' @@ -62,23 +59,6 @@ test('Should not be able to instanciate through cloneClass without puppet', asyn }) -test('should be able to instanciate through cloneClass with puppet', async t => { - const MyContact = cloneClass(Contact) - - MyContact.puppet = new PuppetMock() - - t.doesNotThrow(() => { - const c = MyContact.load('xxx') - t.ok(c, 'should get contact instance from `MyContact.load()') - }, 'should not throw when `MyContact().load`') - - t.doesNotThrow(() => { - const c = MyContact.load('xxx') - t.ok(c, 'should get contact instance from `MyContact.load()`') - }, 'should not throw when `MyContact.load()`') - -}) - test('should throw when instanciate the global class', async t => { t.throws(() => { const c = GlobalContact.load('xxx') diff --git a/src/user/contact.ts b/src/user/contact.ts index af87c28dc..6bea793a2 100644 --- a/src/user/contact.ts +++ b/src/user/contact.ts @@ -17,6 +17,8 @@ * limitations under the License. * */ +import { EventEmitter } from 'events' + import { instanceToClass } from 'clone-class' import { @@ -24,13 +26,12 @@ import { ContactPayload, ContactQueryFilter, ContactType, + FileBox, } from 'wechaty-puppet' +import { Wechaty } from '../wechaty' + import { - Accessory, -} from '../accessory' -import { - FileBox, Raven, log, @@ -54,7 +55,10 @@ export const POOL = Symbol('pool') * @property {string} id - Get Contact id. * This function is depending on the Puppet Implementation, see [puppet-compatible-table](https://github.com/wechaty/wechaty/wiki/Puppet#3-puppet-compatible-table) */ -export class Contact extends Accessory implements Sayable { +class Contact extends EventEmitter implements Sayable { + + static get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } + get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } public static Type = ContactType public static Gender = ContactGender @@ -169,7 +173,7 @@ export class Contact extends Accessory implements Sayable { // use puppet.contactValidate() to confirm double confirm that this contactId is valid. // https://github.com/wechaty/wechaty-puppet-padchat/issues/64 // https://github.com/wechaty/wechaty/issues/1345 - const valid = await this.puppet.contactValidate(contact.id) + const valid = await this.wechaty.puppet.contactValidate(contact.id) if (valid) { log.verbose('Contact', 'find() confirm contact[#%d] with id=%d is valid result, return it.', n, @@ -213,7 +217,7 @@ export class Contact extends Accessory implements Sayable { log.verbose('Contact', 'findAll(%s)', JSON.stringify(query) || '') try { - const contactIdList: string[] = await this.puppet.contactSearch(query) + const contactIdList: string[] = await this.wechaty.puppet.contactSearch(query) const contactList = contactIdList.map(id => this.load(id)) const BATCH_SIZE = 16 @@ -242,7 +246,7 @@ export class Contact extends Accessory implements Sayable { return contactList.filter(contact => !invalidDict[contact.id]) } catch (e) { - log.error('Contact', 'this.puppet.contactFindAll() rejected: %s', e.message) + log.error('Contact', 'this.wechaty.puppet.contactFindAll() rejected: %s', e.message) return [] // fail safe } } @@ -264,7 +268,7 @@ export class Contact extends Accessory implements Sayable { log.verbose('Contact', 'static tags() for %s', this) try { - const tagIdList = await this.puppet.tagContactList() + const tagIdList = await this.wechaty.puppet.tagContactList() const tagList = tagIdList.map(id => this.wechaty.Tag.load(id)) return tagList } catch (e) { @@ -299,8 +303,8 @@ export class Contact extends Accessory implements Sayable { ) } - if (!this.puppet) { - throw new Error('Contact class can not be instantiated without a puppet!') + if (!this.wechaty) { + throw new Error('Contact class can not be instantiated without a wechaty instance!') } } @@ -409,7 +413,7 @@ export class Contact extends Accessory implements Sayable { /** * 1. Text */ - msgId = await this.puppet.messageSendText( + msgId = await this.wechaty.puppet.messageSendText( this.id, something, ) @@ -417,7 +421,7 @@ export class Contact extends Accessory implements Sayable { /** * 2. Contact */ - msgId = await this.puppet.messageSendContact( + msgId = await this.wechaty.puppet.messageSendContact( this.id, something.id, ) @@ -425,7 +429,7 @@ export class Contact extends Accessory implements Sayable { /** * 3. File */ - msgId = await this.puppet.messageSendFile( + msgId = await this.wechaty.puppet.messageSendFile( this.id, something, ) @@ -433,7 +437,7 @@ export class Contact extends Accessory implements Sayable { /** * 4. Link Message */ - msgId = await this.puppet.messageSendUrl( + msgId = await this.wechaty.puppet.messageSendUrl( this.id, something.payload, ) @@ -441,7 +445,7 @@ export class Contact extends Accessory implements Sayable { /** * 5. Mini Program */ - msgId = await this.puppet.messageSendMiniProgram( + msgId = await this.wechaty.puppet.messageSendMiniProgram( this.id, something.payload, ) @@ -517,9 +521,9 @@ export class Contact extends Accessory implements Sayable { } try { - await this.puppet.contactAlias(this.id, newAlias) - await this.puppet.contactPayloadDirty(this.id) - this.payload = await this.puppet.contactPayload(this.id) + await this.wechaty.puppet.contactAlias(this.id, newAlias) + await this.wechaty.puppet.contactPayloadDirty(this.id) + this.payload = await this.wechaty.puppet.contactPayload(this.id) if (newAlias && newAlias !== this.payload.alias) { log.warn('Contact', 'alias(%s) sync with server fail: set(%s) is not equal to get(%s)', newAlias, @@ -690,7 +694,7 @@ export class Contact extends Accessory implements Sayable { log.verbose('Contact', 'avatar()') try { - const fileBox = await this.puppet.contactAvatar(this.id) + const fileBox = await this.wechaty.puppet.contactAvatar(this.id) return fileBox } catch (e) { log.error('Contact', 'avatar() exception: %s', e.message) @@ -709,7 +713,7 @@ export class Contact extends Accessory implements Sayable { log.verbose('Contact', 'tags() for %s', this) try { - const tagIdList = await this.puppet.tagContactList(this.id) + const tagIdList = await this.wechaty.puppet.tagContactList(this.id) const tagList = tagIdList.map(id => this.wechaty.Tag.load(id)) return tagList } catch (e) { @@ -752,7 +756,7 @@ export class Contact extends Accessory implements Sayable { public async ready ( forceSync = false, ): Promise { - log.silly('Contact', 'ready() @ %s with id="%s"', this.puppet, this.id) + log.silly('Contact', 'ready() @ %s with id="%s"', this.wechaty.puppet, this.id) if (!forceSync && this.isReady()) { // already ready log.silly('Contact', 'ready() isReady() true') @@ -761,13 +765,13 @@ export class Contact extends Accessory implements Sayable { try { if (forceSync) { - await this.puppet.contactPayloadDirty(this.id) + await this.wechaty.puppet.contactPayloadDirty(this.id) } - this.payload = await this.puppet.contactPayload(this.id) - // log.silly('Contact', `ready() this.puppet.contactPayload(%s) resolved`, this) + this.payload = await this.wechaty.puppet.contactPayload(this.id) + // log.silly('Contact', `ready() this.wechaty.puppet.contactPayload(%s) resolved`, this) } catch (e) { - log.verbose('Contact', 'ready() this.puppet.contactPayload(%s) exception: %s', + log.verbose('Contact', 'ready() this.wechaty.puppet.contactPayload(%s) exception: %s', this.id, e.message, ) @@ -791,7 +795,7 @@ export class Contact extends Accessory implements Sayable { * const isSelf = contact.self() */ public self (): boolean { - const userId = this.puppet.selfId() + const userId = this.wechaty.puppet.selfId() if (!userId) { return false @@ -815,3 +819,21 @@ export class Contact extends Accessory implements Sayable { } } + +function wechatifyContact (wechaty: Wechaty): typeof Contact { + + class WechatifiedContact extends Contact { + + static get wechaty () { return wechaty } + get wechaty () { return wechaty } + + } + + return WechatifiedContact + +} + +export { + Contact, + wechatifyContact, +} diff --git a/src/user/favorite.ts b/src/user/favorite.ts index 9c0a2f751..cfc8d06a3 100644 --- a/src/user/favorite.ts +++ b/src/user/favorite.ts @@ -19,10 +19,13 @@ */ import { Tag } from './tag' -import { Accessory } from '../accessory' +import { Wechaty } from '../wechaty' import { log } from '../config' -export class Favorite extends Accessory { +class Favorite { + + static get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } + get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } public static list (): Favorite[] { return [] @@ -55,8 +58,6 @@ export class Favorite extends Accessory { * @hideconstructor */ constructor () { - super() - // } public async tags (): Promise { @@ -69,3 +70,21 @@ export class Favorite extends Accessory { } } + +function wechatifyFavorite (wechaty: Wechaty): typeof Favorite { + + class WechatifiedFavorite extends Favorite { + + static get wechaty () { return wechaty } + get wechaty () { return wechaty } + + } + + return WechatifiedFavorite + +} + +export { + Favorite, + wechatifyFavorite, +} diff --git a/src/user/friendship.ts b/src/user/friendship.ts index aef53d5d1..17817676d 100644 --- a/src/user/friendship.ts +++ b/src/user/friendship.ts @@ -17,14 +17,12 @@ * limitations under the License. * */ +import { EventEmitter } from 'events' +import { instanceToClass } from 'clone-class' import { - instanceToClass, -} from 'clone-class' - -import { - Accessory, -} from '../accessory' + Wechaty, +} from '../wechaty' import { log, } from '../config' @@ -55,7 +53,10 @@ import { * * [Examples/Friend-Bot]{@link https://github.com/wechaty/wechaty/blob/1523c5e02be46ebe2cc172a744b2fbe53351540e/examples/friend-bot.ts} */ -export class Friendship extends Accessory implements Acceptable { +class Friendship extends EventEmitter implements Acceptable { + + static get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } + get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } public static Type = FriendshipType @@ -93,7 +94,7 @@ export class Friendship extends Accessory implements Acceptable { log.verbose('Friendship', 'static search("%s")', JSON.stringify(queryFiter), ) - const contactId = await this.puppet.friendshipSearch(queryFiter) + const contactId = await this.wechaty.puppet.friendshipSearch(queryFiter) if (!contactId) { return null @@ -138,7 +139,7 @@ export class Friendship extends Accessory implements Acceptable { contact.id, hello, ) - await this.puppet.friendshipAdd(contact.id, hello) + await this.wechaty.puppet.friendshipAdd(contact.id, hello) } public static async del ( @@ -174,7 +175,7 @@ export class Friendship extends Accessory implements Acceptable { throw new Error('Friendship class can not be instanciated directly! See: https://github.com/wechaty/wechaty/issues/1217') } - if (!this.puppet) { + if (!this.wechaty.puppet) { throw new Error('Friendship class can not be instanciated without a puppet!') } } @@ -206,7 +207,7 @@ export class Friendship extends Accessory implements Acceptable { return } - this.payload = await this.puppet.friendshipPayload(this.id) + this.payload = await this.wechaty.puppet.friendshipPayload(this.id) if (!this.payload) { throw new Error('no payload') @@ -258,7 +259,7 @@ export class Friendship extends Accessory implements Acceptable { log.silly('Friendship', 'accept() to %s', this.payload.contactId) - await this.puppet.friendshipAccept(this.id) + await this.wechaty.puppet.friendshipAccept(this.id) const contact = this.contact() @@ -408,7 +409,7 @@ export class Friendship extends Accessory implements Acceptable { /** * Set the payload back to the puppet for future use */ - await this.puppet.friendshipPayload(payload.id, payload) + await this.wechaty.puppet.friendshipPayload(payload.id, payload) const instance = this.wechaty.Friendship.load(payload.id) await instance.ready() @@ -417,3 +418,21 @@ export class Friendship extends Accessory implements Acceptable { } } + +function wechatifyFriendship (wechaty: Wechaty): typeof Friendship { + + class WechatifiedFriendship extends Friendship { + + static get wechaty () { return wechaty } + get wechaty () { return wechaty } + + } + + return WechatifiedFriendship + +} + +export { + Friendship, + wechatifyFriendship, +} diff --git a/src/user/image.ts b/src/user/image.ts index 4429cd19c..95ef5d2f6 100644 --- a/src/user/image.ts +++ b/src/user/image.ts @@ -23,18 +23,20 @@ import { ImageType, } from 'wechaty-puppet' -import { Accessory } from '../accessory' +import { Wechaty } from '../wechaty' import { FileBox, log, } from '../config' -export class Image extends Accessory { +class Image { + + static get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } + get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } constructor ( public id: string, ) { - super() log.verbose('Image', 'constructor(%s)', id, this.constructor.name, @@ -46,7 +48,7 @@ export class Image extends Accessory { throw new Error('Image class can not be instanciated directly! See: https://github.com/wechaty/wechaty/issues/1217') } - if (!this.puppet) { + if (!this.wechaty.puppet) { throw new Error('Image class can not be instanciated without a puppet!') } } @@ -60,20 +62,38 @@ export class Image extends Accessory { public async thumbnail (): Promise { log.verbose('Image', 'thumbnail() for id: "%s"', this.id) - const fileBox = await this.puppet.messageImage(this.id, ImageType.Thumbnail) + const fileBox = await this.wechaty.puppet.messageImage(this.id, ImageType.Thumbnail) return fileBox } public async hd (): Promise { log.verbose('Image', 'hd() for id: "%s"', this.id) - const fileBox = await this.puppet.messageImage(this.id, ImageType.HD) + const fileBox = await this.wechaty.puppet.messageImage(this.id, ImageType.HD) return fileBox } public async artwork (): Promise { log.verbose('Image', 'artwork() for id: "%s"', this.id) - const fileBox = await this.puppet.messageImage(this.id, ImageType.Artwork) + const fileBox = await this.wechaty.puppet.messageImage(this.id, ImageType.Artwork) return fileBox } } + +function wechatifyImage (wechaty: Wechaty): typeof Image { + + class WechatifiedImage extends Image { + + static get wechaty () { return wechaty } + get wechaty () { return wechaty } + + } + + return WechatifiedImage + +} + +export { + Image, + wechatifyImage, +} diff --git a/src/user/message.ts b/src/user/message.ts index dfddab025..b86ba9370 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -17,9 +17,8 @@ * limitations under the License. * */ -import { - instanceToClass, -} from 'clone-class' +import { EventEmitter } from 'events' +import { instanceToClass } from 'clone-class' import { MessagePayload, @@ -31,8 +30,8 @@ import { escapeRegExp } from '../helper-functions/pure/escape-regexp' import { timestampToDate } from '../helper-functions/pure/timestamp-to-date' import { - Accessory, -} from '../accessory' + Wechaty, +} from '../wechaty' import { AT_SEPARATOR_REGEX, FileBox, @@ -63,7 +62,10 @@ import { Image } from './image' * * [Examples/Ding-Dong-Bot]{@link https://github.com/wechaty/wechaty/blob/1523c5e02be46ebe2cc172a744b2fbe53351540e/examples/ding-dong-bot.ts} */ -export class Message extends Accessory implements Sayable { +class Message extends EventEmitter implements Sayable { + + static get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } + get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } /** * @@ -113,7 +115,7 @@ export class Message extends Accessory implements Sayable { const invalidDict: { [id: string]: true } = {} try { - const MessageIdList = await this.puppet.messageSearch(query) + const MessageIdList = await this.wechaty.puppet.messageSearch(query) const messageList = MessageIdList.map(id => this.load(id)) await Promise.all( messageList.map( @@ -182,7 +184,7 @@ export class Message extends Accessory implements Sayable { throw new Error('Message class can not be instantiated directly! See: https://github.com/wechaty/wechaty/issues/1217') } - if (!this.puppet) { + if (!this.wechaty.puppet) { throw new Error('Message class can not be instantiated without a puppet!') } } @@ -495,7 +497,7 @@ export class Message extends Accessory implements Sayable { ): Promise { log.verbose('Message', 'say(%s)', something) - // const user = this.puppet.userSelf() + // const user = this.wechaty.puppet.userSelf() const from = this.from() // const to = this.to() const room = this.room() @@ -535,7 +537,7 @@ export class Message extends Accessory implements Sayable { mentionIdList = [from.id] } - msgId = await this.puppet.messageSendText( + msgId = await this.wechaty.puppet.messageSendText( conversationId, something, mentionIdList, @@ -544,7 +546,7 @@ export class Message extends Accessory implements Sayable { /** * Contact Card */ - msgId = await this.puppet.messageSendContact( + msgId = await this.wechaty.puppet.messageSendContact( conversationId, something.id, ) @@ -552,7 +554,7 @@ export class Message extends Accessory implements Sayable { /** * File Message */ - msgId = await this.puppet.messageSendFile( + msgId = await this.wechaty.puppet.messageSendFile( conversationId, something, ) @@ -560,7 +562,7 @@ export class Message extends Accessory implements Sayable { /** * Link Message */ - msgId = await this.puppet.messageSendUrl( + msgId = await this.wechaty.puppet.messageSendUrl( conversationId, something.payload, ) @@ -568,7 +570,7 @@ export class Message extends Accessory implements Sayable { /** * MiniProgram */ - msgId = await this.puppet.messageSendMiniProgram( + msgId = await this.wechaty.puppet.messageSendMiniProgram( conversationId, something.payload, ) @@ -600,7 +602,7 @@ export class Message extends Accessory implements Sayable { public async recall (): Promise { log.verbose('Message', 'recall()') - const isSuccess = await this.puppet.messageRecall(this.id) + const isSuccess = await this.wechaty.puppet.messageRecall(this.id) return isSuccess } @@ -641,7 +643,7 @@ export class Message extends Accessory implements Sayable { * } */ public self (): boolean { - const userId = this.puppet.selfId() + const userId = this.wechaty.puppet.selfId() const from = this.from() return !!from && from.id === userId @@ -796,7 +798,7 @@ export class Message extends Accessory implements Sayable { * } */ public async mentionSelf (): Promise { - const selfId = this.puppet.selfId() + const selfId = this.wechaty.puppet.selfId() const mentionList = await this.mentionList() return mentionList.some(contact => contact.id === selfId) } @@ -818,7 +820,7 @@ export class Message extends Accessory implements Sayable { return } - this.payload = await this.puppet.messagePayload(this.id) + this.payload = await this.wechaty.puppet.messagePayload(this.id) if (!this.payload) { throw new Error('no payload') @@ -899,7 +901,7 @@ export class Message extends Accessory implements Sayable { // let contactId try { - await this.puppet.messageForward( + await this.wechaty.puppet.messageForward( to.id, this.id, ) @@ -963,7 +965,7 @@ export class Message extends Accessory implements Sayable { if (this.type() === Message.Type.Text) { throw new Error('text message no file') } - const fileBox = await this.puppet.messageFile(this.id) + const fileBox = await this.wechaty.puppet.messageFile(this.id) return fileBox } @@ -1002,7 +1004,7 @@ export class Message extends Accessory implements Sayable { throw new Error('message not a ShareCard') } - const contactId = await this.puppet.messageContact(this.id) + const contactId = await this.wechaty.puppet.messageContact(this.id) if (!contactId) { throw new Error(`can not get Contact id by message: ${contactId}`) @@ -1024,7 +1026,7 @@ export class Message extends Accessory implements Sayable { throw new Error('message not a Url Link') } - const urlPayload = await this.puppet.messageUrl(this.id) + const urlPayload = await this.wechaty.puppet.messageUrl(this.id) if (!urlPayload) { throw new Error(`no url payload for message ${this.id}`) @@ -1044,7 +1046,7 @@ export class Message extends Accessory implements Sayable { throw new Error('message not a MiniProgram') } - const miniProgramPayload = await this.puppet.messageMiniProgram(this.id) + const miniProgramPayload = await this.wechaty.puppet.messageMiniProgram(this.id) if (!miniProgramPayload) { throw new Error(`no miniProgram payload for message ${this.id}`) @@ -1054,3 +1056,21 @@ export class Message extends Accessory implements Sayable { } } + +function wechatifyMessage (wechaty: Wechaty): typeof Message { + + class WechatifiedMessage extends Message { + + static get wechaty () { return wechaty } + get wechaty () { return wechaty } + + } + + return WechatifiedMessage + +} + +export { + Message, + wechatifyMessage, +} diff --git a/src/user/mini-program.ts b/src/user/mini-program.ts index 595181204..ea65a4e73 100644 --- a/src/user/mini-program.ts +++ b/src/user/mini-program.ts @@ -21,11 +21,15 @@ import { MiniProgramPayload, } from 'wechaty-puppet' +import { Wechaty } from '../wechaty' import { log, } from '../config' -export class MiniProgram { +class MiniProgram { + + static get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } + get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } /** * @@ -87,3 +91,21 @@ export class MiniProgram { } } + +function wechatifyMiniProgram (wechaty: Wechaty): typeof MiniProgram { + + class WechatifiedMiniProgram extends MiniProgram { + + static get wechaty () { return wechaty } + get wechaty () { return wechaty } + + } + + return WechatifiedMiniProgram + +} + +export { + MiniProgram, + wechatifyMiniProgram, +} diff --git a/src/user/moment.ts b/src/user/moment.ts index 9a749d4a4..b03bc0279 100644 --- a/src/user/moment.ts +++ b/src/user/moment.ts @@ -17,9 +17,14 @@ * limitations under the License. * */ +import { Wechaty } from '../wechaty' + import { Contact } from './contact' -export class Moment { +class Moment { + + static get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } + get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } public static post () { // post new moment @@ -41,3 +46,21 @@ export class Moment { } } + +function wechatifyMoment (wechaty: Wechaty): typeof Moment { + + class WechatifiedMoment extends Moment { + + static get wechaty () { return wechaty } + get wechaty () { return wechaty } + + } + + return WechatifiedMoment + +} + +export { + Moment, + wechatifyMoment, +} diff --git a/src/user/room-invitation.ts b/src/user/room-invitation.ts index 760842af3..db96062a0 100644 --- a/src/user/room-invitation.ts +++ b/src/user/room-invitation.ts @@ -22,8 +22,8 @@ import { } from 'clone-class' import { - Accessory, -} from '../accessory' + Wechaty, +} from '../wechaty' import { log, } from '../config' @@ -43,7 +43,10 @@ import { RoomInvitationPayload } from 'wechaty-puppet' * * accept room invitation */ -export class RoomInvitation extends Accessory implements Acceptable { +class RoomInvitation implements Acceptable { + + static get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } + get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } public static load ( this : T, @@ -61,7 +64,6 @@ export class RoomInvitation extends Accessory implements Acceptable { constructor ( public readonly id: string, ) { - super() log.verbose('RoomInvitation', 'constructor(id=%s)', id) const MyClass = instanceToClass(this, RoomInvitation) @@ -70,7 +72,7 @@ export class RoomInvitation extends Accessory implements Acceptable { throw new Error('RoomInvitation class can not be instanciated directly! See: https://github.com/wechaty/wechaty/issues/1217') } - if (!this.puppet) { + if (!this.wechaty.puppet) { throw new Error('RoomInvitation class can not be instanciated without a puppet!') } } @@ -86,7 +88,7 @@ export class RoomInvitation extends Accessory implements Acceptable { * @ignore */ public async toStringAsync (): Promise { - const payload = await this.puppet.roomInvitationPayload(this.id) + const payload = await this.wechaty.puppet.roomInvitationPayload(this.id) return [ 'RoomInvitation#', this.id, @@ -118,7 +120,7 @@ export class RoomInvitation extends Accessory implements Acceptable { public async accept (): Promise { log.verbose('RoomInvitation', 'accept()') - await this.puppet.roomInvitationAccept(this.id) + await this.wechaty.puppet.roomInvitationAccept(this.id) const inviter = await this.inviter() const topic = await this.topic() @@ -155,7 +157,7 @@ export class RoomInvitation extends Accessory implements Acceptable { public async inviter (): Promise { log.verbose('RoomInvitation', 'inviter()') - const payload = await this.puppet.roomInvitationPayload(this.id) + const payload = await this.wechaty.puppet.roomInvitationPayload(this.id) const inviter = this.wechaty.Contact.load(payload.inviterId) return inviter } @@ -173,7 +175,7 @@ export class RoomInvitation extends Accessory implements Acceptable { * .start() */ public async topic (): Promise { - const payload = await this.puppet.roomInvitationPayload(this.id) + const payload = await this.wechaty.puppet.roomInvitationPayload(this.id) // roomTopic deprecated. use topic instead: return payload.topic || payload.topic || '' @@ -190,7 +192,7 @@ export class RoomInvitation extends Accessory implements Acceptable { public async memberCount (): Promise { log.verbose('RoomInvitation', 'memberCount()') - const payload = await this.puppet.roomInvitationPayload(this.id) + const payload = await this.wechaty.puppet.roomInvitationPayload(this.id) // roomMemberCount deprecated. use memberCount instead: return payload.memberCount || payload.memberCount || 0 @@ -212,7 +214,7 @@ export class RoomInvitation extends Accessory implements Acceptable { public async memberList (): Promise { log.verbose('RoomInvitation', 'roomMemberList()') - const payload = await this.puppet.roomInvitationPayload(this.id) + const payload = await this.wechaty.puppet.roomInvitationPayload(this.id) // roomMemberIdList deprecated. use memberIdList isntead. const contactIdList = payload.memberIdList || payload.memberIdList || [] @@ -246,7 +248,7 @@ export class RoomInvitation extends Accessory implements Acceptable { public async date (): Promise { log.verbose('RoomInvitation', 'date()') - const payload = await this.puppet.roomInvitationPayload(this.id) + const payload = await this.wechaty.puppet.roomInvitationPayload(this.id) return timestampToDate(payload.timestamp) } @@ -290,7 +292,7 @@ export class RoomInvitation extends Accessory implements Acceptable { payload = JSON.parse(payload) as RoomInvitationPayload } - await this.puppet.roomInvitationPayload(payload.id, payload) + await this.wechaty.puppet.roomInvitationPayload(payload.id, payload) return this.wechaty.RoomInvitation.load(payload.id) } @@ -310,8 +312,26 @@ export class RoomInvitation extends Accessory implements Acceptable { */ public async toJSON (): Promise { log.verbose('RoomInvitation', 'toJSON()') - const payload = await this.puppet.roomInvitationPayload(this.id) + const payload = await this.wechaty.puppet.roomInvitationPayload(this.id) return JSON.stringify(payload) } } + +function wechatifyRoomInvitation (wechaty: Wechaty): typeof RoomInvitation { + + class WechatifiedRoomInvitation extends RoomInvitation { + + static get wechaty () { return wechaty } + get wechaty () { return wechaty } + + } + + return WechatifiedRoomInvitation + +} + +export { + RoomInvitation, + wechatifyRoomInvitation, +} diff --git a/src/user/room.ts b/src/user/room.ts index bd98afe35..6409005b4 100644 --- a/src/user/room.ts +++ b/src/user/room.ts @@ -17,13 +17,12 @@ * limitations under the License. * */ -import { - instanceToClass, -} from 'clone-class' +import { EventEmitter } from 'events' + +import { instanceToClass } from 'clone-class' + +import { Wechaty } from '../wechaty' -import { - Accessory, -} from '../accessory' import { FOUR_PER_EM_SPACE, FileBox, @@ -66,7 +65,10 @@ export type RoomEventName = keyof typeof ROOM_EVENT_DICT * [Examples/Room-Bot]{@link https://github.com/wechaty/wechaty/blob/1523c5e02be46ebe2cc172a744b2fbe53351540e/examples/room-bot.ts} * */ -export class Room extends Accessory implements Sayable { +class Room extends EventEmitter implements Sayable { + + static get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } + get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } protected static pool: Map @@ -102,7 +104,7 @@ export class Room extends Accessory implements Sayable { try { const contactIdList = contactList.map(contact => contact.id) - const roomId = await this.puppet.roomCreate(contactIdList, topic) + const roomId = await this.wechaty.puppet.roomCreate(contactIdList, topic) const room = this.load(roomId) return room } catch (e) { @@ -140,7 +142,7 @@ export class Room extends Accessory implements Sayable { const invalidDict: { [id: string]: true } = {} try { - const roomIdList = await this.puppet.roomSearch(query) + const roomIdList = await this.wechaty.puppet.roomSearch(query) const roomList = roomIdList.map(id => this.load(id)) await Promise.all( roomList.map( @@ -203,7 +205,7 @@ export class Room extends Accessory implements Sayable { // use puppet.roomValidate() to confirm double confirm that this roomId is valid. // https://github.com/wechaty/wechaty-puppet-padchat/issues/64 // https://github.com/wechaty/wechaty/issues/1345 - const valid = await this.puppet.roomValidate(room.id) + const valid = await this.wechaty.puppet.roomValidate(room.id) if (valid) { log.verbose('Room', 'find() confirm room[#%d] with id=%d is valid result, return it.', n, @@ -285,7 +287,7 @@ export class Room extends Accessory implements Sayable { throw new Error('Room class can not be instantiated directly! See: https://github.com/wechaty/wechaty/issues/1217') } - if (!this.puppet) { + if (!this.wechaty.puppet) { throw new Error('Room class can not be instantiated without a puppet!') } @@ -347,16 +349,16 @@ export class Room extends Accessory implements Sayable { } if (forceSync) { - await this.puppet.roomPayloadDirty(this.id) - await this.puppet.roomMemberPayloadDirty(this.id) + await this.wechaty.puppet.roomPayloadDirty(this.id) + await this.wechaty.puppet.roomMemberPayloadDirty(this.id) } - this.payload = await this.puppet.roomPayload(this.id) + this.payload = await this.wechaty.puppet.roomPayload(this.id) if (!this.payload) { throw new Error('ready() no payload') } - const memberIdList = await this.puppet.roomMemberList(this.id) + const memberIdList = await this.wechaty.puppet.roomMemberList(this.id) await Promise.all( memberIdList @@ -545,7 +547,7 @@ export class Room extends Accessory implements Sayable { // contactId : (mentionList.length && mentionList[0].id) || undefined, // roomId : this.id, // } - msgId = await this.puppet.messageSendText( + msgId = await this.wechaty.puppet.messageSendText( this.id, text, mentionList.map(c => c.id), @@ -554,7 +556,7 @@ export class Room extends Accessory implements Sayable { /** * 2. File Message */ - msgId = await this.puppet.messageSendFile( + msgId = await this.wechaty.puppet.messageSendFile( this.id, something, ) @@ -562,7 +564,7 @@ export class Room extends Accessory implements Sayable { /** * 3. Contact Card */ - msgId = await this.puppet.messageSendContact( + msgId = await this.wechaty.puppet.messageSendContact( this.id, something.id, ) @@ -570,7 +572,7 @@ export class Room extends Accessory implements Sayable { /** * 4. Link Message */ - msgId = await this.puppet.messageSendUrl( + msgId = await this.wechaty.puppet.messageSendUrl( this.id, something.payload, ) @@ -578,7 +580,7 @@ export class Room extends Accessory implements Sayable { /** * 5. Mini Program */ - msgId = await this.puppet.messageSendMiniProgram( + msgId = await this.wechaty.puppet.messageSendMiniProgram( this.id, something.payload, ) @@ -606,7 +608,7 @@ export class Room extends Accessory implements Sayable { /** * No mention in the string */ - return this.puppet.messageSendText( + return this.wechaty.puppet.messageSendText( this.id, textList[0], ) @@ -620,7 +622,7 @@ export class Room extends Accessory implements Sayable { // /** // * Constructed mention string, skip inserting @ signs // */ - // return this.puppet.messageSendText( + // return this.wechaty.puppet.messageSendText( // receiver, // textList[0], // mentionList.map(c => c.id), @@ -648,7 +650,7 @@ export class Room extends Accessory implements Sayable { } finalText += textList[i] - return this.puppet.messageSendText( + return this.wechaty.puppet.messageSendText( this.id, finalText, mentionList.map(c => c.id), @@ -656,7 +658,7 @@ export class Room extends Accessory implements Sayable { } } - public emit (event: 'invite', inviter: Contact, invitation: RoomInvitation) : boolean + public emit (event: 'invite', inviter: Contact, invitation: RoomInvitation) : boolean public emit (event: 'leave', leaverList: Contact[], remover: Contact, date: Date) : boolean public emit (event: 'message', message: Message) : boolean public emit (event: 'join', inviteeList: Contact[], inviter: Contact, date: Date) : boolean @@ -789,7 +791,7 @@ export class Room extends Accessory implements Sayable { */ public async add (contact: Contact): Promise { log.verbose('Room', 'add(%s)', contact) - await this.puppet.roomAdd(this.id, contact.id) + await this.wechaty.puppet.roomAdd(this.id, contact.id) } /** @@ -819,7 +821,7 @@ export class Room extends Accessory implements Sayable { */ public async del (contact: Contact): Promise { log.verbose('Room', 'del(%s)', contact) - await this.puppet.roomDel(this.id, contact.id) + await this.wechaty.puppet.roomDel(this.id, contact.id) // this.delLocal(contact) } @@ -849,7 +851,7 @@ export class Room extends Accessory implements Sayable { */ public async quit (): Promise { log.verbose('Room', 'quit() %s', this) - await this.puppet.roomQuit(this.id) + await this.wechaty.puppet.roomQuit(this.id) } public async topic () : Promise @@ -897,9 +899,9 @@ export class Room extends Accessory implements Sayable { if (this.payload && this.payload.topic) { return this.payload.topic } else { - const memberIdList = await this.puppet.roomMemberList(this.id) + const memberIdList = await this.wechaty.puppet.roomMemberList(this.id) const memberList = memberIdList - .filter(id => id !== this.puppet.selfId()) + .filter(id => id !== this.wechaty.puppet.selfId()) .map(id => this.wechaty.Contact.load(id)) let defaultTopic = (memberList[0] && memberList[0].name()) || '' @@ -910,7 +912,7 @@ export class Room extends Accessory implements Sayable { } } - const future = this.puppet + const future = this.wechaty.puppet .roomTopic(this.id, newTopic) .catch(e => { log.warn('Room', 'topic(newTopic=%s) exception: %s', @@ -959,10 +961,10 @@ export class Room extends Accessory implements Sayable { ) if (typeof text === 'undefined') { - const announcement = await this.puppet.roomAnnounce(this.id) + const announcement = await this.wechaty.puppet.roomAnnounce(this.id) return announcement } else { - await this.puppet.roomAnnounce(this.id, text) + await this.wechaty.puppet.roomAnnounce(this.id, text) } } @@ -983,7 +985,7 @@ export class Room extends Accessory implements Sayable { */ public async qrCode (): Promise { log.verbose('Room', 'qrCode()') - const qrcodeValue = await this.puppet.roomQRCode(this.id) + const qrcodeValue = await this.wechaty.puppet.roomQRCode(this.id) return guardQrCodeValue(qrcodeValue) } @@ -1005,7 +1007,7 @@ export class Room extends Accessory implements Sayable { * .start() */ public async alias (contact: Contact): Promise { - const memberPayload = await this.puppet.roomMemberPayload(this.id, contact.id) + const memberPayload = await this.wechaty.puppet.roomMemberPayload(this.id, contact.id) if (memberPayload && memberPayload.roomAlias) { return memberPayload.roomAlias @@ -1046,7 +1048,7 @@ export class Room extends Accessory implements Sayable { * } */ public async has (contact: Contact): Promise { - const memberIdList = await this.puppet.roomMemberList(this.id) + const memberIdList = await this.wechaty.puppet.roomMemberList(this.id) if (!memberIdList) { return false @@ -1098,7 +1100,7 @@ export class Room extends Accessory implements Sayable { return this.memberList() } - const contactIdList = await this.puppet.roomMemberSearch(this.id, query) + const contactIdList = await this.wechaty.puppet.roomMemberSearch(this.id, query) const contactList = contactIdList.map(id => this.wechaty.Contact.load(id)) return contactList @@ -1178,7 +1180,7 @@ export class Room extends Accessory implements Sayable { private async memberList (): Promise { log.verbose('Room', 'memberList()') - const memberIdList = await this.puppet.roomMemberList(this.id) + const memberIdList = await this.wechaty.puppet.roomMemberList(this.id) if (!memberIdList) { log.warn('Room', 'memberList() not ready') @@ -1222,7 +1224,25 @@ export class Room extends Accessory implements Sayable { public async avatar (): Promise { log.verbose('Room', 'avatar()') - return this.puppet.roomAvatar(this.id) + return this.wechaty.puppet.roomAvatar(this.id) } } + +function wechatifyRoom (wechaty: Wechaty): typeof Room { + + class WechatifiedRoom extends Room { + + static get wechaty () { return wechaty } + get wechaty () { return wechaty } + + } + + return WechatifiedRoom + +} + +export { + Room, + wechatifyRoom, +} diff --git a/src/user/tag.ts b/src/user/tag.ts index 08afce987..e429b88fc 100644 --- a/src/user/tag.ts +++ b/src/user/tag.ts @@ -20,12 +20,15 @@ import { instanceToClass } from 'clone-class' import { log } from '../config' -import { Accessory } from '../accessory' +import { Wechaty } from '../wechaty' import { Contact } from './contact' import { Favorite } from './favorite' -export class Tag extends Accessory { +class Tag { + + static get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } + get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } protected static pool: Map @@ -35,7 +38,6 @@ export class Tag extends Accessory { constructor ( public readonly id: string, ) { - super() log.silly('Tag', `constructor(${id})`) const MyClass = instanceToClass(this, Tag) @@ -47,7 +49,7 @@ export class Tag extends Accessory { ) } - if (!this.puppet) { + if (!this.wechaty.puppet) { throw new Error('Tag class can not be instanciated without a puppet!') } } @@ -143,10 +145,10 @@ export class Tag extends Accessory { */ if (!target || target === Contact || target === this.wechaty.Contact) { - await this.puppet.tagContactDelete(tag.id) + await this.wechaty.puppet.tagContactDelete(tag.id) // TODO: // } else if (!target || target === Favorite || target === this.wechaty.Favorite) { - // await this.puppet.tagFavoriteDelete(tag.id) + // await this.wechaty.puppet.tagFavoriteDelete(tag.id) } } catch (e) { log.error('Tag', 'static delete() exception: %s', e.message) @@ -171,9 +173,9 @@ export class Tag extends Accessory { try { if (to instanceof Contact) { - await this.puppet.tagContactAdd(this.id, to.id) + await this.wechaty.puppet.tagContactAdd(this.id, to.id) } else if (to instanceof Favorite) { - // TODO: await this.puppet.tagAddFavorite(this.tag, to.id) + // TODO: await this.wechaty.puppet.tagAddFavorite(this.tag, to.id) } } catch (e) { log.error('Tag', 'add() exception: %s', e.message) @@ -196,9 +198,9 @@ export class Tag extends Accessory { try { if (from instanceof Contact) { - await this.puppet.tagContactRemove(this.id, from.id) + await this.wechaty.puppet.tagContactRemove(this.id, from.id) } else if (from instanceof Favorite) { - // TODO await this.puppet.tagRemoveFavorite(this.tag, from.id) + // TODO await this.wechaty.puppet.tagRemoveFavorite(this.tag, from.id) } } catch (e) { log.error('Tag', 'remove() exception: %s', e.message) @@ -207,3 +209,21 @@ export class Tag extends Accessory { } } + +function wechatifyTag (wechaty: Wechaty): typeof Tag { + + class WechatifiedTag extends Tag { + + static get wechaty () { return wechaty } + get wechaty () { return wechaty } + + } + + return WechatifiedTag + +} + +export { + Tag, + wechatifyTag, +} diff --git a/src/user/url-link.ts b/src/user/url-link.ts index 456ae9589..666fcae32 100644 --- a/src/user/url-link.ts +++ b/src/user/url-link.ts @@ -31,7 +31,7 @@ import { openGraph, } from '../helper-functions/impure/open-graph' -export class UrlLink { +class UrlLink { /** * @@ -124,3 +124,14 @@ export class UrlLink { } } + +function wechatifyUrlLink (_: any): typeof UrlLink { + + return UrlLink + +} + +export { + UrlLink, + wechatifyUrlLink, +} diff --git a/src/wechaty-events.ts b/src/wechaty-events.ts new file mode 100644 index 000000000..2c5e5c2cd --- /dev/null +++ b/src/wechaty-events.ts @@ -0,0 +1,223 @@ +import { EventEmitter } from 'events' + +import TypedEventEmitter from 'typed-emitter' + +import { + CHAT_EVENT_DICT, + ScanStatus, +} from 'wechaty-puppet' + +import { + Friendship, + ContactSelf, + Room, + RoomInvitation, + Contact, + Message, +} from './user/mod' + +export const WECHATY_EVENT_DICT = { + ...CHAT_EVENT_DICT, + dong : 'Should be emitted after we call `Wechaty.ding()`', + error : "Will be emitted when there's an Error occurred.", + heartbeat : 'Will be emitted periodically after the Wechaty started. If not, means that the Wechaty had died.', + ready : 'All underlined data source are ready for use.', + start : 'Will be emitted after the Wechaty had been started.', + stop : 'Will be emitted after the Wechaty had been stopped.', +} + +export type WechatyEventName = keyof typeof WECHATY_EVENT_DICT + +/** + * Wechaty Event Listener Interfaces + */ +export type WechatyDongEventListener = (data?: string) => void +export type WechatyErrorEventListener = (error: Error) => void +export type WechatyFriendshipEventListener = (friendship: Friendship) => void +export type WechatyHeartbeatEventListener = (data: any) => void +export type WechatyLoginEventListener = (user: ContactSelf) => void +export type WechatyLogoutEventListener = (user: ContactSelf, reason?: string) => void +export type WechatyMessageEventListener = (message: Message) => void +export type WechatyReadyEventListener = () => void +export type WechatyRoomInviteEventListener = (roomInvitation: RoomInvitation) => void +export type WechatyRoomJoinEventListener = (room: Room, inviteeList: Contact[], inviter: Contact, date?: Date) => void +export type WechatyRoomLeaveEventListener = (room: Room, leaverList: Contact[], remover?: Contact, date?: Date) => void +export type WechatyRoomTopicEventListener = (room: Room, newTopic: string, oldTopic: string, changer: Contact, date?: Date) => void +export type WechatyScanEventListener = (qrcode: string, status: ScanStatus, data?: string) => void +export type WechatyStartStopEventListener = () => void + +/** + * @desc Wechaty Class Event Type + * @typedef WechatyEventName + * @property {string} error - When the bot get error, there will be a Wechaty error event fired. + * @property {string} login - After the bot login full successful, the event login will be emitted, with a Contact of current logged in user. + * @property {string} logout - Logout will be emitted when bot detected log out, with a Contact of the current login user. + * @property {string} heartbeat - Get heartbeat of the bot. + * @property {string} friendship - When someone sends you a friend request, there will be a Wechaty friendship event fired. + * @property {string} message - Emit when there's a new message. + * @property {string} ready - Emit when all data has load completed, in wechaty-puppet-padchat, it means it has sync Contact and Room completed + * @property {string} room-join - Emit when anyone join any room. + * @property {string} room-topic - Get topic event, emitted when someone change room topic. + * @property {string} room-leave - Emit when anyone leave the room.
+ * - If someone leaves the room by themselves, WeChat will not notice other people in the room, so the bot will never get the "leave" event. + * @property {string} room-invite - Emit when there is a room invitation, see more in {@link RoomInvitation} + * @property {string} scan - A scan event will be emitted when the bot needs to show you a QR Code for scanning.
+ * It is recommend to install qrcode-terminal(run `npm install qrcode-terminal`) in order to show qrcode in the terminal. + */ + +/** + * @desc Wechaty Class Event Function + * @typedef WechatyEventFunction + * @property {Function} error -(this: Wechaty, error: Error) => void callback function + * @property {Function} login -(this: Wechaty, user: ContactSelf)=> void + * @property {Function} logout -(this: Wechaty, user: ContactSelf) => void + * @property {Function} scan -(this: Wechaty, url: string, code: number) => void
+ *
    + *
  1. URL: {String} the QR code image URL
  2. + *
  3. code: {Number} the scan status code. some known status of the code list here is:
  4. + *
+ *
    + *
  • 0 initial_
  • + *
  • 200 login confirmed
  • + *
  • 201 scanned, wait for confirm
  • + *
  • 408 waits for scan
  • + *
+ * @property {Function} heartbeat -(this: Wechaty, data: any) => void + * @property {Function} friendship -(this: Wechaty, friendship: Friendship) => void + * @property {Function} message -(this: Wechaty, message: Message) => void + * @property {Function} ready -(this: Wechaty) => void + * @property {Function} room-join -(this: Wechaty, room: Room, inviteeList: Contact[], inviter: Contact) => void + * @property {Function} room-topic -(this: Wechaty, room: Room, newTopic: string, oldTopic: string, changer: Contact) => void + * @property {Function} room-leave -(this: Wechaty, room: Room, leaverList: Contact[]) => void + * @property {Function} room-invite -(this: Wechaty, room: Room, roomInvitation: RoomInvitation) => void
+ * see more in {@link RoomInvitation} + */ + +/** + * @listens Wechaty + * @param {WechatyEventName} event - Emit WechatyEvent + * @param {WechatyEventFunction} listener - Depends on the WechatyEvent + * + * @return {Wechaty} - this for chaining, + * see advanced {@link https://github.com/wechaty/wechaty-getting-started/wiki/FAQ-EN#36-why-wechatyonevent-listener-return-wechaty|chaining usage} + * + * @desc + * When the bot get message, it will emit the following Event. + * + * You can do anything you want when in these events functions. + * The main Event name as follows: + * - **scan**: Emit when the bot needs to show you a QR Code for scanning. After scan the qrcode, you can login + * - **login**: Emit when bot login full successful. + * - **logout**: Emit when bot detected log out. + * - **message**: Emit when there's a new message. + * + * see more in {@link WechatyEventName} + * + * @example Event:scan + * // Scan Event will emit when the bot needs to show you a QR Code for scanning + * + * bot.on('scan', (url, status) => { + * console.log(`[${status}] Scan ${url} to login.` ) + * }) + * + * @example Event:login + * // Login Event will emit when bot login full successful. + * + * bot.on('login', (user) => { + * console.log(`user ${user} login`) + * }) + * + * @example Event:logout + * // Logout Event will emit when bot detected log out. + * + * bot.on('logout', (user) => { + * console.log(`user ${user} logout`) + * }) + * + * @example Event:message + * // Message Event will emit when there's a new message. + * + * wechaty.on('message', (message) => { + * console.log(`message ${message} received`) + * }) + * + * @example Event:friendship + * // Friendship Event will emit when got a new friend request, or friendship is confirmed. + * + * bot.on('friendship', (friendship) => { + * if(friendship.type() === Friendship.Type.Receive){ // 1. receive new friendship request from new contact + * const contact = friendship.contact() + * let result = await friendship.accept() + * if(result){ + * console.log(`Request from ${contact.name()} is accept successfully!`) + * } else{ + * console.log(`Request from ${contact.name()} failed to accept!`) + * } + * } else if (friendship.type() === Friendship.Type.Confirm) { // 2. confirm friendship + * console.log(`new friendship confirmed with ${contact.name()}`) + * } + * }) + * + * @example Event:room-join + * // room-join Event will emit when someone join the room. + * + * bot.on('room-join', (room, inviteeList, inviter) => { + * const nameList = inviteeList.map(c => c.name()).join(',') + * console.log(`Room ${room.topic()} got new member ${nameList}, invited by ${inviter}`) + * }) + * + * @example Event:room-leave + * // room-leave Event will emit when someone leave the room. + * + * bot.on('room-leave', (room, leaverList) => { + * const nameList = leaverList.map(c => c.name()).join(',') + * console.log(`Room ${room.topic()} lost member ${nameList}`) + * }) + * + * @example Event:room-topic + * // room-topic Event will emit when someone change the room's topic. + * + * bot.on('room-topic', (room, topic, oldTopic, changer) => { + * console.log(`Room ${room.topic()} topic changed from ${oldTopic} to ${topic} by ${changer.name()}`) + * }) + * + * @example Event:room-invite, RoomInvitation has been encapsulated as a RoomInvitation Class. + * // room-invite Event will emit when there's an room invitation. + * + * bot.on('room-invite', async roomInvitation => { + * try { + * console.log(`received room-invite event.`) + * await roomInvitation.accept() + * } catch (e) { + * console.error(e) + * } + * } + * + * @example Event:error + * // error Event will emit when there's an error occurred. + * + * bot.on('error', (error) => { + * console.error(error) + * }) + */ +interface Events { + dong : WechatyDongEventListener + error : WechatyErrorEventListener + friendship : WechatyFriendshipEventListener + heartbeat : WechatyHeartbeatEventListener + login : WechatyLoginEventListener + logout : WechatyLogoutEventListener + message : WechatyMessageEventListener + ready : WechatyReadyEventListener + 'room-invite' : WechatyRoomInviteEventListener + 'room-join' : WechatyRoomJoinEventListener + 'room-leave' : WechatyRoomLeaveEventListener + 'room-topic' : WechatyRoomTopicEventListener + scan : WechatyScanEventListener + start : WechatyStartStopEventListener + stop : WechatyStartStopEventListener +} + +export const WechatyEventEmitter = EventEmitter as new () => TypedEventEmitter< + Events +> diff --git a/src/wechaty.ts b/src/wechaty.ts index 3fb890041..042a413c2 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -18,15 +18,11 @@ * */ import cuid from 'cuid' -import { EventEmitter } from 'events' import os from 'os' -import TypedEventEmitter from 'typed-emitter' -import { cloneClass } from 'clone-class' import { StateSwitch } from 'state-switch' import { - CHAT_EVENT_DICT, Puppet, MemoryCard, @@ -34,7 +30,6 @@ import { PUPPET_EVENT_DICT, PuppetEventName, PuppetOptions, - ScanStatus, } from 'wechaty-puppet' import { @@ -66,224 +61,34 @@ import { import { Contact, - Tag, ContactSelf, Friendship, - Message, Image, + Message, + MiniProgram, Room, RoomInvitation, + Tag, UrlLink, - MiniProgram, + + wechatifyContact, + wechatifyContactSelf, + wechatifyFriendship, + wechatifyImage, + wechatifyMessage, + wechatifyMiniProgram, + wechatifyRoom, + wechatifyRoomInvitation, + wechatifyTag, + wechatifyUrlLink, } from './user/mod' import { timestampToDate } from './helper-functions/pure/timestamp-to-date' -export const WECHATY_EVENT_DICT = { - ...CHAT_EVENT_DICT, - dong : 'Should be emitted after we call `Wechaty.ding()`', - error : "Will be emitted when there's an Error occurred.", - heartbeat : 'Will be emitted periodically after the Wechaty started. If not, means that the Wechaty had died.', - ready : 'All underlined data source are ready for use.', - start : 'Will be emitted after the Wechaty had been started.', - stop : 'Will be emitted after the Wechaty had been stopped.', -} - -export type WechatyEventName = keyof typeof WECHATY_EVENT_DICT - -/** - * Wechaty Event Listener Interfaces - */ -export type WechatyDongEventListener = (this: Wechaty, data?: string) => void -export type WechatyErrorEventListener = (this: Wechaty, error: Error) => void -export type WechatyFriendshipEventListener = (this: Wechaty, friendship: Friendship) => void -export type WechatyHeartbeatEventListener = (this: Wechaty, data: any) => void -export type WechatyLoginEventListener = (this: Wechaty, user: ContactSelf) => void -export type WechatyLogoutEventListener = (this: Wechaty, user: ContactSelf, reason?: string) => void -export type WechatyMessageEventListener = (this: Wechaty, message: Message) => void -export type WechatyReadyEventListener = (this: Wechaty) => void -export type WechatyRoomInviteEventListener = (this: Wechaty, roomInvitation: RoomInvitation) => void -export type WechatyRoomJoinEventListener = (this: Wechaty, room: Room, inviteeList: Contact[], inviter: Contact, date?: Date) => void -export type WechatyRoomLeaveEventListener = (this: Wechaty, room: Room, leaverList: Contact[], remover?: Contact, date?: Date) => void -export type WechatyRoomTopicEventListener = (this: Wechaty, room: Room, newTopic: string, oldTopic: string, changer: Contact, date?: Date) => void -export type WechatyScanEventListener = (this: Wechaty, qrcode: string, status: ScanStatus, data?: string) => void -export type WechatyStartStopEventListener = (this: Wechaty) => void - -/** - * @desc Wechaty Class Event Type - * @typedef WechatyEventName - * @property {string} error - When the bot get error, there will be a Wechaty error event fired. - * @property {string} login - After the bot login full successful, the event login will be emitted, with a Contact of current logged in user. - * @property {string} logout - Logout will be emitted when bot detected log out, with a Contact of the current login user. - * @property {string} heartbeat - Get heartbeat of the bot. - * @property {string} friendship - When someone sends you a friend request, there will be a Wechaty friendship event fired. - * @property {string} message - Emit when there's a new message. - * @property {string} ready - Emit when all data has load completed, in wechaty-puppet-padchat, it means it has sync Contact and Room completed - * @property {string} room-join - Emit when anyone join any room. - * @property {string} room-topic - Get topic event, emitted when someone change room topic. - * @property {string} room-leave - Emit when anyone leave the room.
- * - If someone leaves the room by themselves, WeChat will not notice other people in the room, so the bot will never get the "leave" event. - * @property {string} room-invite - Emit when there is a room invitation, see more in {@link RoomInvitation} - * @property {string} scan - A scan event will be emitted when the bot needs to show you a QR Code for scanning.
- * It is recommend to install qrcode-terminal(run `npm install qrcode-terminal`) in order to show qrcode in the terminal. - */ - -/** - * @desc Wechaty Class Event Function - * @typedef WechatyEventFunction - * @property {Function} error -(this: Wechaty, error: Error) => void callback function - * @property {Function} login -(this: Wechaty, user: ContactSelf)=> void - * @property {Function} logout -(this: Wechaty, user: ContactSelf) => void - * @property {Function} scan -(this: Wechaty, url: string, code: number) => void
- *
    - *
  1. URL: {String} the QR code image URL
  2. - *
  3. code: {Number} the scan status code. some known status of the code list here is:
  4. - *
- *
    - *
  • 0 initial_
  • - *
  • 200 login confirmed
  • - *
  • 201 scanned, wait for confirm
  • - *
  • 408 waits for scan
  • - *
- * @property {Function} heartbeat -(this: Wechaty, data: any) => void - * @property {Function} friendship -(this: Wechaty, friendship: Friendship) => void - * @property {Function} message -(this: Wechaty, message: Message) => void - * @property {Function} ready -(this: Wechaty) => void - * @property {Function} room-join -(this: Wechaty, room: Room, inviteeList: Contact[], inviter: Contact) => void - * @property {Function} room-topic -(this: Wechaty, room: Room, newTopic: string, oldTopic: string, changer: Contact) => void - * @property {Function} room-leave -(this: Wechaty, room: Room, leaverList: Contact[]) => void - * @property {Function} room-invite -(this: Wechaty, room: Room, roomInvitation: RoomInvitation) => void
- * see more in {@link RoomInvitation} - */ - -/** - * @listens Wechaty - * @param {WechatyEventName} event - Emit WechatyEvent - * @param {WechatyEventFunction} listener - Depends on the WechatyEvent - * - * @return {Wechaty} - this for chaining, - * see advanced {@link https://github.com/wechaty/wechaty-getting-started/wiki/FAQ-EN#36-why-wechatyonevent-listener-return-wechaty|chaining usage} - * - * @desc - * When the bot get message, it will emit the following Event. - * - * You can do anything you want when in these events functions. - * The main Event name as follows: - * - **scan**: Emit when the bot needs to show you a QR Code for scanning. After scan the qrcode, you can login - * - **login**: Emit when bot login full successful. - * - **logout**: Emit when bot detected log out. - * - **message**: Emit when there's a new message. - * - * see more in {@link WechatyEventName} - * - * @example Event:scan - * // Scan Event will emit when the bot needs to show you a QR Code for scanning - * - * bot.on('scan', (url, status) => { - * console.log(`[${status}] Scan ${url} to login.` ) - * }) - * - * @example Event:login - * // Login Event will emit when bot login full successful. - * - * bot.on('login', (user) => { - * console.log(`user ${user} login`) - * }) - * - * @example Event:logout - * // Logout Event will emit when bot detected log out. - * - * bot.on('logout', (user) => { - * console.log(`user ${user} logout`) - * }) - * - * @example Event:message - * // Message Event will emit when there's a new message. - * - * wechaty.on('message', (message) => { - * console.log(`message ${message} received`) - * }) - * - * @example Event:friendship - * // Friendship Event will emit when got a new friend request, or friendship is confirmed. - * - * bot.on('friendship', (friendship) => { - * if(friendship.type() === Friendship.Type.Receive){ // 1. receive new friendship request from new contact - * const contact = friendship.contact() - * let result = await friendship.accept() - * if(result){ - * console.log(`Request from ${contact.name()} is accept successfully!`) - * } else{ - * console.log(`Request from ${contact.name()} failed to accept!`) - * } - * } else if (friendship.type() === Friendship.Type.Confirm) { // 2. confirm friendship - * console.log(`new friendship confirmed with ${contact.name()}`) - * } - * }) - * - * @example Event:room-join - * // room-join Event will emit when someone join the room. - * - * bot.on('room-join', (room, inviteeList, inviter) => { - * const nameList = inviteeList.map(c => c.name()).join(',') - * console.log(`Room ${room.topic()} got new member ${nameList}, invited by ${inviter}`) - * }) - * - * @example Event:room-leave - * // room-leave Event will emit when someone leave the room. - * - * bot.on('room-leave', (room, leaverList) => { - * const nameList = leaverList.map(c => c.name()).join(',') - * console.log(`Room ${room.topic()} lost member ${nameList}`) - * }) - * - * @example Event:room-topic - * // room-topic Event will emit when someone change the room's topic. - * - * bot.on('room-topic', (room, topic, oldTopic, changer) => { - * console.log(`Room ${room.topic()} topic changed from ${oldTopic} to ${topic} by ${changer.name()}`) - * }) - * - * @example Event:room-invite, RoomInvitation has been encapsulated as a RoomInvitation Class. - * // room-invite Event will emit when there's an room invitation. - * - * bot.on('room-invite', async roomInvitation => { - * try { - * console.log(`received room-invite event.`) - * await roomInvitation.accept() - * } catch (e) { - * console.error(e) - * } - * } - * - * @example Event:error - * // error Event will emit when there's an error occurred. - * - * bot.on('error', (error) => { - * console.error(error) - * }) - */ -interface Events { - dong : WechatyDongEventListener - error : WechatyErrorEventListener - friendship : WechatyFriendshipEventListener - heartbeat : WechatyHeartbeatEventListener - login : WechatyLoginEventListener - logout : WechatyLogoutEventListener - message : WechatyMessageEventListener - ready : WechatyReadyEventListener - 'room-invite' : WechatyRoomInviteEventListener - 'room-join' : WechatyRoomJoinEventListener - 'room-leave' : WechatyRoomLeaveEventListener - 'room-topic' : WechatyRoomTopicEventListener - scan : WechatyScanEventListener - start : WechatyStartStopEventListener - stop : WechatyStartStopEventListener -} - -const WechatyEventEmitter = EventEmitter as new () => TypedEventEmitter< - Events -> +import { + WechatyEventEmitter, + WechatyEventName, +} from './wechaty-events' export interface WechatyOptions { memory? : MemoryCard, @@ -356,16 +161,27 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { */ public readonly id : string - public readonly Contact : typeof Contact - public readonly Tag : typeof Tag - public readonly ContactSelf : typeof ContactSelf - public readonly Friendship : typeof Friendship - public readonly Message : typeof Message - public readonly Image : typeof Image - public readonly RoomInvitation: typeof RoomInvitation - public readonly Room : typeof Room - public readonly UrlLink : typeof UrlLink - public readonly MiniProgram : typeof MiniProgram + protected wechatifiedContact? : typeof Contact + protected wechatifiedContactSelf? : typeof ContactSelf + protected wechatifiedFriendship? : typeof Friendship + protected wechatifiedImage? : typeof Image + protected wechatifiedMessage? : typeof Message + protected wechatifiedMiniProgram? : typeof MiniProgram + protected wechatifiedRoom? : typeof Room + protected wechatifiedRoomInvitation? : typeof RoomInvitation + protected wechatifiedTag? : typeof Tag + protected wechatifiedUrlLink? : typeof UrlLink + + public get Contact () : typeof Contact { return this.wechatifiedContact! } + public get ContactSelf () : typeof ContactSelf { return this.wechatifiedContactSelf! } + public get Friendship () : typeof Friendship { return this.wechatifiedFriendship! } + public get Image () : typeof Image { return this.wechatifiedImage! } + public get Message () : typeof Message { return this.wechatifiedMessage! } + public get MiniProgram () : typeof MiniProgram { return this.wechatifiedMiniProgram! } + public get Room () : typeof Room { return this.wechatifiedRoom! } + public get RoomInvitation () : typeof RoomInvitation { return this.wechatifiedRoomInvitation! } + public get Tag () : typeof Tag { return this.wechatifiedTag! } + public get UrlLink () : typeof UrlLink { return this.wechatifiedUrlLink! } /** * Get the global instance of Wechaty @@ -489,18 +305,18 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { * https://github.com/Microsoft/TypeScript/issues/19197 */ // TODO: make Message & Room constructor private??? - this.Contact = cloneClass(Contact) - this.ContactSelf = cloneClass(ContactSelf) - this.Friendship = cloneClass(Friendship) - this.Image = cloneClass(Image) - this.Message = cloneClass(Message) - this.Room = cloneClass(Room) - this.RoomInvitation = cloneClass(RoomInvitation) - this.Tag = cloneClass(Tag) + // this.Contact = cloneClass(Contact) + // this.ContactSelf = cloneClass(ContactSelf) + // this.Friendship = cloneClass(Friendship) + // this.Image = cloneClass(Image) + // this.Message = cloneClass(Message) + // this.Room = cloneClass(Room) + // this.RoomInvitation = cloneClass(RoomInvitation) + // this.Tag = cloneClass(Tag) // No need to set puppet/wechaty, so do not clone - this.UrlLink = UrlLink - this.MiniProgram = MiniProgram + // this.UrlLink = UrlLink + // this.MiniProgram = MiniProgram this.installGlobalPlugin() } @@ -765,29 +581,23 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { protected initPuppetAccessory (puppet: Puppet) { log.verbose('Wechaty', 'initAccessory(%s)', puppet) - /** - * 1. Set Wechaty - */ - this.Contact.wechaty = this - this.ContactSelf.wechaty = this - this.Friendship.wechaty = this - this.Image.wechaty = this - this.Message.wechaty = this - this.Room.wechaty = this - this.RoomInvitation.wechaty = this - this.Tag.wechaty = this + if (this.wechatifiedContactSelf) { + throw new Error('can not be initialized twice!') + } /** - * 2. Set Puppet + * 1. Setup Wechaty User Classes */ - this.Contact.puppet = puppet - this.ContactSelf.puppet = puppet - this.Friendship.puppet = puppet - this.Image.puppet = puppet - this.Message.puppet = puppet - this.Room.puppet = puppet - this.RoomInvitation.puppet = puppet - this.Tag.puppet = puppet + this.wechatifiedContact = wechatifyContact(this) + this.wechatifiedContactSelf = wechatifyContactSelf(this) + this.wechatifiedFriendship = wechatifyFriendship(this) + this.wechatifiedImage = wechatifyImage(this) + this.wechatifiedMessage = wechatifyMessage(this) + this.wechatifiedMiniProgram = wechatifyMiniProgram(this) + this.wechatifiedRoom = wechatifyRoom(this) + this.wechatifiedRoomInvitation = wechatifyRoomInvitation(this) + this.wechatifiedTag = wechatifyTag(this) + this.wechatifiedUrlLink = wechatifyUrlLink(this) this.puppet = puppet From d2174f34113bebc8e509f36e4b9f217f4ca9e277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 27 Jul 2020 02:21:58 +0800 Subject: [PATCH 355/598] Add typed-emitter to Contact & Room (#2014) --- src/events/contact-events.ts | 20 +++++ src/events/mod.ts | 10 +++ src/events/room-events.ts | 116 +++++++++++++++++++++++++++++ src/{ => events}/wechaty-events.ts | 8 +- src/user/contact.ts | 12 +-- src/user/room.ts | 62 +++++++-------- src/wechaty.ts | 2 +- 7 files changed, 183 insertions(+), 47 deletions(-) create mode 100644 src/events/contact-events.ts create mode 100644 src/events/mod.ts create mode 100644 src/events/room-events.ts rename src/{ => events}/wechaty-events.ts (98%) diff --git a/src/events/contact-events.ts b/src/events/contact-events.ts new file mode 100644 index 000000000..6fd8367a6 --- /dev/null +++ b/src/events/contact-events.ts @@ -0,0 +1,20 @@ +import { EventEmitter } from 'events' +import TypedEventEmitter from 'typed-emitter' + +import { + Contact, + Friendship, + Message, +} from '../user/mod' + +export type ContactMessageEventListener = (this: Contact, message: Message, date?: Date) => void +export type ContactFriendshipEventListener = (friendship: Friendship) => void + +interface ContactEvents { + friendship : ContactFriendshipEventListener, + message : ContactMessageEventListener, +} + +export const ContactEventEmitter = EventEmitter as new () => TypedEventEmitter< + ContactEvents +> diff --git a/src/events/mod.ts b/src/events/mod.ts new file mode 100644 index 000000000..1d330724a --- /dev/null +++ b/src/events/mod.ts @@ -0,0 +1,10 @@ +export { + WechatyEventEmitter, +} from './wechaty-events' +export { + RoomEventEmitter, +} from './room-events' + +export { + ContactEventEmitter, +} from './contact-events' diff --git a/src/events/room-events.ts b/src/events/room-events.ts new file mode 100644 index 000000000..287b28aaa --- /dev/null +++ b/src/events/room-events.ts @@ -0,0 +1,116 @@ +import { EventEmitter } from 'events' +import TypedEventEmitter from 'typed-emitter' + +import { + Contact, + Message, + Room, + RoomInvitation, +} from '../user/mod' + +export const ROOM_EVENT_DICT = { + invite : 'tbw', + join : 'tbw', + leave : 'tbw', + message : 'message that received in this room', + topic : 'tbw', +} +export type RoomEventName = keyof typeof ROOM_EVENT_DICT + +/** + * @desc Room Class Event Type + * @typedef RoomEventName + * @property {string} join - Emit when anyone join any room. + * @property {string} topic - Get topic event, emitted when someone change room topic. + * @property {string} leave - Emit when anyone leave the room.
+ * If someone leaves the room by themselves, WeChat will not notice other people in the room, so the bot will never get the "leave" event. + */ + +/** + * @desc Room Class Event Function + * @typedef RoomEventFunction + * @property {Function} room-join - (this: Room, inviteeList: Contact[] , inviter: Contact) => void + * @property {Function} room-topic - (this: Room, topic: string, oldTopic: string, changer: Contact) => void + * @property {Function} room-leave - (this: Room, leaver: Contact) => void + */ + +/** + * @listens Room + * @param {RoomEventName} event - Emit WechatyEvent + * @param {RoomEventFunction} listener - Depends on the WechatyEvent + * @return {this} - this for chain + * + * @example Event:join + * const bot = new Wechaty() + * await bot.start() + * // after logged in... + * const room = await bot.Room.find({topic: 'topic of your room'}) // change `event-room` to any room topic in your WeChat + * if (room) { + * room.on('join', (room, inviteeList, inviter) => { + * const nameList = inviteeList.map(c => c.name()).join(',') + * console.log(`Room got new member ${nameList}, invited by ${inviter}`) + * }) + * } + * + * @example Event:leave + * const bot = new Wechaty() + * await bot.start() + * // after logged in... + * const room = await bot.Room.find({topic: 'topic of your room'}) // change `event-room` to any room topic in your WeChat + * if (room) { + * room.on('leave', (room, leaverList) => { + * const nameList = leaverList.map(c => c.name()).join(',') + * console.log(`Room lost member ${nameList}`) + * }) + * } + * + * @example Event:message + * const bot = new Wechaty() + * await bot.start() + * // after logged in... + * const room = await bot.Room.find({topic: 'topic of your room'}) // change `event-room` to any room topic in your WeChat + * if (room) { + * room.on('message', (message) => { + * console.log(`Room received new message: ${message}`) + * }) + * } + * + * @example Event:topic + * const bot = new Wechaty() + * await bot.start() + * // after logged in... + * const room = await bot.Room.find({topic: 'topic of your room'}) // change `event-room` to any room topic in your WeChat + * if (room) { + * room.on('topic', (room, topic, oldTopic, changer) => { + * console.log(`Room topic changed from ${oldTopic} to ${topic} by ${changer.name()}`) + * }) + * } + * + * @example Event:invite + * const bot = new Wechaty() + * await bot.start() + * // after logged in... + * const room = await bot.Room.find({topic: 'topic of your room'}) // change `event-room` to any room topic in your WeChat + * if (room) { + * room.on('invite', roomInvitation => roomInvitation.accept()) + * } + * + */ + +export type RoomInviteEventListener = (this: Room, inviter: Contact, invitation: RoomInvitation) => void +export type RoomJoinEventListener = (this: Room, inviteeList: Contact[], inviter: Contact, date?: Date) => void +export type RoomLeaveEventListener = (this: Room, leaverList: Contact[], remover?: Contact, date?: Date) => void +export type RoomMessageEventListener = (this: Room, message: Message, date?: Date) => void +export type RoomTopicEventListener = (this: Room, topic: string, oldTopic: string, changer: Contact, date?: Date) => void + +interface RoomEvents { + invite : RoomInviteEventListener + join : RoomJoinEventListener, + leave : RoomLeaveEventListener, + message : RoomMessageEventListener, + topic : RoomTopicEventListener, +} + +export const RoomEventEmitter = EventEmitter as new () => TypedEventEmitter< + RoomEvents +> diff --git a/src/wechaty-events.ts b/src/events/wechaty-events.ts similarity index 98% rename from src/wechaty-events.ts rename to src/events/wechaty-events.ts index 2c5e5c2cd..56b117d4d 100644 --- a/src/wechaty-events.ts +++ b/src/events/wechaty-events.ts @@ -14,9 +14,9 @@ import { RoomInvitation, Contact, Message, -} from './user/mod' +} from '../user/mod' -export const WECHATY_EVENT_DICT = { +const WECHATY_EVENT_DICT = { ...CHAT_EVENT_DICT, dong : 'Should be emitted after we call `Wechaty.ding()`', error : "Will be emitted when there's an Error occurred.", @@ -200,7 +200,7 @@ export type WechatyStartStopEventListener = () => void * console.error(error) * }) */ -interface Events { +interface WechatyEvents { dong : WechatyDongEventListener error : WechatyErrorEventListener friendship : WechatyFriendshipEventListener @@ -219,5 +219,5 @@ interface Events { } export const WechatyEventEmitter = EventEmitter as new () => TypedEventEmitter< - Events + WechatyEvents > diff --git a/src/user/contact.ts b/src/user/contact.ts index 6bea793a2..df1e35b25 100644 --- a/src/user/contact.ts +++ b/src/user/contact.ts @@ -17,8 +17,6 @@ * limitations under the License. * */ -import { EventEmitter } from 'events' - import { instanceToClass } from 'clone-class' import { @@ -41,10 +39,12 @@ import { Sayable, } from '../types' -import { UrlLink } from './url-link' +import { Message } from './message' import { MiniProgram } from './mini-program' -import { Tag } from './tag' -import { Message } from './message' +import { Tag } from './tag' +import { UrlLink } from './url-link' + +import { ContactEventEmitter } from '../events/contact-events' export const POOL = Symbol('pool') @@ -55,7 +55,7 @@ export const POOL = Symbol('pool') * @property {string} id - Get Contact id. * This function is depending on the Puppet Implementation, see [puppet-compatible-table](https://github.com/wechaty/wechaty/wiki/Puppet#3-puppet-compatible-table) */ -class Contact extends EventEmitter implements Sayable { +class Contact extends ContactEventEmitter implements Sayable { static get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } diff --git a/src/user/room.ts b/src/user/room.ts index 6409005b4..7c09267ba 100644 --- a/src/user/room.ts +++ b/src/user/room.ts @@ -17,8 +17,6 @@ * limitations under the License. * */ -import { EventEmitter } from 'events' - import { instanceToClass } from 'clone-class' import { Wechaty } from '../wechaty' @@ -41,7 +39,6 @@ import { import { Contact } from './contact' import { MiniProgram } from './mini-program' import { Message } from './message' -import { RoomInvitation } from './room-invitation' import { UrlLink } from './url-link' import { @@ -50,14 +47,7 @@ import { RoomQueryFilter, } from 'wechaty-puppet' -export const ROOM_EVENT_DICT = { - invite: 'tbw', - join: 'tbw', - leave: 'tbw', - message: 'message that received in this room', - topic: 'tbw', -} -export type RoomEventName = keyof typeof ROOM_EVENT_DICT +import { RoomEventEmitter } from '../events/room-events' /** * All WeChat rooms(groups) will be encapsulated as a Room. @@ -65,7 +55,7 @@ export type RoomEventName = keyof typeof ROOM_EVENT_DICT * [Examples/Room-Bot]{@link https://github.com/wechaty/wechaty/blob/1523c5e02be46ebe2cc172a744b2fbe53351540e/examples/room-bot.ts} * */ -class Room extends EventEmitter implements Sayable { +class Room extends RoomEventEmitter implements Sayable { static get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } get wechaty (): Wechaty { throw new Error('This class can not be used directory. See: https://github.com/wechaty/wechaty/issues/2027') } @@ -658,26 +648,26 @@ class Room extends EventEmitter implements Sayable { } } - public emit (event: 'invite', inviter: Contact, invitation: RoomInvitation) : boolean - public emit (event: 'leave', leaverList: Contact[], remover: Contact, date: Date) : boolean - public emit (event: 'message', message: Message) : boolean - public emit (event: 'join', inviteeList: Contact[], inviter: Contact, date: Date) : boolean - public emit (event: 'topic', topic: string, oldTopic: string, changer: Contact, date: Date) : boolean - public emit (event: never, ...args: never[]): never - - public emit ( - event: RoomEventName, - ...args: any[] - ): boolean { - return super.emit(event, ...args) - } + // public emit (event: 'invite', inviter: Contact, invitation: RoomInvitation) : boolean + // public emit (event: 'leave', leaverList: Contact[], remover: Contact, date: Date) : boolean + // public emit (event: 'message', message: Message) : boolean + // public emit (event: 'join', inviteeList: Contact[], inviter: Contact, date: Date) : boolean + // public emit (event: 'topic', topic: string, oldTopic: string, changer: Contact, date: Date) : boolean + // public emit (event: never, ...args: never[]): never + + // public emit ( + // event: RoomEventName, + // ...args: any[] + // ): boolean { + // return super.emit(event, ...args) + // } - public on (event: 'invite', listener: (this: Room, inviter: Contact, invitation: RoomInvitation) => void) : this - public on (event: 'leave', listener: (this: Room, leaverList: Contact[], remover?: Contact, date?: Date) => void) : this - public on (event: 'message', listener: (this: Room, message: Message, date?: Date) => void) : this - public on (event: 'join', listener: (this: Room, inviteeList: Contact[], inviter: Contact, date?: Date) => void) : this - public on (event: 'topic', listener: (this: Room, topic: string, oldTopic: string, changer: Contact, date?: Date) => void) : this - public on (event: never, ...args: never[]) : never + // public on (event: 'invite', listener: (this: Room, inviter: Contact, invitation: RoomInvitation) => void) : this + // public on (event: 'leave', listener: (this: Room, leaverList: Contact[], remover?: Contact, date?: Date) => void) : this + // public on (event: 'message', listener: (this: Room, message: Message, date?: Date) => void) : this + // public on (event: 'join', listener: (this: Room, inviteeList: Contact[], inviter: Contact, date?: Date) => void) : this + // public on (event: 'topic', listener: (this: Room, topic: string, oldTopic: string, changer: Contact, date?: Date) => void) : this + // public on (event: never, ...args: never[]) : never /** * @desc Room Class Event Type @@ -758,12 +748,12 @@ class Room extends EventEmitter implements Sayable { * } * */ - public on (event: RoomEventName, listener: (...args: any[]) => any): this { - log.verbose('Room', 'on(%s, %s)', event, typeof listener) + // public on (event: RoomEventName, listener: (...args: any[]) => any): this { + // log.verbose('Room', 'on(%s, %s)', event, typeof listener) - super.on(event, listener) // Room is `Sayable` - return this - } + // super.on(event, listener) // Room is `Sayable` + // return this + // } /** * Add contact in a room diff --git a/src/wechaty.ts b/src/wechaty.ts index 042a413c2..f8991595c 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -88,7 +88,7 @@ import { timestampToDate } from './helper-functions/pure/timestamp-to-date' import { WechatyEventEmitter, WechatyEventName, -} from './wechaty-events' +} from './events/wechaty-events' export interface WechatyOptions { memory? : MemoryCard, From 4a4d6e401e6489cf130a08bdad9fad5e78a4cf3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 27 Jul 2020 02:22:12 +0800 Subject: [PATCH 356/598] 0.45.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ec91df338..6e244158f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.45.0", + "version": "0.45.1", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From c60bf0b6073631a7c0bcf3432dac96b4d48d6736 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 27 Jul 2020 02:46:36 +0800 Subject: [PATCH 357/598] upgrade wechaty-puppet to v0.29 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6e244158f..8514ed91e 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "state-switch": "^0.9.9", "typed-emitter": "^1.2.0", "watchdog": "^0.8.17", - "wechaty-puppet": "^0.27.1", + "wechaty-puppet": "^0.29.2", "wechaty-puppet-hostie": "^0.9.1", "wechaty-puppet-mock": "^0.27.2", "ws": "^7.2.3" From 308a296562f41f6995d126f6fed18ac5f4a0016b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 27 Jul 2020 02:46:47 +0800 Subject: [PATCH 358/598] 0.45.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8514ed91e..29f98e49f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.45.1", + "version": "0.45.2", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 063e48be1af0d98c2d049418a5f82f5fa552560e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 28 Jul 2020 01:40:13 +0800 Subject: [PATCH 359/598] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ca0003b19..737908381 100644 --- a/README.md +++ b/README.md @@ -464,7 +464,7 @@ Support this project by becoming a sponsor. Your logo will show up here with a l - [Java Wechaty](https://github.com/wechaty/java-wechaty) - Java WeChaty Conversational AI Chatbot SDK for Wechat Individual Accounts (Java) - [Scala Wechaty](https://github.com/wechaty/scala-wechaty) - Scala WeChaty Conversational AI Chatbot SDK for WechatyIndividual Accounts (Scala) -## :raised_hands: Authors +## :raised_hands: Creators 1. [Huan](https://github.com/huan) [(李卓桓)](http://linkedin.com/in/zixia), Tencent TVP of Chatbot 1. [Rui (李佳芮)](https://pre-angel.com/peoples/jiarui-li/), Microsoft AI MVP From efcac7fd8ea42b8ffa980c5b33f6aac7ffeef10a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 28 Jul 2020 01:47:13 +0800 Subject: [PATCH 360/598] code clean --- package.json | 4 ++-- src/user/friendship.ts | 4 ++-- src/user/image.ts | 4 ++-- src/user/room-invitation.ts | 4 ++-- src/user/tag.ts | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 29f98e49f..cb8c789b3 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,6 @@ "watchdog": "^0.8.17", "wechaty-puppet": "^0.29.2", "wechaty-puppet-hostie": "^0.9.1", - "wechaty-puppet-mock": "^0.27.2", "ws": "^7.2.3" }, "devDependencies": { @@ -136,7 +135,8 @@ "shx": "^0.3.2", "sloc": "^0.2.1", "tstest": "^0.4.10", - "typedoc": "^0.16.11" + "typedoc": "^0.16.11", + "wechaty-puppet-mock": "^0.27.2" }, "files_comment__whitelist_npm_publish": "http://stackoverflow.com/a/8617868/1123955", "files": [ diff --git a/src/user/friendship.ts b/src/user/friendship.ts index 17817676d..fb28fd6c9 100644 --- a/src/user/friendship.ts +++ b/src/user/friendship.ts @@ -172,11 +172,11 @@ class Friendship extends EventEmitter implements Acceptable { const MyClass = instanceToClass(this, Friendship) if (MyClass === Friendship) { - throw new Error('Friendship class can not be instanciated directly! See: https://github.com/wechaty/wechaty/issues/1217') + throw new Error('Friendship class can not be instantiated directly! See: https://github.com/wechaty/wechaty/issues/1217') } if (!this.wechaty.puppet) { - throw new Error('Friendship class can not be instanciated without a puppet!') + throw new Error('Friendship class can not be instantiated without a puppet!') } } diff --git a/src/user/image.ts b/src/user/image.ts index 95ef5d2f6..089127acd 100644 --- a/src/user/image.ts +++ b/src/user/image.ts @@ -45,11 +45,11 @@ class Image { const MyClass = instanceToClass(this, Image) if (MyClass === Image) { - throw new Error('Image class can not be instanciated directly! See: https://github.com/wechaty/wechaty/issues/1217') + throw new Error('Image class can not be instantiated directly! See: https://github.com/wechaty/wechaty/issues/1217') } if (!this.wechaty.puppet) { - throw new Error('Image class can not be instanciated without a puppet!') + throw new Error('Image class can not be instantiated without a puppet!') } } diff --git a/src/user/room-invitation.ts b/src/user/room-invitation.ts index db96062a0..e4e3e221b 100644 --- a/src/user/room-invitation.ts +++ b/src/user/room-invitation.ts @@ -69,11 +69,11 @@ class RoomInvitation implements Acceptable { const MyClass = instanceToClass(this, RoomInvitation) if (MyClass === RoomInvitation) { - throw new Error('RoomInvitation class can not be instanciated directly! See: https://github.com/wechaty/wechaty/issues/1217') + throw new Error('RoomInvitation class can not be instantiated directly! See: https://github.com/wechaty/wechaty/issues/1217') } if (!this.wechaty.puppet) { - throw new Error('RoomInvitation class can not be instanciated without a puppet!') + throw new Error('RoomInvitation class can not be instantiated without a puppet!') } } diff --git a/src/user/tag.ts b/src/user/tag.ts index e429b88fc..ed27df5d2 100644 --- a/src/user/tag.ts +++ b/src/user/tag.ts @@ -44,13 +44,13 @@ class Tag { if (MyClass === Tag) { throw new Error( - 'Tag class can not be instanciated directly!' + 'Tag class can not be instantiated directly!' + 'See: https://github.com/Chatie/wechaty/issues/1217', ) } if (!this.wechaty.puppet) { - throw new Error('Tag class can not be instanciated without a puppet!') + throw new Error('Tag class can not be instantiated without a puppet!') } } From 42eddc9b289b43a555755e9272c67bbb34149e9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 28 Jul 2020 01:47:27 +0800 Subject: [PATCH 361/598] 0.45.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cb8c789b3..2c43bc6e1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.45.2", + "version": "0.45.3", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From e6b2a50a81da2554df4c102ce0583a487014a92a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 28 Jul 2020 01:47:52 +0800 Subject: [PATCH 362/598] 0.45.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2c43bc6e1..904460b17 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.45.3", + "version": "0.45.4", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 5fa1604ba0c763fd774b09ccc02403652bda1bb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 30 Jul 2020 19:19:30 +0800 Subject: [PATCH 363/598] upgrade puppet to use async-map-like memory-card --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 904460b17..62b7fa003 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "state-switch": "^0.9.9", "typed-emitter": "^1.2.0", "watchdog": "^0.8.17", - "wechaty-puppet": "^0.29.2", + "wechaty-puppet": "^0.29.3", "wechaty-puppet-hostie": "^0.9.1", "ws": "^7.2.3" }, From b3daaec6e470633051b74e3150fa1cc6aee94993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 30 Jul 2020 19:32:54 +0800 Subject: [PATCH 364/598] upgrade puppet --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 62b7fa003..7680e8b28 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "state-switch": "^0.9.9", "typed-emitter": "^1.2.0", "watchdog": "^0.8.17", - "wechaty-puppet": "^0.29.3", + "wechaty-puppet": "^0.29.4", "wechaty-puppet-hostie": "^0.9.1", "ws": "^7.2.3" }, From 360e59b291630710e4247ff60c299d7aae8da22d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 30 Jul 2020 19:33:07 +0800 Subject: [PATCH 365/598] 0.45.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7680e8b28..23f3a1377 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.45.4", + "version": "0.45.5", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 37c0a6d9c75f710a4d76a514ff942af65457760d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 31 Jul 2020 17:42:49 +0000 Subject: [PATCH 366/598] build onbuild docker image --- Dockerfile.onbuild | 2 +- scripts/docker.sh | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Dockerfile.onbuild b/Dockerfile.onbuild index 6618c9e94..fd85c3cca 100644 --- a/Dockerfile.onbuild +++ b/Dockerfile.onbuild @@ -1,4 +1,4 @@ -FROM zixia/wechaty +FROM zixia/wechaty:next ONBUILD ARG NODE_ENV ONBUILD ENV NODE_ENV $NODE_ENV diff --git a/scripts/docker.sh b/scripts/docker.sh index 928586e70..89bd20e93 100755 --- a/scripts/docker.sh +++ b/scripts/docker.sh @@ -33,6 +33,12 @@ function deployNext () { echo "Deploying IMAGE=$IMAGE next" docker tag "${ARTIFACT_IMAGE}" "${IMAGE}:next" docker push "${IMAGE}:next" + + # onbuild for next + docker build -t "${IMAGE}:onbuild" - < Dockerfile.onbuild + + echo "Deploying IMAGE=$IMAGE onbuild" + docker push "${IMAGE}:onbuild" } function main () { @@ -75,6 +81,7 @@ function main () { if npx --package @chatie/semver semver-is-prod "$VERSION"; then deployLatest "$artifactImage" "$dockerImage" + deployOnBuild "$artifactImage" "$dockerImage" else deployNext "$artifactImage" "$dockerImage" fi From 1983e298f7f4693483ca6d4431a87727b990594a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 31 Jul 2020 17:43:39 +0000 Subject: [PATCH 367/598] 0.45.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 23f3a1377..3d0610f52 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.45.5", + "version": "0.45.6", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 7ad026bea61e88345b4d5f28819d8838a5c8bf14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 31 Jul 2020 18:11:31 +0000 Subject: [PATCH 368/598] test for onbuild home dir --- bin/entrypoint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/entrypoint.sh b/bin/entrypoint.sh index 4c01e1260..3ab44a548 100755 --- a/bin/entrypoint.sh +++ b/bin/entrypoint.sh @@ -308,7 +308,7 @@ function main() { test) # WECHATY_LOG=silent npm run test:unit - pushd /wechaty + pushd "$HOME" WECHATY_LOG=silent npm run test popd ;; From 48adf1f4b56f25b52cf79b9082aa562e55196032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 31 Jul 2020 18:11:50 +0000 Subject: [PATCH 369/598] 0.45.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3d0610f52..d3fef034a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.45.6", + "version": "0.45.7", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 3c62230909da3b1631eea7f8551893d38f2db287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 31 Jul 2020 18:23:40 +0000 Subject: [PATCH 370/598] deploy wechaty/onbuld --- scripts/docker.sh | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/scripts/docker.sh b/scripts/docker.sh index 89bd20e93..d2cf5c525 100755 --- a/scripts/docker.sh +++ b/scripts/docker.sh @@ -33,12 +33,31 @@ function deployNext () { echo "Deploying IMAGE=$IMAGE next" docker tag "${ARTIFACT_IMAGE}" "${IMAGE}:next" docker push "${IMAGE}:next" +} + +function deployOnbuild () { + ARTIFACT_IMAGE=$1 + TAG=$2 + + docker build -t "wechaty/onbuild:$TAG" - <<__DOCKERFILE_ONBUILD__ +FROM $ARTIFACT_IMAGE + +ONBUILD ARG NODE_ENV +ONBUILD ENV NODE_ENV $NODE_ENV + +ONBUILD WORKDIR /bot + +ONBUILD COPY package.json . +ONBUILD RUN jq 'del(.dependencies.wechaty)' package.json | sponge package.json \ + && npm install \ + && sudo rm -fr /tmp/* ~/.npm +ONBUILD COPY . . - # onbuild for next - docker build -t "${IMAGE}:onbuild" - < Dockerfile.onbuild +CMD [ "npm", "start" ] +__DOCKERFILE_ONBUILD__ - echo "Deploying IMAGE=$IMAGE onbuild" - docker push "${IMAGE}:onbuild" + echo "Deploying wechaty/onbuild:$TAG" + docker push "wechaty/onbuild:$TAG" } function main () { @@ -81,9 +100,10 @@ function main () { if npx --package @chatie/semver semver-is-prod "$VERSION"; then deployLatest "$artifactImage" "$dockerImage" - deployOnBuild "$artifactImage" "$dockerImage" + deployOnbuild "$artifactImage" latest else deployNext "$artifactImage" "$dockerImage" + deployOnbuild "$artifactImage" next fi ;; From 4a086c8e2ea1ac810d9a22e57f1e7e8c3b613015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 31 Jul 2020 18:29:37 +0000 Subject: [PATCH 371/598] fix test for both wechaty & /bot --- bin/entrypoint.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bin/entrypoint.sh b/bin/entrypoint.sh index 3ab44a548..0ffd0deb7 100755 --- a/bin/entrypoint.sh +++ b/bin/entrypoint.sh @@ -308,7 +308,11 @@ function main() { test) # WECHATY_LOG=silent npm run test:unit - pushd "$HOME" + if [ -f "$HOME"/package.json ]; then + pushd "$HOME" + else + pushd /wechaty + fi WECHATY_LOG=silent npm run test popd ;; From 63fa94d69097b5545b6757835f8d2ba64998de3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 31 Jul 2020 18:29:56 +0000 Subject: [PATCH 372/598] 0.45.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d3fef034a..ecca1faaa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.45.7", + "version": "0.45.8", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 26b9d6ed181d164a113974d3988e90203ce38922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 31 Jul 2020 18:32:06 +0000 Subject: [PATCH 373/598] publish to wechaty/wechatyh --- scripts/docker.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/docker.sh b/scripts/docker.sh index d2cf5c525..b5eb83d16 100755 --- a/scripts/docker.sh +++ b/scripts/docker.sh @@ -61,8 +61,8 @@ __DOCKERFILE_ONBUILD__ } function main () { - artifactImage='wechaty:test' - dockerImage='zixia/wechaty' + artifactImage='wechaty:dev' + dockerImage='wechaty/wechaty' # Shellcheck - https://github.com/koalaman/shellcheck/wiki/SC2086 options=('--rm') From 6928f22df2c2960fa8dfc317edc986d595c96dea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 31 Jul 2020 18:33:04 +0000 Subject: [PATCH 374/598] 0.45.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ecca1faaa..01c1b4c38 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.45.8", + "version": "0.45.9", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 8cf79697829879d8f517080567ddd2f9984b8202 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 31 Jul 2020 18:39:50 +0000 Subject: [PATCH 375/598] build with onbuld --- scripts/docker.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/docker.sh b/scripts/docker.sh index b5eb83d16..610c53dc7 100755 --- a/scripts/docker.sh +++ b/scripts/docker.sh @@ -53,6 +53,7 @@ ONBUILD RUN jq 'del(.dependencies.wechaty)' package.json | sponge package.json \ && sudo rm -fr /tmp/* ~/.npm ONBUILD COPY . . +ONBULD npm run build --if-present CMD [ "npm", "start" ] __DOCKERFILE_ONBUILD__ From e18832065c3b2262f9d4ebbdf4e6a5b1f0727068 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 31 Jul 2020 18:43:38 +0000 Subject: [PATCH 376/598] 0.45.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 01c1b4c38..9aa6a916e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.45.9", + "version": "0.45.10", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From cc4ad155b00dc4346e18629633325aa35f1426ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 31 Jul 2020 18:53:44 +0000 Subject: [PATCH 377/598] rename zixia/wechaty -> wechaty/wechaty --- Dockerfile | 6 +++--- Dockerfile.alpine | 6 +++--- Dockerfile.onbuild | 2 +- README.md | 12 ++++++------ scripts/docker.sh | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Dockerfile b/Dockerfile index 124d8c79d..84350015f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -103,8 +103,8 @@ LABEL \ org.label-schema.vendor="Chatie" \ org.label-schema.vcs-ref="$SOURCE_COMMIT" \ org.label-schema.vcs-url="https://github.com/wechaty/wechaty" \ - org.label-schema.docker.cmd="docker run -ti --rm zixia/wechaty " \ - org.label-schema.docker.cmd.test="docker run -ti --rm zixia/wechaty test" \ - org.label-schema.docker.cmd.help="docker run -ti --rm zixia/wechaty help" \ + org.label-schema.docker.cmd="docker run -ti --rm wechaty/wechaty " \ + org.label-schema.docker.cmd.test="docker run -ti --rm wechaty/wechaty test" \ + org.label-schema.docker.cmd.help="docker run -ti --rm wechaty/wechaty help" \ org.label-schema.docker.params="WECHATY_TOKEN=token token from https://www.chatie.io, WECHATY_LOG=verbose Set Verbose Log, TZ='Asia/Shanghai' TimeZone" diff --git a/Dockerfile.alpine b/Dockerfile.alpine index 133b7ce76..a6e7f0a10 100644 --- a/Dockerfile.alpine +++ b/Dockerfile.alpine @@ -77,9 +77,9 @@ LABEL org.label-schema.license="ISC" \ org.label-schema.vendor="AKA Mobi" \ org.label-schema.vcs-ref="$SOURCE_COMMIT" \ org.label-schema.vcs-url="https://github.com/wechaty/wechaty" \ - org.label-schema.docker.cmd="docker run -ti --rm zixia/wechaty " \ - org.label-schema.docker.cmd.test="docker run -ti --rm zixia/wechaty test" \ - org.label-schema.docker.cmd.help="docker run -ti --rm zixia/wechaty help" \ + org.label-schema.docker.cmd="docker run -ti --rm wechaty/wechaty " \ + org.label-schema.docker.cmd.test="docker run -ti --rm wechaty/wechaty test" \ + org.label-schema.docker.cmd.help="docker run -ti --rm wechaty/wechaty help" \ org.label-schema.docker.params="WECHATY_TOKEN=token token from https://www.chatie.io" #RUN npm test diff --git a/Dockerfile.onbuild b/Dockerfile.onbuild index fd85c3cca..f629f72e6 100644 --- a/Dockerfile.onbuild +++ b/Dockerfile.onbuild @@ -1,4 +1,4 @@ -FROM zixia/wechaty:next +FROM wechaty/wechaty:next ONBUILD ARG NODE_ENV ONBUILD ENV NODE_ENV $NODE_ENV diff --git a/README.md b/README.md index 737908381..2b467b335 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Downloads](https://img.shields.io/npm/dm/wechaty.svg?style=flat-square)](https://www.npmjs.com/package/wechaty) [![GitHub stars](https://img.shields.io/github/stars/wechaty/wechaty.svg?label=github%20stars)](https://github.com/wechaty/wechaty) -[![Docker Pulls](https://img.shields.io/docker/pulls/zixia/wechaty.svg?maxAge=2592000)](https://hub.docker.com/r/zixia/wechaty/) +[![Docker Pulls](https://img.shields.io/docker/pulls/wechaty/wechaty.svg?maxAge=2592000)](https://hub.docker.com/r/wechaty/wechaty/) [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-blue.svg)](https://www.typescriptlang.org/) [![Gitter](https://badges.gitter.im/Chatie/wechaty.svg)](https://gitter.im/Chatie/wechaty?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) @@ -15,7 +15,7 @@ Wechaty is a Conversational AI RPA Chatbot SDK for Wechat **Individual** Account :octocat: :beetle: :book: -:whale: +:whale: ## :yum: Voice of Developers @@ -113,8 +113,8 @@ node mybot.js ### 2. Docker -[![Docker Pulls](https://img.shields.io/docker/pulls/zixia/wechaty.svg?maxAge=2592000)](https://hub.docker.com/r/zixia/wechaty/) -[![Docker Layers](https://images.microbadger.com/badges/image/zixia/wechaty.svg)](https://microbadger.com/#/images/zixia/wechaty) +[![Docker Pulls](https://img.shields.io/docker/pulls/wechaty/wechaty.svg?maxAge=2592000)](https://hub.docker.com/r/wechaty/wechaty/) +[![Docker Layers](https://images.microbadger.com/badges/image/wechaty/wechaty.svg)](https://microbadger.com/#/images/wechaty/wechaty) - Wechaty Starter Repository for Docker - @@ -124,14 +124,14 @@ node mybot.js ```shell # for JavaScript -docker run -ti --rm --volume="$(pwd)":/bot zixia/wechaty mybot.js +docker run -ti --rm --volume="$(pwd)":/bot wechaty/wechaty mybot.js ``` 2.2. Run TypeScript ```shell # for TypeScript -docker run -ti --rm --volume="$(pwd)":/bot zixia/wechaty mybot.ts +docker run -ti --rm --volume="$(pwd)":/bot wechaty/wechaty mybot.ts ``` > Learn more about Wechaty Docker at [Wiki:Docker](https://github.com/Wechaty/wechaty/wiki/Docker). diff --git a/scripts/docker.sh b/scripts/docker.sh index 610c53dc7..3bebe76f6 100755 --- a/scripts/docker.sh +++ b/scripts/docker.sh @@ -43,7 +43,7 @@ function deployOnbuild () { FROM $ARTIFACT_IMAGE ONBUILD ARG NODE_ENV -ONBUILD ENV NODE_ENV $NODE_ENV +ONBUILD ENV NODE_ENV \$NODE_ENV ONBUILD WORKDIR /bot From 48b6c5f4e366144247d738b25a03adee5a7c528c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 31 Jul 2020 18:54:08 +0000 Subject: [PATCH 378/598] 0.45.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9aa6a916e..cf025ea1a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.45.10", + "version": "0.45.11", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From e7a40e53d62c85acd3056e68789ecbce97f97ca2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 31 Jul 2020 19:12:17 +0000 Subject: [PATCH 379/598] fix typo --- scripts/docker.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/docker.sh b/scripts/docker.sh index 3bebe76f6..d1d42ae95 100755 --- a/scripts/docker.sh +++ b/scripts/docker.sh @@ -53,7 +53,7 @@ ONBUILD RUN jq 'del(.dependencies.wechaty)' package.json | sponge package.json \ && sudo rm -fr /tmp/* ~/.npm ONBUILD COPY . . -ONBULD npm run build --if-present +ONBUILD npm run build --if-present CMD [ "npm", "start" ] __DOCKERFILE_ONBUILD__ From 7318c048f4ed40b8546a720351a191bb5336c17b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 31 Jul 2020 19:12:38 +0000 Subject: [PATCH 380/598] 0.45.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cf025ea1a..529b09553 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.45.11", + "version": "0.45.12", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From f63d7fffbdcc904310df62b9a1c4319b4b28672c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 31 Jul 2020 19:38:48 +0000 Subject: [PATCH 381/598] fix onbuild npm run --- scripts/docker.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/docker.sh b/scripts/docker.sh index d1d42ae95..c868edebb 100755 --- a/scripts/docker.sh +++ b/scripts/docker.sh @@ -53,7 +53,7 @@ ONBUILD RUN jq 'del(.dependencies.wechaty)' package.json | sponge package.json \ && sudo rm -fr /tmp/* ~/.npm ONBUILD COPY . . -ONBUILD npm run build --if-present +ONBUILD RUN npm run build --if-present CMD [ "npm", "start" ] __DOCKERFILE_ONBUILD__ From 27b052231e06177d56b76cd46082f6956d98e1a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 31 Jul 2020 19:39:07 +0000 Subject: [PATCH 382/598] 0.45.13 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 529b09553..90e2ad77d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.45.12", + "version": "0.45.13", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 04fb3c9b0f1790671a1b891dd5f2467009f49a40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 1 Aug 2020 14:04:24 +0800 Subject: [PATCH 383/598] update official example --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2b467b335..69e352ec1 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ Wechaty.instance() // Global Instance This bot can log all messages to the console after login by scan. -You can find more examples from [Wiki](https://github.com/Wechaty/wechaty/wiki/Examples) and [Example Directory](https://github.com/Wechaty/wechaty/blob/master/examples/). +You can find Official Example at [examples/ding-dong-bot.ts](examples/ding-dong-bot.ts), and more from our [Example Directory](https://github.com/Wechaty/wechaty-getting-started/blob/master/examples/). ## :checkered_flag: Requirements From 5fc5998e992a84f13ea789ca2ff183f30a0a0d43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 1 Aug 2020 14:04:52 +0800 Subject: [PATCH 384/598] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 69e352ec1..1f48e2158 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ Wechaty.instance() // Global Instance This bot can log all messages to the console after login by scan. -You can find Official Example at [examples/ding-dong-bot.ts](examples/ding-dong-bot.ts), and more from our [Example Directory](https://github.com/Wechaty/wechaty-getting-started/blob/master/examples/). +You can find Wechaty Official Example at [examples/ding-dong-bot.ts](examples/ding-dong-bot.ts), and more from our [Example Directory](https://github.com/Wechaty/wechaty-getting-started/blob/master/examples/). ## :checkered_flag: Requirements From 95c2fe87f7e839e64fde7171405c2cfbf354d5e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 1 Aug 2020 15:58:39 +0800 Subject: [PATCH 385/598] fix asscessory tests, and protect user class constructor from public to private --- src/user/contact.accessory.spec.ts | 68 ------------------------------ src/user/contact.spec.ts | 37 +++++++++++++++- src/user/contact.ts | 2 +- src/user/message.spec.ts | 0 src/user/message.ts | 2 +- src/user/room.spec.ts | 0 src/user/room.ts | 2 +- 7 files changed, 39 insertions(+), 72 deletions(-) delete mode 100644 src/user/contact.accessory.spec.ts mode change 100644 => 100755 src/user/contact.spec.ts mode change 100644 => 100755 src/user/message.spec.ts mode change 100644 => 100755 src/user/room.spec.ts diff --git a/src/user/contact.accessory.spec.ts b/src/user/contact.accessory.spec.ts deleted file mode 100644 index 6c877b171..000000000 --- a/src/user/contact.accessory.spec.ts +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env ts-node -/** - * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty - * - * @copyright 2016 Huan LI (李卓桓) , and - * Wechaty Contributors . - * - * 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. - * - */ -import test from 'blue-tape' -// import sinon from 'sinon' - -import { - cloneClass, -} from 'clone-class' - -import { - Contact as GlobalContact, -} from './contact' - -const Contact = cloneClass(GlobalContact) - -test('Should not be able to instanciate directly', async t => { - const MyContact = cloneClass(Contact) - t.throws(() => { - const c = MyContact.load('xxx') - t.fail(c.name()) - }, 'should throw when `Contact.load()`') - - t.throws(() => { - const c = MyContact.load('xxx') - t.fail(c.name()) - }, 'should throw when `Contact.load()`') -}) - -test('Should not be able to instanciate through cloneClass without puppet', async t => { - const MyContact = cloneClass(Contact) - - t.throws(() => { - const c = MyContact.load('xxx') - t.fail(c.name()) - }, 'should throw when `MyContact.load()` without puppet') - - t.throws(() => { - const c = MyContact.load('xxx') - t.fail(c.name()) - }, 'should throw when `MyContact.load()` without puppet') - -}) - -test('should throw when instanciate the global class', async t => { - t.throws(() => { - const c = GlobalContact.load('xxx') - t.fail('should not run to here') - t.fail(c.toString()) - }, 'should throw when we instanciate a global class') -}) diff --git a/src/user/contact.spec.ts b/src/user/contact.spec.ts old mode 100644 new mode 100755 index a9af4b1c5..d44ce9915 --- a/src/user/contact.spec.ts +++ b/src/user/contact.spec.ts @@ -24,7 +24,9 @@ import sinon from 'sinon' import { ContactPayload } from 'wechaty-puppet' import { PuppetMock } from 'wechaty-puppet-mock' -import { Wechaty } from '../wechaty' +import { Wechaty } from '../wechaty' + +import { Contact } from './contact' test('findAll()', async t => { const EXPECTED_CONTACT_ID = 'test-id' @@ -52,3 +54,36 @@ test('findAll()', async t => { await wechaty.stop() }) + +test('Should not be able to instanciate directly', async t => { + t.throws(() => { + const c = Contact.load('xxx') + t.fail(c.name()) + }, 'should throw when `Contact.load()`') + + t.throws(() => { + const c = Contact.load('xxx') + t.fail(c.name()) + }, 'should throw when `Contact.load()`') +}) + +test('Should not be able to instanciate through cloneClass without puppet', async t => { + t.throws(() => { + const c = Contact.load('xxx') + t.fail(c.name()) + }, 'should throw when `MyContact.load()` without puppet') + + t.throws(() => { + const c = Contact.load('xxx') + t.fail(c.name()) + }, 'should throw when `MyContact.load()` without puppet') + +}) + +test('should throw when instanciate the global class', async t => { + t.throws(() => { + const c = Contact.load('xxx') + t.fail('should not run to here') + t.fail(c.toString()) + }, 'should throw when we instanciate a global class') +}) diff --git a/src/user/contact.ts b/src/user/contact.ts index df1e35b25..d3cb7c632 100644 --- a/src/user/contact.ts +++ b/src/user/contact.ts @@ -288,7 +288,7 @@ class Contact extends ContactEventEmitter implements Sayable { /** * @hideconstructor */ - constructor ( + protected constructor ( public readonly id: string, ) { super() diff --git a/src/user/message.spec.ts b/src/user/message.spec.ts old mode 100644 new mode 100755 diff --git a/src/user/message.ts b/src/user/message.ts index b86ba9370..457edf244 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -169,7 +169,7 @@ class Message extends EventEmitter implements Sayable { /** * @hideconstructor */ - constructor ( + protected constructor ( public readonly id: string, ) { super() diff --git a/src/user/room.spec.ts b/src/user/room.spec.ts old mode 100644 new mode 100755 diff --git a/src/user/room.ts b/src/user/room.ts index 7c09267ba..9019aae42 100644 --- a/src/user/room.ts +++ b/src/user/room.ts @@ -265,7 +265,7 @@ class Room extends RoomEventEmitter implements Sayable { * @property {string} id - Room id. * This function is depending on the Puppet Implementation, see [puppet-compatible-table](https://github.com/wechaty/wechaty/wiki/Puppet#3-puppet-compatible-table) */ - constructor ( + protected constructor ( public readonly id: string, ) { super() From 86073d5402d9ecc9279ef2720fc09c8332d849fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 1 Aug 2020 15:58:50 +0800 Subject: [PATCH 386/598] Increase MaxListener for Wechaty --- src/wechaty.ts | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/src/wechaty.ts b/src/wechaty.ts index f8991595c..1d6c36c82 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -297,26 +297,15 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { this.wechaty = this /** - * @ignore - * Clone Classes for this bot and attach the `puppet` to the Class + * Huan(202008): * - * https://stackoverflow.com/questions/36886082/abstract-constructor-type-in-typescript - * https://github.com/Microsoft/TypeScript/issues/5843#issuecomment-290972055 - * https://github.com/Microsoft/TypeScript/issues/19197 + * Set max listeners to 1K, so that we can add lots of listeners without the warning message. + * The listeners might be one of the following functionilities: + * 1. Plugins + * 2. Redux Observables + * 3. etc... */ - // TODO: make Message & Room constructor private??? - // this.Contact = cloneClass(Contact) - // this.ContactSelf = cloneClass(ContactSelf) - // this.Friendship = cloneClass(Friendship) - // this.Image = cloneClass(Image) - // this.Message = cloneClass(Message) - // this.Room = cloneClass(Room) - // this.RoomInvitation = cloneClass(RoomInvitation) - // this.Tag = cloneClass(Tag) - - // No need to set puppet/wechaty, so do not clone - // this.UrlLink = UrlLink - // this.MiniProgram = MiniProgram + super.setMaxListeners(1024) this.installGlobalPlugin() } From 33ef68dbb7f7ff139fee5f7abe1ca91ebb4e3b33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 1 Aug 2020 15:59:02 +0800 Subject: [PATCH 387/598] 0.45.14 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 90e2ad77d..999b67f00 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.45.13", + "version": "0.45.14", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From b597270e90a28ca38dcdae1a16ee24c5b1df915e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 1 Aug 2020 17:49:11 +0800 Subject: [PATCH 388/598] add plugin uninstaller logic --- src/mod.ts | 7 ++++-- src/plugin.spec.ts | 56 ++++++++++++++++++++++++++++++++++++++++++++++ src/plugin.ts | 19 ++++++++++++++++ src/wechaty.ts | 45 ++++++++++++++++++++++++++++--------- 4 files changed, 114 insertions(+), 13 deletions(-) create mode 100755 src/plugin.spec.ts create mode 100644 src/plugin.ts diff --git a/src/mod.ts b/src/mod.ts index cbcfc613a..d2ef41755 100644 --- a/src/mod.ts +++ b/src/mod.ts @@ -38,12 +38,15 @@ export { export { Wechaty, WechatyOptions, +} from './wechaty' +export { WechatyPlugin, -} from './wechaty' + WechatyPluginUninstaller, +} from './plugin' export { PuppetModuleName, -} from './puppet-config' +} from './puppet-config' export { Contact, diff --git a/src/plugin.spec.ts b/src/plugin.spec.ts new file mode 100755 index 000000000..ab5c4a216 --- /dev/null +++ b/src/plugin.spec.ts @@ -0,0 +1,56 @@ +#!/usr/bin/env ts-node + +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ +import test from 'blue-tape' +import sinon from 'sinon' + +import { PuppetMock } from 'wechaty-puppet-mock' + +import { + Wechaty, +} from './wechaty' +import { WechatyPlugin } from './plugin' + +test('Wechaty Plugin uninstaller should be called after wechaty.stop()', async t => { + const spyPluginInstall = sinon.spy() + const spyPluginUninstall = sinon.spy() + + const bot = new Wechaty({ puppet: new PuppetMock() }) + + const plugin: WechatyPlugin = (_bot: Wechaty) => { + spyPluginInstall() + return () => { + spyPluginUninstall() + } + } + + t.true(spyPluginInstall.notCalled, 'should be clean for install spy') + t.true(spyPluginUninstall.notCalled, 'should be clean for uninstall spy') + + bot.use(plugin) + t.true(spyPluginInstall.called, 'should called install spy after use()') + t.true(spyPluginUninstall.notCalled, 'should not call uninstall spy after use()') + + await bot.start() + await bot.stop() + + t.true(spyPluginUninstall.called, 'should called uninstall spy after stop()') +}) diff --git a/src/plugin.ts b/src/plugin.ts new file mode 100644 index 000000000..84b3122a6 --- /dev/null +++ b/src/plugin.ts @@ -0,0 +1,19 @@ +import { Wechaty } from './wechaty' + +export type WechatyPluginUninstaller = () => void + +export type WechatyPluginReturn = void | WechatyPluginUninstaller + +export interface WechatyPlugin { + (bot: Wechaty): WechatyPluginReturn +} + +function isWechatyPluginUninstaller ( + pluginReturn: WechatyPluginReturn, +): pluginReturn is WechatyPluginUninstaller { + return !!pluginReturn +} + +export { + isWechatyPluginUninstaller, +} diff --git a/src/wechaty.ts b/src/wechaty.ts index 1d6c36c82..3d9ca1045 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -20,8 +20,8 @@ import cuid from 'cuid' import os from 'os' -import { StateSwitch } from 'state-switch' - +import { StateSwitch } from 'state-switch' +import { instanceToClass } from 'clone-class' import { Puppet, @@ -88,7 +88,13 @@ import { timestampToDate } from './helper-functions/pure/timestamp-to-date' import { WechatyEventEmitter, WechatyEventName, -} from './events/wechaty-events' +} from './events/wechaty-events' + +import { + WechatyPlugin, + WechatyPluginUninstaller, + isWechatyPluginUninstaller, +} from './plugin' export interface WechatyOptions { memory? : MemoryCard, @@ -102,11 +108,6 @@ export interface WechatyOptions { ioToken? : string, // Io TOKEN } -type WechatyPluginUninstaller = () => void -export interface WechatyPlugin { - (bot: Wechaty): void | WechatyPluginUninstaller -} - const PUPPET_MEMORY_NAME = 'puppet' /** @@ -148,6 +149,8 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { private static globalPluginList: WechatyPlugin[] = [] + private pluginUninstallerList: WechatyPluginUninstaller[] + private memory?: MemoryCard private lifeTimer? : NodeJS.Timer @@ -307,6 +310,7 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { */ super.setMaxListeners(1024) + this.pluginUninstallerList = [] this.installGlobalPlugin() } @@ -356,13 +360,27 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { * */ public use (...plugins: (WechatyPlugin | WechatyPlugin[])[]) { - const pluginList = plugins.flat() - pluginList.forEach(plugin => plugin(this)) + const pluginList = plugins.flat() as WechatyPlugin[] + const uninstallerList = pluginList + .map(plugin => plugin(this)) + .filter(isWechatyPluginUninstaller) + + this.pluginUninstallerList.push( + ...uninstallerList, + ) return this } private installGlobalPlugin () { - (this.constructor as typeof Wechaty).globalPluginList.forEach(plugin => plugin(this)) + + const uninstallerList = instanceToClass(this, Wechaty) + .globalPluginList + .map(plugin => plugin(this)) + .filter(isWechatyPluginUninstaller) + + this.pluginUninstallerList.push( + ...uninstallerList, + ) } private async initPuppet (): Promise { @@ -710,6 +728,11 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { this.lifeTimer = undefined } + while (this.pluginUninstallerList.length > 0) { + const uninstaller = this.pluginUninstallerList.pop() + if (uninstaller) uninstaller() + } + try { await this.puppet.stop() } catch (e) { From 3c9cea4d10c65d0384ff7be47fd9ca1487c1e630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 1 Aug 2020 17:49:27 +0800 Subject: [PATCH 389/598] 0.45.15 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 999b67f00..b97d6efb8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.45.14", + "version": "0.45.15", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 3cc1fa2cbc0964cde32bf801db837f0ff313d0f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 1 Aug 2020 18:36:07 +0800 Subject: [PATCH 390/598] fix race condition for plugin uninstallation --- src/wechaty.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/wechaty.ts b/src/wechaty.ts index 3d9ca1045..4c90704c0 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -712,6 +712,15 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { this.version(), ) + /** + * Uninstall Plugins + * no matter the state is `ON` or `OFF`. + */ + while (this.pluginUninstallerList.length > 0) { + const uninstaller = this.pluginUninstallerList.pop() + if (uninstaller) uninstaller() + } + if (this.state.off()) { log.silly('Wechaty', 'stop() on an stopping/stopped instance') await this.state.ready('off') @@ -728,11 +737,6 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { this.lifeTimer = undefined } - while (this.pluginUninstallerList.length > 0) { - const uninstaller = this.pluginUninstallerList.pop() - if (uninstaller) uninstaller() - } - try { await this.puppet.stop() } catch (e) { From 2115a7b390f314605c6f4f8c849631e56a1734e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 1 Aug 2020 18:36:19 +0800 Subject: [PATCH 391/598] 0.45.16 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b97d6efb8..77035ecfe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.45.15", + "version": "0.45.16", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From e43082217ed00d2ab6518504d592c523378b61ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 2 Aug 2020 16:21:14 +0800 Subject: [PATCH 392/598] template clean --- .github/CODEOWNERS | 3 +- .github/ISSUE_TEMPLATE/wechaty-bug-report.md | 53 +++++++++++--------- .github/PULL_REQUEST_TEMPLATE.md | 26 ++-------- 3 files changed, 34 insertions(+), 48 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4f36e5892..6c7437403 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -2,5 +2,4 @@ # https://help.github.com/articles/about-codeowners/ # -/docs/ @lijiarui @hczhcz @TingYinHelen @ax4 -/examples/ @Gcaufy @hczhcz +/ @wechaty/contributors diff --git a/.github/ISSUE_TEMPLATE/wechaty-bug-report.md b/.github/ISSUE_TEMPLATE/wechaty-bug-report.md index ac6c29f49..d23cee694 100644 --- a/.github/ISSUE_TEMPLATE/wechaty-bug-report.md +++ b/.github/ISSUE_TEMPLATE/wechaty-bug-report.md @@ -1,64 +1,73 @@ --- name: Wechaty Bug Report about: Create a bug report for a bug you found in wechaty - --- -> Important:Please file the issue follow the template, or we won't help you to solve the problem. - +> Important:Please file the issue follow the template, or we won't be able to help you to solve the problem. ## 0. Report Issue Guide 1. Please run the following command and check whether the problem has been fixed: -``` -rm -rf package-lock.json -rm -rf node_modules -npm install -``` -2. Please search in [FAQ List](https://docs.chatie.io/faq) first, and make sure your problem has not been solved before. + ```sh + rm -rf package-lock.json + rm -rf node_modules + npm install + ``` + +2. Please search in [FAQ List](https://wechaty.js.org/faq) first, and make sure your problem has not been solved before. 3. Please search in the issue first, and make sure your problem had not been reported before ## 1. Versions -- What is your wechaty version? + +> What is your wechaty version? + Answer: -- Which puppet are you using for wechaty? (padchat/puppeteer/padpro/...) +> Which puppet are you using for wechaty? (hostie/puppeteer/padchat/...) + Answer: -- What is your wechaty-puppet-XXX(padchat/puppeteer/) version? +> What is your wechaty-puppet-XXX(padchat/puppeteer/) version? + Answer: -- What is your node version? (run `node --version`) +> What is your node version? (run `node --version`) + Answer: -- What os are you using +> What os are you using + Answer: ## 2. Describe the bug -Give a clear and concise description of what the bug is. + +> Give a clear and concise description of what the bug is. ## 3. To Reproduce -This part is very important: if you can not provide any reproduce steps, then the problem will be very hard to be recognized. +> This part is very important: if you can not provide any reproduce steps, then the problem will be very hard to be recognized. **[How to create a Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example)** Steps to reproduce the behavior: + 1. run '...' 2. ... 3. ... ## 4. Expected behavior -Give a clear and concise description of what you expected to happen. + +> Give a clear and concise description of what you expected to happen. ## 5. Actual behavior -If applicable, add screenshots to help explain your problem. But do not paste log screenshots here. +> If applicable, add screenshots to help explain your problem. But do not paste log screenshots here. ## 6. Full Output Logs -Set env `WECHATY_LOG=silly` in order to set log level to silly, then we can get the full log (If you dosen't set log env, log level is info as default, we cannot get the full log) + +> Set env `WECHATY_LOG=silly` in order to set log level to silly, then we can get the full log (If you dosen't set log env, log level is info as default, we cannot get the full log) **We need full log instead of log screenshot or log fragments!** @@ -70,14 +79,12 @@ Show Logs ```shell $ WECHATY_LOG=silly node yourbot.js -Question: Paste your FULL(DO NOT ONLY PROVIDE FRAGMENTS) log messages -Answer: +-> PASTE YOUR FULL(DO NOT ONLY PROVIDE FRAGMENTS) LOG MESSAGES HERE ``` ## 7. Additional context -Add any other context about the problem here. -[bug] +> Add any other context about the problem here. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 6782e18d8..6f04c72a3 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,32 +1,12 @@ -## I'm submitting a... - -``` -[ ] Bug Fix -[ ] Feature -[ ] Other (Refactoring, Added tests, Documentation, ...) -``` - ## Checklist - [ ] Commit Messages follow the [Conventional Commits](https://conventionalcommits.org/) pattern - A feature commit message is prefixed "feat:" - A bugfix commit message is prefixed "fix:" - [ ] Tests for the changes have been added - +- [ ] CI has been passed. (GitHub actions all turns green) +- [ ] SLA has been signed ## Description -_please describe the changes that you are making_ - -_for features, please describe how to use the new feature_ - -_please include a reference to an existing issue, if applicable_ - - -## Does this PR introduce a breaking change? - -``` -[ ] Yes -[ ] No -``` - +> please describe the changes that you are making, with the related issue number. From 6b48ceea027f160a472642ec487ccc91bba0c140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 2 Aug 2020 16:21:25 +0800 Subject: [PATCH 393/598] 0.45.17 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 77035ecfe..a26bc675f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.45.16", + "version": "0.45.17", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 5fa88a8f4964a9c72d5794b7dd97017f016d5c32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 3 Aug 2020 17:52:21 +0800 Subject: [PATCH 394/598] upgrade puppet --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index a26bc675f..c09c2f431 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", "engines": { - "node": ">= 12" + "node": ">= 12", + "wechaty-puppet": ">=0.30.3" }, "wechaty": { "DEFAULT_PORT": 8080, @@ -101,7 +102,7 @@ "state-switch": "^0.9.9", "typed-emitter": "^1.2.0", "watchdog": "^0.8.17", - "wechaty-puppet": "^0.29.4", + "wechaty-puppet": "^0.30.3", "wechaty-puppet-hostie": "^0.9.1", "ws": "^7.2.3" }, From 59c9131830413a8ef80b7159dc4c598fa776236b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 3 Aug 2020 17:52:32 +0800 Subject: [PATCH 395/598] 0.46.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c09c2f431..7edea8a29 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.45.17", + "version": "0.46.0", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 2320b5cbfa37c6cbfd6338e0021962a8c8874b1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 3 Aug 2020 18:01:58 +0800 Subject: [PATCH 396/598] 0.46.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7edea8a29..d0d7e13dd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.46.0", + "version": "0.46.1", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 5ab4e1873eb6dca02fe0cc0265c71780760c40a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 3 Aug 2020 18:35:50 +0800 Subject: [PATCH 397/598] add new puppet for official account --- src/puppet-config.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 4002d3f3b..e9be75c4f 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -39,9 +39,10 @@ export const PUPPET_DEPENDENCIES = { /** * Wechaty External Puppets */ - 'wechaty-puppet-padplus' : '^0.7.30', // https://www.npmjs.com/package/wechaty-puppet-padplus - 'wechaty-puppet-puppeteer' : '^0.23.1', // https://www.npmjs.com/package/wechaty-puppet-puppeteer - 'wechaty-puppet-wechat4u' : '^0.17.4', // https://www.npmjs.com/package/wechaty-puppet-wechat4u + 'wechaty-puppet-official-account' : '^0.2.2', // https://www.npmjs.com/package/wechaty-puppet-official-account + 'wechaty-puppet-padplus' : '^0.7.30', // https://www.npmjs.com/package/wechaty-puppet-padplus + 'wechaty-puppet-puppeteer' : '^0.23.1', // https://www.npmjs.com/package/wechaty-puppet-puppeteer + 'wechaty-puppet-wechat4u' : '^0.17.4', // https://www.npmjs.com/package/wechaty-puppet-wechat4u } export type PuppetModuleName = keyof typeof PUPPET_DEPENDENCIES From 62d88a5de85f059a3a9b042c7482c24e1cd41448 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 3 Aug 2020 18:36:02 +0800 Subject: [PATCH 398/598] 0.46.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d0d7e13dd..318eadd33 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.46.1", + "version": "0.46.2", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 445f5650f79ca52861217ed676d71d9515598f88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 6 Aug 2020 00:24:26 +0800 Subject: [PATCH 399/598] Wechaty is a Conversational SDK for Chatbot Makers --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1f48e2158..17abefdb6 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ ## :hearts: Connecting Chatbots -Wechaty is a Conversational AI RPA Chatbot SDK for Wechat **Individual** Account which can help you create a bot in 6 lines of [JavaScript](https://GitHub.com/Wechaty/wechaty), [Python](https://GitHub.com/Wechaty/python-wechaty/), [Go](https://GitHub.com/Wechaty/go-wechaty/), and [Java](https://GitHub.com/Wechaty/java-wechaty/), with cross-platform support including [Linux, Windows, MacOS](https://github.com/wechaty/wechaty/actions?query=workflow%3ANPM), and [Docker](https://github.com/wechaty/wechaty/actions?query=workflow%3ADocker). +Wechaty is a Conversational SDK for Chatbot Makers which can help you create a bot in 6 lines of [JavaScript](https://GitHub.com/Wechaty/wechaty), [Python](https://GitHub.com/Wechaty/python-wechaty/), [Go](https://GitHub.com/Wechaty/go-wechaty/), and [Java](https://GitHub.com/Wechaty/java-wechaty/), with cross-platform support including [Linux, Windows, MacOS](https://github.com/wechaty/wechaty/actions?query=workflow%3ANPM), and [Docker](https://github.com/wechaty/wechaty/actions?query=workflow%3ADocker). :octocat: :beetle: From b33934ee90f59589592d4feec9b9c02a6d726c8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 6 Aug 2020 01:07:57 +0800 Subject: [PATCH 400/598] fix bio --- README.md | 24 ++++++++++++++---------- package.json | 2 +- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 17abefdb6..a2e4df85c 100644 --- a/README.md +++ b/README.md @@ -453,16 +453,20 @@ Support this project by becoming a sponsor. Your logo will show up here with a l ## :point_down: Multi-language Wechaty -[![Wechaty in Python](https://img.shields.io/badge/Wechaty-Python-blue)](https://github.com/wechaty/python-wechaty) -[![Wechaty in Kotlin](https://img.shields.io/badge/Wechaty-Kotlin-orange)](https://github.com/wechaty/java-wechaty) -[![Wechaty in Go](https://img.shields.io/badge/Wechaty-Go-7de)](https://github.com/wechaty/go-wechaty) -[![Wechaty in Scala](https://img.shields.io/badge/Wechaty-Scala-890)](https://github.com/wechaty/scala-wechaty) - -- [Wechaty](https://github.com/wechaty/wechaty) - Conversatioanl AI Chatot SDK for Wechaty Individual Accounts (TypeScript) -- [Python Wechaty](https://github.com/wechaty/python-wechaty) - Python WeChaty Conversational AI Chatbot SDK for Wechat Individual Accounts (Python) -- [Go Wechaty](https://github.com/wechaty/go-wechaty) - Go WeChaty Conversational AI Chatbot SDK for Wechat Individual Accounts (Go) -- [Java Wechaty](https://github.com/wechaty/java-wechaty) - Java WeChaty Conversational AI Chatbot SDK for Wechat Individual Accounts (Java) -- [Scala Wechaty](https://github.com/wechaty/scala-wechaty) - Scala WeChaty Conversational AI Chatbot SDK for WechatyIndividual Accounts (Scala) +[![Python Wechaty](https://img.shields.io/badge/Wechaty-Python-blue)](https://github.com/wechaty/python-wechaty) +[![Go Wechaty](https://img.shields.io/badge/Wechaty-Go-7de)](https://github.com/wechaty/go-wechaty) +[![Java(Kotlin) Wechaty](https://img.shields.io/badge/Wechaty-Java-f80)](https://github.com/wechaty/java-wechaty) +[![Scala Wechaty](https://img.shields.io/badge/Wechaty-Scala-890)](https://github.com/wechaty/scala-wechaty) +[![PHP Wechaty](https://img.shields.io/badge/Wechaty-PHP-99c)](https://github.com/wechaty/php-wechaty) +[![.NET(C#) Wechatyin](https://img.shields.io/badge/Wechaty-.NET-629)](https://github.com/wechaty/dotnet-wechaty) + +- [Wechaty](https://github.com/wechaty/wechaty) - Conversatioanl SDK for Chatot Makers (TypeScript) +- [Python Wechaty](https://github.com/wechaty/python-wechaty) - Conversational SDK for Chatbot Makers written in Python +- [Go Wechaty](https://github.com/wechaty/go-wechaty) - Conversational SDK for Chatbot Makers written in Go +- [Java Wechaty](https://github.com/wechaty/java-wechaty) - Conversational SDK for Chatbot Makers written in Java(Kotlin) +- [Scala Wechaty](https://github.com/wechaty/scala-wechaty) - Conversational SDK for Chatbot Makers written in Scala +- [PHP Wechaty](https://github.com/wechaty/php-wechaty) - Conversational SDK for Chatbot Makers written in PHP +- [.Net(C#) Wechaty](https://github.com/wechaty/dotnet-wechaty) - Conversational SDK for Chatbot Makers written in .NET(C#) ## :raised_hands: Creators diff --git a/package.json b/package.json index 318eadd33..0cc0b9a22 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wechaty", "version": "0.46.2", - "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", + "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", "engines": { From d75ce36ba03f71b0b19ba3fece1d040a723623fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 6 Aug 2020 01:08:09 +0800 Subject: [PATCH 401/598] 0.46.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0cc0b9a22..e7c3c4ebc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.46.2", + "version": "0.46.3", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From be243b47b013f22850ac7c4e7ffbd542d1458a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 6 Aug 2020 10:56:19 +0800 Subject: [PATCH 402/598] clean log message --- src/wechaty.spec.ts | 8 ++++---- src/wechaty.ts | 22 +++++++++++----------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/wechaty.spec.ts b/src/wechaty.spec.ts index 757c01029..8367dc1f5 100755 --- a/src/wechaty.spec.ts +++ b/src/wechaty.spec.ts @@ -45,8 +45,8 @@ import { class WechatyTest extends Wechaty { - public initPuppetAccessoryTest (puppet: Puppet): void { - return this.initPuppetAccessory(puppet) + public wechatifyUserModulesTest (puppet: Puppet): void { + return this.wechatifyUserModules(puppet) } } @@ -227,8 +227,8 @@ test('initPuppetAccessory()', async t => { const wechatyTest = new WechatyTest() const puppet = new PuppetMock() - t.doesNotThrow(() => wechatyTest.initPuppetAccessoryTest(puppet), 'should not throw for the 1st time init') - t.throws(() => wechatyTest.initPuppetAccessoryTest(puppet), 'should throw for the 2nd time init') + t.doesNotThrow(() => wechatyTest.wechatifyUserModulesTest(puppet), 'should not throw for the 1st time init') + t.throws(() => wechatyTest.wechatifyUserModulesTest(puppet), 'should throw for the 2nd time init') }) // TODO: add test for event args diff --git a/src/wechaty.ts b/src/wechaty.ts index 4c90704c0..fec850be0 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -412,7 +412,15 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { puppetInstance.setMemory(puppetMemory) this.initPuppetEventBridge(puppetInstance) - this.initPuppetAccessory(puppetInstance) + this.wechatifyUserModules(puppetInstance) + + /** + * Private Event + * emit puppet when set + * + * Huan(202005) + */ + ;(this.emit as any)('puppet', puppetInstance) } protected initPuppetEventBridge (puppet: Puppet) { @@ -585,8 +593,8 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { } } - protected initPuppetAccessory (puppet: Puppet) { - log.verbose('Wechaty', 'initAccessory(%s)', puppet) + protected wechatifyUserModules (puppet: Puppet) { + log.verbose('Wechaty', 'wechatifyUserModules(%s)', puppet) if (this.wechatifiedContactSelf) { throw new Error('can not be initialized twice!') @@ -607,14 +615,6 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { this.wechatifiedUrlLink = wechatifyUrlLink(this) this.puppet = puppet - - /** - * Private Event - * emit puppet when set - * - * Huan(202005) - */ - ;(this.emit as any)('puppet', puppet) } /** From 3ac5a8339a16498efa79e97801504d111f0e4aa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 6 Aug 2020 10:56:32 +0800 Subject: [PATCH 403/598] 0.46.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e7c3c4ebc..fa371054a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.46.3", + "version": "0.46.4", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From bd18d73a5a0126de0500efb4cfc2faa3148e5bef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 8 Aug 2020 13:46:14 +0800 Subject: [PATCH 404/598] upgrade hostie --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 23f3a1377..7aee0f90f 100644 --- a/package.json +++ b/package.json @@ -102,7 +102,7 @@ "typed-emitter": "^1.2.0", "watchdog": "^0.8.17", "wechaty-puppet": "^0.29.4", - "wechaty-puppet-hostie": "^0.9.1", + "wechaty-puppet-hostie": "^0.9.11", "ws": "^7.2.3" }, "devDependencies": { From 7fabdb41d277641b603a9e29848d48274c406231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 8 Aug 2020 13:46:39 +0800 Subject: [PATCH 405/598] 0.45.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7aee0f90f..d0719e191 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.45.5", + "version": "0.45.6", "description": "Wechaty is a Bot SDK for Individual Account, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From febacb1658a652a1b79b5b56fe48d59818d97884 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 8 Aug 2020 13:49:25 +0800 Subject: [PATCH 406/598] 0.46.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index edc1ed56a..58f2f3561 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.46.4", + "version": "0.46.5", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 2f3f1f3beebb71e62733ad9a7c93c8587aef8b92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 8 Aug 2020 13:49:54 +0800 Subject: [PATCH 407/598] 0.47.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 58f2f3561..7f091fe64 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.46.5", + "version": "0.47.0", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 6a58de4c3f76f57e1aeec4724f74a64a82d4c69a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 8 Aug 2020 13:50:27 +0800 Subject: [PATCH 408/598] 0.47.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7f091fe64..5ff10ec44 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.0", + "version": "0.47.1", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From a21b38cf1904a5620a154b192ab9abdb48baab80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 8 Aug 2020 14:18:16 +0800 Subject: [PATCH 409/598] support onbuild:version --- scripts/docker.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/docker.sh b/scripts/docker.sh index c868edebb..d5340cc9b 100755 --- a/scripts/docker.sh +++ b/scripts/docker.sh @@ -98,6 +98,7 @@ function main () { version=$(npx pkg-jq -r .version) deployVersion "$artifactImage" "$dockerImage" "$version" + deployOnbuild "$artifactImage" "$version" if npx --package @chatie/semver semver-is-prod "$VERSION"; then deployLatest "$artifactImage" "$dockerImage" From d8d4b6b1493874e09be6b6401eae36b01c1d1504 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 8 Aug 2020 14:19:54 +0800 Subject: [PATCH 410/598] 0.47.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5ff10ec44..11597710b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.1", + "version": "0.47.2", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 6769651779feaf80dd184372c96c9c0e5e16995c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 8 Aug 2020 14:36:54 +0800 Subject: [PATCH 411/598] use artifact image name --- scripts/docker.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/docker.sh b/scripts/docker.sh index d5340cc9b..3de11fcdc 100755 --- a/scripts/docker.sh +++ b/scripts/docker.sh @@ -62,7 +62,7 @@ __DOCKERFILE_ONBUILD__ } function main () { - artifactImage='wechaty:dev' + artifactImage='wechaty:artifact' dockerImage='wechaty/wechaty' # Shellcheck - https://github.com/koalaman/shellcheck/wiki/SC2086 From 0fe3dff6bb70c4b99e0f408d630ba00877ee97af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 8 Aug 2020 14:37:10 +0800 Subject: [PATCH 412/598] 0.47.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 11597710b..aabfd2c90 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.2", + "version": "0.47.3", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 69c8f92487be65657690a61b3a824d2b20375193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 8 Aug 2020 14:43:36 +0800 Subject: [PATCH 413/598] clean version & tag --- scripts/docker.sh | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/scripts/docker.sh b/scripts/docker.sh index 3de11fcdc..f7b976205 100755 --- a/scripts/docker.sh +++ b/scripts/docker.sh @@ -5,12 +5,7 @@ set -eo pipefail function deployVersion () { ARTIFACT_IMAGE=$1 IMAGE=$2 - VERSION=$3 - - SEMVER_MAJOR=$(echo "$VERSION" | cut -d. -f1) - SEMVER_MINOR=$(echo "$VERSION" | cut -d. -f2) - - TAG="$SEMVER_MAJOR.$SEMVER_MINOR" + TAG=$3 echo "Deploying TAG=$TAG" docker tag "${ARTIFACT_IMAGE}" "${IMAGE}:${TAG}" @@ -96,11 +91,14 @@ function main () { deploy) version=$(npx pkg-jq -r .version) + majorVer=$(echo "$version" | cut -d. -f1) + minorVer=$(echo "$version" | cut -d. -f2) + tag="${majorVer}.${minorVer}" - deployVersion "$artifactImage" "$dockerImage" "$version" - deployOnbuild "$artifactImage" "$version" + deployVersion "$artifactImage" "$dockerImage" "$tag" + deployOnbuild "$artifactImage" "$tag" - if npx --package @chatie/semver semver-is-prod "$VERSION"; then + if npx --package @chatie/semver semver-is-prod "$version"; then deployLatest "$artifactImage" "$dockerImage" deployOnbuild "$artifactImage" latest else From bafa1538e6e6edacd624248d96fccb5df23d7ff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 8 Aug 2020 14:43:52 +0800 Subject: [PATCH 414/598] 0.47.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index aabfd2c90..0492f6e33 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.3", + "version": "0.47.4", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 21dd79302f400da45b118b1ec5b7b7c60ffa653e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 8 Aug 2020 15:05:04 +0800 Subject: [PATCH 415/598] 0.47.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0492f6e33..1d72e9b46 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.4", + "version": "0.47.5", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From c9095e222693ff188aa79a267bff6a5385d4deb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 8 Aug 2020 19:03:00 +0800 Subject: [PATCH 416/598] fix hostie start bug --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1d72e9b46..816830a4e 100644 --- a/package.json +++ b/package.json @@ -102,7 +102,7 @@ "state-switch": "^0.9.9", "typed-emitter": "^1.2.0", "watchdog": "^0.8.17", - "wechaty-puppet-hostie": "^0.9.11", + "wechaty-puppet-hostie": "^0.9.13", "wechaty-puppet": "^0.30.3", "ws": "^7.2.3" }, From eda2a07b96505c5d20ab44b28f85edf1b3e19f39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 8 Aug 2020 19:09:37 +0800 Subject: [PATCH 417/598] 0.47.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 816830a4e..16fa11938 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.5", + "version": "0.47.6", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From f4a6acbde8f7d0e288bc7b61d7c639b4e9bae2dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 9 Aug 2020 22:48:27 +0800 Subject: [PATCH 418/598] clean --- NOTICE | 4 ++-- README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/NOTICE b/NOTICE index e664fae43..4b8f8d666 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ -Wechaty, a Conversational AI RPA SDK for Chatbot -Copyright 2016 Huan (李卓桓) and Wechaty Contributors. +Wechaty is a Conversational SDK for Chatbot Makers. +Copyright 2016-now Huan (李卓桓) and Wechaty Community Contributors. This product includes software developed at The Wechaty Organization (https://github.com/wechaty). diff --git a/README.md b/README.md index a2e4df85c..3247328a3 100644 --- a/README.md +++ b/README.md @@ -477,6 +477,6 @@ Support this project by becoming a sponsor. Your logo will show up here with a l ## :email: Copyright & License -- Code & Docs © 2016 Huan, Rui, and Wechaty Contributors +- Code & Docs © 2016-now Huan, Rui, and Wechaty Community Contributors - Code released under the Apache-2.0 License - Docs released under Creative Commons From 752ef4c031d4484676c63ecccdc3ecc32e2d14c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 9 Aug 2020 22:48:39 +0800 Subject: [PATCH 419/598] 0.46.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fa371054a..14831543c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.46.4", + "version": "0.46.5", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 16587031bfe1005b628223520b9a0b90080db856 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 9 Aug 2020 22:49:36 +0800 Subject: [PATCH 420/598] 0.47.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 16fa11938..f1096c0fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.6", + "version": "0.47.7", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From d9c38af05047ada71e1d2435f538da9bd6c53293 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 10 Aug 2020 13:51:04 +0800 Subject: [PATCH 421/598] add svg logos --- docs/images/friday-qrcode.svg | 218 +++++++++++++++++++++++++++ docs/images/wechaty-banner-white.svg | 104 +++++++++++++ docs/images/wechaty-banner.svg | 104 +++++++++++++ 3 files changed, 426 insertions(+) create mode 100644 docs/images/friday-qrcode.svg create mode 100644 docs/images/wechaty-banner-white.svg create mode 100644 docs/images/wechaty-banner.svg diff --git a/docs/images/friday-qrcode.svg b/docs/images/friday-qrcode.svg new file mode 100644 index 000000000..4a8443a65 --- /dev/null +++ b/docs/images/friday-qrcode.svg @@ -0,0 +1,218 @@ + + + + +Created by potrace 1.16, written by Peter Selinger 2001-2019 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/images/wechaty-banner-white.svg b/docs/images/wechaty-banner-white.svg new file mode 100644 index 000000000..17425a8c2 --- /dev/null +++ b/docs/images/wechaty-banner-white.svg @@ -0,0 +1,104 @@ + + + + +Created by potrace 1.16, written by Peter Selinger 2001-2019 + + + + + + + + + + + + diff --git a/docs/images/wechaty-banner.svg b/docs/images/wechaty-banner.svg new file mode 100644 index 000000000..7cd1d77a6 --- /dev/null +++ b/docs/images/wechaty-banner.svg @@ -0,0 +1,104 @@ + + + + +Created by potrace 1.16, written by Peter Selinger 2001-2019 + + + + + + + + + + + + From c215c1a41b5063501f726ad3edaf43bda5f41fca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 10 Aug 2020 13:51:16 +0800 Subject: [PATCH 422/598] use wechaty.js.org host --- .vscode/settings.json | 1 + README.md | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index d3fc16364..5fa7ab956 100755 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -71,6 +71,7 @@ "typescript", ], "cSpell.words": [ + "Gitter", "Wechaty", "appid", "botie", diff --git a/README.md b/README.md index a2e4df85c..d10163569 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Wechaty [![NPM Version](https://img.shields.io/npm/v/wechaty?color=brightgreen)](https://www.npmjs.com/package/wechaty) [![NPM](https://github.com/wechaty/wechaty/workflows/NPM/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ANPM) [![Docker](https://github.com/wechaty/wechaty/workflows/Docker/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ADocker) -[![Wechaty](https://wechaty.github.io/wechaty/images/wechaty-logo-green-en.png)](https://github.com/wechaty/wechaty) +[![Wechaty](https://wechaty.js.org/img/wechaty-logo.svg)](https://github.com/wechaty/wechaty) [![Downloads](https://img.shields.io/npm/dm/wechaty.svg?style=flat-square)](https://www.npmjs.com/package/wechaty) [![GitHub stars](https://img.shields.io/github/stars/wechaty/wechaty.svg?label=github%20stars)](https://github.com/wechaty/wechaty) @@ -43,7 +43,7 @@ See more at [Wiki:Voice Of Developer](https://github.com/Wechaty/wechaty/wiki/Vo Wechaty is used in many ChatBot projects by thousands of developers. If you want to talk with other developers, just scan the following QR Code in WeChat with secret code _wechaty_, join our **Wechaty Developers' Home**. -![Wechaty Developers' Home](https://wechaty.github.io/wechaty/images/bot-qr-code.png) +![Wechaty Developers' Home](https://wechaty.js.org/img/friday-qrcode.svg) Scan now, because other Wechaty developers want to talk with you too! (secret code: _wechaty_) From 442b946bf0e29654a82e62bf4a05ee7b5b5a2336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 10 Aug 2020 13:51:29 +0800 Subject: [PATCH 423/598] 0.47.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 16fa11938..f1096c0fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.6", + "version": "0.47.7", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 7ae124d8195db31d5db4b3522b412000103e0d51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 10 Aug 2020 13:51:59 +0800 Subject: [PATCH 424/598] 0.47.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f1096c0fb..f37c98603 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.7", + "version": "0.47.8", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 0753b10c15f77bb289f5c438b38491088d5f0ef1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 10 Aug 2020 13:52:46 +0800 Subject: [PATCH 425/598] update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 702271067..c552b2df0 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ See more at [Wiki:Voice Of Developer](https://github.com/Wechaty/wechaty/wiki/Vo Wechaty is used in many ChatBot projects by thousands of developers. If you want to talk with other developers, just scan the following QR Code in WeChat with secret code _wechaty_, join our **Wechaty Developers' Home**. -![Wechaty Developers' Home](https://wechaty.js.org/img/friday-qrcode.svg) +![Wechaty Friday.BOT QR Code](https://wechaty.js.org/img/friday-qrcode.svg) Scan now, because other Wechaty developers want to talk with you too! (secret code: _wechaty_) From 29204a375e3073eee12a44c0c970334cf93c3c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 10 Aug 2020 13:52:59 +0800 Subject: [PATCH 426/598] 0.47.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f37c98603..c70187ab8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.8", + "version": "0.47.9", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From ab50765445f378b4a137e6b9d934b1f8fa0a88cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 14 Aug 2020 00:10:11 +0800 Subject: [PATCH 427/598] use docker for changelog --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c70187ab8..7c11f59d6 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "pack": "npm pack", "docs": "bash -x scripts/generate-docs.sh", "coverage": "nyc report --reporter=text-lcov | coveralls", - "changelog": "github_changelog_generator -u wechaty -p wechaty && sed -i'.bak' /greenkeeper/d CHANGELOG.md && sed -i'.bak' /Snyk/d CHANGELOG.md && sed -i'.bak' '/An in-range update of/d' CHANGELOG.md && ts-node scripts/sort-contributiveness.ts < CHANGELOG.md > CHANGELOG.new.md 2>/dev/null && cat CHANGELOG.md >> CHANGELOG.new.md && mv CHANGELOG.new.md CHANGELOG.md", + "changelog": "docker run -it --rm -e CHANGELOG_GITHUB_TOKEN -v \"$(pwd)\":/usr/local/src/your-app ferrarimarco/github-changelog-generator -u wechaty -p wechaty && sed -i'.bak' /greenkeeper/d CHANGELOG.md && sed -i'.bak' /Snyk/d CHANGELOG.md && sed -i'.bak' '/An in-range update of/d' CHANGELOG.md && ts-node scripts/sort-contributiveness.ts < CHANGELOG.md > CHANGELOG.new.md 2>/dev/null && cat CHANGELOG.md >> CHANGELOG.new.md && mv CHANGELOG.new.md CHANGELOG.md", "doctor": "npm run check-node-version && ts-node bin/doctor", "check-node-version": "check-node-version --node \">= 12\"", "lint": "npm run check-node-version && npm run lint:es && npm run lint:ts && npm run lint:sh && npm run lint:md", From 4265cb2e40a4b37ebf62c02f4ca19518ebf11455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 14 Aug 2020 00:10:28 +0800 Subject: [PATCH 428/598] 0.47.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7c11f59d6..10f176e86 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.9", + "version": "0.47.10", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 511792a32bc8b9802e75e9a49a11684121b32f4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 14 Aug 2020 00:19:48 +0800 Subject: [PATCH 429/598] update changelog --- CHANGELOG.md | 67 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18bb6650a..b97046b06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,40 +4,41 @@ ## WECHATY CONTRIBUTORS ### Active Contributors -1. @[lijiarui](https://github.com/lijiarui): [\#1876](https://github.com/wechaty/wechaty/pull/1876) [\#1875](https://github.com/wechaty/wechaty/pull/1875) [\#1859](https://github.com/wechaty/wechaty/pull/1859) [\#1702](https://github.com/wechaty/wechaty/pull/1702) [\#1700](https://github.com/wechaty/wechaty/pull/1700) [\#1692](https://github.com/wechaty/wechaty/pull/1692) [\#1633](https://github.com/wechaty/wechaty/pull/1633) [\#1631](https://github.com/wechaty/wechaty/pull/1631) [\#1615](https://github.com/wechaty/wechaty/pull/1615) [\#1614](https://github.com/wechaty/wechaty/pull/1614) [\#1533](https://github.com/wechaty/wechaty/pull/1533) [\#1514](https://github.com/wechaty/wechaty/pull/1514) [\#1510](https://github.com/wechaty/wechaty/pull/1510) [\#1502](https://github.com/wechaty/wechaty/pull/1502) [\#1498](https://github.com/wechaty/wechaty/pull/1498) [\#1497](https://github.com/wechaty/wechaty/pull/1497) [\#1486](https://github.com/wechaty/wechaty/pull/1486) [\#1482](https://github.com/wechaty/wechaty/pull/1482) [\#1481](https://github.com/wechaty/wechaty/pull/1481) [\#1477](https://github.com/wechaty/wechaty/pull/1477) [\#1408](https://github.com/wechaty/wechaty/pull/1408) [\#1407](https://github.com/wechaty/wechaty/pull/1407) [\#1405](https://github.com/wechaty/wechaty/pull/1405) [\#1402](https://github.com/wechaty/wechaty/pull/1402) [\#1375](https://github.com/wechaty/wechaty/pull/1375) [\#1374](https://github.com/wechaty/wechaty/pull/1374) [\#1373](https://github.com/wechaty/wechaty/pull/1373) [\#1352](https://github.com/wechaty/wechaty/pull/1352) [\#1351](https://github.com/wechaty/wechaty/pull/1351) [\#1348](https://github.com/wechaty/wechaty/pull/1348) [\#1347](https://github.com/wechaty/wechaty/pull/1347) [\#1344](https://github.com/wechaty/wechaty/pull/1344) [\#1341](https://github.com/wechaty/wechaty/pull/1341) [\#1338](https://github.com/wechaty/wechaty/pull/1338) [\#1333](https://github.com/wechaty/wechaty/pull/1333) [\#1331](https://github.com/wechaty/wechaty/pull/1331) [\#1325](https://github.com/wechaty/wechaty/pull/1325) [\#1116](https://github.com/wechaty/wechaty/pull/1116) [\#1086](https://github.com/wechaty/wechaty/pull/1086) [\#816](https://github.com/wechaty/wechaty/pull/816) [\#812](https://github.com/wechaty/wechaty/pull/812) [\#805](https://github.com/wechaty/wechaty/pull/805) [\#798](https://github.com/wechaty/wechaty/pull/798) [\#757](https://github.com/wechaty/wechaty/pull/757) [\#725](https://github.com/wechaty/wechaty/pull/725) [\#440](https://github.com/wechaty/wechaty/pull/440) [\#370](https://github.com/wechaty/wechaty/pull/370) [\#364](https://github.com/wechaty/wechaty/pull/364) [\#362](https://github.com/wechaty/wechaty/pull/362) [\#328](https://github.com/wechaty/wechaty/pull/328) [\#324](https://github.com/wechaty/wechaty/pull/324) [\#323](https://github.com/wechaty/wechaty/pull/323) [\#321](https://github.com/wechaty/wechaty/pull/321) [\#318](https://github.com/wechaty/wechaty/pull/318) [\#303](https://github.com/wechaty/wechaty/pull/303) [\#292](https://github.com/wechaty/wechaty/pull/292) [\#139](https://github.com/wechaty/wechaty/pull/139) [\#112](https://github.com/wechaty/wechaty/pull/112) [\#110](https://github.com/wechaty/wechaty/pull/110) [\#38](https://github.com/wechaty/wechaty/pull/38) -1. @[huan](https://github.com/huan): [\#1931](https://github.com/wechaty/wechaty/pull/1931) [\#1888](https://github.com/wechaty/wechaty/pull/1888) [\#1870](https://github.com/wechaty/wechaty/pull/1870) [\#1782](https://github.com/wechaty/wechaty/pull/1782) [\#1597](https://github.com/wechaty/wechaty/pull/1597) [\#1143](https://github.com/wechaty/wechaty/pull/1143) [\#1131](https://github.com/wechaty/wechaty/pull/1131) [\#1083](https://github.com/wechaty/wechaty/pull/1083) [\#1075](https://github.com/wechaty/wechaty/pull/1075) [\#1074](https://github.com/wechaty/wechaty/pull/1074) [\#1073](https://github.com/wechaty/wechaty/pull/1073) [\#1072](https://github.com/wechaty/wechaty/pull/1072) [\#1071](https://github.com/wechaty/wechaty/pull/1071) [\#860](https://github.com/wechaty/wechaty/pull/860) [\#854](https://github.com/wechaty/wechaty/pull/854) [\#841](https://github.com/wechaty/wechaty/pull/841) [\#831](https://github.com/wechaty/wechaty/pull/831) [\#810](https://github.com/wechaty/wechaty/pull/810) [\#469](https://github.com/wechaty/wechaty/pull/469) [\#462](https://github.com/wechaty/wechaty/pull/462) [\#455](https://github.com/wechaty/wechaty/pull/455) [\#449](https://github.com/wechaty/wechaty/pull/449) [\#396](https://github.com/wechaty/wechaty/pull/396) [\#351](https://github.com/wechaty/wechaty/pull/351) [\#317](https://github.com/wechaty/wechaty/pull/317) [\#316](https://github.com/wechaty/wechaty/pull/316) [\#315](https://github.com/wechaty/wechaty/pull/315) [\#314](https://github.com/wechaty/wechaty/pull/314) [\#313](https://github.com/wechaty/wechaty/pull/313) [\#312](https://github.com/wechaty/wechaty/pull/312) [\#311](https://github.com/wechaty/wechaty/pull/311) [\#168](https://github.com/wechaty/wechaty/pull/168) [\#158](https://github.com/wechaty/wechaty/pull/158) [\#149](https://github.com/wechaty/wechaty/pull/149) [\#146](https://github.com/wechaty/wechaty/pull/146) [\#143](https://github.com/wechaty/wechaty/pull/143) [\#142](https://github.com/wechaty/wechaty/pull/142) [\#141](https://github.com/wechaty/wechaty/pull/141) [\#25](https://github.com/wechaty/wechaty/pull/25) +1. @[lijiarui](https://github.com/lijiarui): [\#2001](https://github.com/wechaty/wechaty/pull/2001) [\#1998](https://github.com/wechaty/wechaty/pull/1998) [\#1876](https://github.com/wechaty/wechaty/pull/1876) [\#1875](https://github.com/wechaty/wechaty/pull/1875) [\#1859](https://github.com/wechaty/wechaty/pull/1859) [\#1702](https://github.com/wechaty/wechaty/pull/1702) [\#1700](https://github.com/wechaty/wechaty/pull/1700) [\#1692](https://github.com/wechaty/wechaty/pull/1692) [\#1633](https://github.com/wechaty/wechaty/pull/1633) [\#1631](https://github.com/wechaty/wechaty/pull/1631) [\#1615](https://github.com/wechaty/wechaty/pull/1615) [\#1614](https://github.com/wechaty/wechaty/pull/1614) [\#1533](https://github.com/wechaty/wechaty/pull/1533) [\#1514](https://github.com/wechaty/wechaty/pull/1514) [\#1510](https://github.com/wechaty/wechaty/pull/1510) [\#1502](https://github.com/wechaty/wechaty/pull/1502) [\#1498](https://github.com/wechaty/wechaty/pull/1498) [\#1497](https://github.com/wechaty/wechaty/pull/1497) [\#1486](https://github.com/wechaty/wechaty/pull/1486) [\#1482](https://github.com/wechaty/wechaty/pull/1482) [\#1481](https://github.com/wechaty/wechaty/pull/1481) [\#1477](https://github.com/wechaty/wechaty/pull/1477) [\#1408](https://github.com/wechaty/wechaty/pull/1408) [\#1407](https://github.com/wechaty/wechaty/pull/1407) [\#1405](https://github.com/wechaty/wechaty/pull/1405) [\#1402](https://github.com/wechaty/wechaty/pull/1402) [\#1375](https://github.com/wechaty/wechaty/pull/1375) [\#1374](https://github.com/wechaty/wechaty/pull/1374) [\#1373](https://github.com/wechaty/wechaty/pull/1373) [\#1352](https://github.com/wechaty/wechaty/pull/1352) [\#1351](https://github.com/wechaty/wechaty/pull/1351) [\#1348](https://github.com/wechaty/wechaty/pull/1348) [\#1347](https://github.com/wechaty/wechaty/pull/1347) [\#1344](https://github.com/wechaty/wechaty/pull/1344) [\#1341](https://github.com/wechaty/wechaty/pull/1341) [\#1338](https://github.com/wechaty/wechaty/pull/1338) [\#1333](https://github.com/wechaty/wechaty/pull/1333) [\#1331](https://github.com/wechaty/wechaty/pull/1331) [\#1325](https://github.com/wechaty/wechaty/pull/1325) [\#1116](https://github.com/wechaty/wechaty/pull/1116) [\#1086](https://github.com/wechaty/wechaty/pull/1086) [\#816](https://github.com/wechaty/wechaty/pull/816) [\#812](https://github.com/wechaty/wechaty/pull/812) [\#805](https://github.com/wechaty/wechaty/pull/805) [\#798](https://github.com/wechaty/wechaty/pull/798) [\#757](https://github.com/wechaty/wechaty/pull/757) [\#725](https://github.com/wechaty/wechaty/pull/725) [\#440](https://github.com/wechaty/wechaty/pull/440) [\#370](https://github.com/wechaty/wechaty/pull/370) [\#364](https://github.com/wechaty/wechaty/pull/364) [\#362](https://github.com/wechaty/wechaty/pull/362) [\#328](https://github.com/wechaty/wechaty/pull/328) [\#324](https://github.com/wechaty/wechaty/pull/324) [\#323](https://github.com/wechaty/wechaty/pull/323) [\#321](https://github.com/wechaty/wechaty/pull/321) [\#318](https://github.com/wechaty/wechaty/pull/318) [\#303](https://github.com/wechaty/wechaty/pull/303) [\#292](https://github.com/wechaty/wechaty/pull/292) [\#139](https://github.com/wechaty/wechaty/pull/139) [\#112](https://github.com/wechaty/wechaty/pull/112) [\#110](https://github.com/wechaty/wechaty/pull/110) [\#38](https://github.com/wechaty/wechaty/pull/38) +1. @[huan](https://github.com/huan): [\#2028](https://github.com/wechaty/wechaty/pull/2028) [\#2021](https://github.com/wechaty/wechaty/pull/2021) [\#1931](https://github.com/wechaty/wechaty/pull/1931) [\#1888](https://github.com/wechaty/wechaty/pull/1888) [\#1870](https://github.com/wechaty/wechaty/pull/1870) [\#1782](https://github.com/wechaty/wechaty/pull/1782) [\#1597](https://github.com/wechaty/wechaty/pull/1597) [\#1143](https://github.com/wechaty/wechaty/pull/1143) [\#1131](https://github.com/wechaty/wechaty/pull/1131) [\#1083](https://github.com/wechaty/wechaty/pull/1083) [\#1075](https://github.com/wechaty/wechaty/pull/1075) [\#1074](https://github.com/wechaty/wechaty/pull/1074) [\#1073](https://github.com/wechaty/wechaty/pull/1073) [\#1072](https://github.com/wechaty/wechaty/pull/1072) [\#1071](https://github.com/wechaty/wechaty/pull/1071) [\#860](https://github.com/wechaty/wechaty/pull/860) [\#854](https://github.com/wechaty/wechaty/pull/854) [\#841](https://github.com/wechaty/wechaty/pull/841) [\#831](https://github.com/wechaty/wechaty/pull/831) [\#810](https://github.com/wechaty/wechaty/pull/810) [\#469](https://github.com/wechaty/wechaty/pull/469) [\#462](https://github.com/wechaty/wechaty/pull/462) [\#455](https://github.com/wechaty/wechaty/pull/455) [\#449](https://github.com/wechaty/wechaty/pull/449) [\#396](https://github.com/wechaty/wechaty/pull/396) [\#351](https://github.com/wechaty/wechaty/pull/351) [\#317](https://github.com/wechaty/wechaty/pull/317) [\#316](https://github.com/wechaty/wechaty/pull/316) [\#315](https://github.com/wechaty/wechaty/pull/315) [\#314](https://github.com/wechaty/wechaty/pull/314) [\#313](https://github.com/wechaty/wechaty/pull/313) [\#312](https://github.com/wechaty/wechaty/pull/312) [\#311](https://github.com/wechaty/wechaty/pull/311) [\#168](https://github.com/wechaty/wechaty/pull/168) [\#158](https://github.com/wechaty/wechaty/pull/158) [\#149](https://github.com/wechaty/wechaty/pull/149) [\#146](https://github.com/wechaty/wechaty/pull/146) [\#143](https://github.com/wechaty/wechaty/pull/143) [\#142](https://github.com/wechaty/wechaty/pull/142) [\#141](https://github.com/wechaty/wechaty/pull/141) [\#25](https://github.com/wechaty/wechaty/pull/25) 1. @[windmemory](https://github.com/windmemory): [\#1832](https://github.com/wechaty/wechaty/pull/1832) [\#1770](https://github.com/wechaty/wechaty/pull/1770) [\#1735](https://github.com/wechaty/wechaty/pull/1735) [\#1729](https://github.com/wechaty/wechaty/pull/1729) [\#1662](https://github.com/wechaty/wechaty/pull/1662) [\#1660](https://github.com/wechaty/wechaty/pull/1660) [\#1643](https://github.com/wechaty/wechaty/pull/1643) [\#1630](https://github.com/wechaty/wechaty/pull/1630) [\#1577](https://github.com/wechaty/wechaty/pull/1577) [\#1571](https://github.com/wechaty/wechaty/pull/1571) [\#1557](https://github.com/wechaty/wechaty/pull/1557) [\#1550](https://github.com/wechaty/wechaty/pull/1550) [\#1538](https://github.com/wechaty/wechaty/pull/1538) [\#1526](https://github.com/wechaty/wechaty/pull/1526) [\#1503](https://github.com/wechaty/wechaty/pull/1503) [\#1457](https://github.com/wechaty/wechaty/pull/1457) -1. @[su-chang](https://github.com/su-chang): [\#1936](https://github.com/wechaty/wechaty/pull/1936) [\#1921](https://github.com/wechaty/wechaty/pull/1921) [\#1915](https://github.com/wechaty/wechaty/pull/1915) [\#1913](https://github.com/wechaty/wechaty/pull/1913) [\#1910](https://github.com/wechaty/wechaty/pull/1910) [\#1900](https://github.com/wechaty/wechaty/pull/1900) [\#1895](https://github.com/wechaty/wechaty/pull/1895) [\#1883](https://github.com/wechaty/wechaty/pull/1883) [\#1868](https://github.com/wechaty/wechaty/pull/1868) [\#1866](https://github.com/wechaty/wechaty/pull/1866) [\#1864](https://github.com/wechaty/wechaty/pull/1864) [\#1861](https://github.com/wechaty/wechaty/pull/1861) [\#1833](https://github.com/wechaty/wechaty/pull/1833) +1. @[su-chang](https://github.com/su-chang): [\#2012](https://github.com/wechaty/wechaty/pull/2012) [\#2011](https://github.com/wechaty/wechaty/pull/2011) [\#1936](https://github.com/wechaty/wechaty/pull/1936) [\#1921](https://github.com/wechaty/wechaty/pull/1921) [\#1915](https://github.com/wechaty/wechaty/pull/1915) [\#1913](https://github.com/wechaty/wechaty/pull/1913) [\#1910](https://github.com/wechaty/wechaty/pull/1910) [\#1900](https://github.com/wechaty/wechaty/pull/1900) [\#1895](https://github.com/wechaty/wechaty/pull/1895) [\#1883](https://github.com/wechaty/wechaty/pull/1883) [\#1868](https://github.com/wechaty/wechaty/pull/1868) [\#1866](https://github.com/wechaty/wechaty/pull/1866) [\#1864](https://github.com/wechaty/wechaty/pull/1864) [\#1861](https://github.com/wechaty/wechaty/pull/1861) [\#1833](https://github.com/wechaty/wechaty/pull/1833) 1. @[mukaiu](https://github.com/mukaiu): [\#1089](https://github.com/wechaty/wechaty/pull/1089) [\#337](https://github.com/wechaty/wechaty/pull/337) [\#470](https://github.com/wechaty/wechaty/pull/470) [\#438](https://github.com/wechaty/wechaty/pull/438) [\#421](https://github.com/wechaty/wechaty/pull/421) [\#420](https://github.com/wechaty/wechaty/pull/420) [\#415](https://github.com/wechaty/wechaty/pull/415) [\#376](https://github.com/wechaty/wechaty/pull/376) 1. @[JasLin](https://github.com/JasLin): [\#404](https://github.com/wechaty/wechaty/pull/404) [\#358](https://github.com/wechaty/wechaty/pull/358) [\#105](https://github.com/wechaty/wechaty/pull/105) [\#100](https://github.com/wechaty/wechaty/pull/100) [\#78](https://github.com/wechaty/wechaty/pull/78) [\#76](https://github.com/wechaty/wechaty/pull/76) +1. @[kis87988](https://github.com/kis87988): [\#1993](https://github.com/wechaty/wechaty/pull/1993) [\#1908](https://github.com/wechaty/wechaty/pull/1908) [\#1623](https://github.com/wechaty/wechaty/pull/1623) [\#1607](https://github.com/wechaty/wechaty/pull/1607) [\#1570](https://github.com/wechaty/wechaty/pull/1570) 1. @[xinbenlv](https://github.com/xinbenlv): [\#1814](https://github.com/wechaty/wechaty/pull/1814) [\#1017](https://github.com/wechaty/wechaty/pull/1017) [\#935](https://github.com/wechaty/wechaty/pull/935) [\#388](https://github.com/wechaty/wechaty/pull/388) [\#361](https://github.com/wechaty/wechaty/pull/361) 1. @[binsee](https://github.com/binsee): [\#844](https://github.com/wechaty/wechaty/pull/844) [\#811](https://github.com/wechaty/wechaty/pull/811) [\#771](https://github.com/wechaty/wechaty/pull/771) [\#744](https://github.com/wechaty/wechaty/pull/744) [\#727](https://github.com/wechaty/wechaty/pull/727) 1. @[linyimin-bupt](https://github.com/linyimin-bupt): [\#1757](https://github.com/wechaty/wechaty/pull/1757) [\#1752](https://github.com/wechaty/wechaty/pull/1752) [\#1750](https://github.com/wechaty/wechaty/pull/1750) [\#1749](https://github.com/wechaty/wechaty/pull/1749) -1. @[kis87988](https://github.com/kis87988): [\#1908](https://github.com/wechaty/wechaty/pull/1908) [\#1623](https://github.com/wechaty/wechaty/pull/1623) [\#1607](https://github.com/wechaty/wechaty/pull/1607) [\#1570](https://github.com/wechaty/wechaty/pull/1570) 1. @[TbhT](https://github.com/TbhT): [\#1713](https://github.com/wechaty/wechaty/pull/1713) [\#1583](https://github.com/wechaty/wechaty/pull/1583) [\#1582](https://github.com/wechaty/wechaty/pull/1582) 1. @[suntong](https://github.com/suntong): [\#1677](https://github.com/wechaty/wechaty/pull/1677) [\#1129](https://github.com/wechaty/wechaty/pull/1129) [\#1123](https://github.com/wechaty/wechaty/pull/1123) 1. @[Gcaufy](https://github.com/Gcaufy): [\#1625](https://github.com/wechaty/wechaty/pull/1625) [\#1620](https://github.com/wechaty/wechaty/pull/1620) [\#310](https://github.com/wechaty/wechaty/pull/310) -1. @[snyk-bot](https://github.com/snyk-bot): [\#1928](https://github.com/wechaty/wechaty/pull/1928) [\#1925](https://github.com/wechaty/wechaty/pull/1925) -1. @[LinuxSuRen](https://github.com/LinuxSuRen): [\#1838](https://github.com/wechaty/wechaty/pull/1838) [\#1836](https://github.com/wechaty/wechaty/pull/1836) +1. @[plainheart](https://github.com/plainheart): [\#2000](https://github.com/wechaty/wechaty/pull/2000) [\#1999](https://github.com/wechaty/wechaty/pull/1999) +1. @[ax4](https://github.com/ax4): [\#1994](https://github.com/wechaty/wechaty/pull/1994) [\#380](https://github.com/wechaty/wechaty/pull/380) 1. @[SilentQianyi](https://github.com/SilentQianyi): [\#1891](https://github.com/wechaty/wechaty/pull/1891) [\#1886](https://github.com/wechaty/wechaty/pull/1886) +1. @[LinuxSuRen](https://github.com/LinuxSuRen): [\#1838](https://github.com/wechaty/wechaty/pull/1838) [\#1836](https://github.com/wechaty/wechaty/pull/1836) ### Contributors -1. @[IdiosApps](https://github.com/IdiosApps): [\#1087](https://github.com/wechaty/wechaty/pull/1087) +1. @[lucifer1004](https://github.com/lucifer1004): [\#1989](https://github.com/wechaty/wechaty/pull/1989) +1. @[rikakomoe](https://github.com/rikakomoe): [\#1904](https://github.com/wechaty/wechaty/pull/1904) +1. @[LanceZhu](https://github.com/LanceZhu): [\#1854](https://github.com/wechaty/wechaty/pull/1854) +1. @[zhaoic](https://github.com/zhaoic): [\#1822](https://github.com/wechaty/wechaty/pull/1822) +1. @[coderwhocode](https://github.com/coderwhocode): [\#1819](https://github.com/wechaty/wechaty/pull/1819) 1. @[gengchen528](https://github.com/gengchen528): [\#1818](https://github.com/wechaty/wechaty/pull/1818) +1. @[monkeywithacupcake](https://github.com/monkeywithacupcake): [\#1759](https://github.com/wechaty/wechaty/pull/1759) 1. @[lhr0909](https://github.com/lhr0909): [\#1666](https://github.com/wechaty/wechaty/pull/1666) 1. @[jzj1993](https://github.com/jzj1993): [\#1661](https://github.com/wechaty/wechaty/pull/1661) -1. @[LanceZhu](https://github.com/LanceZhu): [\#1854](https://github.com/wechaty/wechaty/pull/1854) 1. @[bitwater](https://github.com/bitwater): [\#1532](https://github.com/wechaty/wechaty/pull/1532) -1. @[coderwhocode](https://github.com/coderwhocode): [\#1819](https://github.com/wechaty/wechaty/pull/1819) -1. @[monkeywithacupcake](https://github.com/monkeywithacupcake): [\#1759](https://github.com/wechaty/wechaty/pull/1759) +1. @[IdiosApps](https://github.com/IdiosApps): [\#1087](https://github.com/wechaty/wechaty/pull/1087) 1. @[hiwanz](https://github.com/hiwanz): [\#1036](https://github.com/wechaty/wechaty/pull/1036) 1. @[htoooth](https://github.com/htoooth): [\#1014](https://github.com/wechaty/wechaty/pull/1014) 1. @[zhenyong](https://github.com/zhenyong): [\#770](https://github.com/wechaty/wechaty/pull/770) -1. @[rikakomoe](https://github.com/rikakomoe): [\#1904](https://github.com/wechaty/wechaty/pull/1904) 1. @[xjchengo](https://github.com/xjchengo): [\#416](https://github.com/wechaty/wechaty/pull/416) -1. @[zhaoic](https://github.com/zhaoic): [\#1822](https://github.com/wechaty/wechaty/pull/1822) -1. @[ax4](https://github.com/ax4): [\#380](https://github.com/wechaty/wechaty/pull/380) 1. @[cherry-geqi](https://github.com/cherry-geqi): [\#97](https://github.com/wechaty/wechaty/pull/97) # Changelog @@ -46,9 +47,49 @@ [Full Changelog](https://github.com/wechaty/wechaty/compare/v0.38...HEAD) +**Implemented enhancements:** + +- Refactoring Multi-instance Wechaty Design: Try to remove the Accessory class and related codes [\#2027](https://github.com/wechaty/wechaty/issues/2027) +- Use Typed-Emitter in Wechaty [\#2014](https://github.com/wechaty/wechaty/issues/2014) +- Support WECHATY\_HOSTIE\_PORT environment variable [\#1984](https://github.com/wechaty/wechaty/issues/1984) +- Wechaty v0.23 PadPro Testing, an enhanced pad puppet implementation! [\#1668](https://github.com/wechaty/wechaty/issues/1668) + +**Fixed bugs:** + +- Wechaty.off\(\) not work: can not remove listeners. [\#2019](https://github.com/wechaty/wechaty/issues/2019) +- friendship.contact\(\) will load Contact only, contact.ready\(\) is wanted. [\#1954](https://github.com/wechaty/wechaty/issues/1954) + **Closed issues:** +- BREAKING CHANGES: remove hotImport support from wechaty [\#1997](https://github.com/wechaty/wechaty/issues/1997) +- ERR GRPC\_GATEWAY GRPC SERVER ERROR [\#1996](https://github.com/wechaty/wechaty/issues/1996) +- 微信安装 [\#1990](https://github.com/wechaty/wechaty/issues/1990) +- Cannot read property 'QQ' of undefined [\#1982](https://github.com/wechaty/wechaty/issues/1982) +- Need upgrade wechaty-puppet@0.25.7 version for wechaty [\#1980](https://github.com/wechaty/wechaty/issues/1980) +- The qrcode all the time timeout [\#1977](https://github.com/wechaty/wechaty/issues/1977) +- Upgrade wechaty-puppet-hostie@0.7.10 for fix the bug of friendship.accpet\(\) [\#1966](https://github.com/wechaty/wechaty/issues/1966) +- 23:42:53 SILL GrpcGateway callback type:【invalid-token】 [\#1959](https://github.com/wechaty/wechaty/issues/1959) +- 准备支持企业微信群吗 [\#1958](https://github.com/wechaty/wechaty/issues/1958) +- node-pre-gyp WARN [\#1953](https://github.com/wechaty/wechaty/issues/1953) +- How to filter official account numbers [\#1951](https://github.com/wechaty/wechaty/issues/1951) +- Update wechaty-puppet-hostie version for wechaty [\#1948](https://github.com/wechaty/wechaty/issues/1948) - Is that you? [\#1942](https://github.com/wechaty/wechaty/issues/1942) +- New version release notes for wechaty 0.38 [\#1937](https://github.com/wechaty/wechaty/issues/1937) +- Can the receive the recall " room-leave". [\#1745](https://github.com/wechaty/wechaty/issues/1745) + +**Merged pull requests:** + +- remove Accessories by wechatify user classes [\#2028](https://github.com/wechaty/wechaty/pull/2028) ([huan](https://github.com/huan)) +- fix event listener [\#2021](https://github.com/wechaty/wechaty/pull/2021) ([huan](https://github.com/huan)) +- Upgrade hostie [\#2012](https://github.com/wechaty/wechaty/pull/2012) ([su-chang](https://github.com/su-chang)) +- Upgrade hostie [\#2011](https://github.com/wechaty/wechaty/pull/2011) ([su-chang](https://github.com/su-chang)) +- Update README.md [\#2001](https://github.com/wechaty/wechaty/pull/2001) ([lijiarui](https://github.com/lijiarui)) +- docs: fixed table format flaw of `Message.say` in README.md. [\#2000](https://github.com/wechaty/wechaty/pull/2000) ([plainheart](https://github.com/plainheart)) +- docs: fixed table format flaw of `Contact.say` in README.md. [\#1999](https://github.com/wechaty/wechaty/pull/1999) ([plainheart](https://github.com/plainheart)) +- Update README.md [\#1998](https://github.com/wechaty/wechaty/pull/1998) ([lijiarui](https://github.com/lijiarui)) +- fix: fix the broken URLs links to /bot-qr-code.png [\#1994](https://github.com/wechaty/wechaty/pull/1994) ([ax4](https://github.com/ax4)) +- test: update workflows for node ^12 [\#1993](https://github.com/wechaty/wechaty/pull/1993) ([kis87988](https://github.com/kis87988)) +- fix: typo in README.md [\#1989](https://github.com/wechaty/wechaty/pull/1989) ([lucifer1004](https://github.com/lucifer1004)) ## [v0.38](https://github.com/wechaty/wechaty/tree/v0.38) (2020-04-08) From 953cf09ceeaf5e3a020a9943995e27ecc854f285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 14 Aug 2020 00:20:04 +0800 Subject: [PATCH 430/598] 0.47.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 10f176e86..0de62d078 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.10", + "version": "0.47.11", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From b8af34571cd4df4eb639d3631aade67c74c79611 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 15 Aug 2020 18:35:27 +0800 Subject: [PATCH 431/598] use wechaty.js.org/qrcode/ to replace wechaty.github.io/qrcode/ --- README.md | 16 ++++++++-------- docs/index.md | 4 ++-- examples/ding-dong-bot.ts | 2 +- src/config.ts | 2 +- src/io-client.ts | 2 +- src/wechaty.ts | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index c552b2df0..6e1322c63 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Scan now, because other Wechaty developers want to talk with you too! (secret co ### :book: Resource -Wechaty already held lots of talk and got a lot of blogs in the past 4 years, here is all of the wechaty resouces: +Wechaty already held lots of talk and got a lot of blogs in the past 4 years, here is all of the wechaty resources: - :video_camera: [Youtube Playlist: Watch all of talk video related with Wechaty](https://www.youtube.com/playlist?list=PL8hd9KDTdarDXf_Rxtr8meKhxtgcXMInh) - :page_with_curl: [Full Docs](https://wechaty.js.org/) @@ -65,8 +65,8 @@ Wechaty already held lots of talk and got a lot of blogs in the past 4 years, he const { Wechaty } = require('wechaty') // import { Wechaty } from 'wechaty' Wechaty.instance() // Global Instance -.on('scan', (qrcode, status) => console.log(`Scan QR Code to login: ${status}\nhttps://wechaty.github.io/qrcode/${encodeURIComponent(qrcode)}`)) -.on('login', user => console.log(`User ${user} logined`)) +.on('scan', (qrcode, status) => console.log(`Scan QR Code to login: ${status}\nhttps://wechaty.js.org/qrcode/${encodeURIComponent(qrcode)}`)) +.on('login', user => console.log(`User ${user} logged in`)) .on('message', message => console.log(`Message: ${message}`)) .start() ``` @@ -92,7 +92,7 @@ We have a Wechaty starter repository for beginners with the simplest setting. It If you are new to Wechaty and want to try it the first time, we'd like to strong recommend you starting from this repository, and using it as your starter template for your project. -Otherwise, please saved the above _The World's Shortest ChatBot Code: 6 lines of JavaScript_ example to a file named `mybot.js` before you can use either NPM or Docker to run it. +Otherwise, please saved the above _The World's Shortest ChatBot Code: 6 lines of JavaScript_ example to a file named `bot.js` before you can use either NPM or Docker to run it. ### 1. Npm @@ -106,9 +106,9 @@ Otherwise, please saved the above _The World's Shortest ChatBot Code: 6 lines of npm init npm install wechaty -# create your first mybot.js file, you can copy/paste from the above "The World's Shortest ChatBot Code: 6 lines of JavaScript" +# create your first bot.js file, you can copy/paste from the above "The World's Shortest ChatBot Code: 6 lines of JavaScript" # then: -node mybot.js +node bot.js ``` ### 2. Docker @@ -124,14 +124,14 @@ node mybot.js ```shell # for JavaScript -docker run -ti --rm --volume="$(pwd)":/bot wechaty/wechaty mybot.js +docker run -ti --rm --volume="$(pwd)":/bot wechaty/wechaty bot.js ``` 2.2. Run TypeScript ```shell # for TypeScript -docker run -ti --rm --volume="$(pwd)":/bot wechaty/wechaty mybot.ts +docker run -ti --rm --volume="$(pwd)":/bot wechaty/wechaty bot.ts ``` > Learn more about Wechaty Docker at [Wiki:Docker](https://github.com/Wechaty/wechaty/wiki/Docker). diff --git a/docs/index.md b/docs/index.md index 6c63aded0..524a24ab1 100644 --- a/docs/index.md +++ b/docs/index.md @@ -142,8 +142,8 @@ Creates an instance of Wechaty. ```js const { Wechaty } = require('wechaty') const bot = new Wechaty() -bot.on('scan', (qrcode, status) => console.log('https://wechaty.github.io/qrcode/' + encodeURIComponent(qrcode))) -bot.on('login', user => console.log(`User ${user} logined`)) +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() ``` diff --git a/examples/ding-dong-bot.ts b/examples/ding-dong-bot.ts index 95ffd2cba..d726e85f5 100644 --- a/examples/ding-dong-bot.ts +++ b/examples/ding-dong-bot.ts @@ -77,7 +77,7 @@ function onScan (qrcode: string, status: ScanStatus) { generate(qrcode) const qrcodeImageUrl = [ - 'https://wechaty.github.io/qrcode/', + 'https://wechaty.js.org/qrcode/', encodeURIComponent(qrcode), ].join('') diff --git a/src/config.ts b/src/config.ts index ecc01dd4b..f3457ef0a 100644 --- a/src/config.ts +++ b/src/config.ts @@ -163,7 +163,7 @@ export const AT_SEPARATOR_REGEX = /[\u2005\u0020]/ export function qrcodeValueToImageUrl (qrcodeValue: string): string { return [ - 'https://wechaty.github.io/qrcode/', + 'https://wechaty.js.org/qrcode/', encodeURIComponent(qrcodeValue), ].join('') } diff --git a/src/io-client.ts b/src/io-client.ts index ad59726c1..e4f9cc0eb 100644 --- a/src/io-client.ts +++ b/src/io-client.ts @@ -152,7 +152,7 @@ export class IoClient { .on('scan', (url, code) => { log.info('IoClient', [ `[${code}] ${url}]`, - `Online QR Code Image: https://wechaty.github.io/qrcode/${url}`, + `Online QR Code Image: https://wechaty.js.org/qrcode/${url}`, ].join('\n')) }) } diff --git a/src/wechaty.ts b/src/wechaty.ts index fec850be0..1d9bb52b8 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -128,7 +128,7 @@ const PUPPET_MEMORY_NAME = 'puppet' * @example The World's Shortest ChatBot Code: 6 lines of JavaScript * const { Wechaty } = require('wechaty') * const bot = new Wechaty() - * bot.on('scan', (qrCode, status) => console.log('https://wechaty.github.io/qrcode/' + encodeURIComponent(qrcode))) + * 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() From 2bc06a33a5ac23877cb3d04164589ec2494a0280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 15 Aug 2020 18:35:47 +0800 Subject: [PATCH 432/598] 0.47.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0de62d078..007e12d6c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.11", + "version": "0.47.12", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 33ec3ccd7fb15ef115c735183c246cab6c3be83f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 16 Aug 2020 02:29:30 +0800 Subject: [PATCH 433/598] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6e1322c63..9ea5a16b8 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![GitHub stars](https://img.shields.io/github/stars/wechaty/wechaty.svg?label=github%20stars)](https://github.com/wechaty/wechaty) [![Docker Pulls](https://img.shields.io/docker/pulls/wechaty/wechaty.svg?maxAge=2592000)](https://hub.docker.com/r/wechaty/wechaty/) [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-blue.svg)](https://www.typescriptlang.org/) -[![Gitter](https://badges.gitter.im/Chatie/wechaty.svg)](https://gitter.im/Chatie/wechaty?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) +[![Gitter](https://badges.gitter.im/wechaty/wechaty.svg)](https://gitter.im/wechaty/wechaty?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) ## :hearts: Connecting Chatbots From 489a0da5e3b038f96eb01d52f93b7d8ffa2aba27 Mon Sep 17 00:00:00 2001 From: Yuan Gao Date: Tue, 18 Aug 2020 20:36:11 +0800 Subject: [PATCH 434/598] feat: add scoped wxwork puppet into puppet config (#2043) * add scoped wxwork puppet into puppet config * skip install scoped puppet * 0.47.13 --- package.json | 2 +- src/puppet-config.ts | 1 + src/puppet-manager.ts | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 007e12d6c..1b7236faa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.12", + "version": "0.47.13", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", diff --git a/src/puppet-config.ts b/src/puppet-config.ts index e9be75c4f..ed5fe06f8 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -29,6 +29,7 @@ export const PUPPET_DEPENDENCIES = { * Scoped puppets */ '@juzibot/wechaty-puppet-donut': '^0.3', // https://www.npmjs.com/package/wechaty-puppet-donut (to be published) + '@juzibot/wechaty-puppet-wxwork': '*', // https://www.npmjs.com/package/wechaty-puppet-wxwork (to be published) /** * Wechaty Internal Puppets: dependence by package.json diff --git a/src/puppet-manager.ts b/src/puppet-manager.ts index 9e7f91f85..3bc1c3703 100644 --- a/src/puppet-manager.ts +++ b/src/puppet-manager.ts @@ -254,6 +254,7 @@ export class PuppetManager { const skipList = [ '@juzibot/wechaty-puppet-donut', // windows puppet + '@juzibot/wechaty-puppet-wxwork', // wxwork puppet ] const moduleList: string[] = [] From db9dd130e0ff93979d2815f870f62bcabd0debb8 Mon Sep 17 00:00:00 2001 From: Yuan Gao Date: Wed, 19 Aug 2020 13:50:29 +0800 Subject: [PATCH 435/598] add phone method in contact class (#2039) * add phone method in contact class * 0.47.13 * 0.47.14 * update wechaty-puppet version * add jsdoc for contact.phone --- package.json | 6 +++--- src/user/contact.ts | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 1b7236faa..16c14a6b2 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,12 @@ { "name": "wechaty", - "version": "0.47.13", + "version": "0.47.14", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", "engines": { "node": ">= 12", - "wechaty-puppet": ">=0.30.3" + "wechaty-puppet": ">=0.31.1" }, "wechaty": { "DEFAULT_PORT": 8080, @@ -103,7 +103,7 @@ "typed-emitter": "^1.2.0", "watchdog": "^0.8.17", "wechaty-puppet-hostie": "^0.9.13", - "wechaty-puppet": "^0.30.3", + "wechaty-puppet": "^0.31.1", "ws": "^7.2.3" }, "devDependencies": { diff --git a/src/user/contact.ts b/src/user/contact.ts index d3cb7c632..594920d9f 100644 --- a/src/user/contact.ts +++ b/src/user/contact.ts @@ -537,6 +537,51 @@ class Contact extends ContactEventEmitter implements Sayable { } } + /** + * GET / SET / DELETE the phone list for a contact + * + * @param {(none | string[])} phoneList + * @returns {(Promise)} + * @example GET the phone list for a contact, return {(Promise)} + * const phoneList = await contact.phone() + * if (phone.length === 0) { + * console.log('You have not yet set any phone number for contact ' + contact.name()) + * } else { + * console.log('You have already set phone numbers for contact ' + contact.name() + ':' + phoneList.join(',')) + * } + * + * @example SET the phoneList for a contact + * try { + * const phoneList = ['13999999999', '13888888888'] + * await contact.alias(phoneList) + * console.log(`change ${contact.name()}'s phone successfully!`) + * } catch (e) { + * console.log(`failed to change ${contact.name()} phone!`) + * } + */ + public async phone (): Promise + public async phone (phoneList: string[]): Promise + public async phone (phoneList?: string[]): Promise { + log.silly('Contact', 'phone(%s)', phoneList === undefined ? '' : JSON.stringify(phoneList)) + + if (!this.payload) { + throw new Error('no payload') + } + + if (typeof phoneList === 'undefined') { + return this.wechaty.puppet.contactPhone(this.id) + } + + try { + await this.wechaty.puppet.contactPhone(this.id, phoneList) + await this.wechaty.puppet.contactPayloadDirty(this.id) + this.payload = await this.wechaty.puppet.contactPayload(this.id) + } catch (e) { + log.error('Contact', 'phone(%s) rejected: %s', JSON.stringify(phoneList), e.message) + Raven.captureException(e) + } + } + /** * * @description From 5d389fad4b2f8f1217355561597e08df693e294d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 19 Aug 2020 16:55:02 +0800 Subject: [PATCH 436/598] use puppet.dirtyPayload (https://github.com/wechaty/wechaty-puppet-hostie/issues/43) --- package.json | 5 ++--- src/user/contact.ts | 7 ++++--- src/user/room.ts | 5 +++-- src/wechaty.ts | 5 +++-- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 16c14a6b2..ee2705deb 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,7 @@ "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", "engines": { - "node": ">= 12", - "wechaty-puppet": ">=0.31.1" + "node": ">= 12" }, "wechaty": { "DEFAULT_PORT": 8080, @@ -103,7 +102,7 @@ "typed-emitter": "^1.2.0", "watchdog": "^0.8.17", "wechaty-puppet-hostie": "^0.9.13", - "wechaty-puppet": "^0.31.1", + "wechaty-puppet": "^0.31.4", "ws": "^7.2.3" }, "devDependencies": { diff --git a/src/user/contact.ts b/src/user/contact.ts index 594920d9f..e89088c1b 100644 --- a/src/user/contact.ts +++ b/src/user/contact.ts @@ -25,6 +25,7 @@ import { ContactQueryFilter, ContactType, FileBox, + PayloadType, } from 'wechaty-puppet' import { Wechaty } from '../wechaty' @@ -522,7 +523,7 @@ class Contact extends ContactEventEmitter implements Sayable { try { await this.wechaty.puppet.contactAlias(this.id, newAlias) - await this.wechaty.puppet.contactPayloadDirty(this.id) + await this.wechaty.puppet.dirtyPayload(PayloadType.Contact, this.id) this.payload = await this.wechaty.puppet.contactPayload(this.id) if (newAlias && newAlias !== this.payload.alias) { log.warn('Contact', 'alias(%s) sync with server fail: set(%s) is not equal to get(%s)', @@ -574,7 +575,7 @@ class Contact extends ContactEventEmitter implements Sayable { try { await this.wechaty.puppet.contactPhone(this.id, phoneList) - await this.wechaty.puppet.contactPayloadDirty(this.id) + await this.wechaty.puppet.dirtyPayload(PayloadType.Contact, this.id) this.payload = await this.wechaty.puppet.contactPayload(this.id) } catch (e) { log.error('Contact', 'phone(%s) rejected: %s', JSON.stringify(phoneList), e.message) @@ -810,7 +811,7 @@ class Contact extends ContactEventEmitter implements Sayable { try { if (forceSync) { - await this.wechaty.puppet.contactPayloadDirty(this.id) + await this.wechaty.puppet.dirtyPayload(PayloadType.Contact, this.id) } this.payload = await this.wechaty.puppet.contactPayload(this.id) // log.silly('Contact', `ready() this.wechaty.puppet.contactPayload(%s) resolved`, this) diff --git a/src/user/room.ts b/src/user/room.ts index 9019aae42..7d73824d5 100644 --- a/src/user/room.ts +++ b/src/user/room.ts @@ -45,6 +45,7 @@ import { RoomMemberQueryFilter, RoomPayload, RoomQueryFilter, + PayloadType, } from 'wechaty-puppet' import { RoomEventEmitter } from '../events/room-events' @@ -339,8 +340,8 @@ class Room extends RoomEventEmitter implements Sayable { } if (forceSync) { - await this.wechaty.puppet.roomPayloadDirty(this.id) - await this.wechaty.puppet.roomMemberPayloadDirty(this.id) + await this.wechaty.puppet.dirtyPayload(PayloadType.Room, this.id) + await this.wechaty.puppet.dirtyPayload(PayloadType.RoomMember, this.id) } this.payload = await this.wechaty.puppet.roomPayload(this.id) diff --git a/src/wechaty.ts b/src/wechaty.ts index 1d9bb52b8..e89b98433 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -30,6 +30,7 @@ import { PUPPET_EVENT_DICT, PuppetEventName, PuppetOptions, + PayloadType, } from 'wechaty-puppet' import { @@ -552,8 +553,8 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { // issue #254 const selfId = this.puppet.selfId() if (selfId && payload.removeeIdList.includes(selfId)) { - await this.puppet.roomPayloadDirty(payload.roomId) - await this.puppet.roomMemberPayloadDirty(payload.roomId) + await this.puppet.dirtyPayload(PayloadType.Room, payload.roomId) + await this.puppet.dirtyPayload(PayloadType.RoomMember, payload.roomId) } }) From 2b06d9f18661d7ce27b3b115c84f531b396eb364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 19 Aug 2020 16:55:18 +0800 Subject: [PATCH 437/598] 0.47.15 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ee2705deb..e0748d8f4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.14", + "version": "0.47.15", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 938d2ed7a6c1b407b1fe4aae9afe460005163ff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 19 Aug 2020 17:27:10 +0800 Subject: [PATCH 438/598] fix dirty exception --- package.json | 2 +- src/wechaty.ts | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index e0748d8f4..d0b1ba5aa 100644 --- a/package.json +++ b/package.json @@ -102,7 +102,7 @@ "typed-emitter": "^1.2.0", "watchdog": "^0.8.17", "wechaty-puppet-hostie": "^0.9.13", - "wechaty-puppet": "^0.31.4", + "wechaty-puppet": "^0.31.5", "ws": "^7.2.3" }, "devDependencies": { diff --git a/src/wechaty.ts b/src/wechaty.ts index e89b98433..8882a9cb0 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -584,6 +584,10 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { // Do not propagation `reset` event from puppet break + case 'dirty': + // Huan(202008): do we need to deal with the `dirty` event in Wechaty? + break + default: /** * Check: The eventName here should have the type `never` From 9816c62d81b7ff2e0c3292c841454e24f020905c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 19 Aug 2020 17:27:23 +0800 Subject: [PATCH 439/598] 0.47.16 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d0b1ba5aa..6143867b7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.15", + "version": "0.47.16", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 7d9d022bdcf902f56da5587850c790dc2f243b97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 19 Aug 2020 17:29:19 +0800 Subject: [PATCH 440/598] TODO: implement the dirty logic (https://github.com/wechaty/wechaty-puppet-hostie/issues/43) --- src/wechaty.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/wechaty.ts b/src/wechaty.ts index 8882a9cb0..f88e08a76 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -585,7 +585,10 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { break case 'dirty': - // Huan(202008): do we need to deal with the `dirty` event in Wechaty? + /** + * TODO: Huan(202008) do we need to deal with the `dirty` event in Wechaty? + * clean all the pools for Contact, Room, Message, etc. + */ break default: From cb3684cfebc46d691cf523a0b023407a17db2190 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 19 Aug 2020 17:29:32 +0800 Subject: [PATCH 441/598] 0.47.17 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6143867b7..086300529 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.16", + "version": "0.47.17", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From f6cd406c279b1ec1321761d33b05bd51bf09b656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 19 Aug 2020 17:40:51 +0800 Subject: [PATCH 442/598] TODO: implement the dirty logic (https://github.com/wechaty/wechaty-puppet-hostie/issues/43) --- src/wechaty.ts | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/wechaty.ts b/src/wechaty.ts index f88e08a76..4187b7fd6 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -588,7 +588,37 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { /** * TODO: Huan(202008) do we need to deal with the `dirty` event in Wechaty? * clean all the pools for Contact, Room, Message, etc. + * + * CAUTION: should update it smoothly instead of just delete the cache! + * there's lots of race conditions, like: + * 1. ... to be collected */ + puppet.on('dirty', async ({ payloadType, payloadId }) => { + switch (payloadType) { + case PayloadType.RoomMember: + case PayloadType.Contact: + await this.Contact.load(payloadId).ready(true) + break + case PayloadType.Room: + await this.Room.load(payloadId).ready(true) + break + + /** + * Huan(202008): noop for the following + */ + case PayloadType.Friendship: + // Friendship has no payload + // await this.Friendship.load(payloadId) + break + case PayloadType.Message: + // Message does not need to dirty (?) + break + + case PayloadType.Unknown: + default: + throw new Error('unknown payload type: ' + payloadType) + } + }) break default: From 8bb311c407fb66ecd699c3cf6f2d880c391458ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 19 Aug 2020 17:41:05 +0800 Subject: [PATCH 443/598] 0.47.18 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 086300529..24b297c4e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.17", + "version": "0.47.18", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 7963bcfe9b327fc101e20be3efdb0031f390533f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 19 Aug 2020 17:41:39 +0800 Subject: [PATCH 444/598] implement the dirty logic (https://github.com/wechaty/wechaty-puppet-hostie/issues/43) --- src/wechaty.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wechaty.ts b/src/wechaty.ts index 4187b7fd6..bf3e4a366 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -597,10 +597,10 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { switch (payloadType) { case PayloadType.RoomMember: case PayloadType.Contact: - await this.Contact.load(payloadId).ready(true) + await this.Contact.load(payloadId).sync() break case PayloadType.Room: - await this.Room.load(payloadId).ready(true) + await this.Room.load(payloadId).sync() break /** From cbd4b10f9da1f4d09a2bcbee26dc4d461f9780eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 19 Aug 2020 17:41:55 +0800 Subject: [PATCH 445/598] 0.47.19 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 24b297c4e..181791511 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.18", + "version": "0.47.19", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 0d26dfa861e2b0a06eb41cefeee771454c72bea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 19 Aug 2020 17:46:24 +0800 Subject: [PATCH 446/598] clean --- src/wechaty.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/wechaty.ts b/src/wechaty.ts index bf3e4a366..b5500bc9d 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -586,12 +586,7 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { case 'dirty': /** - * TODO: Huan(202008) do we need to deal with the `dirty` event in Wechaty? - * clean all the pools for Contact, Room, Message, etc. - * - * CAUTION: should update it smoothly instead of just delete the cache! - * there's lots of race conditions, like: - * 1. ... to be collected + * https://github.com/wechaty/wechaty-puppet-hostie/issues/43 */ puppet.on('dirty', async ({ payloadType, payloadId }) => { switch (payloadType) { From d08a1331939fea0b65ed9035d1252bf10cfac67d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 19 Aug 2020 17:46:38 +0800 Subject: [PATCH 447/598] 0.47.20 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 181791511..259ec8202 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.19", + "version": "0.47.20", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From c0fc661c1de40a6d8ee3705b53baa071113b495b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 22 Aug 2020 19:35:13 +0800 Subject: [PATCH 448/598] remove deprecated methods (#2049) --- package.json | 46 +++++++++++++++---------------- src/user/contact.ts | 55 +------------------------------------ src/user/friendship.ts | 10 ------- src/user/message.ts | 32 --------------------- src/user/room-invitation.ts | 29 ------------------- src/user/room.ts | 29 ------------------- src/wechaty.ts | 18 ------------ 7 files changed, 24 insertions(+), 195 deletions(-) diff --git a/package.json b/package.json index 259ec8202..b6523ad35 100644 --- a/package.json +++ b/package.json @@ -83,59 +83,59 @@ }, "homepage": "https://github.com/wechaty/", "dependencies": { - "brolog": "^1.8.3", + "brolog": "^1.12.4", "clone-class": "^0.7.3", "cuid": "^2.1.8", "dotenv": "^8.2.0", "in-gfw": "^1.2.0", - "json-rpc-peer": "^0.15.5", + "json-rpc-peer": "^0.16.0", "npm-programmatic": "0.0.12", "open-graph": "^0.2.4", "opencollective": "^1.0.3", - "opencollective-postinstall": "^2.0.2", + "opencollective-postinstall": "^2.0.3", "pkg-dir": "^4.2.0", - "portfinder": "^1.0.25", - "promise-retry": "^1.1.1", + "portfinder": "^1.0.28", + "promise-retry": "^2.0.1", "raven": "^2.6.4", "read-pkg-up": "^7.0.1", "state-switch": "^0.9.9", - "typed-emitter": "^1.2.0", + "typed-emitter": "^1.3.0", "watchdog": "^0.8.17", "wechaty-puppet-hostie": "^0.9.13", - "wechaty-puppet": "^0.31.5", - "ws": "^7.2.3" + "wechaty-puppet": "^0.32.3", + "ws": "^7.3.1" }, "devDependencies": { - "@babel/core": "^7.8.7", - "@babel/node": "^7.8.7", - "@babel/preset-env": "^7.8.7", - "@chatie/eslint-config": "^0.11.5", - "@chatie/git-scripts": "^0.5.2", + "@babel/core": "^7.11.4", + "@babel/node": "^7.10.5", + "@babel/preset-env": "^7.11.0", + "@chatie/eslint-config": "^0.12.1", + "@chatie/git-scripts": "^0.6.2", "@chatie/semver": "^0.4.7", - "@chatie/tsconfig": "^0.8.0", - "@types/cuid": "^1.3.0", + "@chatie/tsconfig": "^0.10.1", + "@types/cuid": "^1.3.1", "@types/dotenv": "^8.2.0", - "@types/glob": "^7.1.1", + "@types/glob": "^7.1.3", "@types/open-graph": "^0.2.0", "@types/promise-retry": "^1.1.3", "@types/raven": "^2.5.3", "@types/retry": "^0.12.0", - "@types/ws": "^7.2.2", + "@types/ws": "^7.2.6", "apiai": "^4.0.3", - "check-node-version": "^4.0.2", - "coveralls": "^3.0.9", + "check-node-version": "^4.0.3", + "coveralls": "^3.1.0", "cross-env": "^7.0.2", "finis": "^0.4.4", "glob": "^7.1.6", - "jsdoc-to-markdown": "^5.0.3", - "markdownlint-cli": "^0.22.0", - "nyc": "^15.0.0", + "jsdoc-to-markdown": "^6.0.1", + "markdownlint-cli": "^0.23.2", + "nyc": "^15.1.0", "pkg-jq": "^0.2.4", "qrcode-terminal": "^0.12.0", "shx": "^0.3.2", "sloc": "^0.2.1", "tstest": "^0.4.10", - "typedoc": "^0.16.11", + "typedoc": "^0.18.0", "wechaty-puppet-mock": "^0.27.2" }, "files_comment__whitelist_npm_publish": "http://stackoverflow.com/a/8617868/1123955", diff --git a/src/user/contact.ts b/src/user/contact.ts index e89088c1b..df6ab0633 100644 --- a/src/user/contact.ts +++ b/src/user/contact.ts @@ -570,7 +570,7 @@ class Contact extends ContactEventEmitter implements Sayable { } if (typeof phoneList === 'undefined') { - return this.wechaty.puppet.contactPhone(this.id) + return this.payload.phone } try { @@ -583,20 +583,6 @@ class Contact extends ContactEventEmitter implements Sayable { } } - /** - * - * @description - * Should use {@link Contact#friend} instead - * - * @deprecated - * @ignore - */ - public stranger (): null | boolean { - log.warn('Contact', 'stranger() DEPRECATED. use friend() instead.') - if (!this.payload) return null - return !this.friend() - } - /** * Check if contact is friend * @@ -618,33 +604,6 @@ class Contact extends ContactEventEmitter implements Sayable { return this.payload.friend || null } - /** - * @ignore - * @see {@link https://github.com/Chatie/webwx-app-tracker/blob/7c59d35c6ea0cff38426a4c5c912a086c4c512b2/formatted/webwxApp.js#L3243|webwxApp.js#L324} - * @see {@link https://github.com/Urinx/WeixinBot/blob/master/README.md|Urinx/WeixinBot/README} - */ - /** - * @description - * Check if it's a official account, should use {@link Contact#type} instead - * @deprecated - * @ignore - */ - public official (): boolean { - log.warn('Contact', 'official() DEPRECATED. use type() instead') - return !!this.payload && (this.payload.type === ContactType.Official) - } - - /** - * @description - * Check if it's a personal account, should use {@link Contact#type} instead - * @deprecated - * @ignore - */ - public personal (): boolean { - log.warn('Contact', 'personal() DEPRECATED. use type() instead') - return !!this.payload && this.payload.type === ContactType.Personal - } - /** * Enum for ContactType * @enum {number} @@ -768,18 +727,6 @@ class Contact extends ContactEventEmitter implements Sayable { } } - /** - * @description - * Force reload(re-ready()) data for Contact, use {@link Contact#sync} instead - * - * @deprecated - * @ignore - */ - public refresh (): Promise { - log.warn('Contact', 'refresh() DEPRECATED. use sync() instead.') - return this.sync() - } - /** * Force reload data for Contact, Sync data from low-level API again. * diff --git a/src/user/friendship.ts b/src/user/friendship.ts index fb28fd6c9..3b36179be 100644 --- a/src/user/friendship.ts +++ b/src/user/friendship.ts @@ -105,16 +105,6 @@ class Friendship extends EventEmitter implements Acceptable { return contact } - /** - * @description - * use {@link Friendship#add} instead - * @deprecated - */ - public static async send (contact: Contact, hello: string) { - log.warn('Friendship', 'static send() DEPRECATED, use add() instead.') - return this.add(contact, hello) - } - /** * Send a Friend Request to a `contact` with message `hello`. * diff --git a/src/user/message.ts b/src/user/message.ts index 457edf244..2d3d887fd 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -327,17 +327,6 @@ class Message extends EventEmitter implements Sayable { return room } - /** - * @description - * use {@link Message#text} instead - * - * @deprecated - */ - public content (): string { - log.warn('Message', 'content() DEPRECATED. use text() instead.') - return this.text() - } - /** * Get the text content of the message * @@ -777,17 +766,6 @@ class Message extends EventEmitter implements Sayable { return textWithoutMention.trim() } - /** - * @description - * should use {@link Message#mention} instead - * @deprecated - * @ignore - */ - public async mentioned (): Promise { - log.warn('Message', 'mentioned() DEPRECATED. use mention() instead.') - return this.mentionList() - } - /** * Check if a message is mention self. * @@ -938,16 +916,6 @@ class Message extends EventEmitter implements Sayable { return ageSeconds } - /** - * @description - * use {@link Message#toFileBox} instead - * @deprecated - */ - public async file (): Promise { - log.warn('Message', 'file() DEPRECATED. use toFileBox() instead.') - return this.toFileBox() - } - /** * Extract the Media File from the Message, and put it into the FileBox. * > Tips: diff --git a/src/user/room-invitation.ts b/src/user/room-invitation.ts index e4e3e221b..17f36c036 100644 --- a/src/user/room-invitation.ts +++ b/src/user/room-invitation.ts @@ -177,36 +177,17 @@ class RoomInvitation implements Acceptable { public async topic (): Promise { const payload = await this.wechaty.puppet.roomInvitationPayload(this.id) - // roomTopic deprecated. use topic instead: return payload.topic || payload.topic || '' } - /** - * @deprecated: use topic() instead - * @ignore - */ - public async roomTopic (): Promise { - return this.topic() - } - public async memberCount (): Promise { log.verbose('RoomInvitation', 'memberCount()') const payload = await this.wechaty.puppet.roomInvitationPayload(this.id) - // roomMemberCount deprecated. use memberCount instead: return payload.memberCount || payload.memberCount || 0 } - /** - * @deprecated: use memberCount() instead - * @ignore - */ - public async roomMemberCount (): Promise { - log.warn('RoomInvitation', 'roomMemberCount() DEPRECATED. use memberCount() instead.') - return this.memberCount() - } - /** * List of Room Members that you known(is friend) * @ignore @@ -216,7 +197,6 @@ class RoomInvitation implements Acceptable { const payload = await this.wechaty.puppet.roomInvitationPayload(this.id) - // roomMemberIdList deprecated. use memberIdList isntead. const contactIdList = payload.memberIdList || payload.memberIdList || [] const contactList = contactIdList.map( @@ -231,15 +211,6 @@ class RoomInvitation implements Acceptable { return contactList } - /** - * @deprecated: use memberList() instead. - * @ignore - */ - public async roomMemberList (): Promise { - log.warn('RoomInvitation', 'roomMemberList() DEPRECATED. use memberList() instead.') - return this.roomMemberList() - } - /** * Get the invitation time * diff --git a/src/user/room.ts b/src/user/room.ts index 7d73824d5..fa18a1f95 100644 --- a/src/user/room.ts +++ b/src/user/room.ts @@ -302,15 +302,6 @@ class Room extends RoomEventEmitter implements Sayable { } } - /** - * @ignore - * @ignore - * @deprecated: Use `sync()` instead - */ - public async refresh (): Promise { - await this.sync() - } - /** * Force reload data for Room, Sync data from puppet API again. * @@ -959,14 +950,6 @@ class Room extends RoomEventEmitter implements Sayable { } } - /** - * @deprecated: use qrCode() instead - */ - public async qrcode () { - log.warn('Room', 'qrcode() is deprecated. use qrCode() instead.') - return this.qrCode() - } - /** * Get QR Code Value of the Room from the room, which can be used as scan and join the room. * > Tips: @@ -1007,18 +990,6 @@ class Room extends RoomEventEmitter implements Sayable { return null } - /** - * Same as function alias - * @param {Contact} contact - * @returns {Promise} - * @deprecated: use room.alias() instead - * @ignore - */ - public async roomAlias (contact: Contact): Promise { - log.warn('Room', 'roomAlias() DEPRECATED. use room.alias() instead') - return this.alias(contact) - } - /** * Check if the room has member `contact`, the return is a Promise and must be `await`-ed * diff --git a/src/wechaty.ts b/src/wechaty.ts index b5500bc9d..e1a5c2461 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -101,9 +101,6 @@ export interface WechatyOptions { memory? : MemoryCard, name? : string, // Wechaty Name - // @deprecated: use `name` instead of `profile` - profile? : null | string, // DEPRECATED: use name instead - puppet? : PuppetModuleName | Puppet, // Puppet name or instance puppetOptions? : PuppetOptions, // Puppet TOKEN ioToken? : string, // Io TOKEN @@ -287,10 +284,6 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { super() log.verbose('Wechaty', 'constructor()') - if (!options.name && options.profile) { - log.verbose('Wechaty', 'constructor() WechatyOptions.profile DEPRECATED. use WechatyOptions.name instead.') - options.name = options.profile - } this.memory = this.options.memory this.id = cuid() @@ -838,17 +831,6 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { } } - /** - * @description - * Should use {@link Wechaty#userSelf} instead - * @deprecated Use `userSelf()` instead - * @ignore - */ - public self (): Contact { - log.warn('Wechaty', 'self() DEPRECATED. use userSelf() instead.') - return this.userSelf() - } - /** * Get current user * From b3eb47fe961b4e00d3fd34bbc8c5e75dd960c0e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 22 Aug 2020 19:35:25 +0800 Subject: [PATCH 449/598] 0.47.21 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b6523ad35..d61628d8b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.20", + "version": "0.47.21", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 04f7edec33cf5da054e8871d58a02cc4f1c16648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 22 Aug 2020 19:37:38 +0800 Subject: [PATCH 450/598] Upgrade to TypeScript 4.0! --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d61628d8b..5403f161f 100644 --- a/package.json +++ b/package.json @@ -112,7 +112,7 @@ "@chatie/eslint-config": "^0.12.1", "@chatie/git-scripts": "^0.6.2", "@chatie/semver": "^0.4.7", - "@chatie/tsconfig": "^0.10.1", + "@chatie/tsconfig": "^0.13.0", "@types/cuid": "^1.3.1", "@types/dotenv": "^8.2.0", "@types/glob": "^7.1.3", From 1b70cf3cd9b17dad25d665b710b9d077cb0d15a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 22 Aug 2020 19:37:50 +0800 Subject: [PATCH 451/598] 0.47.22 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5403f161f..8b492143a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.21", + "version": "0.47.22", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 06bcf10660f8279674d2b51491c7f8d19bbe8af9 Mon Sep 17 00:00:00 2001 From: Yuan Gao Date: Sat, 22 Aug 2020 20:24:25 +0800 Subject: [PATCH 452/598] feat: add more methods into contact class (#2048) * add more methods into contact class * fix code with new wechaty-puppet * 0.47.21 * 0.47.23 --- package.json | 2 +- src/user/contact.ts | 66 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 8b492143a..4a26db3e2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.22", + "version": "0.47.23", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", diff --git a/src/user/contact.ts b/src/user/contact.ts index df6ab0633..ba3c75456 100644 --- a/src/user/contact.ts +++ b/src/user/contact.ts @@ -583,6 +583,72 @@ class Contact extends ContactEventEmitter implements Sayable { } } + public async corporation (): Promise + public async corporation (remark: string | null): Promise + public async corporation (remark?: string | null): Promise { + log.silly('Contact', 'corporation(%s)', remark) + + if (!this.payload) { + throw new Error('no payload') + } + + if (typeof remark === 'undefined') { + return this.payload.corporation || null + } + + if (this.payload.type !== ContactType.Individual) { + throw new Error('Can not set corporation remark on non individual contact.') + } + + try { + await this.wechaty.puppet.contactCorporationRemark(this.id, remark) + await this.wechaty.puppet.dirtyPayload(PayloadType.Contact, this.id) + this.payload = await this.wechaty.puppet.contactPayload(this.id) + } catch (e) { + log.error('Contact', 'corporation(%s) rejected: %s', remark, e.message) + Raven.captureException(e) + } + } + + public async description (): Promise + public async description (newDescription: string | null): Promise + public async description (newDescription?: string | null): Promise { + log.silly('Contact', 'description(%s)', newDescription) + + if (!this.payload) { + throw new Error('no payload') + } + + if (typeof newDescription === 'undefined') { + return this.payload.description || null + } + + try { + await this.wechaty.puppet.contactDescription(this.id, newDescription) + await this.wechaty.puppet.dirtyPayload(PayloadType.Contact, this.id) + this.payload = await this.wechaty.puppet.contactPayload(this.id) + } catch (e) { + log.error('Contact', 'description(%s) rejected: %s', newDescription, e.message) + Raven.captureException(e) + } + } + + public title (): string | null { + if (!this.payload) { + throw new Error('no payload') + } + + return this.payload.title || null + } + + public coworker (): boolean { + if (!this.payload) { + throw new Error('no payload') + } + + return !!this.payload.coworker + } + /** * Check if contact is friend * From 491a7c533ccd7660ad44682e88681c52070673ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 22 Aug 2020 23:52:36 +0800 Subject: [PATCH 453/598] throw a nice error message when we call user module before start wechaty --- src/wechaty.ts | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/src/wechaty.ts b/src/wechaty.ts index e1a5c2461..95c5c2eb6 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -131,7 +131,7 @@ const PUPPET_MEMORY_NAME = 'puppet' * bot.on('message', message => console.log(`Message: ${message}`)) * bot.start() */ -export class Wechaty extends WechatyEventEmitter implements Sayable { +class Wechaty extends WechatyEventEmitter implements Sayable { public static readonly VERSION = VERSION @@ -173,16 +173,16 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { protected wechatifiedTag? : typeof Tag protected wechatifiedUrlLink? : typeof UrlLink - public get Contact () : typeof Contact { return this.wechatifiedContact! } - public get ContactSelf () : typeof ContactSelf { return this.wechatifiedContactSelf! } - public get Friendship () : typeof Friendship { return this.wechatifiedFriendship! } - public get Image () : typeof Image { return this.wechatifiedImage! } - public get Message () : typeof Message { return this.wechatifiedMessage! } - public get MiniProgram () : typeof MiniProgram { return this.wechatifiedMiniProgram! } - public get Room () : typeof Room { return this.wechatifiedRoom! } - public get RoomInvitation () : typeof RoomInvitation { return this.wechatifiedRoomInvitation! } - public get Tag () : typeof Tag { return this.wechatifiedTag! } - public get UrlLink () : typeof UrlLink { return this.wechatifiedUrlLink! } + public get Contact () : typeof Contact { return guardWechatify(this.wechatifiedContact) } + public get ContactSelf () : typeof ContactSelf { return guardWechatify(this.wechatifiedContactSelf) } + public get Friendship () : typeof Friendship { return guardWechatify(this.wechatifiedFriendship) } + public get Image () : typeof Image { return guardWechatify(this.wechatifiedImage) } + public get Message () : typeof Message { return guardWechatify(this.wechatifiedMessage) } + public get MiniProgram () : typeof MiniProgram { return guardWechatify(this.wechatifiedMiniProgram) } + public get Room () : typeof Room { return guardWechatify(this.wechatifiedRoom) } + public get RoomInvitation () : typeof RoomInvitation { return guardWechatify(this.wechatifiedRoomInvitation) } + public get Tag () : typeof Tag { return guardWechatify(this.wechatifiedTag) } + public get UrlLink () : typeof UrlLink { return guardWechatify(this.wechatifiedUrlLink) } /** * Get the global instance of Wechaty @@ -1011,3 +1011,17 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { } } + +/** + * Huan(202008): we will bind the wechaty puppet with user modules (Contact, Room, etc) together inside the start() method + */ +function guardWechatify (userModule?: T): T { + if (!userModule) { + throw new Error('Wechaty user module (for example, wechaty.Room) can not be used before wechaty.start()!') + } + return userModule +} + +export { + Wechaty, +} From cf560a5c017ca8ab46f5aa042d3045dacea4ad8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 22 Aug 2020 23:52:48 +0800 Subject: [PATCH 454/598] 0.47.24 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4a26db3e2..114430c35 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.23", + "version": "0.47.24", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 68c1c603ed8a937434469dc7abcfa63de2cf7118 Mon Sep 17 00:00:00 2001 From: Yuan Gao Date: Sun, 23 Aug 2020 23:54:14 +0800 Subject: [PATCH 455/598] 0.48.0 (#2050) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 114430c35..b44ba89e9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.24", + "version": "0.48.0", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 37f04141b10808529ec768ae1913a9113f555eb4 Mon Sep 17 00:00:00 2001 From: Yuan Gao Date: Mon, 24 Aug 2020 14:00:13 +0800 Subject: [PATCH 456/598] bump hostie version to be the stable one (#2051) * bump hostie version to be the stable one * 0.48.1 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b44ba89e9..e75d06f59 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.48.0", + "version": "0.48.1", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", @@ -101,7 +101,7 @@ "state-switch": "^0.9.9", "typed-emitter": "^1.3.0", "watchdog": "^0.8.17", - "wechaty-puppet-hostie": "^0.9.13", + "wechaty-puppet-hostie": "^0.10.0", "wechaty-puppet": "^0.32.3", "ws": "^7.3.1" }, From 2beef1809af0fa5612dd22704295ec87f8e39058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 24 Aug 2020 17:21:17 +0800 Subject: [PATCH 457/598] link images to wechaty.js.org --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9ea5a16b8..53252a116 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Wechaty [![NPM Version](https://img.shields.io/npm/v/wechaty?color=brightgreen)](https://www.npmjs.com/package/wechaty) [![NPM](https://github.com/wechaty/wechaty/workflows/NPM/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ANPM) [![Docker](https://github.com/wechaty/wechaty/workflows/Docker/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ADocker) -[![Wechaty](https://wechaty.js.org/img/wechaty-logo.svg)](https://github.com/wechaty/wechaty) +[![Wechaty](https://wechaty.js.org/img/wechaty-logo.svg)](https://wechaty.js.org) [![Downloads](https://img.shields.io/npm/dm/wechaty.svg?style=flat-square)](https://www.npmjs.com/package/wechaty) [![GitHub stars](https://img.shields.io/github/stars/wechaty/wechaty.svg?label=github%20stars)](https://github.com/wechaty/wechaty) @@ -356,12 +356,12 @@ See: ## :sparkling_heart: POWERED BY WECHATY -[![Powered by Wechaty](https://img.shields.io/badge/Powered%20By-Wechaty-brightgreen.svg)](https://github.com/Wechaty/wechaty) +[![Powered by Wechaty](https://img.shields.io/badge/Powered%20By-Wechaty-brightgreen.svg)](https://wechaty.js.org) ### :sparkles: Wechaty Badge ```markdown -[![Powered by Wechaty](https://img.shields.io/badge/Powered%20By-Wechaty-brightgreen.svg)](https://github.com/Wechaty/wechaty) +[![Powered by Wechaty](https://img.shields.io/badge/Powered%20By-Wechaty-brightgreen.svg)](https://wechaty.js.org) ``` Get more embed html/markdown code from [Wiki:Badge](https://github.com/wechaty/wechaty/wiki/Badge) From fc0838ef4b9d2bec555d70f7501a1e36bd730b31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 24 Aug 2020 18:20:45 +0800 Subject: [PATCH 458/598] update links --- scripts/generate-docs.sh | 4 ++-- src/wechaty.ts | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/generate-docs.sh b/scripts/generate-docs.sh index d780d20b5..28bbacc68 100755 --- a/scripts/generate-docs.sh +++ b/scripts/generate-docs.sh @@ -23,9 +23,9 @@ DOCS_INDEX_MD=docs/index.md cat <<_EOF_ > "$DOCS_INDEX_MD" # Wechaty v$(jq -r .version package.json) Documentation -- Blog - +- Website - +- Docs Site - - API References - -- Docs Site - _EOF_ diff --git a/src/wechaty.ts b/src/wechaty.ts index b5500bc9d..af851ce49 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -603,7 +603,6 @@ export class Wechaty extends WechatyEventEmitter implements Sayable { */ case PayloadType.Friendship: // Friendship has no payload - // await this.Friendship.load(payloadId) break case PayloadType.Message: // Message does not need to dirty (?) From 2fe44b8c91129f2b44e2d9a07e66e43a951f80a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 24 Aug 2020 18:22:07 +0800 Subject: [PATCH 459/598] 0.48.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e75d06f59..d76a7b069 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.48.1", + "version": "0.48.2", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 159c5beb4620f811d799a494157f4a1c873b2040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 24 Aug 2020 18:22:56 +0800 Subject: [PATCH 460/598] update jsdocs --- docs/index.md | 578 +++++++++++++++++++++++--------------------------- 1 file changed, 268 insertions(+), 310 deletions(-) diff --git a/docs/index.md b/docs/index.md index 524a24ab1..62331fd9b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,20 +1,20 @@ -# Wechaty v0.37.7 Documentation +# Wechaty v0.48.2 Documentation -- Blog - +- Website - +- Docs Site - - API References - -- Docs Site - ## Classes
+## Constants + +
+
cuid_1
+

Wechaty Chatbot SDK - https://github.com/wechaty/wechaty

+
+
clone_class_1
+

Wechaty Chatbot SDK - https://github.com/wechaty/wechaty

+
+
clone_class_1
+

Wechaty Chatbot SDK - https://github.com/wechaty/wechaty

+
+
wechaty_puppet_1
+

Wechaty Chatbot SDK - https://github.com/wechaty/wechaty

+
+
events_1
+

Wechaty Chatbot SDK - https://github.com/wechaty/wechaty

+
+
events_1
+

Wechaty Chatbot SDK - https://github.com/wechaty/wechaty

+
+
clone_class_1
+

Wechaty Chatbot SDK - https://github.com/wechaty/wechaty

+
+
+ +## Functions + +
+
guardWechatify()
+

Huan(202008): we will bind the wechaty puppet with user modules (Contact, Room, etc) together inside the start() method

+
+
+ ## Typedefs
PuppetModuleName

The term 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 the component that helps Wechaty to control the WeChat(that's the reason we call it puppet). The plugins are named XXXPuppet, for example:

  • PuppetPuppeteer:
  • @@ -72,12 +106,6 @@ The plugins are named XXXPuppet, for example:

    WechatyOptions

    The option parameter to create a wechaty instance

    -
    WechatyEventName
    -

    Wechaty Class Event Type

    -
    -
    WechatyEventFunction
    -

    Wechaty Class Event Function

    -
    RoomQueryFilter

    The filter to find the room: {topic: string | RegExp}

    @@ -100,11 +128,11 @@ The plugins are named XXXPuppet, for example:

    ## Wechaty Main bot class. -A `Bot` is a wechat client depends on which puppet you use. +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 +- 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/wechaty-getting-started/wiki/FAQ-EN#31-what-is-a-puppet-in-wechaty) @@ -117,8 +145,9 @@ See more: * [Wechaty](#Wechaty) * [new Wechaty([options])](#new_Wechaty_new) * _instance_ + * [.wechatifiedContact](#Wechaty+wechatifiedContact) * [.name()](#Wechaty+name) - * [.on(event, listener)](#Wechaty+on) ⇒ [Wechaty](#Wechaty) + * [.use(...plugins)](#Wechaty+use) ⇒ [Wechaty](#Wechaty) * [.start()](#Wechaty+start) ⇒ Promise.<void> * [.stop()](#Wechaty+stop) ⇒ Promise.<void> * [.logout()](#Wechaty+logout) ⇒ Promise.<void> @@ -127,6 +156,7 @@ See more: * [.say(something)](#Wechaty+say) ⇒ Promise.<void> * _static_ * [.instance([options])](#Wechaty.instance) + * [.use(...plugins)](#Wechaty.use) ⇒ [Wechaty](#Wechaty) @@ -142,142 +172,44 @@ Creates an instance of Wechaty. ```js const { Wechaty } = require('wechaty') const bot = new Wechaty() -bot.on('scan', (qrcode, status) => console.log('https://wechaty.js.org/qrcode/' + encodeURIComponent(qrcode))) +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() ``` + + +### wechaty.wechatifiedContact +1. Setup Wechaty User Classes + +**Kind**: instance property of [Wechaty](#Wechaty) ### wechaty.name() -Wechaty bot name set by `optoins.name` +Wechaty bot name set by `options.name` default: `wechaty` **Kind**: instance method of [Wechaty](#Wechaty) - - -### wechaty.on(event, listener) ⇒ [Wechaty](#Wechaty) -When the bot get message, it will emit the following Event. + -You can do anything you want when in these events functions. -The main Event name as follows: -- **scan**: Emit when the bot needs to show you a QR Code for scanning. After scan the qrcode, you can login -- **login**: Emit when bot login full successful. -- **logout**: Emit when bot detected log out. -- **message**: Emit when there's a new message. - -see more in [WechatyEventName](#WechatyEventName) +### wechaty.use(...plugins) ⇒ [Wechaty](#Wechaty) +For wechaty ecosystem, allow user to define a 3rd party plugin for the current wechaty instance. **Kind**: instance method of [Wechaty](#Wechaty) -**Returns**: [Wechaty](#Wechaty) - - this for chaining, -see advanced [chaining usage](https://github.com/wechaty/wechaty-getting-started/wiki/FAQ-EN#36-why-wechatyonevent-listener-return-wechaty) +**Returns**: [Wechaty](#Wechaty) - - this for chaining, | Param | Type | Description | | --- | --- | --- | -| event | [WechatyEventName](#WechatyEventName) | Emit WechatyEvent | -| listener | [WechatyEventFunction](#WechatyEventFunction) | Depends on the WechatyEvent | - -**Example** *(Event:scan)* -```js -// Scan Event will emit when the bot needs to show you a QR Code for scanning +| ...plugins | Array.<WechatyPlugin> | The plugins you want to use | -bot.on('scan', (url, status) => { - console.log(`[${status}] Scan ${url} to login.` ) -}) -``` -**Example** *(Event:login )* -```js -// Login Event will emit when bot login full successful. - -bot.on('login', (user) => { - console.log(`user ${user} login`) -}) -``` -**Example** *(Event:logout )* -```js -// Logout Event will emit when bot detected log out. - -bot.on('logout', (user) => { - console.log(`user ${user} logout`) -}) -``` -**Example** *(Event:message )* -```js -// Message Event will emit when there's a new message. - -wechaty.on('message', (message) => { - console.log(`message ${message} received`) -}) -``` -**Example** *(Event:friendship )* -```js -// Friendship Event will emit when got a new friend request, or friendship is confirmed. - -bot.on('friendship', (friendship) => { - if(friendship.type() === Friendship.Type.Receive){ // 1. receive new friendship request from new contact - const contact = friendship.contact() - let result = await friendship.accept() - if(result){ - console.log(`Request from ${contact.name()} is accept succesfully!`) - } else{ - console.log(`Request from ${contact.name()} failed to accept!`) - } - } else if (friendship.type() === Friendship.Type.Confirm) { // 2. confirm friendship - console.log(`new friendship confirmed with ${contact.name()}`) - } - }) -``` -**Example** *(Event:room-join )* -```js -// room-join Event will emit when someone join the room. - -bot.on('room-join', (room, inviteeList, inviter) => { - const nameList = inviteeList.map(c => c.name()).join(',') - console.log(`Room ${room.topic()} got new member ${nameList}, invited by ${inviter}`) -}) -``` -**Example** *(Event:room-leave )* -```js -// room-leave Event will emit when someone leave the room. - -bot.on('room-leave', (room, leaverList) => { - const nameList = leaverList.map(c => c.name()).join(',') - console.log(`Room ${room.topic()} lost member ${nameList}`) -}) -``` -**Example** *(Event:room-topic )* -```js -// room-topic Event will emit when someone change the room's topic. - -bot.on('room-topic', (room, topic, oldTopic, changer) => { - console.log(`Room ${room.topic()} topic changed from ${oldTopic} to ${topic} by ${changer.name()}`) -}) -``` -**Example** *(Event:room-invite, RoomInvitation has been encapsulated as a RoomInvitation Class. )* -```js -// room-invite Event will emit when there's an room invitation. - -bot.on('room-invite', async roomInvitation => { - try { - console.log(`received room-invite event.`) - await roomInvitation.accept() - } catch (e) { - console.error(e) - } -} -``` -**Example** *(Event:error )* +**Example** ```js -// error Event will emit when there's an error occurred. - -bot.on('error', (error) => { - console.error(error) -}) +// The same usage with Wechaty.use(). ``` ### wechaty.start() ⇒ Promise.<void> -When you start the bot, bot will begin to login, need you wechat scan qrcode to login +When you start the bot, bot will begin to login, need you WeChat scan qrcode to login > Tips: All the bot operation needs to be triggered after start() is done **Kind**: instance method of [Wechaty](#Wechaty) @@ -315,9 +247,9 @@ Get the logon / logoff state **Example** ```js if (bot.logonoff()) { - console.log('Bot logined') + console.log('Bot logged in') } else { - console.log('Bot not logined') + console.log('Bot not logged in') } ``` @@ -404,14 +336,38 @@ const { Wechaty } = require('wechaty') Wechaty.instance() // Global instance .on('scan', (url, status) => console.log(`Scan QR Code to login: ${status}\n${url}`)) -.on('login', user => console.log(`User ${user} logined`)) +.on('login', user => console.log(`User ${user} logged in`)) .on('message', message => console.log(`Message: ${message}`)) .start() ``` + + +### Wechaty.use(...plugins) ⇒ [Wechaty](#Wechaty) +For wechaty ecosystem, allow user to define a 3rd party plugin for the all wechaty instances + +**Kind**: static method of [Wechaty](#Wechaty) +**Returns**: [Wechaty](#Wechaty) - - this for chaining, + +| Param | Type | Description | +| --- | --- | --- | +| ...plugins | Array.<WechatyPlugin> | The plugins you want to use | + +**Example** +```js +// Report all chat message to my server. + +function WechatyReportPlugin(options: { url: string }) { + return function (this: Wechaty) { + this.on('message', message => http.post(options.url, { data: message })) + } +} + +bot.use(WechatyReportPlugin({ url: 'http://somewhere.to.report.your.data.com' }) +``` ## Room -All wechat rooms(groups) will be encapsulated as a Room. +All WeChat rooms(groups) will be encapsulated as a Room. [Examples/Room-Bot](https://github.com/wechaty/wechaty/blob/1523c5e02be46ebe2cc172a744b2fbe53351540e/examples/room-bot.ts) @@ -427,13 +383,12 @@ All wechat rooms(groups) will be encapsulated as a Room. * _instance_ * [.sync()](#Room+sync) ⇒ Promise.<void> * [.say(textOrContactOrFileOrUrlOrMini, [mention])](#Room+say) ⇒ Promise.<(void\|Message)> - * [.on(event, listener)](#Room+on) ⇒ this * [.add(contact)](#Room+add) ⇒ Promise.<void> * [.del(contact)](#Room+del) ⇒ Promise.<void> * [.quit()](#Room+quit) ⇒ Promise.<void> * [.topic([newTopic])](#Room+topic) ⇒ Promise.<(string\|void)> * [.announce([text])](#Room+announce) ⇒ Promise.<(void\|string)> - * [.qrcode()](#Room+qrcode) ⇒ Promise.<string> + * [.qrCode()](#Room+qrCode) ⇒ Promise.<string> * [.alias(contact)](#Room+alias) ⇒ Promise.<(string\|null)> * [.has(contact)](#Room+has) ⇒ Promise.<boolean> * [.memberAll([query])](#Room+memberAll) ⇒ Promise.<Array.<Contact>> @@ -448,7 +403,7 @@ All wechat rooms(groups) will be encapsulated as a Room. ### room.sync() ⇒ Promise.<void> -Force reload data for Room, Sync data from lowlevel API again. +Force reload data for Room, Sync data from puppet API again. **Kind**: instance method of [Room](#Room) **Example** @@ -529,77 +484,6 @@ const miniProgram = new MiniProgram ({ await room.say(miniProgram) const msg = await room.say(miniProgram) // only supported by puppet-padplus ``` - - -### room.on(event, listener) ⇒ this -**Kind**: instance method of [Room](#Room) -**Returns**: this - - this for chain - -| Param | Type | Description | -| --- | --- | --- | -| event | [RoomEventName](#RoomEventName) | Emit WechatyEvent | -| listener | [RoomEventFunction](#RoomEventFunction) | Depends on the WechatyEvent | - -**Example** *(Event:join )* -```js -const bot = new Wechaty() -await bot.start() -// after logged in... -const room = await bot.Room.find({topic: 'topic of your room'}) // change `event-room` to any room topic in your wechat -if (room) { - room.on('join', (room, inviteeList, inviter) => { - const nameList = inviteeList.map(c => c.name()).join(',') - console.log(`Room got new member ${nameList}, invited by ${inviter}`) - }) -} -``` -**Example** *(Event:leave )* -```js -const bot = new Wechaty() -await bot.start() -// after logged in... -const room = await bot.Room.find({topic: 'topic of your room'}) // change `event-room` to any room topic in your wechat -if (room) { - room.on('leave', (room, leaverList) => { - const nameList = leaverList.map(c => c.name()).join(',') - console.log(`Room lost member ${nameList}`) - }) -} -``` -**Example** *(Event:message )* -```js -const bot = new Wechaty() -await bot.start() -// after logged in... -const room = await bot.Room.find({topic: 'topic of your room'}) // change `event-room` to any room topic in your wechat -if (room) { - room.on('message', (message) => { - console.log(`Room received new message: ${message}`) - }) -} -``` -**Example** *(Event:topic )* -```js -const bot = new Wechaty() -await bot.start() -// after logged in... -const room = await bot.Room.find({topic: 'topic of your room'}) // change `event-room` to any room topic in your wechat -if (room) { - room.on('topic', (room, topic, oldTopic, changer) => { - console.log(`Room topic changed from ${oldTopic} to ${topic} by ${changer.name()}`) - }) -} -``` -**Example** *(Event:invite )* -```js -const bot = new Wechaty() -await bot.start() -// after logged in... -const room = await bot.Room.find({topic: 'topic of your room'}) // change `event-room` to any room topic in your wechat -if (room) { - room.on('invite', roomInvitation => roomInvitation.accept()) -} -``` ### room.add(contact) ⇒ Promise.<void> @@ -621,8 +505,8 @@ This function is depending on the Puppet Implementation, see [puppet-compatible- const bot = new Wechaty() await bot.start() // after logged in... -const contact = await bot.Contact.find({name: 'lijiarui'}) // change 'lijiarui' to any contact in your wechat -const room = await bot.Room.find({topic: 'wechat'}) // change 'wechat' to any room topic in your wechat +const contact = await bot.Contact.find({name: 'lijiarui'}) // change 'lijiarui' to any contact in your WeChat +const room = await bot.Room.find({topic: 'WeChat'}) // change 'WeChat' to any room topic in your WeChat if (room) { try { await room.add(contact) @@ -653,7 +537,7 @@ This function is depending on the Puppet Implementation, see [puppet-compatible- const bot = new Wechaty() await bot.start() // after logged in... -const room = await bot.Room.find({topic: 'wechat'}) // change 'wechat' to any room topic in your wechat +const room = await bot.Room.find({topic: 'WeChat'}) // change 'WeChat' to any room topic in your WeChat const contact = await bot.Contact.find({name: 'lijiarui'}) // change 'lijiarui' to any room member in the room you just set if (room) { try { @@ -747,9 +631,9 @@ const oldAnnounce = await room.announce() await room.announce('change announce to wechaty!') console.log(`room announce change from ${oldAnnounce} to ${room.announce()}`) ``` - + -### room.qrcode() ⇒ Promise.<string> +### room.qrCode() ⇒ Promise.<string> Get QR Code Value of the Room from the room, which can be used as scan and join the room. > Tips: 1. This function is depending on the Puppet Implementation, see [puppet-compatible-table](https://github.com/wechaty/wechaty/wiki/Puppet#3-puppet-compatible-table) @@ -799,8 +683,8 @@ Check if the room has member `contact`, the return is a Promise and must be `awa const bot = new Wechaty() await bot.start() // after logged in... -const contact = await bot.Contact.find({name: 'lijiarui'}) // change 'lijiarui' to any of contact in your wechat -const room = await bot.Room.find({topic: 'wechaty'}) // change 'wechaty' to any of the room in your wechat +const contact = await bot.Contact.find({name: 'lijiarui'}) // change 'lijiarui' to any of contact in your WeChat +const room = await bot.Room.find({topic: 'wechaty'}) // change 'wechaty' to any of the room in your WeChat if (contact && room) { if (await room.has(contact)) { console.log(`${contact.name()} is in the room wechaty!`) @@ -827,10 +711,10 @@ Find all contacts in a room **Example** ```js -const roomList:Conatct[] | null = await room.findAll() +const roomList:Contact[] | null = await room.findAll() if(roomList) console.log(`room all member list: `, roomList) -const memberContactList: Conatct[] | null =await room.findAll(`abc`) +const memberContactList: Contact[] | null =await room.findAll(`abc`) console.log(`contact list with all name, room alias, alias are abc:`, memberContactList) ``` @@ -849,9 +733,9 @@ Find all contacts in a room, if get many, return the first one. const bot = new Wechaty() await bot.start() // after logged in... -const room = await bot.Room.find({topic: 'wechaty'}) // change 'wechaty' to any room name in your wechat +const room = await bot.Room.find({topic: 'wechaty'}) // change 'wechaty' to any room name in your WeChat if (room) { - const member = await room.member('lijiarui') // change 'lijiarui' to any room member in your wechat + const member = await room.member('lijiarui') // change 'lijiarui' to any room member in your WeChat if (member) { console.log(`wechaty room got the member: ${member.name()}`) } else { @@ -864,9 +748,9 @@ if (room) { const bot = new Wechaty() await bot.start() // after logged in... -const room = await bot.Room.find({topic: 'wechaty'}) // change 'wechaty' to any room name in your wechat +const room = await bot.Room.find({topic: 'wechaty'}) // change 'wechaty' to any room name in your WeChat if (room) { - const member = await room.member({name: 'lijiarui'}) // change 'lijiarui' to any room member in your wechat + const member = await room.member({name: 'lijiarui'}) // change 'lijiarui' to any room member in your WeChat if (member) { console.log(`wechaty room got the member: ${member.name()}`) } else { @@ -910,10 +794,10 @@ Create a new room. | contactList | [Array.<Contact>](#Contact) | | [topic] | string | -**Example** *(Creat a room with 'lijiarui' and 'juxiaomi', the room topic is 'ding - created')* +**Example** *(Creat a room with 'lijiarui' and 'huan', the room topic is 'ding - created')* ```js -const helperContactA = await Contact.find({ name: 'lijiarui' }) // change 'lijiarui' to any contact in your wechat -const helperContactB = await Contact.find({ name: 'juxiaomi' }) // change 'juxiaomi' to any contact in your wechat +const helperContactA = await Contact.find({ name: 'lijiarui' }) // change 'lijiarui' to any contact in your WeChat +const helperContactB = await Contact.find({ name: 'huan' }) // change 'huan' to any contact in your WeChat const contactList = [helperContactA, helperContactB] console.log('Bot', 'contactList: %s', contactList.join(',')) const room = await Room.create(contactList, 'ding') @@ -1193,7 +1077,7 @@ const tags = await contact.tags() ### contact.sync() ⇒ Promise.<this> -Force reload data for Contact, Sync data from lowlevel API again. +Force reload data for Contact, Sync data from low-level API again. **Kind**: instance method of [Contact](#Contact) **Example** @@ -1254,7 +1138,7 @@ If use Contact.findAll() get the contact list of the bot. const bot = new Wechaty() await bot.start() const contactList = await bot.Contact.findAll() // get the contact list of the bot -const contactList = await bot.Contact.findAll({ name: 'ruirui' }) // find allof the contacts whose name is 'ruirui' +const contactList = await bot.Contact.findAll({ name: 'ruirui' }) // find all of the contacts whose name is 'ruirui' const contactList = await bot.Contact.findAll({ alias: 'lijiarui' }) // find all of the contacts whose alias is 'lijiarui' ``` @@ -1374,7 +1258,6 @@ Send, receive friend request, and friend confirmation events. * [.toJSON()](#Friendship+toJSON) ⇒ FriendshipPayload * _static_ * [.search(condition)](#Friendship.search) ⇒ [Promise.<Contact>](#Contact) - * ~~[.send()](#Friendship.send)~~ * [.add(contact, hello)](#Friendship.add) ⇒ Promise.<void> * [.fromJSON()](#Friendship.fromJSON) @@ -1513,14 +1396,6 @@ const friend_weixin = await bot.Friendship.search({weixin: 'weixin_account'}) console.log(`This is the new friend info searched by phone : ${friend_phone}`) await bot.Friendship.add(friend_phone, 'hello') ``` - - -### ~~Friendship.send()~~ -***Deprecated*** - -use [Friendship#add](Friendship#add) instead - -**Kind**: static method of [Friendship](#Friendship) ### Friendship.add(contact, hello) ⇒ Promise.<void> @@ -1572,7 +1447,6 @@ All wechat messages will be encapsulated as a Message. * [.from()](#Message+from) ⇒ [Contact](#Contact) * [.to()](#Message+to) ⇒ [Contact](#Contact) \| null * [.room()](#Message+room) ⇒ [Room](#Room) \| null - * ~~[.content()](#Message+content)~~ * [.text()](#Message+text) ⇒ string * [.toRecalled()](#Message+toRecalled) * [.say(textOrContactOrFile, [mention])](#Message+say) ⇒ Promise.<(void\|Message)> @@ -1584,7 +1458,6 @@ All wechat messages will be encapsulated as a Message. * [.forward(to)](#Message+forward) ⇒ Promise.<void> * [.date()](#Message+date) * [.age()](#Message+age) ⇒ number - * ~~[.file()](#Message+file)~~ * [.toFileBox()](#Message+toFileBox) ⇒ Promise.<FileBox> * [.toImage()](#Message+toImage) ⇒ Image * [.toContact()](#Message+toContact) ⇒ [Promise.<Contact>](#Contact) @@ -1646,14 +1519,6 @@ bot }) .start() ``` - - -### ~~message.content()~~ -***Deprecated*** - -use [text](#Message+text) instead - -**Kind**: instance method of [Message](#Message) ### message.text() ⇒ string @@ -1728,8 +1593,8 @@ bot // 2. send Text if (/^dong$/i.test(m.text())) { - await msg.say('dingdingding') - const message = await msg.say('dingdingding') // only supported by puppet-padplus + await msg.say('ding') + const message = await msg.say('ding') // only supported by puppet-padplus } // 3. send Contact @@ -1903,14 +1768,7 @@ and when we received it in Wechaty, the time is `8:43:15`, then the age() will return `8:43:15 - 8:43:01 = 14 (seconds)` **Kind**: instance method of [Message](#Message) - - -### ~~message.file()~~ -***Deprecated*** - -use [toFileBox](#Message+toFileBox) instead - -**Kind**: instance method of [Message](#Message) +**Returns**: number - message age in seconds. ### message.toFileBox() ⇒ Promise.<FileBox> @@ -2074,11 +1932,157 @@ const dataFromDisk // get the room invitation info data from disk const roomInvitation = await bot.RoomInvitation.fromJSON(dataFromDisk) await roomInvitation.accept() ``` + + +## cuid\_1 +Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + +**Kind**: global constant +**Copyright**: 2016 Huan LI (李卓桓) , and + Wechaty Contributors . + + 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. + + +## clone\_class\_1 +Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + +**Kind**: global constant +**Copyright**: 2016 Huan LI (李卓桓) , and + Wechaty Contributors . + + 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. + + +## clone\_class\_1 +Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + +**Kind**: global constant +**Copyright**: 2016 Huan LI (李卓桓) , and + Wechaty Contributors . + + 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. + + +## wechaty\_puppet\_1 +Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + +**Kind**: global constant +**Copyright**: 2016 Huan LI (李卓桓) , and + Wechaty Contributors . + + 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. + + +## events\_1 +Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + +**Kind**: global constant +**Copyright**: 2016 Huan LI (李卓桓) , and + Wechaty Contributors . + + 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. + + +## events\_1 +Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + +**Kind**: global constant +**Copyright**: 2016 Huan LI (李卓桓) , and + Wechaty Contributors . + + 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. + + +## clone\_class\_1 +Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + +**Kind**: global constant +**Copyright**: 2016 Huan LI (李卓桓) , and + Wechaty Contributors . + + 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. + + +## guardWechatify() +Huan(202008): we will bind the wechaty puppet with user modules (Contact, Room, etc) together inside the start() method + +**Kind**: global function ## PuppetModuleName The term [Puppet](https://github.com/wechaty/wechaty/wiki/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 the component that helps Wechaty to control the WeChat(that's the reason we call it puppet). The plugins are named XXXPuppet, for example: - [PuppetPuppeteer](https://github.com/wechaty/wechaty-puppet-puppeteer): - [PuppetPadchat](https://github.com/wechaty/wechaty-puppet-padchat) @@ -2090,7 +2094,7 @@ The plugins are named XXXPuppet, for example: | --- | --- | --- | | PUPPET_DEFAULT | string | The default puppet. | | wechaty-puppet-wechat4u | string | 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. | -| wechaty-puppet-padchat | string | - Using the WebSocket protocol to connect with a Protocol Server for controlling the iPad Wechat program. | +| wechaty-puppet-padchat | string | - Using the WebSocket protocol to connect with a Protocol Server for controlling the iPad WeChat program. | | wechaty-puppet-puppeteer | string | - Using the [google puppeteer](https://github.com/GoogleChrome/puppeteer) to control the [WeChat Web API](https://wx.qq.com/) via a chrome browser. | | wechaty-puppet-mock | string | - Using the mock data to mock wechat operation, just for test. | @@ -2104,57 +2108,11 @@ The option parameter to create a wechaty instance | Name | Type | Description | | --- | --- | --- | -| name | string | Wechaty Name.
    When you set this:
    `new Wechaty({name: 'wechaty-name'}) `
    it will generate a file called `wechaty-name.memory-card.json`.
    This file stores the bot's login information.
    If the file is valid, the bot can auto login so you don't need to scan the qrcode to login again.
    Also, you can set the environment variable for `WECHATY_NAME` to set this value when you start.
    eg: `WECHATY_NAME="your-cute-bot-name" node bot.js` | +| name | string | Wechaty Name.
    When you set this:
    `new Wechaty({name: 'wechaty-name'}) `
    it will generate a file called `wechaty-name.memory-card.json`.
    This file stores the login information for bot.
    If the file is valid, the bot can auto login so you don't need to scan the qrCode to login again.
    Also, you can set the environment variable for `WECHATY_NAME` to set this value when you start.
    eg: `WECHATY_NAME="your-cute-bot-name" node bot.js` | | puppet | [PuppetModuleName](#PuppetModuleName) \| Puppet | Puppet name or instance | | puppetOptions | Partial.<PuppetOptions> | Puppet TOKEN | | ioToken | string | Io TOKEN | - - -## WechatyEventName -Wechaty Class Event Type - -**Kind**: global typedef -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| error | string | When the bot get error, there will be a Wechaty error event fired. | -| login | string | After the bot login full successful, the event login will be emitted, with a Contact of current logined user. | -| logout | string | Logout will be emitted when bot detected log out, with a Contact of the current login user. | -| heartbeat | string | Get bot's heartbeat. | -| friendship | string | When someone sends you a friend request, there will be a Wechaty friendship event fired. | -| message | string | Emit when there's a new message. | -| ready | string | Emit when all data has load completed, in wechaty-puppet-padchat, it means it has sync Contact and Room completed | -| room-join | string | Emit when anyone join any room. | -| room-topic | string | Get topic event, emitted when someone change room topic. | -| room-leave | string | Emit when anyone leave the room.
    - If someone leaves the room by themselves, wechat will not notice other people in the room, so the bot will never get the "leave" event. | -| room-invite | string | Emit when there is a room invitation, see more in [RoomInvitation](#RoomInvitation) | -| scan | string | A scan event will be emitted when the bot needs to show you a QR Code for scanning.
    It is recommend to install qrcode-terminal(run `npm install qrcode-terminal`) in order to show qrcode in the terminal. | - - - -## WechatyEventFunction -Wechaty Class Event Function - -**Kind**: global typedef -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| error | function | (this: Wechaty, error: Error) => void callback function | -| login | function | (this: Wechaty, user: ContactSelf)=> void | -| logout | function | (this: Wechaty, user: ContactSelf) => void | -| scan | function | (this: Wechaty, url: string, code: number) => void
    1. URL: {String} the QR code image URL
    2. code: {Number} the scan status code. some known status of the code list here is:
    • 0 initial_
    • 200 login confirmed
    • 201 scaned, wait for confirm
    • 408 waits for scan
    | -| heartbeat | function | (this: Wechaty, data: any) => void | -| friendship | function | (this: Wechaty, friendship: Friendship) => void | -| message | function | (this: Wechaty, message: Message) => void | -| ready | function | (this: Wechaty) => void | -| room-join | function | (this: Wechaty, room: Room, inviteeList: Contact[], inviter: Contact) => void | -| room-topic | function | (this: Wechaty, room: Room, newTopic: string, oldTopic: string, changer: Contact) => void | -| room-leave | function | (this: Wechaty, room: Room, leaverList: Contact[]) => void | -| room-invite | function | (this: Wechaty, room: Room, roomInvitation: RoomInvitation) => void
    see more in [RoomInvitation](#RoomInvitation) | - ## RoomQueryFilter @@ -2179,7 +2137,7 @@ Room Class Event Type | --- | --- | --- | | join | string | Emit when anyone join any room. | | topic | string | Get topic event, emitted when someone change room topic. | -| leave | string | Emit when anyone leave the room.
    If someone leaves the room by themselves, wechat will not notice other people in the room, so the bot will never get the "leave" event. | +| leave | string | Emit when anyone leave the room.
    If someone leaves the room by themselves, WeChat will not notice other people in the room, so the bot will never get the "leave" event. | @@ -2205,7 +2163,7 @@ The way to search member by Room.member() | Name | Type | Description | | --- | --- | --- | -| name | string | Find the contact by wechat name in a room, equal to `Contact.name()`. | +| name | string | Find the contact by WeChat name in a room, equal to `Contact.name()`. | | roomAlias | string | Find the contact by alias set by the bot for others in a room. | | contactAlias | string | Find the contact by alias set by the contact out of a room, equal to `Contact.alias()`. [More Detail](https://github.com/wechaty/wechaty/issues/365) | From 4ea5562f17dacc6f835f67c82a90c2a40bfe777f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 24 Aug 2020 18:23:12 +0800 Subject: [PATCH 461/598] 0.48.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d76a7b069..79ed83d0a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.48.2", + "version": "0.48.3", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From f1bab91b45ada544a103475d53a63301518cda4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 27 Aug 2020 15:20:25 +0800 Subject: [PATCH 462/598] add gitter puppet --- .vscode/settings.json | 1 + src/puppet-config.ts | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 5fa7ab956..81362cdbd 100755 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -92,6 +92,7 @@ "thumbnailurl", "wechat", "weixin", + "wxwork", "zbeekman", "zixia" ], diff --git a/src/puppet-config.ts b/src/puppet-config.ts index ed5fe06f8..f5451ece1 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -1,3 +1,4 @@ +/* eslint-disable sort-keys */ /** * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * @@ -40,10 +41,15 @@ export const PUPPET_DEPENDENCIES = { /** * Wechaty External Puppets */ - 'wechaty-puppet-official-account' : '^0.2.2', // https://www.npmjs.com/package/wechaty-puppet-official-account 'wechaty-puppet-padplus' : '^0.7.30', // https://www.npmjs.com/package/wechaty-puppet-padplus 'wechaty-puppet-puppeteer' : '^0.23.1', // https://www.npmjs.com/package/wechaty-puppet-puppeteer 'wechaty-puppet-wechat4u' : '^0.17.4', // https://www.npmjs.com/package/wechaty-puppet-wechat4u + + /** + * Other + */ + 'wechaty-puppet-gitter' : '^0.3.1', // https://www.npmjs.com/package/wechaty-puppet-gitter + 'wechaty-puppet-official-account' : '^0.2.2', // https://www.npmjs.com/package/wechaty-puppet-official-account } export type PuppetModuleName = keyof typeof PUPPET_DEPENDENCIES From 7c2caaf959e967768b0b4baa129147a7e3fa8f26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 27 Aug 2020 15:20:42 +0800 Subject: [PATCH 463/598] 0.48.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 79ed83d0a..c1de3ff02 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.48.3", + "version": "0.48.4", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 407a592b687b30a364397ff94b4c81ebef6ae94c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 27 Aug 2020 15:39:10 +0800 Subject: [PATCH 464/598] fix typo --- examples/ding-dong-bot.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/ding-dong-bot.ts b/examples/ding-dong-bot.ts index d726e85f5..2ab751730 100644 --- a/examples/ding-dong-bot.ts +++ b/examples/ding-dong-bot.ts @@ -91,11 +91,10 @@ function onScan (qrcode: string, status: ScanStatus) { function onLogin (user: Contact) { console.info(`${user.name()} login`) - bot.say('Wechaty login').catch(console.error) } function onLogout (user: Contact) { - console.info(`${user.name()} logouted`) + console.info(`${user.name()} logged out`) } function onError (e: Error) { From 4c7464aa92e71170ab1fadfc739c2304913eb0f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 27 Aug 2020 15:39:23 +0800 Subject: [PATCH 465/598] 0.48.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c1de3ff02..5669c7e50 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.48.4", + "version": "0.48.5", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From cec5b84eec934c2bae951d89ba174dfac4022887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 29 Aug 2020 21:10:38 +0800 Subject: [PATCH 466/598] add location user module --- src/user/location.ts | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/user/location.ts diff --git a/src/user/location.ts b/src/user/location.ts new file mode 100644 index 000000000..1d7467204 --- /dev/null +++ b/src/user/location.ts @@ -0,0 +1,39 @@ +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ + +/** + * Location information + */ +class Location { + + /** + * @param {number} latitude + * @param {number} longitude + * @param {?string} description + */ + constructor ( + public latitude : number, + public longitude : number, + public description : string, + ) {} + +} + +export { Location } From 630e0ed3098eb9b70849d91da2a0a1c3d1856fca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 29 Aug 2020 21:10:53 +0800 Subject: [PATCH 467/598] 0.47.25 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 114430c35..ec7501dac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.47.24", + "version": "0.47.25", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 2c1f138248fe8810a9de5e3bbba72d33d698b0e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 29 Aug 2020 21:11:23 +0800 Subject: [PATCH 468/598] 0.48.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5669c7e50..21586ca59 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.48.5", + "version": "0.48.6", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From d25cd6223f6404fd80c022d9a86f89d9c58e51fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 1 Sep 2020 14:38:01 +0800 Subject: [PATCH 469/598] clean --- src/version.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.spec.ts b/src/version.spec.ts index 1a0942718..29091c073 100755 --- a/src/version.spec.ts +++ b/src/version.spec.ts @@ -19,7 +19,7 @@ * limitations under the License. * */ -import test from 'blue-tape' +import test from 'tstest' import { VERSION, From 9aeb8dff7c90e04e485d889712db9c0b9ae470ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 1 Sep 2020 14:38:50 +0800 Subject: [PATCH 470/598] 0.48.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 21586ca59..98b4d0019 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.48.6", + "version": "0.48.7", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 113b0ad46ff5f83620f8605064977d154bd803bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 1 Sep 2020 14:43:51 +0800 Subject: [PATCH 471/598] add telegram channel for wechaty --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 53252a116..2d3367afc 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ [![Docker Pulls](https://img.shields.io/docker/pulls/wechaty/wechaty.svg?maxAge=2592000)](https://hub.docker.com/r/wechaty/wechaty/) [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-blue.svg)](https://www.typescriptlang.org/) [![Gitter](https://badges.gitter.im/wechaty/wechaty.svg)](https://gitter.im/wechaty/wechaty?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) +[![Telegram Wechaty Channel](https://img.shields.io/badge/chat-on%20telegram-blue)](https://t.me/wechaty) ## :hearts: Connecting Chatbots From 34a7b7f5af297152b7920815401c71cd78c856fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 1 Sep 2020 14:44:19 +0800 Subject: [PATCH 472/598] 0.48.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 98b4d0019..9ad6fa5b2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.48.7", + "version": "0.48.8", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From d0f8188f8a0003d807169adee92c98607683da1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 2 Sep 2020 17:49:52 +0800 Subject: [PATCH 473/598] add bibtex cite code --- README.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2d3367afc..aa97971f5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Wechaty [![NPM Version](https://img.shields.io/npm/v/wechaty?color=brightgreen)](https://www.npmjs.com/package/wechaty) [![NPM](https://github.com/wechaty/wechaty/workflows/NPM/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ANPM) [![Docker](https://github.com/wechaty/wechaty/workflows/Docker/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ADocker) + Wechaty [![NPM Version](https://img.shields.io/npm/v/wechaty?color=brightgreen)](https://www.npmjs.com/package/wechaty) [![NPM](https://github.com/wechaty/wechaty/workflows/NPM/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ANPM) [![Docker](https://github.com/wechaty/wechaty/workflows/Docker/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ADocker) [![Wechaty](https://wechaty.js.org/img/wechaty-logo.svg)](https://wechaty.js.org) @@ -476,6 +476,21 @@ Support this project by becoming a sponsor. Your logo will show up here with a l [![Profile of Huan LI (李卓桓) on StackOverflow](https://stackoverflow.com/users/flair/1123955.png)](https://stackoverflow.com/users/1123955/huan) +## Cite Wechaty + +To cite this project in publications: + +```bibtex +@misc{wechaty, + author = {Huan LI, Jiarui LI}, + title = {Wechaty: Conversational SDK for Chatbot Makers}, + year = {2016}, + publisher = {GitHub}, + journal = {GitHub Repository}, + howpublished = {\url{https://github.com/wechaty/wechaty}}, +} +``` + ## :email: Copyright & License - Code & Docs © 2016-now Huan, Rui, and Wechaty Community Contributors From cc08e80789c10dccc685ed92fa9c6e110c44dd1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 2 Sep 2020 17:50:08 +0800 Subject: [PATCH 474/598] 0.48.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9ad6fa5b2..7af3df9e1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.48.8", + "version": "0.48.9", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 73d7e65006568c30afd72317234992d79493b0a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 2 Sep 2020 18:06:56 +0800 Subject: [PATCH 475/598] add star history badge --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index aa97971f5..7f177f889 100644 --- a/README.md +++ b/README.md @@ -414,6 +414,10 @@ So a tireless bot working for me 24x7 on wechat, monitoring/filtering the most i At last, It's built for huan's personal study purpose of Automatically Testing. +## Stargazers over time + +[![Stargazers over time](https://starchart.cc/wechaty/wechaty.svg)](https://starchart.cc/wechaty/wechaty) + ## :two_hearts: Contributors [![GitHub issues](https://img.shields.io/github/issues/wechaty/wechaty.svg)](https://github.com/Wechaty/wechaty/issues) From 8f137aa5a4b0d8e716146e961ebbe086bc0bb3a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 2 Sep 2020 18:07:11 +0800 Subject: [PATCH 476/598] 0.48.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7af3df9e1..331fbb7b3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.48.9", + "version": "0.48.10", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 3c338f5d7ab4038eec9c9b5ad1f637294e7cddec Mon Sep 17 00:00:00 2001 From: Yuan Gao Date: Mon, 28 Sep 2020 17:48:53 +0800 Subject: [PATCH 477/598] Split to trunks when making requests of room.findAll() and room.ready() (#2067) * add pagination on room.findAll() and room.ready() * 0.48.11 --- package.json | 2 +- src/user/room.ts | 64 +++++++++++++++++++++++++++++++----------------- 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index 331fbb7b3..df5d0bece 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.48.10", + "version": "0.48.11", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", diff --git a/src/user/room.ts b/src/user/room.ts index fa18a1f95..04c5a81d9 100644 --- a/src/user/room.ts +++ b/src/user/room.ts @@ -130,22 +130,34 @@ class Room extends RoomEventEmitter implements Sayable { ): Promise> { log.verbose('Room', 'findAll(%s)', JSON.stringify(query) || '') - const invalidDict: { [id: string]: true } = {} - try { const roomIdList = await this.wechaty.puppet.roomSearch(query) const roomList = roomIdList.map(id => this.load(id)) - await Promise.all( - roomList.map( - room => room.ready() - .catch(e => { - log.warn('Room', 'findAll() room.ready() rejection: %s', e) - invalidDict[room.id] = true - }) - ), - ) - return roomList.filter(room => !invalidDict[room.id]) + const BATCH_SIZE = 10 + let batchIndex = 0 + + const invalidSet: Set = new Set() + while (batchIndex * BATCH_SIZE < roomList.length) { + const batchRoomList = roomList.slice( + BATCH_SIZE * batchIndex, + BATCH_SIZE * (batchIndex + 1), + ) + + await Promise.all( + batchRoomList.map( + room => room.ready() + .catch(e => { + log.warn('Room', 'findAll() room.ready() rejection:\n%s', e.stack) + invalidSet.add(room.id) + }) + ), + ) + + batchIndex++ + } + + return roomList.filter(room => !invalidSet.has(room.id)) } catch (e) { log.verbose('Room', 'findAll() rejected: %s', e.message) @@ -342,16 +354,24 @@ class Room extends RoomEventEmitter implements Sayable { const memberIdList = await this.wechaty.puppet.roomMemberList(this.id) - await Promise.all( - memberIdList - .map(id => this.wechaty.Contact.load(id)) - .map(contact => { - contact.ready() - .catch(e => { - log.verbose('Room', 'ready() member.ready() rejection: %s', e) - }) - }), - ) + const memberList = memberIdList.map(id => this.wechaty.Contact.load(id)) + + const BATCH_SIZE = 16 + let batchIndex = 0 + + while (batchIndex * BATCH_SIZE < memberList.length) { + const batchMemberList = memberList.slice( + BATCH_SIZE * batchIndex, + BATCH_SIZE * (batchIndex + 1), + ) + await Promise.all( + batchMemberList.map( + c => c.ready().catch(e => log.error('Room', 'ready() member.ready() exception:\n%s', e.stack)) + ), + ) + + batchIndex++ + } } /** From 8a41a64c443623dc188d2be06b474706e33bb4ca Mon Sep 17 00:00:00 2001 From: Yuan Gao Date: Tue, 6 Oct 2020 16:23:43 +0800 Subject: [PATCH 478/598] fix #2073 (#2074) * fix #2073 * 0.48.12 * 0.48.13 --- package.json | 2 +- src/user/message.ts | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index df5d0bece..6f1e8d80f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.48.11", + "version": "0.48.13", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", diff --git a/src/user/message.ts b/src/user/message.ts index 2d3d887fd..214c11f97 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -872,17 +872,22 @@ class Message extends EventEmitter implements Sayable { * }) * .start() */ - public async forward (to: Room | Contact): Promise { + public async forward (to: Room | Contact): Promise { log.verbose('Message', 'forward(%s)', to) // let roomId // let contactId try { - await this.wechaty.puppet.messageForward( + const msgId = await this.wechaty.puppet.messageForward( to.id, this.id, ) + if (msgId) { + const msg = this.wechaty.Message.load(msgId) + await msg.ready() + return msg + } } catch (e) { log.error('Message', 'forward(%s) exception: %s', to, e) throw e From 19a7d255a84192905cc41f519ea3ef9334d2f2d2 Mon Sep 17 00:00:00 2001 From: Yuan Gao Date: Tue, 27 Oct 2020 16:26:18 +0800 Subject: [PATCH 479/598] Bump minor 49 (#2078) * 0.49.0 * update hostie version to take advantage of the new stream grpc methods --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 6f1e8d80f..a84f0a8f9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.48.13", + "version": "0.49.0", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", @@ -101,7 +101,7 @@ "state-switch": "^0.9.9", "typed-emitter": "^1.3.0", "watchdog": "^0.8.17", - "wechaty-puppet-hostie": "^0.10.0", + "wechaty-puppet-hostie": "^0.11.0", "wechaty-puppet": "^0.32.3", "ws": "^7.3.1" }, From 5168f67ba6bba7d01467559cd57f08d232011de9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 27 Oct 2020 22:38:32 +0800 Subject: [PATCH 480/598] fix io client qrcode by encodeURIComponent --- src/io-client.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/io-client.ts b/src/io-client.ts index e4f9cc0eb..ecbe2c543 100644 --- a/src/io-client.ts +++ b/src/io-client.ts @@ -151,8 +151,8 @@ export class IoClient { .on('message', msg => this.onMessage(msg)) .on('scan', (url, code) => { log.info('IoClient', [ - `[${code}] ${url}]`, - `Online QR Code Image: https://wechaty.js.org/qrcode/${url}`, + `[${code}] ${url}`, + `Online QR Code Image: https://wechaty.js.org/qrcode/${encodeURIComponent(url)}`, ].join('\n')) }) } From b5a4a21e2f129a192a9cf0efd56a1a530ebede46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 27 Oct 2020 22:38:46 +0800 Subject: [PATCH 481/598] 0.48.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 331fbb7b3..df5d0bece 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.48.10", + "version": "0.48.11", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 86ee89f27b63f8a0232a40ebed2e944705ebf28a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 27 Oct 2020 22:41:14 +0800 Subject: [PATCH 482/598] upgrade deps --- package.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index a84f0a8f9..0301d622c 100644 --- a/package.json +++ b/package.json @@ -93,22 +93,22 @@ "open-graph": "^0.2.4", "opencollective": "^1.0.3", "opencollective-postinstall": "^2.0.3", - "pkg-dir": "^4.2.0", + "pkg-dir": "^5.0.0", "portfinder": "^1.0.28", "promise-retry": "^2.0.1", "raven": "^2.6.4", "read-pkg-up": "^7.0.1", "state-switch": "^0.9.9", - "typed-emitter": "^1.3.0", + "typed-emitter": "^1.3.1", "watchdog": "^0.8.17", "wechaty-puppet-hostie": "^0.11.0", "wechaty-puppet": "^0.32.3", "ws": "^7.3.1" }, "devDependencies": { - "@babel/core": "^7.11.4", - "@babel/node": "^7.10.5", - "@babel/preset-env": "^7.11.0", + "@babel/core": "^7.12.3", + "@babel/node": "^7.12.1", + "@babel/preset-env": "^7.12.1", "@chatie/eslint-config": "^0.12.1", "@chatie/git-scripts": "^0.6.2", "@chatie/semver": "^0.4.7", @@ -116,11 +116,11 @@ "@types/cuid": "^1.3.1", "@types/dotenv": "^8.2.0", "@types/glob": "^7.1.3", - "@types/open-graph": "^0.2.0", + "@types/open-graph": "^0.2.1", "@types/promise-retry": "^1.1.3", "@types/raven": "^2.5.3", "@types/retry": "^0.12.0", - "@types/ws": "^7.2.6", + "@types/ws": "^7.2.8", "apiai": "^4.0.3", "check-node-version": "^4.0.3", "coveralls": "^3.1.0", @@ -128,15 +128,15 @@ "finis": "^0.4.4", "glob": "^7.1.6", "jsdoc-to-markdown": "^6.0.1", - "markdownlint-cli": "^0.23.2", + "markdownlint-cli": "^0.24.0", "nyc": "^15.1.0", "pkg-jq": "^0.2.4", "qrcode-terminal": "^0.12.0", - "shx": "^0.3.2", + "shx": "^0.3.3", "sloc": "^0.2.1", "tstest": "^0.4.10", - "typedoc": "^0.18.0", - "wechaty-puppet-mock": "^0.27.2" + "typedoc": "^0.19.2", + "wechaty-puppet-mock": "^0.28.1" }, "files_comment__whitelist_npm_publish": "http://stackoverflow.com/a/8617868/1123955", "files": [ From 12578713ea57fe6c106f93a2860cf4c4acd8d21a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 27 Oct 2020 22:41:28 +0800 Subject: [PATCH 483/598] 0.49.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0301d622c..f784b239e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.49.0", + "version": "0.49.1", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 7468db459c7df26c6a6220132148dbe36723df0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 27 Oct 2020 22:48:49 +0800 Subject: [PATCH 484/598] upgrade puppet to v0.33 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f784b239e..829edcdc8 100644 --- a/package.json +++ b/package.json @@ -102,7 +102,7 @@ "typed-emitter": "^1.3.1", "watchdog": "^0.8.17", "wechaty-puppet-hostie": "^0.11.0", - "wechaty-puppet": "^0.32.3", + "wechaty-puppet": "^0.33.2", "ws": "^7.3.1" }, "devDependencies": { From 40ed32f8cf8adb12bd74f0cabb04995dda229f15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 27 Oct 2020 22:53:45 +0800 Subject: [PATCH 485/598] 0.49.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 829edcdc8..1ab5238e7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.49.1", + "version": "0.49.2", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 5505b640c49b80de69c87e10ac7fbe0fa3352349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 27 Oct 2020 22:56:33 +0800 Subject: [PATCH 486/598] 0.49.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1ab5238e7..54dc2035b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.49.2", + "version": "0.49.3", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 12aa8930d4c891ce4c40a8f695231bd5c5675b8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 27 Oct 2020 23:27:00 +0800 Subject: [PATCH 487/598] 0.49.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 54dc2035b..068538db5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.49.3", + "version": "0.49.4", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From f0cd305ecaa169844bc6e16952a90bf58260c83c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 28 Oct 2020 16:41:43 +0800 Subject: [PATCH 488/598] fix typos --- src/io.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/io.ts b/src/io.ts index ce96afa29..78c9a6511 100644 --- a/src/io.ts +++ b/src/io.ts @@ -213,7 +213,7 @@ export class Io { let endpoint = 'wss://' + this.options.apihost + '/v0/websocket' // XXX quick and dirty: use no ssl for APIHOST other than official - // FIXME: use a configuarable VARIABLE for the domain name at here: + // FIXME: use a configurable VARIABLE for the domain name at here: if (!/api\.chatie\.io/.test(this.options.apihost)) { endpoint = 'ws://' + this.options.apihost + '/v0/websocket' } @@ -491,7 +491,7 @@ export class Io { try { await Promise.all(list) } catch (e) { - log.error('Io', 'send() exceptio: %s', e.stack) + log.error('Io', 'send() exception: %s', e.stack) throw e } } @@ -534,11 +534,11 @@ export class Io { /** * - * Prepare to be overwriten by server setting + * Prepare to be overwritten by server setting * */ private async ioMessage (m: Message): Promise { - log.silly('Io', 'ioMessage() is a nop function before be overwriten from cloud') + log.silly('Io', 'ioMessage() is a nop function before be overwritten from cloud') if (typeof this.onMessage === 'function') { await this.onMessage(m) } From 5e65c85be59091166a51433c398d5ef467978161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 28 Oct 2020 16:42:06 +0800 Subject: [PATCH 489/598] 0.49.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 068538db5..e7b25b8d2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.49.4", + "version": "0.49.5", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From af42df16c82e482b0ac5e20138b7365bd0b6603f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 1 Nov 2020 21:40:28 +0800 Subject: [PATCH 490/598] clean --- bin/io-client.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bin/io-client.ts b/bin/io-client.ts index e465df925..71ea4462c 100644 --- a/bin/io-client.ts +++ b/bin/io-client.ts @@ -62,8 +62,7 @@ async function main () { const wechaty = new Wechaty({ name: token }) - const WECHATY_HOSTIE_PORT = 'WECHATY_HOSTIE_PORT' - const port = parseInt(process.env[WECHATY_HOSTIE_PORT] || '0') + const port = parseInt(process.env.WECHATY_HOSTIE_PORT || '0') const options: IoClientOptions = { token, From 1bae900d4175d4ecdebdaa4e9cb0e36b88e485b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 6 Nov 2020 12:19:29 +0800 Subject: [PATCH 491/598] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7f177f889..068a7c5db 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ - Wechaty [![NPM Version](https://img.shields.io/npm/v/wechaty?color=brightgreen)](https://www.npmjs.com/package/wechaty) [![NPM](https://github.com/wechaty/wechaty/workflows/NPM/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ANPM) [![Docker](https://github.com/wechaty/wechaty/workflows/Docker/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ADocker) +# Wechaty [![NPM Version](https://img.shields.io/npm/v/wechaty?color=brightgreen)](https://www.npmjs.com/package/wechaty) [![NPM](https://github.com/wechaty/wechaty/workflows/NPM/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ANPM) [![Docker](https://github.com/wechaty/wechaty/workflows/Docker/badge.svg)](https://github.com/wechaty/wechaty/actions?query=workflow%3ADocker) [![Wechaty](https://wechaty.js.org/img/wechaty-logo.svg)](https://wechaty.js.org) From c9b68ec995621dba45cd0f1db048827714b4a189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 7 Nov 2020 17:07:43 +0800 Subject: [PATCH 492/598] add credit link --- src/io-peer/json-rpc-peer.d.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/io-peer/json-rpc-peer.d.ts b/src/io-peer/json-rpc-peer.d.ts index 18f9205e4..6c198e5a4 100644 --- a/src/io-peer/json-rpc-peer.d.ts +++ b/src/io-peer/json-rpc-peer.d.ts @@ -1,3 +1,7 @@ +/** + * Add typescript definitions #60 + * https://github.com/JsCommunity/json-rpc-peer/pull/60 + */ declare module 'json-rpc-peer' { /// From d10d7ed3d7a3363e943f74f2a70419dd4dfc1cbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 7 Nov 2020 17:07:50 +0800 Subject: [PATCH 493/598] fix typo --- src/io-client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/io-client.ts b/src/io-client.ts index ecbe2c543..20f492f96 100644 --- a/src/io-client.ts +++ b/src/io-client.ts @@ -137,7 +137,7 @@ export class IoClient { } private async hookWechaty (wechaty: Wechaty): Promise { - log.verbose('IoClient', 'initWechaty()') + log.verbose('IoClient', 'hookWechaty()') if (this.state.off()) { const e = new Error('state.off() is true, skipped') From 36baaa6ad04cb52004eb6d7540c095b78d4e1f73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 7 Nov 2020 18:01:52 +0800 Subject: [PATCH 494/598] upgrade json-rpc-peer to v0.17 --- package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index e7b25b8d2..d5cf1dd82 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.49.5", + "version": "0.49.6", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", @@ -88,7 +88,7 @@ "cuid": "^2.1.8", "dotenv": "^8.2.0", "in-gfw": "^1.2.0", - "json-rpc-peer": "^0.16.0", + "json-rpc-peer": "^0.17.0", "npm-programmatic": "0.0.12", "open-graph": "^0.2.4", "opencollective": "^1.0.3", @@ -101,13 +101,13 @@ "state-switch": "^0.9.9", "typed-emitter": "^1.3.1", "watchdog": "^0.8.17", + "wechaty-puppet": "^0.33.3", "wechaty-puppet-hostie": "^0.11.0", - "wechaty-puppet": "^0.33.2", "ws": "^7.3.1" }, "devDependencies": { "@babel/core": "^7.12.3", - "@babel/node": "^7.12.1", + "@babel/node": "^7.12.6", "@babel/preset-env": "^7.12.1", "@chatie/eslint-config": "^0.12.1", "@chatie/git-scripts": "^0.6.2", @@ -120,7 +120,7 @@ "@types/promise-retry": "^1.1.3", "@types/raven": "^2.5.3", "@types/retry": "^0.12.0", - "@types/ws": "^7.2.8", + "@types/ws": "^7.2.9", "apiai": "^4.0.3", "check-node-version": "^4.0.3", "coveralls": "^3.1.0", From 7f9adf59fc0590cabf8118cdd56de004f4ada3af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 7 Nov 2020 18:02:09 +0800 Subject: [PATCH 495/598] 0.49.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d5cf1dd82..3ba810cc5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.49.6", + "version": "0.49.7", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From dcf93fd792679ae27d1a619a6e495651a54c8862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 7 Nov 2020 18:03:55 +0800 Subject: [PATCH 496/598] 0.49.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3ba810cc5..7a5e9f9c3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.49.7", + "version": "0.49.8", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 225ce704144aee428773f7c6baf846d078d8e0c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B6=E9=91=AB?= Date: Sun, 8 Nov 2020 02:58:38 +0800 Subject: [PATCH 497/598] Update Dockerfile (#2079) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 按照 https://github.com/wechaty/wechaty/issues/1986 的方法用docker创建Hostie Token时,docker端报错。加入libxtst6库后可以完美运行。 --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 84350015f..87d4d4dae 100644 --- a/Dockerfile +++ b/Dockerfile @@ -34,6 +34,7 @@ RUN apt-get update \ tzdata \ vim \ wget \ + libxtst6 \ && apt-get purge --auto-remove \ && rm -rf /tmp/* /var/lib/apt/lists/* From ace23d3052176a295ed2b73f9ab22ee5ef31e57c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 9 Nov 2020 18:58:30 +0800 Subject: [PATCH 498/598] 0.50.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7a5e9f9c3..b0c54f26d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.49.8", + "version": "0.50.0", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 8f1a4d17ff7d6e058aad5c7db0c5a609d29df96d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 9 Nov 2020 18:58:54 +0800 Subject: [PATCH 499/598] 0.50.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b0c54f26d..9e8f040f6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.50.0", + "version": "0.50.1", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 7fd8c3e2b7fe256542a5020551ffb79c24abb000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 9 Nov 2020 23:39:38 +0800 Subject: [PATCH 500/598] clean scan payload after login --- src/io.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/io.ts b/src/io.ts index 78c9a6511..2c467b9ff 100644 --- a/src/io.ts +++ b/src/io.ts @@ -159,6 +159,7 @@ export class Io { this.ws = await this.initWebSocket() + this.options.wechaty.on('login', () => { this.scanPayload = undefined }) this.options.wechaty.on('scan', (qrcode, status) => { this.scanPayload = { ...this.scanPayload, From fb341ee0967c9f9541a1abaa70d4f1d8fb389abf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 9 Nov 2020 23:39:52 +0800 Subject: [PATCH 501/598] 0.50.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9e8f040f6..5962027ca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.50.1", + "version": "0.50.2", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 81e4fc8f21d1078f744710a52865aacce319d6e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 10 Nov 2020 00:49:14 +0800 Subject: [PATCH 502/598] enable io sync message botie support --- src/io.ts | 65 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/src/io.ts b/src/io.ts index 2c467b9ff..30766a29f 100644 --- a/src/io.ts +++ b/src/io.ts @@ -93,6 +93,20 @@ interface IoEventAny { type IoEvent = IoEventScan | IoEventJsonRpc | IoEventAny +/** + * https://github.com/Chatie/botie/issues/2 + * https://github.com/actions/github-script/blob/f035cea4677903b153fa754aa8c2bba66f8dc3eb/src/async-function.ts#L6 + */ +const AsyncFunction = Object.getPrototypeOf(async () => null).constructor + +// function callAsyncFunction ( +// args: U, +// source: string +// ): Promise { +// const fn = new AsyncFunction(...Object.keys(args), source) +// return fn(...Object.values(args)) +// } + export class Io { private readonly id : string @@ -191,8 +205,8 @@ export class Io { wechaty.on('error', error => this.send({ name: 'error', payload: error })) wechaty.on('heartbeat', data => this.send({ name: 'heartbeat', payload: { cuid: this.id, data } })) - wechaty.on('login', user => this.send({ name: 'login', payload: user })) - wechaty.on('logout', user => this.send({ name: 'logout', payload: user })) + wechaty.on('login', user => this.send({ name: 'login', payload: user.payload })) + wechaty.on('logout', user => this.send({ name: 'logout', payload: user.payload })) wechaty.on('message', message => this.ioMessage(message)) // FIXME: payload schema need to be defined universal @@ -285,26 +299,20 @@ export class Io { case 'botie': { const payload = ioEvent.payload - if (payload.onMessage) { - const script = payload.script - try { - /** - * https://github.com/Chatie/botie/issues/2 - * const AsyncFunction = Object.getPrototypeOf(async () => {}).constructor - * const fn = new AsyncFunction('require', 'github', 'context', script) - */ - // eslint-disable-next-line - const fn = eval(script) - - if (typeof fn === 'function') { - this.onMessage = fn - } else { - log.warn('Io', 'server pushed function is invalid') - } - } catch (e) { - log.warn('Io', 'server pushed function exception: %s', e) - this.options.wechaty.emit('error', e) + + const args = payload.args + const script = payload.script + + try { + if (args[0] === 'message' && args.length === 1) { + const fn = new AsyncFunction(...args, script) + this.onMessage = fn + } else { + log.warn('Io', 'server pushed function is invalid. args: %s', JSON.stringify(args)) } + } catch (e) { + log.warn('Io', 'server pushed function exception: %s', e) + this.options.wechaty.emit('error', e) } } break @@ -327,10 +335,7 @@ export class Io { if (wechaty.logonoff()) { const loginEvent: IoEvent = { name : 'login', - payload : { - id : wechaty.userSelf().id, - name : wechaty.userSelf().name(), - }, + payload : (wechaty.userSelf() as any).payload, } await this.send(loginEvent) } @@ -545,4 +550,14 @@ export class Io { } } + protected async syncMessage (m: Message): Promise { + log.silly('Io', 'syncMessage(%s)', m) + + const messageEvent: IoEvent = { + name : 'message', + payload : (m as any).payload, + } + await this.send(messageEvent) + } + } From df89f8b634b03659705aba14c375174dfe5fedc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 10 Nov 2020 00:49:28 +0800 Subject: [PATCH 503/598] 0.50.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5962027ca..120e84dec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.50.2", + "version": "0.50.3", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 7cb469684a185e3b8a49f1963383ed9519c237ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 10 Nov 2020 01:01:47 +0800 Subject: [PATCH 504/598] use source for botie payload --- src/io.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/io.ts b/src/io.ts index 30766a29f..1f88f98a0 100644 --- a/src/io.ts +++ b/src/io.ts @@ -301,11 +301,11 @@ export class Io { const payload = ioEvent.payload const args = payload.args - const script = payload.script + const source = payload.source try { if (args[0] === 'message' && args.length === 1) { - const fn = new AsyncFunction(...args, script) + const fn = new AsyncFunction(...args, source) this.onMessage = fn } else { log.warn('Io', 'server pushed function is invalid. args: %s', JSON.stringify(args)) From d700a9ac62bb25ba1353274436bb7bdd7abdbcff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 10 Nov 2020 01:02:01 +0800 Subject: [PATCH 505/598] 0.50.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 120e84dec..97af208ef 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.50.3", + "version": "0.50.4", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From c9f5bf750c72f2451798d01826bd2ecccfa5ae3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 12 Nov 2020 13:43:00 +0800 Subject: [PATCH 506/598] add whatsapp to official puppet names (https://github.com/wechaty/wechaty-puppet-whatsapp/issues/1) --- src/puppet-config.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index f5451ece1..085ac6e06 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -48,8 +48,9 @@ export const PUPPET_DEPENDENCIES = { /** * Other */ - 'wechaty-puppet-gitter' : '^0.3.1', // https://www.npmjs.com/package/wechaty-puppet-gitter - 'wechaty-puppet-official-account' : '^0.2.2', // https://www.npmjs.com/package/wechaty-puppet-official-account + 'wechaty-puppet-gitter' : '*', // https://www.npmjs.com/package/wechaty-puppet-gitter + 'wechaty-puppet-official-account' : '*', // https://www.npmjs.com/package/wechaty-puppet-official-account + 'wechaty-puppet-whatsapp' : '*', // https://www.npmjs.com/package/wechaty-puppet-whatsapp } export type PuppetModuleName = keyof typeof PUPPET_DEPENDENCIES From 7e97620e2a92841227a6ae355efa615c5af95b32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 12 Nov 2020 13:43:12 +0800 Subject: [PATCH 507/598] 0.50.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 97af208ef..64ffd4b36 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.50.4", + "version": "0.50.5", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 05c00414451ac1f157ba05845f0ac885404a26db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 13 Nov 2020 16:49:15 +0800 Subject: [PATCH 508/598] use a helper function for better FileBox instance check (https://github.com/wechaty/wechaty-puppet-hostie/issues/99) --- src/helper-functions/mod.ts | 1 + src/helper-functions/pure/is-file-box.spec.ts | 42 +++++++++++++++++++ src/helper-functions/pure/is-file-box.ts | 13 ++++++ .../pure/timestamp-to-date.spec.ts | 1 + src/helper-functions/pure/try-wait.spec.ts | 0 src/helper-functions/pure/xml.spec.ts | 0 src/user/contact.ts | 3 +- src/user/message.ts | 8 +++- src/user/room.ts | 3 +- 9 files changed, 68 insertions(+), 3 deletions(-) create mode 100755 src/helper-functions/pure/is-file-box.spec.ts create mode 100644 src/helper-functions/pure/is-file-box.ts mode change 100644 => 100755 src/helper-functions/pure/timestamp-to-date.spec.ts mode change 100644 => 100755 src/helper-functions/pure/try-wait.spec.ts mode change 100644 => 100755 src/helper-functions/pure/xml.spec.ts diff --git a/src/helper-functions/mod.ts b/src/helper-functions/mod.ts index 8cd1496d8..2552597a7 100644 --- a/src/helper-functions/mod.ts +++ b/src/helper-functions/mod.ts @@ -21,6 +21,7 @@ export { getPort } from './impure/get-port' export { generateToken } from './impure/generate-token' export { tryWait } from './pure/try-wait' +export { isFileBox } from './pure/is-file-box' export { digestEmoji, plainText, diff --git a/src/helper-functions/pure/is-file-box.spec.ts b/src/helper-functions/pure/is-file-box.spec.ts new file mode 100755 index 000000000..8a0c58531 --- /dev/null +++ b/src/helper-functions/pure/is-file-box.spec.ts @@ -0,0 +1,42 @@ +#!/usr/bin/env ts-node +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ +import { test } from 'tstest' + +import { FileBox } from 'file-box' + +import { isFileBox } from './is-file-box' + +test('isFileBox: instanceof', async t => { + const f = FileBox.fromBuffer(Buffer.from('a'), 'a') + t.true(isFileBox(f), 'should be FileBox for a real FileBox') +}) + +test('isFileBox: constructor.name', async t => { + class FileBox {} + const f = new FileBox() + + t.true(isFileBox(f), 'should be FileBox for the same name class') +}) + +test('isFileBox: n/a', async t => { + const o = {} + t.false(isFileBox(o), 'should not be FileBox for a {}') +}) diff --git a/src/helper-functions/pure/is-file-box.ts b/src/helper-functions/pure/is-file-box.ts new file mode 100644 index 000000000..e5f848339 --- /dev/null +++ b/src/helper-functions/pure/is-file-box.ts @@ -0,0 +1,13 @@ +import { FileBox } from 'file-box' + +function isFileBox (o: any): o is FileBox { + if (o instanceof FileBox) { + return true + } else if (o && o.constructor && o.constructor.name === 'FileBox') { + return true + } + + return false +} + +export { isFileBox } diff --git a/src/helper-functions/pure/timestamp-to-date.spec.ts b/src/helper-functions/pure/timestamp-to-date.spec.ts old mode 100644 new mode 100755 index 472e8399e..7ad194aab --- a/src/helper-functions/pure/timestamp-to-date.spec.ts +++ b/src/helper-functions/pure/timestamp-to-date.spec.ts @@ -1,3 +1,4 @@ +#!/usr/bin/env ts-node /** * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * diff --git a/src/helper-functions/pure/try-wait.spec.ts b/src/helper-functions/pure/try-wait.spec.ts old mode 100644 new mode 100755 diff --git a/src/helper-functions/pure/xml.spec.ts b/src/helper-functions/pure/xml.spec.ts old mode 100644 new mode 100755 diff --git a/src/user/contact.ts b/src/user/contact.ts index ba3c75456..3c7c23e1d 100644 --- a/src/user/contact.ts +++ b/src/user/contact.ts @@ -46,6 +46,7 @@ import { Tag } from './tag' import { UrlLink } from './url-link' import { ContactEventEmitter } from '../events/contact-events' +import { isFileBox } from '../helper-functions/mod' export const POOL = Symbol('pool') @@ -426,7 +427,7 @@ class Contact extends ContactEventEmitter implements Sayable { this.id, something.id, ) - } else if (something instanceof FileBox) { + } else if (isFileBox(something)) { /** * 3. File */ diff --git a/src/user/message.ts b/src/user/message.ts index 214c11f97..321e6f301 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -28,6 +28,7 @@ import { import { escapeRegExp } from '../helper-functions/pure/escape-regexp' import { timestampToDate } from '../helper-functions/pure/timestamp-to-date' +import { isFileBox } from '../helper-functions/pure/is-file-box' import { Wechaty, @@ -539,7 +540,12 @@ class Message extends EventEmitter implements Sayable { conversationId, something.id, ) - } else if (something instanceof FileBox) { + } else if (isFileBox(something)) { + /** + * Be aware of minified codes: + * https://stackoverflow.com/questions/1249531/how-to-get-a-javascript-objects-class#comment60309941_1249554 + */ + /** * File Message */ diff --git a/src/user/room.ts b/src/user/room.ts index 04c5a81d9..3b15db636 100644 --- a/src/user/room.ts +++ b/src/user/room.ts @@ -49,6 +49,7 @@ import { } from 'wechaty-puppet' import { RoomEventEmitter } from '../events/room-events' +import { isFileBox } from '../helper-functions/mod' /** * All WeChat rooms(groups) will be encapsulated as a Room. @@ -554,7 +555,7 @@ class Room extends RoomEventEmitter implements Sayable { text, mentionList.map(c => c.id), ) - } else if (something instanceof FileBox) { + } else if (isFileBox(something)) { /** * 2. File Message */ From a7b367c909d3e10e41861655023f12b31df61396 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 13 Nov 2020 16:49:38 +0800 Subject: [PATCH 509/598] 0.50.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 64ffd4b36..bc1033d67 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.50.5", + "version": "0.50.6", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 2e951b7538540a5a94a867ad46ac86721a7c33af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 13 Nov 2020 17:02:24 +0800 Subject: [PATCH 510/598] loost Puppet instance type checking (#2024) --- .../pure/is-wechaty-puppet.spec.ts | 42 +++++++++++++++++++ .../pure/is-wechaty-puppet.ts | 13 ++++++ src/puppet-manager.ts | 8 ++-- 3 files changed, 60 insertions(+), 3 deletions(-) create mode 100755 src/helper-functions/pure/is-wechaty-puppet.spec.ts create mode 100644 src/helper-functions/pure/is-wechaty-puppet.ts diff --git a/src/helper-functions/pure/is-wechaty-puppet.spec.ts b/src/helper-functions/pure/is-wechaty-puppet.spec.ts new file mode 100755 index 000000000..ac5a5d682 --- /dev/null +++ b/src/helper-functions/pure/is-wechaty-puppet.spec.ts @@ -0,0 +1,42 @@ +#!/usr/bin/env ts-node +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ +import { test } from 'tstest' + +import { PuppetMock } from 'wechaty-puppet-mock' + +import { isWechatyPuppet } from './is-wechaty-puppet' + +test('isWechatyPuppet: instanceof', async t => { + const p = new PuppetMock() + t.true(isWechatyPuppet(p), 'should be Puppet for a real Puppet (mock)') +}) + +test('isWechatyPuppet: constructor.name', async t => { + class Puppet {} + const f = new Puppet() + + t.true(isWechatyPuppet(f), 'should be Puppet for the same name class') +}) + +test('isWechatyPuppet: n/a', async t => { + const o = {} + t.false(isWechatyPuppet(o), 'should not be Puppet for a {}') +}) diff --git a/src/helper-functions/pure/is-wechaty-puppet.ts b/src/helper-functions/pure/is-wechaty-puppet.ts new file mode 100644 index 000000000..1445b1d25 --- /dev/null +++ b/src/helper-functions/pure/is-wechaty-puppet.ts @@ -0,0 +1,13 @@ +import { Puppet } from 'wechaty-puppet' + +function isWechatyPuppet (o: any): o is Puppet { + if (o instanceof Puppet) { + return true + } else if (o && o.constructor && o.constructor.name === 'Puppet') { + return true + } + + return false +} + +export { isWechatyPuppet } diff --git a/src/puppet-manager.ts b/src/puppet-manager.ts index 3bc1c3703..effb98138 100644 --- a/src/puppet-manager.ts +++ b/src/puppet-manager.ts @@ -31,6 +31,8 @@ import { PuppetOptions, } from 'wechaty-puppet' +import { isWechatyPuppet } from './helper-functions/pure/is-wechaty-puppet' + import { log, } from './config' @@ -58,14 +60,14 @@ export class PuppetManager { /** * Huan(202001): (DEPRECATED) When we are developing, we might experiencing we have two version of wechaty-puppet installed, - * if `optoins.puppet` is Puppet v1, but the `Puppet` in Wechaty is v2, + * if `options.puppet` is Puppet v1, but the `Puppet` in Wechaty is v2, * then options.puppet will not instanceof Puppet. * So I changed here to match not a string as a workaround. * * Huan(202020): The wechaty-puppet-xxx must NOT dependencies `wechaty-puppet` so that it can be `instanceof`-ed * wechaty-puppet-xxx should put `wechaty-puppet` in `devDependencies` and `peerDependencies`. */ - if (options.puppet instanceof Puppet) { + if (isWechatyPuppet(options.puppet)) { puppetInstance = await this.resolveInstance(options.puppet) } else if (typeof options.puppet !== 'string') { log.error('PuppetManager', 'resolve() %s', @@ -85,7 +87,7 @@ export class PuppetManager { * When we have different puppet with different `constructor()` args. * For example: PuppetA allow `constructor()` but PuppetB requires `constructor(options)` * - * SOLUTION: we enforce all the PuppetImplenmentation to have `options` and should not allow default parameter. + * SOLUTION: we enforce all the PuppetImplementation to have `options` and should not allow default parameter. * Issue: https://github.com/wechaty/wechaty-puppet/issues/2 */ puppetInstance = new MyPuppet(options.puppetOptions) From 70fff8238602778209feef7631c7c54c2f0c49e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 13 Nov 2020 17:03:07 +0800 Subject: [PATCH 511/598] 0.50.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bc1033d67..9f860b6e9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.50.6", + "version": "0.50.7", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 0d2ff03a0c657a4c4a6c3e0489535e9ca3622dee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 19 Nov 2020 21:49:26 +0800 Subject: [PATCH 512/598] create looseInstanceOfClass (#2090) (#2091) * create looseInstanceOfClass (#2090) * 0.50.8 * 0.51.0 * 0.51.1 --- package.json | 4 +- src/config.ts | 10 +++ src/helper-functions/mod.ts | 6 +- src/helper-functions/pure/is-file-box.spec.ts | 42 ----------- src/helper-functions/pure/is-file-box.ts | 13 ---- .../pure/is-wechaty-puppet.spec.ts | 42 ----------- .../pure/is-wechaty-puppet.ts | 13 ---- .../pure/loose-instance-of-class.spec.ts | 71 +++++++++++++++++++ .../pure/loose-instance-of-class.ts | 19 +++++ src/puppet-manager.ts | 11 ++- src/user/contact.ts | 12 ++-- src/user/message.ts | 14 ++-- src/user/room.ts | 10 +-- 13 files changed, 132 insertions(+), 135 deletions(-) delete mode 100755 src/helper-functions/pure/is-file-box.spec.ts delete mode 100644 src/helper-functions/pure/is-file-box.ts delete mode 100755 src/helper-functions/pure/is-wechaty-puppet.spec.ts delete mode 100644 src/helper-functions/pure/is-wechaty-puppet.ts create mode 100755 src/helper-functions/pure/loose-instance-of-class.spec.ts create mode 100644 src/helper-functions/pure/loose-instance-of-class.ts diff --git a/package.json b/package.json index 9f860b6e9..331c7c347 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.50.7", + "version": "0.51.1", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", @@ -101,7 +101,7 @@ "state-switch": "^0.9.9", "typed-emitter": "^1.3.1", "watchdog": "^0.8.17", - "wechaty-puppet": "^0.33.3", + "wechaty-puppet": "^0.33.6", "wechaty-puppet-hostie": "^0.11.0", "ws": "^7.3.1" }, diff --git a/src/config.ts b/src/config.ts index f3457ef0a..7ef530ae7 100644 --- a/src/config.ts +++ b/src/config.ts @@ -31,6 +31,8 @@ import { log, } from 'wechaty-puppet' +import { looseInstanceOfClass } from './helper-functions/mod' + import { PuppetModuleName, PUPPET_NAME_DEFAULT, @@ -173,11 +175,19 @@ export function isProduction (): boolean { || process.env.NODE_ENV === 'prod' } +/** + * Huan(202011): + * Create a `looseInstanceOfClass` to check `FileBox` and `Puppet` instances #2090 + * https://github.com/wechaty/wechaty/issues/2090 + */ +const looseInstanceOfFileBox = looseInstanceOfClass(FileBox) + export { log, FileBox, MemoryCard, Raven, + looseInstanceOfFileBox, VERSION, } diff --git a/src/helper-functions/mod.ts b/src/helper-functions/mod.ts index 2552597a7..9c68a76e6 100644 --- a/src/helper-functions/mod.ts +++ b/src/helper-functions/mod.ts @@ -20,8 +20,8 @@ export { getPort } from './impure/get-port' export { generateToken } from './impure/generate-token' -export { tryWait } from './pure/try-wait' -export { isFileBox } from './pure/is-file-box' +export { tryWait } from './pure/try-wait' +export { looseInstanceOfClass } from './pure/loose-instance-of-class' export { digestEmoji, plainText, @@ -29,4 +29,4 @@ export { stripHtml, unescapeHtml, unifyEmoji, -} from './pure/xml' +} from './pure/xml' diff --git a/src/helper-functions/pure/is-file-box.spec.ts b/src/helper-functions/pure/is-file-box.spec.ts deleted file mode 100755 index 8a0c58531..000000000 --- a/src/helper-functions/pure/is-file-box.spec.ts +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env ts-node -/** - * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty - * - * @copyright 2016 Huan LI (李卓桓) , and - * Wechaty Contributors . - * - * 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. - * - */ -import { test } from 'tstest' - -import { FileBox } from 'file-box' - -import { isFileBox } from './is-file-box' - -test('isFileBox: instanceof', async t => { - const f = FileBox.fromBuffer(Buffer.from('a'), 'a') - t.true(isFileBox(f), 'should be FileBox for a real FileBox') -}) - -test('isFileBox: constructor.name', async t => { - class FileBox {} - const f = new FileBox() - - t.true(isFileBox(f), 'should be FileBox for the same name class') -}) - -test('isFileBox: n/a', async t => { - const o = {} - t.false(isFileBox(o), 'should not be FileBox for a {}') -}) diff --git a/src/helper-functions/pure/is-file-box.ts b/src/helper-functions/pure/is-file-box.ts deleted file mode 100644 index e5f848339..000000000 --- a/src/helper-functions/pure/is-file-box.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { FileBox } from 'file-box' - -function isFileBox (o: any): o is FileBox { - if (o instanceof FileBox) { - return true - } else if (o && o.constructor && o.constructor.name === 'FileBox') { - return true - } - - return false -} - -export { isFileBox } diff --git a/src/helper-functions/pure/is-wechaty-puppet.spec.ts b/src/helper-functions/pure/is-wechaty-puppet.spec.ts deleted file mode 100755 index ac5a5d682..000000000 --- a/src/helper-functions/pure/is-wechaty-puppet.spec.ts +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env ts-node -/** - * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty - * - * @copyright 2016 Huan LI (李卓桓) , and - * Wechaty Contributors . - * - * 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. - * - */ -import { test } from 'tstest' - -import { PuppetMock } from 'wechaty-puppet-mock' - -import { isWechatyPuppet } from './is-wechaty-puppet' - -test('isWechatyPuppet: instanceof', async t => { - const p = new PuppetMock() - t.true(isWechatyPuppet(p), 'should be Puppet for a real Puppet (mock)') -}) - -test('isWechatyPuppet: constructor.name', async t => { - class Puppet {} - const f = new Puppet() - - t.true(isWechatyPuppet(f), 'should be Puppet for the same name class') -}) - -test('isWechatyPuppet: n/a', async t => { - const o = {} - t.false(isWechatyPuppet(o), 'should not be Puppet for a {}') -}) diff --git a/src/helper-functions/pure/is-wechaty-puppet.ts b/src/helper-functions/pure/is-wechaty-puppet.ts deleted file mode 100644 index 1445b1d25..000000000 --- a/src/helper-functions/pure/is-wechaty-puppet.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Puppet } from 'wechaty-puppet' - -function isWechatyPuppet (o: any): o is Puppet { - if (o instanceof Puppet) { - return true - } else if (o && o.constructor && o.constructor.name === 'Puppet') { - return true - } - - return false -} - -export { isWechatyPuppet } diff --git a/src/helper-functions/pure/loose-instance-of-class.spec.ts b/src/helper-functions/pure/loose-instance-of-class.spec.ts new file mode 100755 index 000000000..6c99bb961 --- /dev/null +++ b/src/helper-functions/pure/loose-instance-of-class.spec.ts @@ -0,0 +1,71 @@ +#!/usr/bin/env ts-node +/** + * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty + * + * @copyright 2016 Huan LI (李卓桓) , and + * Wechaty Contributors . + * + * 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. + * + */ +import { test } from 'tstest' + +import { FileBox } from 'file-box' + +import { looseInstanceOfClass } from './loose-instance-of-class' + +test('looseInstanceOfClass: instanceof', async t => { + class Test {} + const looseInstanceOfTest = looseInstanceOfClass(Test) + const test = new Test() + t.true(looseInstanceOfTest(test), 'should be true for a real Test') +}) + +test('looseInstanceOfClass: constructor.name', async t => { + class Test {} + const looseInstanceOfTest = looseInstanceOfClass(Test) + + const OrigTest = Test + t.equal(Test, OrigTest, 'should be the same class reference at beginning') + + { + class Test {} + t.notEqual(OrigTest, Test, 'should has a new Test class different to the original Test class') + const f = new Test() + t.true(looseInstanceOfTest(f), 'should be true for the same name class like Test') + } + +}) + +test('looseInstanceOfClass: n/a', async t => { + class Test {} + const looseInstanceOfTest = looseInstanceOfClass(Test) + + const o = {} + t.false(looseInstanceOfTest(o), 'should be false for non-Test: {}') +}) + +test('looseInstanceOfClass for FileBox', async t => { + const f = FileBox.fromQRCode('test') + const looseInstanceOfFileBox = looseInstanceOfClass(FileBox) + + const OrigFileBox = FileBox + { + class FileBox {} + t.notEqual(OrigFileBox, FileBox, 'should be two different FileBox class') + + t.true(f instanceof OrigFileBox, 'should be instanceof OrigFileBox') + t.false(f instanceof FileBox, 'should not instanceof another FileBox class for one FileBox instance') + t.true(looseInstanceOfFileBox(f), 'should be true for looseInstanceOfFileBox because the class has the same name') + } +}) diff --git a/src/helper-functions/pure/loose-instance-of-class.ts b/src/helper-functions/pure/loose-instance-of-class.ts new file mode 100644 index 000000000..8aed8b9e9 --- /dev/null +++ b/src/helper-functions/pure/loose-instance-of-class.ts @@ -0,0 +1,19 @@ +/** + * Huan(202011) + * Create a `looseInstanceOfClass` to check `FileBox` and `Puppet` instances #2090 + * https://github.com/wechaty/wechaty/issues/2090 + */ + +function looseInstanceOfClass (klass: T) { + return (o: any): o is InstanceType => { + if (o instanceof klass) { + return true + } else if (o && o.constructor && o.constructor.name === klass.name) { + return true + } + + return false + } +} + +export { looseInstanceOfClass } diff --git a/src/puppet-manager.ts b/src/puppet-manager.ts index effb98138..c2a21f0f7 100644 --- a/src/puppet-manager.ts +++ b/src/puppet-manager.ts @@ -31,7 +31,7 @@ import { PuppetOptions, } from 'wechaty-puppet' -import { isWechatyPuppet } from './helper-functions/pure/is-wechaty-puppet' +import { looseInstanceOfClass } from './helper-functions/pure/loose-instance-of-class' import { log, @@ -46,6 +46,13 @@ export interface ResolveOptions { puppetOptions? : PuppetOptions, } +/** + * Huan(202011): + * Create a `looseInstanceOfClass` to check `FileBox` and `Puppet` instances #2090 + * https://github.com/wechaty/wechaty/issues/2090 + */ +const looseInstanceOfPuppet = looseInstanceOfClass(Puppet as any as Puppet & { new (...args: any): Puppet }) + export class PuppetManager { public static async resolve ( @@ -67,7 +74,7 @@ export class PuppetManager { * Huan(202020): The wechaty-puppet-xxx must NOT dependencies `wechaty-puppet` so that it can be `instanceof`-ed * wechaty-puppet-xxx should put `wechaty-puppet` in `devDependencies` and `peerDependencies`. */ - if (isWechatyPuppet(options.puppet)) { + if (looseInstanceOfPuppet(options.puppet)) { puppetInstance = await this.resolveInstance(options.puppet) } else if (typeof options.puppet !== 'string') { log.error('PuppetManager', 'resolve() %s', diff --git a/src/user/contact.ts b/src/user/contact.ts index 3c7c23e1d..e6f692c71 100644 --- a/src/user/contact.ts +++ b/src/user/contact.ts @@ -28,25 +28,25 @@ import { PayloadType, } from 'wechaty-puppet' -import { Wechaty } from '../wechaty' +import { Wechaty } from '../wechaty' import { Raven, log, qrCodeForChatie, -} from '../config' + looseInstanceOfFileBox, +} from '../config' import { Sayable, -} from '../types' +} from '../types' import { Message } from './message' import { MiniProgram } from './mini-program' import { Tag } from './tag' import { UrlLink } from './url-link' -import { ContactEventEmitter } from '../events/contact-events' -import { isFileBox } from '../helper-functions/mod' +import { ContactEventEmitter } from '../events/contact-events' export const POOL = Symbol('pool') @@ -427,7 +427,7 @@ class Contact extends ContactEventEmitter implements Sayable { this.id, something.id, ) - } else if (isFileBox(something)) { + } else if (looseInstanceOfFileBox(something)) { /** * 3. File */ diff --git a/src/user/message.ts b/src/user/message.ts index 321e6f301..3ca36c144 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -26,20 +26,20 @@ import { MessageType, } from 'wechaty-puppet' -import { escapeRegExp } from '../helper-functions/pure/escape-regexp' -import { timestampToDate } from '../helper-functions/pure/timestamp-to-date' -import { isFileBox } from '../helper-functions/pure/is-file-box' +import { escapeRegExp } from '../helper-functions/pure/escape-regexp' +import { timestampToDate } from '../helper-functions/pure/timestamp-to-date' import { Wechaty, -} from '../wechaty' +} from '../wechaty' import { AT_SEPARATOR_REGEX, FileBox, log, Raven, -} from '../config' + looseInstanceOfFileBox, +} from '../config' import { Sayable, } from '../types' @@ -56,7 +56,7 @@ import { import { MiniProgram, } from './mini-program' -import { Image } from './image' +import { Image } from './image' /** * All wechat messages will be encapsulated as a Message. @@ -540,7 +540,7 @@ class Message extends EventEmitter implements Sayable { conversationId, something.id, ) - } else if (isFileBox(something)) { + } else if (looseInstanceOfFileBox(something)) { /** * Be aware of minified codes: * https://stackoverflow.com/questions/1249531/how-to-get-a-javascript-objects-class#comment60309941_1249554 diff --git a/src/user/room.ts b/src/user/room.ts index 3b15db636..e83e207bf 100644 --- a/src/user/room.ts +++ b/src/user/room.ts @@ -19,7 +19,7 @@ */ import { instanceToClass } from 'clone-class' -import { Wechaty } from '../wechaty' +import { Wechaty } from '../wechaty' import { FOUR_PER_EM_SPACE, @@ -27,10 +27,11 @@ import { log, Raven, -} from '../config' + looseInstanceOfFileBox, +} from '../config' import { Sayable, -} from '../types' +} from '../types' import { guardQrCodeValue, @@ -49,7 +50,6 @@ import { } from 'wechaty-puppet' import { RoomEventEmitter } from '../events/room-events' -import { isFileBox } from '../helper-functions/mod' /** * All WeChat rooms(groups) will be encapsulated as a Room. @@ -555,7 +555,7 @@ class Room extends RoomEventEmitter implements Sayable { text, mentionList.map(c => c.id), ) - } else if (isFileBox(something)) { + } else if (looseInstanceOfFileBox(something)) { /** * 2. File Message */ From 1c247222bfc24549e3cc3d06abf43a6a36e0bdf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 20 Nov 2020 14:05:29 +0800 Subject: [PATCH 513/598] fix file-box --- src/config.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/config.ts b/src/config.ts index 7ef530ae7..aaf9c9aab 100644 --- a/src/config.ts +++ b/src/config.ts @@ -180,7 +180,12 @@ export function isProduction (): boolean { * Create a `looseInstanceOfClass` to check `FileBox` and `Puppet` instances #2090 * https://github.com/wechaty/wechaty/issues/2090 */ -const looseInstanceOfFileBox = looseInstanceOfClass(FileBox) +type FileBoxClass = FileBox & { + new (...args: any): FileBox +} +const looseInstanceOfFileBox = looseInstanceOfClass( + FileBox as any as FileBoxClass +) export { log, From 9a824a7557240de3fc55bc531331aaa0b35fc7a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 20 Nov 2020 14:06:59 +0800 Subject: [PATCH 514/598] fix file-box --- src/helper-functions/pure/loose-instance-of-class.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helper-functions/pure/loose-instance-of-class.spec.ts b/src/helper-functions/pure/loose-instance-of-class.spec.ts index 6c99bb961..10ea4a449 100755 --- a/src/helper-functions/pure/loose-instance-of-class.spec.ts +++ b/src/helper-functions/pure/loose-instance-of-class.spec.ts @@ -57,7 +57,7 @@ test('looseInstanceOfClass: n/a', async t => { test('looseInstanceOfClass for FileBox', async t => { const f = FileBox.fromQRCode('test') - const looseInstanceOfFileBox = looseInstanceOfClass(FileBox) + const looseInstanceOfFileBox = looseInstanceOfClass(FileBox as any as FileBox & { new (...args: any): FileBox }) const OrigFileBox = FileBox { From b22d0f3747fe4c88400d46ccd61fffa434d4572d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 20 Nov 2020 14:07:13 +0800 Subject: [PATCH 515/598] 0.51.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 331c7c347..58887932f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.51.1", + "version": "0.51.2", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 6c36d664079abad58d18cf7ecf3810d3e76af653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 23 Nov 2020 17:09:44 +0800 Subject: [PATCH 516/598] rename from -> talker (#2094) --- src/user/message.ts | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/user/message.ts b/src/user/message.ts index 3ca36c144..1645a67d8 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -225,10 +225,6 @@ class Message extends EventEmitter implements Sayable { return msgStrList.join('') } - public talker (): Contact { - return this.from()! - } - public conversation (): Contact | Room { if (this.room()) { return this.room()! @@ -238,25 +234,25 @@ class Message extends EventEmitter implements Sayable { } /** - * Get the sender from a message. + * Get the talker of a message. * @returns {Contact} * @example * const bot = new Wechaty() * bot * .on('message', async m => { - * const contact = msg.from() + * const talker = msg.talker() * const text = msg.text() * const room = msg.room() * if (room) { * const topic = await room.topic() - * console.log(`Room: ${topic} Contact: ${contact.name()} Text: ${text}`) + * console.log(`Room: ${topic} Contact: ${talker.name()} Text: ${text}`) * } else { - * console.log(`Contact: ${contact.name()} Text: ${text}`) + * console.log(`Contact: ${talker.name()} Text: ${text}`) * } * }) * .start() */ - public from (): null | Contact { + public talker (): Contact { if (!this.payload) { throw new Error('no payload') } @@ -268,13 +264,28 @@ class Message extends EventEmitter implements Sayable { const fromId = this.payload.fromId if (!fromId) { - return null + // Huan(202011): It seems that the fromId will never be null? + // return null + throw new Error('payload.fromId is null?') } const from = this.wechaty.Contact.load(fromId) return from } + /** + * Use `message.talker()` to replace `message.from()` #2094 + * https://github.com/wechaty/wechaty/issues/2094 + */ + public from (): null | Contact { + log.warn('Message', 'from() is deprecated, use talker() instead.') + try { + return this.talker() + } catch (e) { + return null + } + } + /** * Get the destination of the message * Message.to() will return null if a message is in a room, use Message.room() to get the room. From a5d1e5a3314babfdfca879373f9e71dab2f4f5b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 23 Nov 2020 17:09:58 +0800 Subject: [PATCH 517/598] 0.51.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 58887932f..e4949fa47 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.51.2", + "version": "0.51.3", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 7b84e5221bdb1be93cf60803d5189fa1193325ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 24 Nov 2020 14:35:20 +0800 Subject: [PATCH 518/598] add gitter & deprecate padplus --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 068a7c5db..060971c2d 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ [![GitHub stars](https://img.shields.io/github/stars/wechaty/wechaty.svg?label=github%20stars)](https://github.com/wechaty/wechaty) [![Docker Pulls](https://img.shields.io/docker/pulls/wechaty/wechaty.svg?maxAge=2592000)](https://hub.docker.com/r/wechaty/wechaty/) [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-blue.svg)](https://www.typescriptlang.org/) + [![Gitter](https://badges.gitter.im/wechaty/wechaty.svg)](https://gitter.im/wechaty/wechaty?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Telegram Wechaty Channel](https://img.shields.io/badge/chat-on%20telegram-blue)](https://t.me/wechaty) @@ -42,12 +43,16 @@ See more at [Wiki:Voice Of Developer](https://github.com/Wechaty/wechaty/wiki/Vo ### :raising_hand: Join Us +[![Gitter](https://badges.gitter.im/wechaty/wechaty.svg)](https://gitter.im/wechaty/wechaty?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) + Wechaty is used in many ChatBot projects by thousands of developers. If you want to talk with other developers, just scan the following QR Code in WeChat with secret code _wechaty_, join our **Wechaty Developers' Home**. ![Wechaty Friday.BOT QR Code](https://wechaty.js.org/img/friday-qrcode.svg) Scan now, because other Wechaty developers want to talk with you too! (secret code: _wechaty_) +> You are also welcome to join our Gitter channel at with your GitHub account! + ### :book: Resource Wechaty already held lots of talk and got a lot of blogs in the past 4 years, here is all of the wechaty resources: @@ -148,12 +153,13 @@ Currently we support the following puppet providers: | Protocol | Puppet Provider | Environment Variable | | --- | --- | --- | | Web | PuppetPuppeteer | `export WECHATY_PUPPET=wechaty-puppet-puppeteer` | -| iPad | PuppetPadplus | `export WECHATY_PUPPET=wechaty-puppet-padplus` | -| Mac | PuppetMacpro | `export WECHATY_PUPPET=wechaty-puppet-macpro` | | Mock | PuppetMock | `export WECHATY_PUPPET=wechaty-puppet-mock` | | Web | PuppetWechat4u | `export WECHATY_PUPPET=wechaty-puppet-wechat4u` | -| iPad | PuppetPadpro **DEPRECATED** | `export WECHATY_PUPPET=wechaty-puppet-padpro` | -| iPad | PuppetPadchat **DEPRECATED** | `export WECHATY_PUPPET=wechaty-puppet-padchat` | +| iPad | PuppetPadLoca | `export WECHATY_PUPPET=wechaty-puppet-padlocal` | +| iPad | ~~PuppetPadpro~~ **DEPRECATED** | `export WECHATY_PUPPET=wechaty-puppet-padpro` | +| iPad | ~~PuppetPadchat~~ **DEPRECATED** | `export WECHATY_PUPPET=wechaty-puppet-padchat` | +| iPad | ~~PuppetPadplus~~ **DEPRECATED** | `export WECHATY_PUPPET=wechaty-puppet-padplus` | +| Mac | ~~PuppetMacpro~~ **DEPRECATED** | `export WECHATY_PUPPET=wechaty-puppet-macpro` | Learn more about Wechaty Puppet from the Puppet Wiki: From b2288fa95ee1e5774f032fb00360f1f733f31057 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 24 Nov 2020 15:02:32 +0800 Subject: [PATCH 519/598] strict typing check for typescript v4 --- src/helper-functions/impure/get-port.spec.ts | 2 +- src/helper-functions/impure/open-graph.ts | 2 ++ src/io.ts | 6 +++--- src/wechaty.spec.ts | 6 +++--- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/helper-functions/impure/get-port.spec.ts b/src/helper-functions/impure/get-port.spec.ts index d44df4114..31bb6e85f 100644 --- a/src/helper-functions/impure/get-port.spec.ts +++ b/src/helper-functions/impure/get-port.spec.ts @@ -36,7 +36,7 @@ test('getPort() for an available socket port', async t => { const server = net.createServer(socket => { console.info(socket) }) - await new Promise(resolve => server.listen(port, resolve)) + await new Promise(resolve => server.listen(port, resolve)) serverList.push(server) port = await getPort() diff --git a/src/helper-functions/impure/open-graph.ts b/src/helper-functions/impure/open-graph.ts index 30e0dcfa9..606206924 100644 --- a/src/helper-functions/impure/open-graph.ts +++ b/src/helper-functions/impure/open-graph.ts @@ -24,6 +24,8 @@ export async function openGraph (url: string): Promise { og(url, (err, meta) => { if (err) { reject(err) + } else if (!meta) { + reject(new Error('meta is undefined')) } else { resolve(meta) } diff --git a/src/io.ts b/src/io.ts index 1f88f98a0..c05dc8d55 100644 --- a/src/io.ts +++ b/src/io.ts @@ -227,7 +227,7 @@ export class Io { } let endpoint = 'wss://' + this.options.apihost + '/v0/websocket' - // XXX quick and dirty: use no ssl for APIHOST other than official + // XXX quick and dirty: use no ssl for API_HOST other than official // FIXME: use a configurable VARIABLE for the domain name at here: if (!/api\.chatie\.io/.test(this.options.apihost)) { endpoint = 'ws://' + this.options.apihost + '/v0/websocket' @@ -481,7 +481,7 @@ export class Io { const data = JSON.stringify( this.eventBuffer.shift(), ) - const p = new Promise((resolve, reject) => ws.send( + const p = new Promise((resolve, reject) => ws.send( data, (err: undefined | Error) => { if (err) { @@ -526,7 +526,7 @@ export class Io { } this.ws.close() - await new Promise(resolve => { + await new Promise(resolve => { if (this.ws) { this.ws.once('close', resolve) } else { diff --git a/src/wechaty.spec.ts b/src/wechaty.spec.ts index 8367dc1f5..03d7a1314 100755 --- a/src/wechaty.spec.ts +++ b/src/wechaty.spec.ts @@ -152,7 +152,7 @@ test.skip('SKIP DEALING WITH THE LISTENER EXCEPTIONS. on(event, Function)', asyn test.skip('SKIP DEALING WITH THE LISTENER EXCEPTIONS. test async error', async (t) => { - // Do not modify the gloabl Wechaty instance + // Do not modify the global Wechaty instance class MyWechatyTest extends Wechaty {} const EXPECTED_ERROR = new Error('test') @@ -162,12 +162,12 @@ test.skip('SKIP DEALING WITH THE LISTENER EXCEPTIONS. test async error', async ( }) const asyncErrorFunction = function () { - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { setTimeout(function () { reject(EXPECTED_ERROR) }, 100) // tslint ask resolve must be called, - // so write a fasly value, so that it never called + // so write a falsy value, so that it never called if (+new Date() < 0) { resolve() } From f4febd8e88a99ccd268590dfba41d4a71d0067ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Tue, 24 Nov 2020 15:02:45 +0800 Subject: [PATCH 520/598] 0.51.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e4949fa47..3c866cb5b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.51.3", + "version": "0.51.4", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 0bc28e2430ec6111fd340994ef3c7c68b317b3f5 Mon Sep 17 00:00:00 2001 From: SuperChang Date: Wed, 25 Nov 2020 21:49:33 +0800 Subject: [PATCH 521/598] Update contact.ts (#2095) fix: return payload friend --- src/user/contact.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/user/contact.ts b/src/user/contact.ts index e6f692c71..66c269b3c 100644 --- a/src/user/contact.ts +++ b/src/user/contact.ts @@ -668,7 +668,11 @@ class Contact extends ContactEventEmitter implements Sayable { if (!this.payload) { return null } - return this.payload.friend || null + if (typeof this.payload.friend === 'boolean') { + return this.payload.friend + } else { + return null + } } /** From e1e3433e65c4a6fce4070d85a502126a5e01519e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 27 Nov 2020 19:16:00 +0800 Subject: [PATCH 522/598] rename from() to talker() from message --- src/user/message.spec.ts | 2 +- src/user/message.ts | 23 +++++++++++------------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/user/message.spec.ts b/src/user/message.spec.ts index baed42cb0..d4ec2844d 100755 --- a/src/user/message.spec.ts +++ b/src/user/message.spec.ts @@ -95,7 +95,7 @@ test('recalled()', async t => { const recalledMessage = await message.toRecalled() t.assert(recalledMessage, 'recalled message should exist.') t.equal(recalledMessage!.id, EXPECTED_RECALLED_MESSAGE_ID, 'Recalled message should have the right id.') - t.equal(recalledMessage!.from()!.id, EXPECTED_FROM_CONTACT_ID, 'Recalled message should have the right from contact id.') + t.equal(recalledMessage!.talker().id, EXPECTED_FROM_CONTACT_ID, 'Recalled message should have the right from contact id.') t.equal(recalledMessage!.to()!.id, EXPECTED_TO_CONTACT_ID, 'Recalled message should have the right to contact id.') t.equal(recalledMessage!.room()!.id, EXPECTED_ROOM_ID, 'Recalled message should have the right room id.') diff --git a/src/user/message.ts b/src/user/message.ts index 1645a67d8..a42a2eeaf 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -202,9 +202,8 @@ class Message extends EventEmitter implements Sayable { 'Message', `#${MessageType[this.type()]}`, '[', - this.from() - ? '🗣' + this.from() - : '', + '🗣', + this.talker(), this.room() ? '@👥' + this.room() : '', @@ -229,7 +228,7 @@ class Message extends EventEmitter implements Sayable { if (this.room()) { return this.room()! } else { - return this.from()! + return this.talker() } } @@ -499,7 +498,7 @@ class Message extends EventEmitter implements Sayable { log.verbose('Message', 'say(%s)', something) // const user = this.wechaty.puppet.userSelf() - const from = this.from() + const talker = this.talker() // const to = this.to() const room = this.room() @@ -509,9 +508,9 @@ class Message extends EventEmitter implements Sayable { if (room) { conversation = room conversationId = room.id - } else if (from) { - conversation = from - conversationId = from.id + } else if (talker) { + conversation = talker + conversationId = talker.id } else { throw new Error('neither room nor from?') } @@ -534,8 +533,8 @@ class Message extends EventEmitter implements Sayable { * Text Message */ let mentionIdList - if (from && await this.mentionSelf()) { - mentionIdList = [from.id] + if (talker && await this.mentionSelf()) { + mentionIdList = [talker.id] } msgId = await this.wechaty.puppet.messageSendText( @@ -650,9 +649,9 @@ class Message extends EventEmitter implements Sayable { */ public self (): boolean { const userId = this.wechaty.puppet.selfId() - const from = this.from() + const talker = this.talker() - return !!from && from.id === userId + return !!talker && talker.id === userId } /** From 30c446b2b78c92166a1d613952e77d3e3fdbbe1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 27 Nov 2020 19:16:26 +0800 Subject: [PATCH 523/598] 0.51.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3c866cb5b..49817b09d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.51.4", + "version": "0.51.5", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From c7502002d3f8d04eaaf2f2df64782043f7724961 Mon Sep 17 00:00:00 2001 From: lijiarui Date: Fri, 4 Dec 2020 19:25:44 +0800 Subject: [PATCH 524/598] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 060971c2d..e38a6a177 100644 --- a/README.md +++ b/README.md @@ -155,7 +155,9 @@ Currently we support the following puppet providers: | Web | PuppetPuppeteer | `export WECHATY_PUPPET=wechaty-puppet-puppeteer` | | Mock | PuppetMock | `export WECHATY_PUPPET=wechaty-puppet-mock` | | Web | PuppetWechat4u | `export WECHATY_PUPPET=wechaty-puppet-wechat4u` | -| iPad | PuppetPadLoca | `export WECHATY_PUPPET=wechaty-puppet-padlocal` | +| iPad | PuppetRock | `export WECHATY_PUPPET=wechaty-puppet-hostie` | +| iPad | PuppetPadLocal | `export WECHATY_PUPPET=wechaty-puppet-hostie` | +| Windows | PuppetDonut | `export WECHATY_PUPPET=wechaty-puppet-hostie` | | iPad | ~~PuppetPadpro~~ **DEPRECATED** | `export WECHATY_PUPPET=wechaty-puppet-padpro` | | iPad | ~~PuppetPadchat~~ **DEPRECATED** | `export WECHATY_PUPPET=wechaty-puppet-padchat` | | iPad | ~~PuppetPadplus~~ **DEPRECATED** | `export WECHATY_PUPPET=wechaty-puppet-padplus` | From c202ba22dec781e52fbef1f16aad0057732c0d0f Mon Sep 17 00:00:00 2001 From: lijiarui Date: Fri, 4 Dec 2020 20:01:10 +0800 Subject: [PATCH 525/598] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e38a6a177..caf9461f8 100644 --- a/README.md +++ b/README.md @@ -153,6 +153,7 @@ Currently we support the following puppet providers: | Protocol | Puppet Provider | Environment Variable | | --- | --- | --- | | Web | PuppetPuppeteer | `export WECHATY_PUPPET=wechaty-puppet-puppeteer` | +| Windows | PuppetWxwork | `export WECHATY_PUPPET=wechaty-puppet-hostie` | | Mock | PuppetMock | `export WECHATY_PUPPET=wechaty-puppet-mock` | | Web | PuppetWechat4u | `export WECHATY_PUPPET=wechaty-puppet-wechat4u` | | iPad | PuppetRock | `export WECHATY_PUPPET=wechaty-puppet-hostie` | From 116d94751923e49f962b2b49593428a049e19866 Mon Sep 17 00:00:00 2001 From: lijiarui Date: Fri, 4 Dec 2020 20:04:44 +0800 Subject: [PATCH 526/598] Update README.md --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index caf9461f8..3e2a0ec09 100644 --- a/README.md +++ b/README.md @@ -152,13 +152,13 @@ Currently we support the following puppet providers: | Protocol | Puppet Provider | Environment Variable | | --- | --- | --- | -| Web | PuppetPuppeteer | `export WECHATY_PUPPET=wechaty-puppet-puppeteer` | -| Windows | PuppetWxwork | `export WECHATY_PUPPET=wechaty-puppet-hostie` | -| Mock | PuppetMock | `export WECHATY_PUPPET=wechaty-puppet-mock` | -| Web | PuppetWechat4u | `export WECHATY_PUPPET=wechaty-puppet-wechat4u` | -| iPad | PuppetRock | `export WECHATY_PUPPET=wechaty-puppet-hostie` | -| iPad | PuppetPadLocal | `export WECHATY_PUPPET=wechaty-puppet-hostie` | -| Windows | PuppetDonut | `export WECHATY_PUPPET=wechaty-puppet-hostie` | +| Web | [PuppetPuppeteer](https://github.com/wechaty/wechaty-puppet-puppeteer) | `export WECHATY_PUPPET=wechaty-puppet-puppeteer` | +| Windows | [PuppetWxwork](https://github.com/juzibot/wxwork-tester) | `export WECHATY_PUPPET=wechaty-puppet-hostie` | +| Mock | [PuppetMock](https://github.com/wechaty/wechaty-puppet-mock) | `export WECHATY_PUPPET=wechaty-puppet-mock` | +| Web | [PuppetWechat4u](https://github.com/wechaty/wechaty-puppet-wechat4u) | `export WECHATY_PUPPET=wechaty-puppet-wechat4u` | +| iPad | [PuppetRock](https://github.com/wechaty/puppet-service-providers) | `export WECHATY_PUPPET=wechaty-puppet-hostie` | +| iPad | [PuppetPadLocal](https://github.com/wechaty/puppet-service-providers) | `export WECHATY_PUPPET=wechaty-puppet-hostie` | +| Windows | [PuppetDonut](https://github.com/wechaty/puppet-service-providers) | `export WECHATY_PUPPET=wechaty-puppet-hostie` | | iPad | ~~PuppetPadpro~~ **DEPRECATED** | `export WECHATY_PUPPET=wechaty-puppet-padpro` | | iPad | ~~PuppetPadchat~~ **DEPRECATED** | `export WECHATY_PUPPET=wechaty-puppet-padchat` | | iPad | ~~PuppetPadplus~~ **DEPRECATED** | `export WECHATY_PUPPET=wechaty-puppet-padplus` | From b79000090bd68e6d152041c21f9929e6362d613a Mon Sep 17 00:00:00 2001 From: lijiarui Date: Fri, 4 Dec 2020 20:23:47 +0800 Subject: [PATCH 527/598] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3e2a0ec09..c8190273b 100644 --- a/README.md +++ b/README.md @@ -148,7 +148,7 @@ Wechaty is very powerful that it can run over different protocols. You can speci If you cannot use Web protocol, you can apply other protocal following the instruction here: We provide free token to support developers build a valuable WeChat chatbot. -Currently we support the following puppet providers: +Currently we support the following [puppet providers](https://github.com/wechaty/puppet-service-providers): | Protocol | Puppet Provider | Environment Variable | | --- | --- | --- | From afbf11946e1a0a03d42755da046be711971722cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 6 Dec 2020 15:21:19 +0800 Subject: [PATCH 528/598] add wechaty-puppet-padlocal to the puppet config (#2102) --- src/puppet-config.ts | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 085ac6e06..17dd9f772 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -20,20 +20,20 @@ */ export const PUPPET_DEPENDENCIES = { /** - * The following puppets were DEPRECATED + * The following puppets were DEPRECATED before 2020 */ // 'wechaty-puppet-ioscat' : '^0.5.22', // https://www.npmjs.com/package/wechaty-puppet-ioscat // 'wechaty-puppet-padchat' : '^0.19.3', // https://www.npmjs.com/package/wechaty-puppet-padchat // 'wechaty-puppet-padpro' : '^0.3.21', // https://www.npmjs.com/package/wechaty-puppet-padpro /** - * Scoped puppets + * Deprecated on Dec 2020 + * https://github.com/wechaty/puppet-service-providers/issues/11 */ - '@juzibot/wechaty-puppet-donut': '^0.3', // https://www.npmjs.com/package/wechaty-puppet-donut (to be published) - '@juzibot/wechaty-puppet-wxwork': '*', // https://www.npmjs.com/package/wechaty-puppet-wxwork (to be published) + // 'wechaty-puppet-padplus' : '^0.7.30', // https://www.npmjs.com/package/wechaty-puppet-padplus /** - * Wechaty Internal Puppets: dependence by package.json + * Wechaty Internal Puppets: dependency by package.json */ 'wechaty-puppet-hostie' : '*', // https://www.npmjs.com/package/wechaty-puppet-hostie 'wechaty-puppet-mock' : '*', // https://www.npmjs.com/package/wechaty-puppet-mock @@ -41,16 +41,18 @@ export const PUPPET_DEPENDENCIES = { /** * Wechaty External Puppets */ - 'wechaty-puppet-padplus' : '^0.7.30', // https://www.npmjs.com/package/wechaty-puppet-padplus - 'wechaty-puppet-puppeteer' : '^0.23.1', // https://www.npmjs.com/package/wechaty-puppet-puppeteer - 'wechaty-puppet-wechat4u' : '^0.17.4', // https://www.npmjs.com/package/wechaty-puppet-wechat4u - - /** - * Other - */ + 'wechaty-puppet-puppeteer' : '*', // https://www.npmjs.com/package/wechaty-puppet-puppeteer + 'wechaty-puppet-wechat4u' : '*', // https://www.npmjs.com/package/wechaty-puppet-wechat4u 'wechaty-puppet-gitter' : '*', // https://www.npmjs.com/package/wechaty-puppet-gitter 'wechaty-puppet-official-account' : '*', // https://www.npmjs.com/package/wechaty-puppet-official-account + 'wechaty-puppet-padlocal' : '*', // https://www.npmjs.com/package/wechaty-puppet-padlocal 'wechaty-puppet-whatsapp' : '*', // https://www.npmjs.com/package/wechaty-puppet-whatsapp + + /** + * Scoped puppets + */ + '@juzibot/wechaty-puppet-donut': '^0.3', // https://www.npmjs.com/package/wechaty-puppet-donut (to be published) + '@juzibot/wechaty-puppet-wxwork': '*', // https://www.npmjs.com/package/wechaty-puppet-wxwork (to be published) } export type PuppetModuleName = keyof typeof PUPPET_DEPENDENCIES From 34ff3e0ea5b7df17ab14a2e16cbd9c40306c997d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 6 Dec 2020 15:21:56 +0800 Subject: [PATCH 529/598] 0.51.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 49817b09d..7a4c49111 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.51.5", + "version": "0.51.6", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 60b52296194a43feb78ef642e9b94d1cfdd93bf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 6 Dec 2020 15:23:00 +0800 Subject: [PATCH 530/598] 0.51.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7a4c49111..e71ec6d7c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.51.6", + "version": "0.51.7", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 66f89587ad677a541464cd5481a17a02a4c5a343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 6 Dec 2020 15:37:27 +0800 Subject: [PATCH 531/598] remove padplus from smoke testing (#2087) --- tests/fixtures/smoke-testing.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/fixtures/smoke-testing.ts b/tests/fixtures/smoke-testing.ts index d777d256c..deb4bd423 100644 --- a/tests/fixtures/smoke-testing.ts +++ b/tests/fixtures/smoke-testing.ts @@ -38,10 +38,10 @@ function getBotList (): Wechaty[] { }) ) } - if (process.env.WECHATY_PUPPET_PADPLUS_TOKEN) { + if (process.env.WECHATY_PUPPET_PADLOCAL_TOKEN) { botList.push( new Wechaty({ - puppet: 'wechaty-puppet-padplus', + puppet: 'wechaty-puppet-padlocal', }) ) } From d3bd69b938a0e37d990a747781ee29f7ec379f54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sun, 6 Dec 2020 15:37:43 +0800 Subject: [PATCH 532/598] 0.51.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e71ec6d7c..c751c1802 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.51.7", + "version": "0.51.8", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 141da77c3f3b979e632ada278f275a7131498b34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 7 Dec 2020 18:10:26 +0800 Subject: [PATCH 533/598] add url link unit test --- src/user/url-link.spec.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100755 src/user/url-link.spec.ts diff --git a/src/user/url-link.spec.ts b/src/user/url-link.spec.ts new file mode 100755 index 000000000..8fe9c1486 --- /dev/null +++ b/src/user/url-link.spec.ts @@ -0,0 +1,13 @@ +#!/usr/bin/env ts-node + +import test from 'tstest' + +import { UrlLink } from './url-link' + +test('UrlLink', async t => { + const urlLink = await UrlLink.create('https://wechaty.js.org/2020/07/02/wechat-bot-in-ten-minutes') + t.true(urlLink.title, 'should have title',) + t.true(urlLink.description, 'should have description',) + t.true(urlLink.url, 'should have url',) + t.true(urlLink.thumbnailUrl, 'should have thumbnailUrl',) +}) From 1c08782985367d6b4b70b0b974b6f6d037b865ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 7 Dec 2020 18:10:40 +0800 Subject: [PATCH 534/598] 0.51.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c751c1802..efb66e873 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.51.8", + "version": "0.51.9", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 2c5b46c0492a8f8b94b84406ad3da3037a7d7b9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 7 Dec 2020 18:12:50 +0800 Subject: [PATCH 535/598] add strict check --- src/user/url-link.spec.ts | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/user/url-link.spec.ts b/src/user/url-link.spec.ts index 8fe9c1486..fc99ba8c5 100755 --- a/src/user/url-link.spec.ts +++ b/src/user/url-link.spec.ts @@ -5,9 +5,17 @@ import test from 'tstest' import { UrlLink } from './url-link' test('UrlLink', async t => { - const urlLink = await UrlLink.create('https://wechaty.js.org/2020/07/02/wechat-bot-in-ten-minutes') - t.true(urlLink.title, 'should have title',) - t.true(urlLink.description, 'should have description',) - t.true(urlLink.url, 'should have url',) - t.true(urlLink.thumbnailUrl, 'should have thumbnailUrl',) + const URL = 'https://wechaty.js.org/2020/07/02/wechat-bot-in-ten-minutes' + const EXPECTED_PAYLOAD = { + description: '十分钟实现一个智能问答微信聊天机器人', + thumbnailUrl: 'https://wechaty.js.org/assets/developers/luweicn/avatar.png', + title: '十分钟实现一个智能问答微信聊天机器人', + url: 'https://wechaty.js.org/2020/07/02/wechat-bot-in-ten-minutes' + } + + const urlLink = await UrlLink.create(URL) + t.equal(urlLink.title(), EXPECTED_PAYLOAD.title, 'should have title',) + t.equal(urlLink.description(), EXPECTED_PAYLOAD.description, 'should have description',) + t.equal(urlLink.url(), EXPECTED_PAYLOAD.url, 'should have url',) + t.equal(urlLink.thumbnailUrl(), EXPECTED_PAYLOAD.thumbnailUrl, 'should have thumbnailUrl',) }) From d09067b74cc1241f4bb94bcd68a8a9bde2a94c08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 7 Dec 2020 18:13:41 +0800 Subject: [PATCH 536/598] clean --- src/user/url-link.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/user/url-link.spec.ts b/src/user/url-link.spec.ts index fc99ba8c5..3fa4b4a45 100755 --- a/src/user/url-link.spec.ts +++ b/src/user/url-link.spec.ts @@ -10,7 +10,7 @@ test('UrlLink', async t => { description: '十分钟实现一个智能问答微信聊天机器人', thumbnailUrl: 'https://wechaty.js.org/assets/developers/luweicn/avatar.png', title: '十分钟实现一个智能问答微信聊天机器人', - url: 'https://wechaty.js.org/2020/07/02/wechat-bot-in-ten-minutes' + url: 'https://wechaty.js.org/2020/07/02/wechat-bot-in-ten-minutes', } const urlLink = await UrlLink.create(URL) From 113db885b2778f956e82fc965655b55bfae3cf23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 7 Dec 2020 18:14:00 +0800 Subject: [PATCH 537/598] 0.51.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index efb66e873..df6246b80 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.51.9", + "version": "0.51.10", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 44afa0066e84e2fa0470b63d717b8e0bc7bf80d1 Mon Sep 17 00:00:00 2001 From: profthecopyright <54515051+profthecopyright@users.noreply.github.com> Date: Tue, 8 Dec 2020 22:51:56 -0500 Subject: [PATCH 538/598] Update room-invitation.ts (#2104) topic() returns a Promise instead of Promise. The document is incorrect. --- src/user/room-invitation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/user/room-invitation.ts b/src/user/room-invitation.ts index 17f36c036..33c8f85d3 100644 --- a/src/user/room-invitation.ts +++ b/src/user/room-invitation.ts @@ -165,7 +165,7 @@ class RoomInvitation implements Acceptable { /** * Get the room topic from room invitation * - * @returns {Contact} + * @returns {string} * @example * const bot = new Wechaty() * bot.on('room-invite', async roomInvitation => { From bbc2db1afc686b85496fd0226871882ea6e5f2bc Mon Sep 17 00:00:00 2001 From: Huan Date: Wed, 16 Dec 2020 18:38:30 +0800 Subject: [PATCH 539/598] add puppet event to emitter typing --- src/events/wechaty-events.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/events/wechaty-events.ts b/src/events/wechaty-events.ts index 56b117d4d..2c18d8540 100644 --- a/src/events/wechaty-events.ts +++ b/src/events/wechaty-events.ts @@ -4,6 +4,7 @@ import TypedEventEmitter from 'typed-emitter' import { CHAT_EVENT_DICT, + Puppet, ScanStatus, } from 'wechaty-puppet' @@ -38,6 +39,7 @@ export type WechatyHeartbeatEventListener = (data: any) => void export type WechatyLoginEventListener = (user: ContactSelf) => void export type WechatyLogoutEventListener = (user: ContactSelf, reason?: string) => void export type WechatyMessageEventListener = (message: Message) => void +export type WechatyPuppetEventListener = (puppet: Puppet) => void export type WechatyReadyEventListener = () => void export type WechatyRoomInviteEventListener = (roomInvitation: RoomInvitation) => void export type WechatyRoomJoinEventListener = (room: Room, inviteeList: Contact[], inviter: Contact, date?: Date) => void @@ -201,6 +203,10 @@ export type WechatyStartStopEventListener = () => void * }) */ interface WechatyEvents { + 'room-invite' : WechatyRoomInviteEventListener + 'room-join' : WechatyRoomJoinEventListener + 'room-leave' : WechatyRoomLeaveEventListener + 'room-topic' : WechatyRoomTopicEventListener dong : WechatyDongEventListener error : WechatyErrorEventListener friendship : WechatyFriendshipEventListener @@ -208,11 +214,8 @@ interface WechatyEvents { login : WechatyLoginEventListener logout : WechatyLogoutEventListener message : WechatyMessageEventListener + puppet : WechatyPuppetEventListener ready : WechatyReadyEventListener - 'room-invite' : WechatyRoomInviteEventListener - 'room-join' : WechatyRoomJoinEventListener - 'room-leave' : WechatyRoomLeaveEventListener - 'room-topic' : WechatyRoomTopicEventListener scan : WechatyScanEventListener start : WechatyStartStopEventListener stop : WechatyStartStopEventListener From 068f670ed4b8d471c0b4ca49f0a9503644a84866 Mon Sep 17 00:00:00 2001 From: Huan Date: Wed, 16 Dec 2020 18:38:41 +0800 Subject: [PATCH 540/598] 0.51.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index df6246b80..98ba67f27 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.51.10", + "version": "0.51.11", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From f0ff912d5723cc91ecb9e2443c1b6c8b3d602c0c Mon Sep 17 00:00:00 2001 From: Huan Date: Wed, 16 Dec 2020 18:43:19 +0800 Subject: [PATCH 541/598] add puppet to wechaty event names --- src/events/wechaty-events.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/events/wechaty-events.ts b/src/events/wechaty-events.ts index 2c18d8540..4186952d7 100644 --- a/src/events/wechaty-events.ts +++ b/src/events/wechaty-events.ts @@ -22,6 +22,7 @@ const WECHATY_EVENT_DICT = { dong : 'Should be emitted after we call `Wechaty.ding()`', error : "Will be emitted when there's an Error occurred.", heartbeat : 'Will be emitted periodically after the Wechaty started. If not, means that the Wechaty had died.', + puppet : 'Will be emitted when the puppet has been set.', ready : 'All underlined data source are ready for use.', start : 'Will be emitted after the Wechaty had been started.', stop : 'Will be emitted after the Wechaty had been stopped.', From cc0247faa198567dc7a9d2a9970ebec47761d6fc Mon Sep 17 00:00:00 2001 From: Huan Date: Thu, 17 Dec 2020 18:02:54 +0800 Subject: [PATCH 542/598] Working on RxJS related deps --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 98ba67f27..c133a124c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.51.11", + "version": "0.53.0", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", @@ -102,7 +102,7 @@ "typed-emitter": "^1.3.1", "watchdog": "^0.8.17", "wechaty-puppet": "^0.33.6", - "wechaty-puppet-hostie": "^0.11.0", + "wechaty-puppet-hostie": "^0.13.1", "ws": "^7.3.1" }, "devDependencies": { From 7ad1a4030da1dd755117a245fedace5b19ec38c6 Mon Sep 17 00:00:00 2001 From: Huan Date: Thu, 17 Dec 2020 18:03:09 +0800 Subject: [PATCH 543/598] 0.53.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c133a124c..aace8a221 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.53.0", + "version": "0.53.1", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From f33566e37e17b5c3aa260ae32d813da687a4a204 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 17 Dec 2020 23:56:29 +0800 Subject: [PATCH 544/598] Rename NODE_AUTH_TOKEN -> NPM_TOKEN --- .github/workflows/npm.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index ad958f485..1a9b14969 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -66,7 +66,7 @@ jobs: else npm publish fi env: - NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }} + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Is Not A Publish Branch if: steps.check-branch.outputs.match != 'true' run: echo 'Not A Publish Branch' From 795ccc5155f95b34f97a6209c5a38d50b8319b11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 7 Jan 2021 17:57:31 +0800 Subject: [PATCH 545/598] Use Debian instead of Ubuntu for our Docker (#2114) --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 87d4d4dae..d4b4c4fef 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:eoan +FROM debian:buster LABEL maintainer="Huan LI (李卓桓) " ENV DEBIAN_FRONTEND noninteractive From 8ac9f6d9882db3dd3a86c05c8f13a4d60c3341a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 7 Jan 2021 17:59:49 +0800 Subject: [PATCH 546/598] 0.53.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index aace8a221..a501e7c62 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.53.1", + "version": "0.53.2", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 152c594036b6d56c6a879b4e3b0c0cd5eaabdae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 7 Jan 2021 18:12:39 +0800 Subject: [PATCH 547/598] Update Node.js v12 -> v14 (#2115) --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index d4b4c4fef..82c15f059 100644 --- a/Dockerfile +++ b/Dockerfile @@ -38,7 +38,7 @@ RUN apt-get update \ && apt-get purge --auto-remove \ && rm -rf /tmp/* /var/lib/apt/lists/* -RUN curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - \ +RUN curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash - \ && apt-get update && apt-get install -y --no-install-recommends nodejs \ && apt-get purge --auto-remove \ && rm -rf /tmp/* /var/lib/apt/lists/* From 55e54c87a43caaf5eae01482b7d1e22b899ac145 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 7 Jan 2021 18:13:04 +0800 Subject: [PATCH 548/598] 0.53.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a501e7c62..187e7fbac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.53.2", + "version": "0.53.3", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 7e62792b15e162c059f319137c537f56f897e8b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 7 Jan 2021 18:27:07 +0800 Subject: [PATCH 549/598] RPA SDK --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c8190273b..e2be63968 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ ## :hearts: Connecting Chatbots -Wechaty is a Conversational SDK for Chatbot Makers which can help you create a bot in 6 lines of [JavaScript](https://GitHub.com/Wechaty/wechaty), [Python](https://GitHub.com/Wechaty/python-wechaty/), [Go](https://GitHub.com/Wechaty/go-wechaty/), and [Java](https://GitHub.com/Wechaty/java-wechaty/), with cross-platform support including [Linux, Windows, MacOS](https://github.com/wechaty/wechaty/actions?query=workflow%3ANPM), and [Docker](https://github.com/wechaty/wechaty/actions?query=workflow%3ADocker). +Wechaty is a RPA (Robotic Process Automation) SDK for Chatbot Makers which can help you create a bot in 6 lines of [JavaScript](https://GitHub.com/Wechaty/wechaty), [Python](https://GitHub.com/Wechaty/python-wechaty/), [Go](https://GitHub.com/Wechaty/go-wechaty/), and [Java](https://GitHub.com/Wechaty/java-wechaty/), with cross-platform support including [Linux, Windows, MacOS](https://github.com/wechaty/wechaty/actions?query=workflow%3ANPM), and [Docker](https://github.com/wechaty/wechaty/actions?query=workflow%3ADocker). :octocat: :beetle: From 9486202fc63945911535e793decf9cdee20a4fcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Thu, 7 Jan 2021 18:30:28 +0800 Subject: [PATCH 550/598] RPA SDK --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index e2be63968..b66d1183d 100644 --- a/README.md +++ b/README.md @@ -474,13 +474,13 @@ Support this project by becoming a sponsor. Your logo will show up here with a l [![PHP Wechaty](https://img.shields.io/badge/Wechaty-PHP-99c)](https://github.com/wechaty/php-wechaty) [![.NET(C#) Wechatyin](https://img.shields.io/badge/Wechaty-.NET-629)](https://github.com/wechaty/dotnet-wechaty) -- [Wechaty](https://github.com/wechaty/wechaty) - Conversatioanl SDK for Chatot Makers (TypeScript) -- [Python Wechaty](https://github.com/wechaty/python-wechaty) - Conversational SDK for Chatbot Makers written in Python -- [Go Wechaty](https://github.com/wechaty/go-wechaty) - Conversational SDK for Chatbot Makers written in Go -- [Java Wechaty](https://github.com/wechaty/java-wechaty) - Conversational SDK for Chatbot Makers written in Java(Kotlin) -- [Scala Wechaty](https://github.com/wechaty/scala-wechaty) - Conversational SDK for Chatbot Makers written in Scala -- [PHP Wechaty](https://github.com/wechaty/php-wechaty) - Conversational SDK for Chatbot Makers written in PHP -- [.Net(C#) Wechaty](https://github.com/wechaty/dotnet-wechaty) - Conversational SDK for Chatbot Makers written in .NET(C#) +- [Wechaty](https://github.com/wechaty/wechaty) - RPA SDK for Chatot Makers (TypeScript) +- [Python Wechaty](https://github.com/wechaty/python-wechaty) - RPA SDK for Chatbot Makers written in Python +- [Go Wechaty](https://github.com/wechaty/go-wechaty) - RPA SDK for Chatbot Makers written in Go +- [Java Wechaty](https://github.com/wechaty/java-wechaty) - RPA SDK for Chatbot Makers written in Java(Kotlin) +- [Scala Wechaty](https://github.com/wechaty/scala-wechaty) - RPA SDK for Chatbot Makers written in Scala +- [PHP Wechaty](https://github.com/wechaty/php-wechaty) - RPA SDK for Chatbot Makers written in PHP +- [.Net(C#) Wechaty](https://github.com/wechaty/dotnet-wechaty) - RPA SDK for Chatbot Makers written in .NET(C#) ## :raised_hands: Creators From 042d45b21b5f6a7c45645d37ad2175a6a6576a81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 8 Jan 2021 00:16:26 +0800 Subject: [PATCH 551/598] use cache to speed up github action --- .github/workflows/node.js.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 52f3a3c99..455396c43 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -23,6 +23,12 @@ jobs: uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} + - uses: actions/cache@v2 + with: + path: ~/.npm + key: ${{ runner.os }}-wechaty-cache + restore-keys: | + ${{ runner.os }}-wechaty- - run: npm install - run: npm run build --if-present - run: npm test From 86f9c7e81f3c64530e33b8df54ba2376d3895b25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 8 Jan 2021 00:19:22 +0800 Subject: [PATCH 552/598] use cache for node & npm --- .github/workflows/node.js.yml | 4 ++-- .github/workflows/npm.yml | 33 +++++++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 455396c43..14d824db4 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -14,13 +14,13 @@ jobs: strategy: matrix: os: [macos-latest, windows-latest, ubuntu-latest] - node-version: [12, 14] + node-version: [14, 15] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 + uses: actions/setup-node@v2 with: node-version: ${{ matrix.node-version }} - uses: actions/cache@v2 diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index 1a9b14969..8677d9fde 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -8,11 +8,16 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: Use Node.js 12 - uses: actions/setup-node@v1 + - name: Use Node.js 15 + uses: actions/setup-node@v2 with: - node-version: 12 - + node-version: 15 + - uses: actions/cache@v2 + with: + path: ~/.npm + key: ${{ runner.os }}-wechaty-cache + restore-keys: | + ${{ runner.os }}-wechaty- - name: Install Dependencies run: npm install @@ -25,9 +30,15 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/setup-node@v2 with: - node-version: 12 + node-version: 15 + - uses: actions/cache@v2 + with: + path: ~/.npm + key: ${{ runner.os }}-wechaty-cache + restore-keys: | + ${{ runner.os }}-wechaty- - run: npm install - run: ./scripts/generate-version.sh - run: ./scripts/npm-pack-testing.sh @@ -41,10 +52,16 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/setup-node@v2 with: - node-version: 12 + node-version: 15 registry-url: https://registry.npmjs.org/ + - uses: actions/cache@v2 + with: + path: ~/.npm + key: ${{ runner.os }}-wechaty-cache + restore-keys: | + ${{ runner.os }}-wechaty- - run: npm install - run: ./scripts/generate-version.sh - run: ./scripts/package-publish-config-tag.sh From b1de8716464a25ed89e4f9151cfad02734319e12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 8 Jan 2021 00:19:37 +0800 Subject: [PATCH 553/598] 0.53.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 187e7fbac..ac45a273b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.53.3", + "version": "0.53.4", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 04d3967cbffb36cd1e3f0bc58e6bc6e11af0bf61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 8 Jan 2021 00:31:18 +0800 Subject: [PATCH 554/598] node v15 not support grpc yet --- .github/workflows/node.js.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 14d824db4..4ad4d9593 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -14,7 +14,7 @@ jobs: strategy: matrix: os: [macos-latest, windows-latest, ubuntu-latest] - node-version: [14, 15] + node-version: [14] runs-on: ${{ matrix.os }} steps: From b12d5dc1339dd589cf1f5a7c88b095273a79b6d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 8 Jan 2021 00:31:30 +0800 Subject: [PATCH 555/598] 0.53.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ac45a273b..c2c1dceb0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.53.4", + "version": "0.53.5", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 2961fd4f5b2ed14d3b6333c190c588a6524658c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 8 Jan 2021 20:58:11 +0800 Subject: [PATCH 556/598] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c2c1dceb0..86b769cea 100644 --- a/package.json +++ b/package.json @@ -130,7 +130,7 @@ "jsdoc-to-markdown": "^6.0.1", "markdownlint-cli": "^0.24.0", "nyc": "^15.1.0", - "pkg-jq": "^0.2.4", + "pkg-jq": "^0.2.7", "qrcode-terminal": "^0.12.0", "shx": "^0.3.3", "sloc": "^0.2.1", From 3b7b45d5e62d49c3aadc6d385c9c5d2084af5216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 8 Jan 2021 22:01:48 +0800 Subject: [PATCH 557/598] Upgrade pkg-jq --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 86b769cea..18c5c7334 100644 --- a/package.json +++ b/package.json @@ -130,7 +130,7 @@ "jsdoc-to-markdown": "^6.0.1", "markdownlint-cli": "^0.24.0", "nyc": "^15.1.0", - "pkg-jq": "^0.2.7", + "pkg-jq": "^0.2.11", "qrcode-terminal": "^0.12.0", "shx": "^0.3.3", "sloc": "^0.2.1", From fc14c4576dec4a84e99a2612fcf903ac00b421b5 Mon Sep 17 00:00:00 2001 From: Huan Date: Mon, 11 Jan 2021 19:55:20 +0800 Subject: [PATCH 558/598] use better cache for gh actions --- .github/workflows/node.js.yml | 18 ++++++++---- .github/workflows/npm.yml | 52 +++++++++++++++++++++++++---------- 2 files changed, 51 insertions(+), 19 deletions(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 4ad4d9593..e881039de 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -19,16 +19,24 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v2 - with: - node-version: ${{ matrix.node-version }} + # + # Cache + # + - name: Create cache hash file (remove .version) + run: | # remove .version because we change it automatically in every push + cat /dev/null > hash.file + grep -v version package.json >> hash.file - uses: actions/cache@v2 with: path: ~/.npm - key: ${{ runner.os }}-wechaty-cache + key: ${{ runner.os }}-wechaty-${{ hashFiles('hash.file') }} restore-keys: | ${{ runner.os }}-wechaty- + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} - run: npm install - run: npm run build --if-present - run: npm test diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index 8677d9fde..b1fc27c0e 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -8,16 +8,24 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: Use Node.js 15 - uses: actions/setup-node@v2 - with: - node-version: 15 + # + # Cache + # + - name: Create cache hash file (remove .version) + run: | # remove .version because we change it automatically in every push + cat /dev/null > hash.file + grep -v version package.json >> hash.file - uses: actions/cache@v2 with: path: ~/.npm - key: ${{ runner.os }}-wechaty-cache + key: ${{ runner.os }}-wechaty-${{ hashFiles('hash.file') }} restore-keys: | ${{ runner.os }}-wechaty- + + - name: Use Node.js 15 + uses: actions/setup-node@v2 + with: + node-version: 15 - name: Install Dependencies run: npm install @@ -30,15 +38,23 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 - with: - node-version: 15 + # + # Cache + # + - name: Create cache hash file (remove .version) + run: | # remove .version because we change it automatically in every push + cat /dev/null > hash.file + grep -v version package.json >> hash.file - uses: actions/cache@v2 with: path: ~/.npm - key: ${{ runner.os }}-wechaty-cache + key: ${{ runner.os }}-wechaty-${{ hashFiles('hash.file') }} restore-keys: | ${{ runner.os }}-wechaty- + + - uses: actions/setup-node@v2 + with: + node-version: 15 - run: npm install - run: ./scripts/generate-version.sh - run: ./scripts/npm-pack-testing.sh @@ -52,16 +68,24 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 - with: - node-version: 15 - registry-url: https://registry.npmjs.org/ + # + # Cache + # + - name: Create cache hash file (remove .version) + run: | # remove .version because we change it automatically in every push + cat /dev/null > hash.file + grep -v version package.json >> hash.file - uses: actions/cache@v2 with: path: ~/.npm - key: ${{ runner.os }}-wechaty-cache + key: ${{ runner.os }}-wechaty-${{ hashFiles('hash.file') }} restore-keys: | ${{ runner.os }}-wechaty- + + - uses: actions/setup-node@v2 + with: + node-version: 15 + registry-url: https://registry.npmjs.org/ - run: npm install - run: ./scripts/generate-version.sh - run: ./scripts/package-publish-config-tag.sh From 5be704effcad9e7aad8afab82885c287aa604a56 Mon Sep 17 00:00:00 2001 From: Huan Date: Mon, 11 Jan 2021 19:55:31 +0800 Subject: [PATCH 559/598] 0.53.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 86b769cea..a5a9bee03 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.53.5", + "version": "0.53.6", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 548c0751f754842573ca28e85379e7b9ffec3ef5 Mon Sep 17 00:00:00 2001 From: Huan Date: Mon, 11 Jan 2021 19:57:47 +0800 Subject: [PATCH 560/598] 0.53.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3015028e7..10df26129 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.53.6", + "version": "0.53.7", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From a68f155ea046145f726ed51bed51d0f46bb71ef0 Mon Sep 17 00:00:00 2001 From: lijiarui Date: Fri, 15 Jan 2021 14:54:37 +0800 Subject: [PATCH 561/598] Update README.md (#2118) change puppet service provider link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b66d1183d..69d216eea 100644 --- a/README.md +++ b/README.md @@ -148,7 +148,7 @@ Wechaty is very powerful that it can run over different protocols. You can speci If you cannot use Web protocol, you can apply other protocal following the instruction here: We provide free token to support developers build a valuable WeChat chatbot. -Currently we support the following [puppet providers](https://github.com/wechaty/puppet-service-providers): +Currently we support the following [puppet providers](https://wechaty.js.org/docs/puppet-services/) : | Protocol | Puppet Provider | Environment Variable | | --- | --- | --- | From db7beb2b2030fd6b51aa6e13231997c85769f15e Mon Sep 17 00:00:00 2001 From: Huan Date: Fri, 15 Jan 2021 15:00:37 +0800 Subject: [PATCH 562/598] use naive hashFile --- .github/workflows/node.js.yml | 9 +-------- .github/workflows/npm.yml | 27 +++------------------------ 2 files changed, 4 insertions(+), 32 deletions(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index e881039de..7791d17d5 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -19,17 +19,10 @@ jobs: steps: - uses: actions/checkout@v2 - # - # Cache - # - - name: Create cache hash file (remove .version) - run: | # remove .version because we change it automatically in every push - cat /dev/null > hash.file - grep -v version package.json >> hash.file - uses: actions/cache@v2 with: path: ~/.npm - key: ${{ runner.os }}-wechaty-${{ hashFiles('hash.file') }} + key: ${{ runner.os }}-wechaty-${{ hashFiles('**/packages.json') }} restore-keys: | ${{ runner.os }}-wechaty- diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index b1fc27c0e..9453a95f4 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -8,17 +8,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - # - # Cache - # - - name: Create cache hash file (remove .version) - run: | # remove .version because we change it automatically in every push - cat /dev/null > hash.file - grep -v version package.json >> hash.file - uses: actions/cache@v2 with: path: ~/.npm - key: ${{ runner.os }}-wechaty-${{ hashFiles('hash.file') }} + key: ${{ runner.os }}-wechaty-${{ hashFiles('**/package.json') }} restore-keys: | ${{ runner.os }}-wechaty- @@ -38,17 +31,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - # - # Cache - # - - name: Create cache hash file (remove .version) - run: | # remove .version because we change it automatically in every push - cat /dev/null > hash.file - grep -v version package.json >> hash.file - uses: actions/cache@v2 with: path: ~/.npm - key: ${{ runner.os }}-wechaty-${{ hashFiles('hash.file') }} + key: ${{ runner.os }}-wechaty-${{ hashFiles('**/package.json') }} restore-keys: | ${{ runner.os }}-wechaty- @@ -68,17 +54,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - # - # Cache - # - - name: Create cache hash file (remove .version) - run: | # remove .version because we change it automatically in every push - cat /dev/null > hash.file - grep -v version package.json >> hash.file - uses: actions/cache@v2 with: path: ~/.npm - key: ${{ runner.os }}-wechaty-${{ hashFiles('hash.file') }} + key: ${{ runner.os }}-wechaty-${{ hashFiles('**/package.json') }} restore-keys: | ${{ runner.os }}-wechaty- From d107fb9a1ccccc136e545616b302cb1a349e9afb Mon Sep 17 00:00:00 2001 From: Huan Date: Fri, 15 Jan 2021 15:00:54 +0800 Subject: [PATCH 563/598] 0.53.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 10df26129..a53bf2b68 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.53.7", + "version": "0.53.8", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From c1d871c5a5e662ca03868fc1e25fe01fdd3e79d1 Mon Sep 17 00:00:00 2001 From: Huan Date: Fri, 15 Jan 2021 15:03:35 +0800 Subject: [PATCH 564/598] fix typo --- .github/workflows/node.js.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 7791d17d5..efe8d1aeb 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -22,7 +22,7 @@ jobs: - uses: actions/cache@v2 with: path: ~/.npm - key: ${{ runner.os }}-wechaty-${{ hashFiles('**/packages.json') }} + key: ${{ runner.os }}-wechaty-${{ hashFiles('**/package.json') }} restore-keys: | ${{ runner.os }}-wechaty- From 9cd4fdd22bdbbed376fcc18abadc04269de568d1 Mon Sep 17 00:00:00 2001 From: Huan Date: Fri, 15 Jan 2021 15:03:50 +0800 Subject: [PATCH 565/598] 0.53.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a53bf2b68..5dc72532e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.53.8", + "version": "0.53.9", "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 584e3e57a2bdffe80e4ad6c1977e22f83fba6ada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 23 Jan 2021 17:32:08 +0800 Subject: [PATCH 566/598] rename wechaty-puppet-hostie -> wechaty-puppet-service (#2124) --- .github/ISSUE_TEMPLATE/wechaty-bug-report.md | 2 +- README.md | 8 ++++---- bin/io-client.ts | 2 +- package.json | 6 +++--- src/io-client.ts | 20 ++++++++++---------- src/io-peer/io-peer.spec.ts | 12 ++++++++++-- src/io-peer/io-peer.ts | 14 +++++++++++--- src/io.spec.ts | 6 +++--- src/io.ts | 14 +++++++------- src/puppet-config.ts | 2 +- src/wechaty.ts | 2 +- tests/fixtures/smoke-testing.ts | 4 ++-- 12 files changed, 54 insertions(+), 38 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/wechaty-bug-report.md b/.github/ISSUE_TEMPLATE/wechaty-bug-report.md index d23cee694..ea2a2ef7f 100644 --- a/.github/ISSUE_TEMPLATE/wechaty-bug-report.md +++ b/.github/ISSUE_TEMPLATE/wechaty-bug-report.md @@ -25,7 +25,7 @@ about: Create a bug report for a bug you found in wechaty Answer: -> Which puppet are you using for wechaty? (hostie/puppeteer/padchat/...) +> Which puppet are you using for wechaty? (puppeteer/padlocal/service...) Answer: diff --git a/README.md b/README.md index 69d216eea..81c6475e0 100644 --- a/README.md +++ b/README.md @@ -153,12 +153,12 @@ Currently we support the following [puppet providers](https://wechaty.js.org/doc | Protocol | Puppet Provider | Environment Variable | | --- | --- | --- | | Web | [PuppetPuppeteer](https://github.com/wechaty/wechaty-puppet-puppeteer) | `export WECHATY_PUPPET=wechaty-puppet-puppeteer` | -| Windows | [PuppetWxwork](https://github.com/juzibot/wxwork-tester) | `export WECHATY_PUPPET=wechaty-puppet-hostie` | +| Windows | [PuppetWxwork](https://github.com/juzibot/wxwork-tester) | `export WECHATY_PUPPET=wechaty-puppet-service` | | Mock | [PuppetMock](https://github.com/wechaty/wechaty-puppet-mock) | `export WECHATY_PUPPET=wechaty-puppet-mock` | | Web | [PuppetWechat4u](https://github.com/wechaty/wechaty-puppet-wechat4u) | `export WECHATY_PUPPET=wechaty-puppet-wechat4u` | -| iPad | [PuppetRock](https://github.com/wechaty/puppet-service-providers) | `export WECHATY_PUPPET=wechaty-puppet-hostie` | -| iPad | [PuppetPadLocal](https://github.com/wechaty/puppet-service-providers) | `export WECHATY_PUPPET=wechaty-puppet-hostie` | -| Windows | [PuppetDonut](https://github.com/wechaty/puppet-service-providers) | `export WECHATY_PUPPET=wechaty-puppet-hostie` | +| iPad | [PuppetRock](https://github.com/wechaty/puppet-service-providers) | `export WECHATY_PUPPET=wechaty-puppet-service` | +| iPad | [PuppetPadLocal](https://github.com/wechaty/puppet-service-providers) | `export WECHATY_PUPPET=wechaty-puppet-service` | +| Windows | [PuppetDonut](https://github.com/wechaty/puppet-service-providers) | `export WECHATY_PUPPET=wechaty-puppet-service` | | iPad | ~~PuppetPadpro~~ **DEPRECATED** | `export WECHATY_PUPPET=wechaty-puppet-padpro` | | iPad | ~~PuppetPadchat~~ **DEPRECATED** | `export WECHATY_PUPPET=wechaty-puppet-padchat` | | iPad | ~~PuppetPadplus~~ **DEPRECATED** | `export WECHATY_PUPPET=wechaty-puppet-padplus` | diff --git a/bin/io-client.ts b/bin/io-client.ts index 71ea4462c..1da789664 100644 --- a/bin/io-client.ts +++ b/bin/io-client.ts @@ -62,7 +62,7 @@ async function main () { const wechaty = new Wechaty({ name: token }) - const port = parseInt(process.env.WECHATY_HOSTIE_PORT || '0') + const port = parseInt(process.env.WECHATY_PUPPET_SERVER_PORT || '0') const options: IoClientOptions = { token, diff --git a/package.json b/package.json index 5dc72532e..2ec98e37d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wechaty", - "version": "0.53.9", - "description": "Wechaty is Conversational SDK Chatbot Makers, Powered by TypeScript, Docker, and 💖", + "version": "0.55.0", + "description": "Wechaty is a RPA SDK for Chatbot Makers.", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", "engines": { @@ -102,7 +102,7 @@ "typed-emitter": "^1.3.1", "watchdog": "^0.8.17", "wechaty-puppet": "^0.33.6", - "wechaty-puppet-hostie": "^0.13.1", + "wechaty-puppet-service": "^0.14.5", "ws": "^7.3.1" }, "devDependencies": { diff --git a/src/io-client.ts b/src/io-client.ts index 20f492f96..8a0ecc06b 100644 --- a/src/io-client.ts +++ b/src/io-client.ts @@ -26,7 +26,7 @@ import { StateSwitch } from 'state-switch' import { PuppetServer, PuppetServerOptions, -} from 'wechaty-puppet-hostie' +} from 'wechaty-puppet-service' import { Message } from './user/mod' @@ -80,11 +80,11 @@ export class IoClient { this.state = new StateSwitch('IoClient', { log }) } - private async startHostie () { - log.verbose('IoClient', 'startHostie()') + private async startPuppetServer () { + log.verbose('IoClient', 'startPuppetServer()') if (this.puppetServer) { - throw new Error('hostie server exists') + throw new Error('puppet server exists') } const options: PuppetServerOptions = { @@ -96,11 +96,11 @@ export class IoClient { await this.puppetServer.start() } - private async stopHostie () { - log.verbose('IoClient', 'stopHostie()') + private async stopPuppetServer () { + log.verbose('IoClient', 'stopPuppetService()') if (!this.puppetServer) { - throw new Error('hostie server does not exist') + throw new Error('puppet server does not exist') } await this.puppetServer.stop() @@ -125,7 +125,7 @@ export class IoClient { await this.options.wechaty.start() - await this.startHostie() + await this.startPuppetServer() this.state.on(true) @@ -171,7 +171,7 @@ export class IoClient { } this.io = new Io({ - hostiePort : this.options.port, + servicePort : this.options.port, token : this.options.token, wechaty : this.options.wechaty, }) @@ -222,7 +222,7 @@ export class IoClient { this.state.off('pending') await this.stopIo() - await this.stopHostie() + await this.stopPuppetServer() await this.options.wechaty.stop() this.state.off(true) diff --git a/src/io-peer/io-peer.spec.ts b/src/io-peer/io-peer.spec.ts index 5c3261682..ed2a18bf9 100755 --- a/src/io-peer/io-peer.spec.ts +++ b/src/io-peer/io-peer.spec.ts @@ -34,12 +34,16 @@ import { test('getPeer()', async t => { const EXPECTED_PORT = 8788 const server = getPeer({ - hostieGrpcPort: EXPECTED_PORT, + serviceGrpcPort: EXPECTED_PORT, }) const client = new Peer() server.pipe(client).pipe(server) + /** + * Huan(202101) Need to be fixed by new IO Bus system. + * See: https://github.com/wechaty/wechaty-puppet-service/issues/118 + */ const port = await client.request('getHostieGrpcPort') t.equal(port, EXPECTED_PORT, 'should get the right port') }) @@ -47,9 +51,13 @@ test('getPeer()', async t => { test('exec()', async t => { const EXPECTED_PORT = 8788 const server = getPeer({ - hostieGrpcPort: EXPECTED_PORT, + serviceGrpcPort: EXPECTED_PORT, }) + /** + * Huan(202101) Need to be fixed by new IO Bus system. + * See: https://github.com/wechaty/wechaty-puppet-service/issues/118 + */ const request = format.request(42, 'getHostieGrpcPort') const response = await server.exec(request) as string // console.info('response: ', response) diff --git a/src/io-peer/io-peer.ts b/src/io-peer/io-peer.ts index bacc94601..3c3b4d51c 100644 --- a/src/io-peer/io-peer.ts +++ b/src/io-peer/io-peer.ts @@ -20,14 +20,18 @@ const isJsonRpcResponse = (payload: JsonRpcPayload): payload is JsonRpcPaylo const isJsonRpcError = (payload: JsonRpcPayload): payload is JsonRpcPayloadError => ('error' in payload) interface IoPeerOptions { - hostieGrpcPort: number, + serviceGrpcPort: number, } const getPeer = (options: IoPeerOptions) => { - const getHostieGrpcPort = () => options.hostieGrpcPort + const getServiceGrpcPort = () => options.serviceGrpcPort const serviceImpl = { - getHostieGrpcPort, + /** + * Huan(202101) Need to be fixed by new IO Bus system. + * See: https://github.com/wechaty/wechaty-puppet-service/issues/118 + */ + getHostieGrpcPort: getServiceGrpcPort, } const onMessage = async (message: JsonRpcPayload): Promise => { @@ -45,6 +49,10 @@ const getPeer = (options: IoPeerOptions) => { const serviceMethodName = method as keyof typeof serviceImpl switch (serviceMethodName) { + /** + * Huan(202101) Need to be fixed by new IO Bus system. + * See: https://github.com/wechaty/wechaty-puppet-service/issues/118 + */ case 'getHostieGrpcPort': return serviceImpl[serviceMethodName]() diff --git a/src/io.spec.ts b/src/io.spec.ts index d4635a230..89104881c 100755 --- a/src/io.spec.ts +++ b/src/io.spec.ts @@ -27,9 +27,9 @@ import { Wechaty } from './wechaty' test('Io restart without problem', async t => { const io = new Io({ // token must not contain any white spaces - hostiePort: 8788, - token : 'mock_token_in_wechaty/wechaty/src/io.spec.ts', - wechaty : new Wechaty(), + servicePort : 8788, + token : 'mock_token_in_wechaty/wechaty/src/io.spec.ts', + wechaty : new Wechaty(), }) try { diff --git a/src/io.ts b/src/io.ts index c05dc8d55..de46553ec 100644 --- a/src/io.ts +++ b/src/io.ts @@ -51,11 +51,11 @@ import { } from './io-peer/io-peer' export interface IoOptions { - wechaty: Wechaty, - token: string, - apihost?: string, - protocol?: string, - hostiePort?:number, + wechaty : Wechaty, + token : string, + apihost? : string, + protocol? : string, + servicePort? : number, } export const IO_EVENT_DICT = { @@ -143,9 +143,9 @@ export class Io { this.id, ) - if (options.hostiePort) { + if (options.servicePort) { this.jsonRpc = getPeer({ - hostieGrpcPort: this.options.hostiePort!, + serviceGrpcPort: this.options.servicePort!, }) } diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 17dd9f772..f56331bc4 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -35,7 +35,7 @@ export const PUPPET_DEPENDENCIES = { /** * Wechaty Internal Puppets: dependency by package.json */ - 'wechaty-puppet-hostie' : '*', // https://www.npmjs.com/package/wechaty-puppet-hostie + 'wechaty-puppet-service' : '*', // https://www.npmjs.com/package/wechaty-puppet-service 'wechaty-puppet-mock' : '*', // https://www.npmjs.com/package/wechaty-puppet-mock /** diff --git a/src/wechaty.ts b/src/wechaty.ts index 82e2af159..b0aed6f9b 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -579,7 +579,7 @@ class Wechaty extends WechatyEventEmitter implements Sayable { case 'dirty': /** - * https://github.com/wechaty/wechaty-puppet-hostie/issues/43 + * https://github.com/wechaty/wechaty-puppet-service/issues/43 */ puppet.on('dirty', async ({ payloadType, payloadId }) => { switch (payloadType) { diff --git a/tests/fixtures/smoke-testing.ts b/tests/fixtures/smoke-testing.ts index deb4bd423..3945c0eda 100644 --- a/tests/fixtures/smoke-testing.ts +++ b/tests/fixtures/smoke-testing.ts @@ -31,10 +31,10 @@ function getBotList (): Wechaty[] { // new Wechaty({ puppet: 'wechaty-puppet-puppeteer' }), ] - if (process.env.WECHATY_PUPPET_HOSTIE_TOKEN) { + if (process.env.WECHATY_PUPPET_SERVICE_TOKEN) { botList.push( new Wechaty({ - puppet: 'wechaty-puppet-hostie', + puppet: 'wechaty-puppet-service', }) ) } From 023f525f14c32957d9ead2556c7b96f1e9578911 Mon Sep 17 00:00:00 2001 From: Huan Date: Sat, 23 Jan 2021 22:05:40 +0800 Subject: [PATCH 567/598] add deprecate warning message for WECHATY_HOSTIE_PORT (#2122) --- bin/io-client.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/bin/io-client.ts b/bin/io-client.ts index 1da789664..0cb0f6ffc 100644 --- a/bin/io-client.ts +++ b/bin/io-client.ts @@ -62,7 +62,21 @@ async function main () { const wechaty = new Wechaty({ name: token }) - const port = parseInt(process.env.WECHATY_PUPPET_SERVER_PORT || '0') + let port + if (process.env.WECHATY_HOSTIE_PORT) { + /** + * https://github.com/wechaty/wechaty/issues/2122 + */ + log.warn('Wechaty', [ + '', + 'WECHATY_HOSTIE_PORT is deprecated.', + 'Use WECHATY_PUPPET_SERVER_PORT instead.', + 'See: https://github.com/wechaty/wechaty/issues/2122', + ].join(' ')) + port = parseInt(process.env.WECHATY_HOSTIE_PORT) + } else if (process.env.WECHATY_PUPPET_SERVER_PORT) { + port = parseInt(process.env.WECHATY_PUPPET_SERVER_PORT) + } const options: IoClientOptions = { token, From 1c1d12f6b8e4f5442b15c7743ba19376215fa7a8 Mon Sep 17 00:00:00 2001 From: Huan Date: Sat, 23 Jan 2021 22:07:03 +0800 Subject: [PATCH 568/598] 0.55.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2ec98e37d..f8a073c19 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.55.0", + "version": "0.55.1", "description": "Wechaty is a RPA SDK for Chatbot Makers.", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 78d05a2365982777b902dc0b2cf571b6c9e482cd Mon Sep 17 00:00:00 2001 From: Huan Date: Mon, 25 Jan 2021 15:40:45 +0800 Subject: [PATCH 569/598] 0.56.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f8a073c19..3394b7db6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.55.1", + "version": "0.56.0", "description": "Wechaty is a RPA SDK for Chatbot Makers.", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 3a4ccdcd6346343571941b30bebad26add6189e2 Mon Sep 17 00:00:00 2001 From: Huan Date: Mon, 25 Jan 2021 15:40:58 +0800 Subject: [PATCH 570/598] 0.56.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3394b7db6..596830814 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.56.0", + "version": "0.56.1", "description": "Wechaty is a RPA SDK for Chatbot Makers.", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 7763d205078dd440c6677c623a11bbf5789c3b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 25 Jan 2021 16:24:58 +0800 Subject: [PATCH 571/598] Changelog for v0.56 --- CHANGELOG.md | 71 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b97046b06..1fc88a7f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,28 +4,27 @@ ## WECHATY CONTRIBUTORS ### Active Contributors -1. @[lijiarui](https://github.com/lijiarui): [\#2001](https://github.com/wechaty/wechaty/pull/2001) [\#1998](https://github.com/wechaty/wechaty/pull/1998) [\#1876](https://github.com/wechaty/wechaty/pull/1876) [\#1875](https://github.com/wechaty/wechaty/pull/1875) [\#1859](https://github.com/wechaty/wechaty/pull/1859) [\#1702](https://github.com/wechaty/wechaty/pull/1702) [\#1700](https://github.com/wechaty/wechaty/pull/1700) [\#1692](https://github.com/wechaty/wechaty/pull/1692) [\#1633](https://github.com/wechaty/wechaty/pull/1633) [\#1631](https://github.com/wechaty/wechaty/pull/1631) [\#1615](https://github.com/wechaty/wechaty/pull/1615) [\#1614](https://github.com/wechaty/wechaty/pull/1614) [\#1533](https://github.com/wechaty/wechaty/pull/1533) [\#1514](https://github.com/wechaty/wechaty/pull/1514) [\#1510](https://github.com/wechaty/wechaty/pull/1510) [\#1502](https://github.com/wechaty/wechaty/pull/1502) [\#1498](https://github.com/wechaty/wechaty/pull/1498) [\#1497](https://github.com/wechaty/wechaty/pull/1497) [\#1486](https://github.com/wechaty/wechaty/pull/1486) [\#1482](https://github.com/wechaty/wechaty/pull/1482) [\#1481](https://github.com/wechaty/wechaty/pull/1481) [\#1477](https://github.com/wechaty/wechaty/pull/1477) [\#1408](https://github.com/wechaty/wechaty/pull/1408) [\#1407](https://github.com/wechaty/wechaty/pull/1407) [\#1405](https://github.com/wechaty/wechaty/pull/1405) [\#1402](https://github.com/wechaty/wechaty/pull/1402) [\#1375](https://github.com/wechaty/wechaty/pull/1375) [\#1374](https://github.com/wechaty/wechaty/pull/1374) [\#1373](https://github.com/wechaty/wechaty/pull/1373) [\#1352](https://github.com/wechaty/wechaty/pull/1352) [\#1351](https://github.com/wechaty/wechaty/pull/1351) [\#1348](https://github.com/wechaty/wechaty/pull/1348) [\#1347](https://github.com/wechaty/wechaty/pull/1347) [\#1344](https://github.com/wechaty/wechaty/pull/1344) [\#1341](https://github.com/wechaty/wechaty/pull/1341) [\#1338](https://github.com/wechaty/wechaty/pull/1338) [\#1333](https://github.com/wechaty/wechaty/pull/1333) [\#1331](https://github.com/wechaty/wechaty/pull/1331) [\#1325](https://github.com/wechaty/wechaty/pull/1325) [\#1116](https://github.com/wechaty/wechaty/pull/1116) [\#1086](https://github.com/wechaty/wechaty/pull/1086) [\#816](https://github.com/wechaty/wechaty/pull/816) [\#812](https://github.com/wechaty/wechaty/pull/812) [\#805](https://github.com/wechaty/wechaty/pull/805) [\#798](https://github.com/wechaty/wechaty/pull/798) [\#757](https://github.com/wechaty/wechaty/pull/757) [\#725](https://github.com/wechaty/wechaty/pull/725) [\#440](https://github.com/wechaty/wechaty/pull/440) [\#370](https://github.com/wechaty/wechaty/pull/370) [\#364](https://github.com/wechaty/wechaty/pull/364) [\#362](https://github.com/wechaty/wechaty/pull/362) [\#328](https://github.com/wechaty/wechaty/pull/328) [\#324](https://github.com/wechaty/wechaty/pull/324) [\#323](https://github.com/wechaty/wechaty/pull/323) [\#321](https://github.com/wechaty/wechaty/pull/321) [\#318](https://github.com/wechaty/wechaty/pull/318) [\#303](https://github.com/wechaty/wechaty/pull/303) [\#292](https://github.com/wechaty/wechaty/pull/292) [\#139](https://github.com/wechaty/wechaty/pull/139) [\#112](https://github.com/wechaty/wechaty/pull/112) [\#110](https://github.com/wechaty/wechaty/pull/110) [\#38](https://github.com/wechaty/wechaty/pull/38) -1. @[huan](https://github.com/huan): [\#2028](https://github.com/wechaty/wechaty/pull/2028) [\#2021](https://github.com/wechaty/wechaty/pull/2021) [\#1931](https://github.com/wechaty/wechaty/pull/1931) [\#1888](https://github.com/wechaty/wechaty/pull/1888) [\#1870](https://github.com/wechaty/wechaty/pull/1870) [\#1782](https://github.com/wechaty/wechaty/pull/1782) [\#1597](https://github.com/wechaty/wechaty/pull/1597) [\#1143](https://github.com/wechaty/wechaty/pull/1143) [\#1131](https://github.com/wechaty/wechaty/pull/1131) [\#1083](https://github.com/wechaty/wechaty/pull/1083) [\#1075](https://github.com/wechaty/wechaty/pull/1075) [\#1074](https://github.com/wechaty/wechaty/pull/1074) [\#1073](https://github.com/wechaty/wechaty/pull/1073) [\#1072](https://github.com/wechaty/wechaty/pull/1072) [\#1071](https://github.com/wechaty/wechaty/pull/1071) [\#860](https://github.com/wechaty/wechaty/pull/860) [\#854](https://github.com/wechaty/wechaty/pull/854) [\#841](https://github.com/wechaty/wechaty/pull/841) [\#831](https://github.com/wechaty/wechaty/pull/831) [\#810](https://github.com/wechaty/wechaty/pull/810) [\#469](https://github.com/wechaty/wechaty/pull/469) [\#462](https://github.com/wechaty/wechaty/pull/462) [\#455](https://github.com/wechaty/wechaty/pull/455) [\#449](https://github.com/wechaty/wechaty/pull/449) [\#396](https://github.com/wechaty/wechaty/pull/396) [\#351](https://github.com/wechaty/wechaty/pull/351) [\#317](https://github.com/wechaty/wechaty/pull/317) [\#316](https://github.com/wechaty/wechaty/pull/316) [\#315](https://github.com/wechaty/wechaty/pull/315) [\#314](https://github.com/wechaty/wechaty/pull/314) [\#313](https://github.com/wechaty/wechaty/pull/313) [\#312](https://github.com/wechaty/wechaty/pull/312) [\#311](https://github.com/wechaty/wechaty/pull/311) [\#168](https://github.com/wechaty/wechaty/pull/168) [\#158](https://github.com/wechaty/wechaty/pull/158) [\#149](https://github.com/wechaty/wechaty/pull/149) [\#146](https://github.com/wechaty/wechaty/pull/146) [\#143](https://github.com/wechaty/wechaty/pull/143) [\#142](https://github.com/wechaty/wechaty/pull/142) [\#141](https://github.com/wechaty/wechaty/pull/141) [\#25](https://github.com/wechaty/wechaty/pull/25) -1. @[windmemory](https://github.com/windmemory): [\#1832](https://github.com/wechaty/wechaty/pull/1832) [\#1770](https://github.com/wechaty/wechaty/pull/1770) [\#1735](https://github.com/wechaty/wechaty/pull/1735) [\#1729](https://github.com/wechaty/wechaty/pull/1729) [\#1662](https://github.com/wechaty/wechaty/pull/1662) [\#1660](https://github.com/wechaty/wechaty/pull/1660) [\#1643](https://github.com/wechaty/wechaty/pull/1643) [\#1630](https://github.com/wechaty/wechaty/pull/1630) [\#1577](https://github.com/wechaty/wechaty/pull/1577) [\#1571](https://github.com/wechaty/wechaty/pull/1571) [\#1557](https://github.com/wechaty/wechaty/pull/1557) [\#1550](https://github.com/wechaty/wechaty/pull/1550) [\#1538](https://github.com/wechaty/wechaty/pull/1538) [\#1526](https://github.com/wechaty/wechaty/pull/1526) [\#1503](https://github.com/wechaty/wechaty/pull/1503) [\#1457](https://github.com/wechaty/wechaty/pull/1457) -1. @[su-chang](https://github.com/su-chang): [\#2012](https://github.com/wechaty/wechaty/pull/2012) [\#2011](https://github.com/wechaty/wechaty/pull/2011) [\#1936](https://github.com/wechaty/wechaty/pull/1936) [\#1921](https://github.com/wechaty/wechaty/pull/1921) [\#1915](https://github.com/wechaty/wechaty/pull/1915) [\#1913](https://github.com/wechaty/wechaty/pull/1913) [\#1910](https://github.com/wechaty/wechaty/pull/1910) [\#1900](https://github.com/wechaty/wechaty/pull/1900) [\#1895](https://github.com/wechaty/wechaty/pull/1895) [\#1883](https://github.com/wechaty/wechaty/pull/1883) [\#1868](https://github.com/wechaty/wechaty/pull/1868) [\#1866](https://github.com/wechaty/wechaty/pull/1866) [\#1864](https://github.com/wechaty/wechaty/pull/1864) [\#1861](https://github.com/wechaty/wechaty/pull/1861) [\#1833](https://github.com/wechaty/wechaty/pull/1833) +1. @[lijiarui](https://github.com/lijiarui): [\#2118](https://github.com/wechaty/wechaty/pull/2118) [\#1876](https://github.com/wechaty/wechaty/pull/1876) [\#1875](https://github.com/wechaty/wechaty/pull/1875) [\#1859](https://github.com/wechaty/wechaty/pull/1859) [\#1702](https://github.com/wechaty/wechaty/pull/1702) [\#1700](https://github.com/wechaty/wechaty/pull/1700) [\#1692](https://github.com/wechaty/wechaty/pull/1692) [\#1633](https://github.com/wechaty/wechaty/pull/1633) [\#1631](https://github.com/wechaty/wechaty/pull/1631) [\#1615](https://github.com/wechaty/wechaty/pull/1615) [\#1614](https://github.com/wechaty/wechaty/pull/1614) [\#1533](https://github.com/wechaty/wechaty/pull/1533) [\#1514](https://github.com/wechaty/wechaty/pull/1514) [\#1510](https://github.com/wechaty/wechaty/pull/1510) [\#1502](https://github.com/wechaty/wechaty/pull/1502) [\#1498](https://github.com/wechaty/wechaty/pull/1498) [\#1497](https://github.com/wechaty/wechaty/pull/1497) [\#1486](https://github.com/wechaty/wechaty/pull/1486) [\#1482](https://github.com/wechaty/wechaty/pull/1482) [\#1481](https://github.com/wechaty/wechaty/pull/1481) [\#1477](https://github.com/wechaty/wechaty/pull/1477) [\#1408](https://github.com/wechaty/wechaty/pull/1408) [\#1407](https://github.com/wechaty/wechaty/pull/1407) [\#1405](https://github.com/wechaty/wechaty/pull/1405) [\#1402](https://github.com/wechaty/wechaty/pull/1402) [\#1375](https://github.com/wechaty/wechaty/pull/1375) [\#1374](https://github.com/wechaty/wechaty/pull/1374) [\#1373](https://github.com/wechaty/wechaty/pull/1373) [\#1352](https://github.com/wechaty/wechaty/pull/1352) [\#1351](https://github.com/wechaty/wechaty/pull/1351) [\#1348](https://github.com/wechaty/wechaty/pull/1348) [\#1347](https://github.com/wechaty/wechaty/pull/1347) [\#1344](https://github.com/wechaty/wechaty/pull/1344) [\#1341](https://github.com/wechaty/wechaty/pull/1341) [\#1338](https://github.com/wechaty/wechaty/pull/1338) [\#1333](https://github.com/wechaty/wechaty/pull/1333) [\#1331](https://github.com/wechaty/wechaty/pull/1331) [\#1325](https://github.com/wechaty/wechaty/pull/1325) [\#1313](https://github.com/wechaty/wechaty/pull/1313) [\#1116](https://github.com/wechaty/wechaty/pull/1116) [\#1086](https://github.com/wechaty/wechaty/pull/1086) [\#816](https://github.com/wechaty/wechaty/pull/816) [\#812](https://github.com/wechaty/wechaty/pull/812) [\#805](https://github.com/wechaty/wechaty/pull/805) [\#798](https://github.com/wechaty/wechaty/pull/798) [\#757](https://github.com/wechaty/wechaty/pull/757) [\#725](https://github.com/wechaty/wechaty/pull/725) [\#440](https://github.com/wechaty/wechaty/pull/440) [\#370](https://github.com/wechaty/wechaty/pull/370) [\#364](https://github.com/wechaty/wechaty/pull/364) [\#362](https://github.com/wechaty/wechaty/pull/362) [\#328](https://github.com/wechaty/wechaty/pull/328) [\#324](https://github.com/wechaty/wechaty/pull/324) [\#323](https://github.com/wechaty/wechaty/pull/323) [\#321](https://github.com/wechaty/wechaty/pull/321) [\#318](https://github.com/wechaty/wechaty/pull/318) [\#303](https://github.com/wechaty/wechaty/pull/303) [\#292](https://github.com/wechaty/wechaty/pull/292) [\#139](https://github.com/wechaty/wechaty/pull/139) [\#112](https://github.com/wechaty/wechaty/pull/112) [\#110](https://github.com/wechaty/wechaty/pull/110) [\#38](https://github.com/wechaty/wechaty/pull/38) +1. @[huan](https://github.com/huan): [\#2124](https://github.com/wechaty/wechaty/pull/2124) [\#2091](https://github.com/wechaty/wechaty/pull/2091) [\#2028](https://github.com/wechaty/wechaty/pull/2028) [\#1931](https://github.com/wechaty/wechaty/pull/1931) [\#1888](https://github.com/wechaty/wechaty/pull/1888) [\#1870](https://github.com/wechaty/wechaty/pull/1870) [\#1782](https://github.com/wechaty/wechaty/pull/1782) [\#1597](https://github.com/wechaty/wechaty/pull/1597) [\#1143](https://github.com/wechaty/wechaty/pull/1143) [\#1131](https://github.com/wechaty/wechaty/pull/1131) [\#1083](https://github.com/wechaty/wechaty/pull/1083) [\#1075](https://github.com/wechaty/wechaty/pull/1075) [\#1074](https://github.com/wechaty/wechaty/pull/1074) [\#1073](https://github.com/wechaty/wechaty/pull/1073) [\#1072](https://github.com/wechaty/wechaty/pull/1072) [\#1071](https://github.com/wechaty/wechaty/pull/1071) [\#860](https://github.com/wechaty/wechaty/pull/860) [\#854](https://github.com/wechaty/wechaty/pull/854) [\#841](https://github.com/wechaty/wechaty/pull/841) [\#831](https://github.com/wechaty/wechaty/pull/831) [\#810](https://github.com/wechaty/wechaty/pull/810) [\#469](https://github.com/wechaty/wechaty/pull/469) [\#462](https://github.com/wechaty/wechaty/pull/462) [\#455](https://github.com/wechaty/wechaty/pull/455) [\#449](https://github.com/wechaty/wechaty/pull/449) [\#396](https://github.com/wechaty/wechaty/pull/396) [\#351](https://github.com/wechaty/wechaty/pull/351) [\#317](https://github.com/wechaty/wechaty/pull/317) [\#316](https://github.com/wechaty/wechaty/pull/316) [\#315](https://github.com/wechaty/wechaty/pull/315) [\#314](https://github.com/wechaty/wechaty/pull/314) [\#313](https://github.com/wechaty/wechaty/pull/313) [\#312](https://github.com/wechaty/wechaty/pull/312) [\#311](https://github.com/wechaty/wechaty/pull/311) [\#168](https://github.com/wechaty/wechaty/pull/168) [\#158](https://github.com/wechaty/wechaty/pull/158) [\#149](https://github.com/wechaty/wechaty/pull/149) [\#146](https://github.com/wechaty/wechaty/pull/146) [\#143](https://github.com/wechaty/wechaty/pull/143) [\#142](https://github.com/wechaty/wechaty/pull/142) [\#141](https://github.com/wechaty/wechaty/pull/141) [\#25](https://github.com/wechaty/wechaty/pull/25) +1. @[windmemory](https://github.com/windmemory): [\#2078](https://github.com/wechaty/wechaty/pull/2078) [\#2074](https://github.com/wechaty/wechaty/pull/2074) [\#2067](https://github.com/wechaty/wechaty/pull/2067) [\#2051](https://github.com/wechaty/wechaty/pull/2051) [\#2050](https://github.com/wechaty/wechaty/pull/2050) [\#2048](https://github.com/wechaty/wechaty/pull/2048) [\#2043](https://github.com/wechaty/wechaty/pull/2043) [\#2039](https://github.com/wechaty/wechaty/pull/2039) [\#1832](https://github.com/wechaty/wechaty/pull/1832) [\#1770](https://github.com/wechaty/wechaty/pull/1770) [\#1735](https://github.com/wechaty/wechaty/pull/1735) [\#1729](https://github.com/wechaty/wechaty/pull/1729) [\#1662](https://github.com/wechaty/wechaty/pull/1662) [\#1660](https://github.com/wechaty/wechaty/pull/1660) [\#1643](https://github.com/wechaty/wechaty/pull/1643) [\#1630](https://github.com/wechaty/wechaty/pull/1630) [\#1577](https://github.com/wechaty/wechaty/pull/1577) [\#1571](https://github.com/wechaty/wechaty/pull/1571) [\#1557](https://github.com/wechaty/wechaty/pull/1557) [\#1550](https://github.com/wechaty/wechaty/pull/1550) [\#1538](https://github.com/wechaty/wechaty/pull/1538) [\#1526](https://github.com/wechaty/wechaty/pull/1526) [\#1503](https://github.com/wechaty/wechaty/pull/1503) [\#1457](https://github.com/wechaty/wechaty/pull/1457) +1. @[su-chang](https://github.com/su-chang): [\#2095](https://github.com/wechaty/wechaty/pull/2095) [\#1936](https://github.com/wechaty/wechaty/pull/1936) [\#1921](https://github.com/wechaty/wechaty/pull/1921) [\#1915](https://github.com/wechaty/wechaty/pull/1915) [\#1913](https://github.com/wechaty/wechaty/pull/1913) [\#1910](https://github.com/wechaty/wechaty/pull/1910) [\#1900](https://github.com/wechaty/wechaty/pull/1900) [\#1895](https://github.com/wechaty/wechaty/pull/1895) [\#1883](https://github.com/wechaty/wechaty/pull/1883) [\#1868](https://github.com/wechaty/wechaty/pull/1868) [\#1866](https://github.com/wechaty/wechaty/pull/1866) [\#1864](https://github.com/wechaty/wechaty/pull/1864) [\#1861](https://github.com/wechaty/wechaty/pull/1861) [\#1833](https://github.com/wechaty/wechaty/pull/1833) 1. @[mukaiu](https://github.com/mukaiu): [\#1089](https://github.com/wechaty/wechaty/pull/1089) [\#337](https://github.com/wechaty/wechaty/pull/337) [\#470](https://github.com/wechaty/wechaty/pull/470) [\#438](https://github.com/wechaty/wechaty/pull/438) [\#421](https://github.com/wechaty/wechaty/pull/421) [\#420](https://github.com/wechaty/wechaty/pull/420) [\#415](https://github.com/wechaty/wechaty/pull/415) [\#376](https://github.com/wechaty/wechaty/pull/376) 1. @[JasLin](https://github.com/JasLin): [\#404](https://github.com/wechaty/wechaty/pull/404) [\#358](https://github.com/wechaty/wechaty/pull/358) [\#105](https://github.com/wechaty/wechaty/pull/105) [\#100](https://github.com/wechaty/wechaty/pull/100) [\#78](https://github.com/wechaty/wechaty/pull/78) [\#76](https://github.com/wechaty/wechaty/pull/76) -1. @[kis87988](https://github.com/kis87988): [\#1993](https://github.com/wechaty/wechaty/pull/1993) [\#1908](https://github.com/wechaty/wechaty/pull/1908) [\#1623](https://github.com/wechaty/wechaty/pull/1623) [\#1607](https://github.com/wechaty/wechaty/pull/1607) [\#1570](https://github.com/wechaty/wechaty/pull/1570) 1. @[xinbenlv](https://github.com/xinbenlv): [\#1814](https://github.com/wechaty/wechaty/pull/1814) [\#1017](https://github.com/wechaty/wechaty/pull/1017) [\#935](https://github.com/wechaty/wechaty/pull/935) [\#388](https://github.com/wechaty/wechaty/pull/388) [\#361](https://github.com/wechaty/wechaty/pull/361) 1. @[binsee](https://github.com/binsee): [\#844](https://github.com/wechaty/wechaty/pull/844) [\#811](https://github.com/wechaty/wechaty/pull/811) [\#771](https://github.com/wechaty/wechaty/pull/771) [\#744](https://github.com/wechaty/wechaty/pull/744) [\#727](https://github.com/wechaty/wechaty/pull/727) +1. @[kis87988](https://github.com/kis87988): [\#1908](https://github.com/wechaty/wechaty/pull/1908) [\#1623](https://github.com/wechaty/wechaty/pull/1623) [\#1607](https://github.com/wechaty/wechaty/pull/1607) [\#1570](https://github.com/wechaty/wechaty/pull/1570) 1. @[linyimin-bupt](https://github.com/linyimin-bupt): [\#1757](https://github.com/wechaty/wechaty/pull/1757) [\#1752](https://github.com/wechaty/wechaty/pull/1752) [\#1750](https://github.com/wechaty/wechaty/pull/1750) [\#1749](https://github.com/wechaty/wechaty/pull/1749) 1. @[TbhT](https://github.com/TbhT): [\#1713](https://github.com/wechaty/wechaty/pull/1713) [\#1583](https://github.com/wechaty/wechaty/pull/1583) [\#1582](https://github.com/wechaty/wechaty/pull/1582) 1. @[suntong](https://github.com/suntong): [\#1677](https://github.com/wechaty/wechaty/pull/1677) [\#1129](https://github.com/wechaty/wechaty/pull/1129) [\#1123](https://github.com/wechaty/wechaty/pull/1123) 1. @[Gcaufy](https://github.com/Gcaufy): [\#1625](https://github.com/wechaty/wechaty/pull/1625) [\#1620](https://github.com/wechaty/wechaty/pull/1620) [\#310](https://github.com/wechaty/wechaty/pull/310) -1. @[plainheart](https://github.com/plainheart): [\#2000](https://github.com/wechaty/wechaty/pull/2000) [\#1999](https://github.com/wechaty/wechaty/pull/1999) -1. @[ax4](https://github.com/ax4): [\#1994](https://github.com/wechaty/wechaty/pull/1994) [\#380](https://github.com/wechaty/wechaty/pull/380) 1. @[SilentQianyi](https://github.com/SilentQianyi): [\#1891](https://github.com/wechaty/wechaty/pull/1891) [\#1886](https://github.com/wechaty/wechaty/pull/1886) 1. @[LinuxSuRen](https://github.com/LinuxSuRen): [\#1838](https://github.com/wechaty/wechaty/pull/1838) [\#1836](https://github.com/wechaty/wechaty/pull/1836) ### Contributors -1. @[lucifer1004](https://github.com/lucifer1004): [\#1989](https://github.com/wechaty/wechaty/pull/1989) -1. @[rikakomoe](https://github.com/rikakomoe): [\#1904](https://github.com/wechaty/wechaty/pull/1904) +1. @[profthecopyright](https://github.com/profthecopyright): [\#2104](https://github.com/wechaty/wechaty/pull/2104) +1. @[yesxin](https://github.com/yesxin): [\#2079](https://github.com/wechaty/wechaty/pull/2079) +1. @[satouriko](https://github.com/satouriko): [\#1904](https://github.com/wechaty/wechaty/pull/1904) 1. @[LanceZhu](https://github.com/LanceZhu): [\#1854](https://github.com/wechaty/wechaty/pull/1854) 1. @[zhaoic](https://github.com/zhaoic): [\#1822](https://github.com/wechaty/wechaty/pull/1822) 1. @[coderwhocode](https://github.com/coderwhocode): [\#1819](https://github.com/wechaty/wechaty/pull/1819) @@ -39,28 +38,46 @@ 1. @[htoooth](https://github.com/htoooth): [\#1014](https://github.com/wechaty/wechaty/pull/1014) 1. @[zhenyong](https://github.com/zhenyong): [\#770](https://github.com/wechaty/wechaty/pull/770) 1. @[xjchengo](https://github.com/xjchengo): [\#416](https://github.com/wechaty/wechaty/pull/416) +1. @[ax4](https://github.com/ax4): [\#380](https://github.com/wechaty/wechaty/pull/380) 1. @[cherry-geqi](https://github.com/cherry-geqi): [\#97](https://github.com/wechaty/wechaty/pull/97) # Changelog -## [Unreleased](https://github.com/wechaty/wechaty/tree/HEAD) +## [v0.56](https://github.com/wechaty/wechaty/tree/v0.56) (2021-01-25) -[Full Changelog](https://github.com/wechaty/wechaty/compare/v0.38...HEAD) +[Full Changelog](https://github.com/wechaty/wechaty/compare/v0.38...v0.56) **Implemented enhancements:** +- Switch from `wechaty-puppet-hostie` to `wechaty-puppet-service` [\#2122](https://github.com/wechaty/wechaty/issues/2122) +- Add wechaty-puppet-padlocal to our puppet config [\#2102](https://github.com/wechaty/wechaty/issues/2102) +- Use `message.talker\(\)` to replace `message.from\(\)` [\#2094](https://github.com/wechaty/wechaty/issues/2094) +- Create a `looseInstanceOfClass` to check `FileBox` and `Puppet` instances [\#2090](https://github.com/wechaty/wechaty/issues/2090) +- Issue with batch operation on room loading process [\#2068](https://github.com/wechaty/wechaty/issues/2068) +- Support more properties on contact [\#2036](https://github.com/wechaty/wechaty/issues/2036) - Refactoring Multi-instance Wechaty Design: Try to remove the Accessory class and related codes [\#2027](https://github.com/wechaty/wechaty/issues/2027) - Use Typed-Emitter in Wechaty [\#2014](https://github.com/wechaty/wechaty/issues/2014) - Support WECHATY\_HOSTIE\_PORT environment variable [\#1984](https://github.com/wechaty/wechaty/issues/1984) - Wechaty v0.23 PadPro Testing, an enhanced pad puppet implementation! [\#1668](https://github.com/wechaty/wechaty/issues/1668) +- Using wechaty to start a wechatOA account [\#1016](https://github.com/wechaty/wechaty/issues/1016) **Fixed bugs:** +- FileBox instance type checking problem [\#2035](https://github.com/wechaty/wechaty/issues/2035) - Wechaty.off\(\) not work: can not remove listeners. [\#2019](https://github.com/wechaty/wechaty/issues/2019) - friendship.contact\(\) will load Contact only, contact.ready\(\) is wanted. [\#1954](https://github.com/wechaty/wechaty/issues/1954) **Closed issues:** +- 不能登录,也没显示二维码就直接退出 [\#2099](https://github.com/wechaty/wechaty/issues/2099) +- Can't login after scan the qrcode [\#2092](https://github.com/wechaty/wechaty/issues/2092) +- 网络不好程序自动重启后推送异常 [\#2088](https://github.com/wechaty/wechaty/issues/2088) +- Message.forward\(\) does not support returning a message [\#2073](https://github.com/wechaty/wechaty/issues/2073) +- bot.Friendship.add\(\) 总是报错 [\#2060](https://github.com/wechaty/wechaty/issues/2060) +- 在使用FileBox 发送视频时候出现问题 [\#2059](https://github.com/wechaty/wechaty/issues/2059) +- The AWS Access Key Id you provided does not exist in our records. [\#2058](https://github.com/wechaty/wechaty/issues/2058) +- When setting up hostie token gateway, Account was locked after 5 getContactInfo call within a second. [\#2040](https://github.com/wechaty/wechaty/issues/2040) +- Support phone related operations [\#2037](https://github.com/wechaty/wechaty/issues/2037) - BREAKING CHANGES: remove hotImport support from wechaty [\#1997](https://github.com/wechaty/wechaty/issues/1997) - ERR GRPC\_GATEWAY GRPC SERVER ERROR [\#1996](https://github.com/wechaty/wechaty/issues/1996) - 微信安装 [\#1990](https://github.com/wechaty/wechaty/issues/1990) @@ -74,22 +91,29 @@ - How to filter official account numbers [\#1951](https://github.com/wechaty/wechaty/issues/1951) - Update wechaty-puppet-hostie version for wechaty [\#1948](https://github.com/wechaty/wechaty/issues/1948) - Is that you? [\#1942](https://github.com/wechaty/wechaty/issues/1942) +- ipad WeChat login will automatically log out, The returned QR code is invalid, you cannot log in again, you must restart [\#1940](https://github.com/wechaty/wechaty/issues/1940) - New version release notes for wechaty 0.38 [\#1937](https://github.com/wechaty/wechaty/issues/1937) - Can the receive the recall " room-leave". [\#1745](https://github.com/wechaty/wechaty/issues/1745) +- Refactor message.ts file to fit the requirement in CodeClimate [\#1663](https://github.com/wechaty/wechaty/issues/1663) +- Want to get information about sent-out message [\#1501](https://github.com/wechaty/wechaty/issues/1501) **Merged pull requests:** +- rename wechaty-puppet-hostie -\> wechaty-puppet-service [\#2124](https://github.com/wechaty/wechaty/pull/2124) ([huan](https://github.com/huan)) +- Update README.md [\#2118](https://github.com/wechaty/wechaty/pull/2118) ([lijiarui](https://github.com/lijiarui)) +- Update room-invitation.ts [\#2104](https://github.com/wechaty/wechaty/pull/2104) ([profthecopyright](https://github.com/profthecopyright)) +- Update contact.ts [\#2095](https://github.com/wechaty/wechaty/pull/2095) ([su-chang](https://github.com/su-chang)) +- create looseInstanceOfClass \(\#2090\) [\#2091](https://github.com/wechaty/wechaty/pull/2091) ([huan](https://github.com/huan)) +- Update Dockerfile [\#2079](https://github.com/wechaty/wechaty/pull/2079) ([yesxin](https://github.com/yesxin)) +- Bump minor 49 [\#2078](https://github.com/wechaty/wechaty/pull/2078) ([windmemory](https://github.com/windmemory)) +- fix \#2073 [\#2074](https://github.com/wechaty/wechaty/pull/2074) ([windmemory](https://github.com/windmemory)) +- Split to trunks when making requests of room.findAll\(\) and room.ready\(\) [\#2067](https://github.com/wechaty/wechaty/pull/2067) ([windmemory](https://github.com/windmemory)) +- bump hostie version to be the stable one [\#2051](https://github.com/wechaty/wechaty/pull/2051) ([windmemory](https://github.com/windmemory)) +- 0.48.0 [\#2050](https://github.com/wechaty/wechaty/pull/2050) ([windmemory](https://github.com/windmemory)) +- feat: add more methods into contact class [\#2048](https://github.com/wechaty/wechaty/pull/2048) ([windmemory](https://github.com/windmemory)) +- feat: add scoped wxwork puppet into puppet config [\#2043](https://github.com/wechaty/wechaty/pull/2043) ([windmemory](https://github.com/windmemory)) +- add phone method in contact class [\#2039](https://github.com/wechaty/wechaty/pull/2039) ([windmemory](https://github.com/windmemory)) - remove Accessories by wechatify user classes [\#2028](https://github.com/wechaty/wechaty/pull/2028) ([huan](https://github.com/huan)) -- fix event listener [\#2021](https://github.com/wechaty/wechaty/pull/2021) ([huan](https://github.com/huan)) -- Upgrade hostie [\#2012](https://github.com/wechaty/wechaty/pull/2012) ([su-chang](https://github.com/su-chang)) -- Upgrade hostie [\#2011](https://github.com/wechaty/wechaty/pull/2011) ([su-chang](https://github.com/su-chang)) -- Update README.md [\#2001](https://github.com/wechaty/wechaty/pull/2001) ([lijiarui](https://github.com/lijiarui)) -- docs: fixed table format flaw of `Message.say` in README.md. [\#2000](https://github.com/wechaty/wechaty/pull/2000) ([plainheart](https://github.com/plainheart)) -- docs: fixed table format flaw of `Contact.say` in README.md. [\#1999](https://github.com/wechaty/wechaty/pull/1999) ([plainheart](https://github.com/plainheart)) -- Update README.md [\#1998](https://github.com/wechaty/wechaty/pull/1998) ([lijiarui](https://github.com/lijiarui)) -- fix: fix the broken URLs links to /bot-qr-code.png [\#1994](https://github.com/wechaty/wechaty/pull/1994) ([ax4](https://github.com/ax4)) -- test: update workflows for node ^12 [\#1993](https://github.com/wechaty/wechaty/pull/1993) ([kis87988](https://github.com/kis87988)) -- fix: typo in README.md [\#1989](https://github.com/wechaty/wechaty/pull/1989) ([lucifer1004](https://github.com/lucifer1004)) ## [v0.38](https://github.com/wechaty/wechaty/tree/v0.38) (2020-04-08) @@ -170,7 +194,7 @@ **Merged pull requests:** - fix: wechaty-puppet-dll temporary unavailable [\#1908](https://github.com/wechaty/wechaty/pull/1908) ([kis87988](https://github.com/kis87988)) -- docs: improve ding-dong-bot example [\#1904](https://github.com/wechaty/wechaty/pull/1904) ([rikakomoe](https://github.com/rikakomoe)) +- docs: improve ding-dong-bot example [\#1904](https://github.com/wechaty/wechaty/pull/1904) ([satouriko](https://github.com/satouriko)) - Add reason for logout event [\#1900](https://github.com/wechaty/wechaty/pull/1900) ([su-chang](https://github.com/su-chang)) - Friend search [\#1895](https://github.com/wechaty/wechaty/pull/1895) ([su-chang](https://github.com/su-chang)) - Delay friendship [\#1891](https://github.com/wechaty/wechaty/pull/1891) ([SilentQianyi](https://github.com/SilentQianyi)) @@ -622,6 +646,7 @@ - save room join sys message to cache [\#1333](https://github.com/wechaty/wechaty/pull/1333) ([lijiarui](https://github.com/lijiarui)) - add function in self-testing-bot.ts [\#1331](https://github.com/wechaty/wechaty/pull/1331) ([lijiarui](https://github.com/lijiarui)) - Room bot example [\#1325](https://github.com/wechaty/wechaty/pull/1325) ([lijiarui](https://github.com/lijiarui)) +- add function friendRequestSend [\#1313](https://github.com/wechaty/wechaty/pull/1313) ([lijiarui](https://github.com/lijiarui)) ## [v0.14.0](https://github.com/wechaty/wechaty/tree/v0.14.0) (2018-04-15) @@ -646,7 +671,6 @@ - fix description [\#1027](https://github.com/wechaty/wechaty/issues/1027) - ERR Profile save\(\) exception: Error: EACCES: permission denied, open '/bot/demo.wechaty.json' [\#982](https://github.com/wechaty/wechaty/issues/982) - Dockerfile.onbuild build error.Directory permissions wrong [\#961](https://github.com/wechaty/wechaty/issues/961) -- \[docker\] onbuild failed to start when we put `wechaty` as dependency in package.json [\#500](https://github.com/wechaty/wechaty/issues/500) **Closed issues:** @@ -781,6 +805,7 @@ - wechaty v0.8.54 does not install all required component [\#522](https://github.com/wechaty/wechaty/issues/522) - message.mentioned\(\) does not work as expected [\#512](https://github.com/wechaty/wechaty/issues/512) - Some types of media file is saved as a 0 byte file. [\#504](https://github.com/wechaty/wechaty/issues/504) +- \[docker\] onbuild failed to start when we put `wechaty` as dependency in package.json [\#500](https://github.com/wechaty/wechaty/issues/500) - ts-node commond not found after update docker image [\#492](https://github.com/wechaty/wechaty/issues/492) - may be not need .vscode folder, need .editorconfig [\#489](https://github.com/wechaty/wechaty/issues/489) - `Room.findAll\(\)` should always return a `ready\(\)`-ed instance [\#477](https://github.com/wechaty/wechaty/issues/477) From a2ff203e4e6ce794a21253704f82b0aeab22c191 Mon Sep 17 00:00:00 2001 From: Huan Date: Wed, 27 Jan 2021 14:15:07 +0800 Subject: [PATCH 572/598] compatible with wechaty-puppet-hostie module name (https://github.com/wechaty/wechaty-puppet-service/issues/118) --- src/puppet-config.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index f56331bc4..42105c39c 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -32,6 +32,14 @@ export const PUPPET_DEPENDENCIES = { */ // 'wechaty-puppet-padplus' : '^0.7.30', // https://www.npmjs.com/package/wechaty-puppet-padplus + /** + * Deprecated on Jan 2021: rename to wechaty-puppet-service + * https://github.com/wechaty/wechaty-puppet-service/issues/118 + * + * Huan(202101): will be removed after Dec 31, 2021 + */ + 'wechaty-puppet-hostie' : '*', // https://www.npmjs.com/package/wechaty-puppet-hostie + /** * Wechaty Internal Puppets: dependency by package.json */ From 6ae5b0de1ebd49064e07ebda467073180e91f6c6 Mon Sep 17 00:00:00 2001 From: Huan Date: Wed, 27 Jan 2021 14:15:22 +0800 Subject: [PATCH 573/598] 0.56.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 596830814..4b84c7097 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.56.1", + "version": "0.56.2", "description": "Wechaty is a RPA SDK for Chatbot Makers.", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From aba17d0aa26e9309a9825fec5bb8802608fd3d6c Mon Sep 17 00:00:00 2001 From: Huan Date: Wed, 27 Jan 2021 22:24:28 +0800 Subject: [PATCH 574/598] use node v12 instead of v14 in docker image for maximum compatibility. (e.g. https://github.com/huggingface/tokenizers/issues/603) --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 82c15f059..d4b4c4fef 100644 --- a/Dockerfile +++ b/Dockerfile @@ -38,7 +38,7 @@ RUN apt-get update \ && apt-get purge --auto-remove \ && rm -rf /tmp/* /var/lib/apt/lists/* -RUN curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash - \ +RUN curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - \ && apt-get update && apt-get install -y --no-install-recommends nodejs \ && apt-get purge --auto-remove \ && rm -rf /tmp/* /var/lib/apt/lists/* From 9ebc5f4dcccc0e8ccd4c7a1fdf49f81b2b27055d Mon Sep 17 00:00:00 2001 From: Huan Date: Wed, 27 Jan 2021 22:29:34 +0800 Subject: [PATCH 575/598] 0.56.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4b84c7097..5c048e09a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.56.2", + "version": "0.56.3", "description": "Wechaty is a RPA SDK for Chatbot Makers.", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 16b8b251ed8e8c19dd3f6df794c73e55404257f0 Mon Sep 17 00:00:00 2001 From: Huan Date: Thu, 28 Jan 2021 20:30:26 +0800 Subject: [PATCH 576/598] 0.57.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5c048e09a..e2f2e31be 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.56.3", + "version": "0.57.0", "description": "Wechaty is a RPA SDK for Chatbot Makers.", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 7456d74c3b18caea1ef725b5d94d0efcd8b74176 Mon Sep 17 00:00:00 2001 From: Huan Date: Thu, 28 Jan 2021 20:36:09 +0800 Subject: [PATCH 577/598] default puppet: service (#2127) --- src/puppet-config.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 42105c39c..a15a54dde 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -65,4 +65,5 @@ export const PUPPET_DEPENDENCIES = { export type PuppetModuleName = keyof typeof PUPPET_DEPENDENCIES -export const PUPPET_NAME_DEFAULT: PuppetModuleName = 'wechaty-puppet-puppeteer' +// Huan(202001): we change default puppet from puppet-puppeteer -> puppet-service +export const PUPPET_NAME_DEFAULT: PuppetModuleName = 'wechaty-puppet-service' From 59d22b80bcf639175d50ffdc09e69a5f154cdd0d Mon Sep 17 00:00:00 2001 From: Huan Date: Thu, 28 Jan 2021 20:36:24 +0800 Subject: [PATCH 578/598] 0.57.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e2f2e31be..0901e1efc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.57.0", + "version": "0.57.1", "description": "Wechaty is a RPA SDK for Chatbot Makers.", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From a2fdb0f5648f59ae909cfb74717bdcdf84e4ee9f Mon Sep 17 00:00:00 2001 From: Huan Date: Fri, 29 Jan 2021 16:35:53 +0800 Subject: [PATCH 579/598] upgrade wechaty-puppet to v0.34 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0901e1efc..b61e11577 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "state-switch": "^0.9.9", "typed-emitter": "^1.3.1", "watchdog": "^0.8.17", - "wechaty-puppet": "^0.33.6", + "wechaty-puppet": "^0.34.1", "wechaty-puppet-service": "^0.14.5", "ws": "^7.3.1" }, From 2a8689ad05aaebdd0fd0dd5ac8137470dbc11a1b Mon Sep 17 00:00:00 2001 From: Huan Date: Fri, 29 Jan 2021 16:38:35 +0800 Subject: [PATCH 580/598] 0.57.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b61e11577..7ae6e76dc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.57.1", + "version": "0.57.2", "description": "Wechaty is a RPA SDK for Chatbot Makers.", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From d1f7191b8b5b517b5c382f11b1658d2a9d278481 Mon Sep 17 00:00:00 2001 From: Huan Date: Fri, 29 Jan 2021 16:42:17 +0800 Subject: [PATCH 581/598] change default puppet to puppet-service --- src/config.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.spec.ts b/src/config.spec.ts index d4e2b938a..117e57fea 100755 --- a/src/config.spec.ts +++ b/src/config.spec.ts @@ -87,7 +87,7 @@ test('systemPuppetName ()', async t => { const WECHATY_PUPPET_ORIG = process.env.WECHATY_PUPPET delete process.env.WECHATY_PUPPET - t.equal(config.systemPuppetName(), 'wechaty-puppet-puppeteer', 'should get wechaty-puppet-puppeteer as puppet name') + t.equal(config.systemPuppetName(), 'wechaty-puppet-service', 'should get wechaty-puppet-service as default puppet name') process.env.WECHATY_PUPPET = 'wechaty-puppet-mock' t.equal(config.systemPuppetName(), 'wechaty-puppet-mock', 'should get puppet name from process.env') From c33f4e7cd24d59f2a842f45f46bddef23d92d6bf Mon Sep 17 00:00:00 2001 From: Huan Date: Fri, 29 Jan 2021 16:42:28 +0800 Subject: [PATCH 582/598] 0.57.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7ae6e76dc..d85bda420 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.57.2", + "version": "0.57.3", "description": "Wechaty is a RPA SDK for Chatbot Makers.", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From ba80fe51e2961bae4852d2ae966dc64b0113ca92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 3 Feb 2021 00:24:52 +0800 Subject: [PATCH 583/598] upgrade deps --- package.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index d85bda420..4506099fa 100644 --- a/package.json +++ b/package.json @@ -103,16 +103,16 @@ "watchdog": "^0.8.17", "wechaty-puppet": "^0.34.1", "wechaty-puppet-service": "^0.14.5", - "ws": "^7.3.1" + "ws": "^7.4.2" }, "devDependencies": { - "@babel/core": "^7.12.3", - "@babel/node": "^7.12.6", - "@babel/preset-env": "^7.12.1", - "@chatie/eslint-config": "^0.12.1", + "@babel/core": "^7.12.10", + "@babel/node": "^7.12.10", + "@babel/preset-env": "^7.12.11", + "@chatie/eslint-config": "^0.12.3", "@chatie/git-scripts": "^0.6.2", "@chatie/semver": "^0.4.7", - "@chatie/tsconfig": "^0.13.0", + "@chatie/tsconfig": "^0.14.1", "@types/cuid": "^1.3.1", "@types/dotenv": "^8.2.0", "@types/glob": "^7.1.3", @@ -120,23 +120,23 @@ "@types/promise-retry": "^1.1.3", "@types/raven": "^2.5.3", "@types/retry": "^0.12.0", - "@types/ws": "^7.2.9", + "@types/ws": "^7.4.0", "apiai": "^4.0.3", "check-node-version": "^4.0.3", "coveralls": "^3.1.0", - "cross-env": "^7.0.2", + "cross-env": "^7.0.3", "finis": "^0.4.4", "glob": "^7.1.6", "jsdoc-to-markdown": "^6.0.1", - "markdownlint-cli": "^0.24.0", + "markdownlint-cli": "^0.26.0", "nyc": "^15.1.0", "pkg-jq": "^0.2.11", "qrcode-terminal": "^0.12.0", "shx": "^0.3.3", "sloc": "^0.2.1", "tstest": "^0.4.10", - "typedoc": "^0.19.2", - "wechaty-puppet-mock": "^0.28.1" + "typedoc": "^0.20.20", + "wechaty-puppet-mock": "^0.28.2" }, "files_comment__whitelist_npm_publish": "http://stackoverflow.com/a/8617868/1123955", "files": [ From a0963e6692d6a59dbdc0844e77ea54c2712533b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 3 Feb 2021 00:25:04 +0800 Subject: [PATCH 584/598] 0.57.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4506099fa..a4f5862a0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.57.3", + "version": "0.57.4", "description": "Wechaty is a RPA SDK for Chatbot Makers.", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 20d8c9c68491217cf6439438883c2aaf1a13a27c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 3 Feb 2021 00:44:09 +0800 Subject: [PATCH 585/598] fix docker deploy for branches --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 04d6452ab..a91ee5f1d 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -25,7 +25,7 @@ jobs: publish: name: Publish needs: [build] - if: github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/v[0-9]+')) + if: github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/v')) runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 From 040784c94a137ae9da7fbea8095a9b5d2b385e5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 3 Feb 2021 00:44:21 +0800 Subject: [PATCH 586/598] 0.57.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a4f5862a0..b40d39aac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.57.4", + "version": "0.57.5", "description": "Wechaty is a RPA SDK for Chatbot Makers.", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 58b7956c049b42d4d6555e893a80b2a7787b42bd Mon Sep 17 00:00:00 2001 From: Yuan Gao Date: Mon, 8 Feb 2021 19:52:15 +0800 Subject: [PATCH 587/598] pass custom server host to io server (#2138) * pass custom server host to io server * fix test * modify code according to comments --- src/config.ts | 1 + src/io.ts | 2 +- src/user/url-link.spec.ts | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/config.ts b/src/config.ts index aaf9c9aab..cdef14ab5 100644 --- a/src/config.ts +++ b/src/config.ts @@ -119,6 +119,7 @@ export class Config { public default = DEFAULT_SETTING public apihost = process.env.WECHATY_APIHOST || DEFAULT_SETTING.DEFAULT_APIHOST + public serviceIp = process.env.WECHATY_PUPPET_SERVICE_IP || '' public systemPuppetName (): PuppetModuleName { return ( diff --git a/src/io.ts b/src/io.ts index de46553ec..effefc866 100644 --- a/src/io.ts +++ b/src/io.ts @@ -135,7 +135,7 @@ export class Io { this.id = options.wechaty.id - this.protocol = options.protocol + '|' + options.wechaty.id + this.protocol = options.protocol + '|' + options.wechaty.id + '|' + config.serviceIp + '|' + options.servicePort log.verbose('Io', 'instantiated with apihost[%s], token[%s], protocol[%s], cuid[%s]', options.apihost, options.token, diff --git a/src/user/url-link.spec.ts b/src/user/url-link.spec.ts index 3fa4b4a45..680706ee8 100755 --- a/src/user/url-link.spec.ts +++ b/src/user/url-link.spec.ts @@ -8,7 +8,7 @@ test('UrlLink', async t => { const URL = 'https://wechaty.js.org/2020/07/02/wechat-bot-in-ten-minutes' const EXPECTED_PAYLOAD = { description: '十分钟实现一个智能问答微信聊天机器人', - thumbnailUrl: 'https://wechaty.js.org/assets/developers/luweicn/avatar.png', + thumbnailUrl: 'https://wechaty.js.org/assets/contributors/luweicn/avatar.png', title: '十分钟实现一个智能问答微信聊天机器人', url: 'https://wechaty.js.org/2020/07/02/wechat-bot-in-ten-minutes', } From 8f8ae6a6cedb3bb746201d9905fbfa995fa325cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Mon, 8 Feb 2021 19:53:18 +0800 Subject: [PATCH 588/598] 0.57.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b40d39aac..cbf8311b9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.57.5", + "version": "0.57.6", "description": "Wechaty is a RPA SDK for Chatbot Makers.", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From b4e6ea4fc7cb845fcc7c59a0ca9d0a972dca01f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 10 Feb 2021 21:24:20 +0800 Subject: [PATCH 589/598] support puppet lark (https://github.com/wechaty/wechaty-puppet-lark/issues/4) --- src/puppet-config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index a15a54dde..0d44418f8 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -55,6 +55,7 @@ export const PUPPET_DEPENDENCIES = { 'wechaty-puppet-official-account' : '*', // https://www.npmjs.com/package/wechaty-puppet-official-account 'wechaty-puppet-padlocal' : '*', // https://www.npmjs.com/package/wechaty-puppet-padlocal 'wechaty-puppet-whatsapp' : '*', // https://www.npmjs.com/package/wechaty-puppet-whatsapp + 'wechaty-puppet-lark' : '*', // https://www.npmjs.com/package/wechaty-puppet-lark /** * Scoped puppets From cf172b271acac5d2f8bb37f8a3de12c97c998b6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 10 Feb 2021 21:24:36 +0800 Subject: [PATCH 590/598] 0.57.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cbf8311b9..df8f7f258 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.57.6", + "version": "0.57.7", "description": "Wechaty is a RPA SDK for Chatbot Makers.", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 938bfed3176b63013b11e8907993562fd1626725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 10 Feb 2021 21:25:15 +0800 Subject: [PATCH 591/598] clean --- src/puppet-config.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 0d44418f8..0fe7143bb 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -36,7 +36,7 @@ export const PUPPET_DEPENDENCIES = { * Deprecated on Jan 2021: rename to wechaty-puppet-service * https://github.com/wechaty/wechaty-puppet-service/issues/118 * - * Huan(202101): will be removed after Dec 31, 2021 + * TODO: Huan(202101): will be removed after Dec 31, 2021 */ 'wechaty-puppet-hostie' : '*', // https://www.npmjs.com/package/wechaty-puppet-hostie @@ -51,11 +51,12 @@ export const PUPPET_DEPENDENCIES = { */ 'wechaty-puppet-puppeteer' : '*', // https://www.npmjs.com/package/wechaty-puppet-puppeteer 'wechaty-puppet-wechat4u' : '*', // https://www.npmjs.com/package/wechaty-puppet-wechat4u + 'wechaty-puppet-padlocal' : '*', // https://www.npmjs.com/package/wechaty-puppet-padlocal + 'wechaty-puppet-gitter' : '*', // https://www.npmjs.com/package/wechaty-puppet-gitter + 'wechaty-puppet-lark' : '*', // https://www.npmjs.com/package/wechaty-puppet-lark 'wechaty-puppet-official-account' : '*', // https://www.npmjs.com/package/wechaty-puppet-official-account - 'wechaty-puppet-padlocal' : '*', // https://www.npmjs.com/package/wechaty-puppet-padlocal 'wechaty-puppet-whatsapp' : '*', // https://www.npmjs.com/package/wechaty-puppet-whatsapp - 'wechaty-puppet-lark' : '*', // https://www.npmjs.com/package/wechaty-puppet-lark /** * Scoped puppets From f7ec5843ddc4b7b6e86ae92caecd3a92a53938ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Wed, 10 Feb 2021 21:25:32 +0800 Subject: [PATCH 592/598] 0.57.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index df8f7f258..01b4fc2eb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.57.7", + "version": "0.57.8", "description": "Wechaty is a RPA SDK for Chatbot Makers.", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From 695580c759444628592ff387ae415b3865c57746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 12 Feb 2021 18:23:26 +0800 Subject: [PATCH 593/598] use npm-run-all --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 01b4fc2eb..29dd24f07 100644 --- a/package.json +++ b/package.json @@ -15,14 +15,14 @@ "scripts": { "build": "tsc", "clean": "shx rm -fr dist/*", - "dist": "npm run clean && npm run build", + "dist": "npm-run-all clean build", "pack": "npm pack", "docs": "bash -x scripts/generate-docs.sh", "coverage": "nyc report --reporter=text-lcov | coveralls", "changelog": "docker run -it --rm -e CHANGELOG_GITHUB_TOKEN -v \"$(pwd)\":/usr/local/src/your-app ferrarimarco/github-changelog-generator -u wechaty -p wechaty && sed -i'.bak' /greenkeeper/d CHANGELOG.md && sed -i'.bak' /Snyk/d CHANGELOG.md && sed -i'.bak' '/An in-range update of/d' CHANGELOG.md && ts-node scripts/sort-contributiveness.ts < CHANGELOG.md > CHANGELOG.new.md 2>/dev/null && cat CHANGELOG.md >> CHANGELOG.new.md && mv CHANGELOG.new.md CHANGELOG.md", "doctor": "npm run check-node-version && ts-node bin/doctor", "check-node-version": "check-node-version --node \">= 12\"", - "lint": "npm run check-node-version && npm run lint:es && npm run lint:ts && npm run lint:sh && npm run lint:md", + "lint": "npm-run-all check-node-version lint:es lint:ts lint:sh lint:md", "lint:es": "eslint --ignore-pattern node_modules/ --ignore-pattern fixtures/ \"{bin,examples,src,scripts,tests}/**/*.ts\"", "lint:md": "markdownlint README.md", "lint:ts": "tsc --noEmit", @@ -129,6 +129,7 @@ "glob": "^7.1.6", "jsdoc-to-markdown": "^6.0.1", "markdownlint-cli": "^0.26.0", + "npm-run-all": "^4.1.5", "nyc": "^15.1.0", "pkg-jq": "^0.2.11", "qrcode-terminal": "^0.12.0", From 5e4b384badc70dca97f05c3100ab4801bce1a9a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Fri, 12 Feb 2021 18:23:40 +0800 Subject: [PATCH 594/598] 0.57.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 29dd24f07..7a634b30c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.57.8", + "version": "0.57.9", "description": "Wechaty is a RPA SDK for Chatbot Makers.", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From c3077fb9f477b410c7cadc2bf4fe770c746e173e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 13 Feb 2021 12:36:07 +0800 Subject: [PATCH 595/598] specific puppet versions --- src/puppet-config.ts | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 0fe7143bb..543cf0279 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -47,19 +47,22 @@ export const PUPPET_DEPENDENCIES = { 'wechaty-puppet-mock' : '*', // https://www.npmjs.com/package/wechaty-puppet-mock /** - * Wechaty External Puppets + * WeChat External Puppets */ - 'wechaty-puppet-puppeteer' : '*', // https://www.npmjs.com/package/wechaty-puppet-puppeteer - 'wechaty-puppet-wechat4u' : '*', // https://www.npmjs.com/package/wechaty-puppet-wechat4u - 'wechaty-puppet-padlocal' : '*', // https://www.npmjs.com/package/wechaty-puppet-padlocal + 'wechaty-puppet-puppeteer' : '>=0.22.1', // https://www.npmjs.com/package/wechaty-puppet-puppeteer + 'wechaty-puppet-wechat4u' : '>=0.17.7', // https://www.npmjs.com/package/wechaty-puppet-wechat4u + 'wechaty-puppet-padlocal' : '>=0.2.31', // https://www.npmjs.com/package/wechaty-puppet-padlocal + 'wechaty-puppet-official-account' : '>=0.5.43', // https://www.npmjs.com/package/wechaty-puppet-official-account - 'wechaty-puppet-gitter' : '*', // https://www.npmjs.com/package/wechaty-puppet-gitter - 'wechaty-puppet-lark' : '*', // https://www.npmjs.com/package/wechaty-puppet-lark - 'wechaty-puppet-official-account' : '*', // https://www.npmjs.com/package/wechaty-puppet-official-account - 'wechaty-puppet-whatsapp' : '*', // https://www.npmjs.com/package/wechaty-puppet-whatsapp + /** + * Non-WeChat External Puppets + */ + 'wechaty-puppet-gitter' : '>=0.4.7', // https://www.npmjs.com/package/wechaty-puppet-gitter + 'wechaty-puppet-lark' : '>=0.4.5', // https://www.npmjs.com/package/wechaty-puppet-lark + 'wechaty-puppet-whatsapp' : '>=0.2.2', // https://www.npmjs.com/package/wechaty-puppet-whatsapp /** - * Scoped puppets + * Scoped puppets (private) */ '@juzibot/wechaty-puppet-donut': '^0.3', // https://www.npmjs.com/package/wechaty-puppet-donut (to be published) '@juzibot/wechaty-puppet-wxwork': '*', // https://www.npmjs.com/package/wechaty-puppet-wxwork (to be published) From abe684adbbacb01067926b1d8afa23be91c77a0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 13 Feb 2021 12:36:18 +0800 Subject: [PATCH 596/598] 0.57.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7a634b30c..d948ceeec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.57.9", + "version": "0.57.10", "description": "Wechaty is a RPA SDK for Chatbot Makers.", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts", From ffea96c97c5c462a81b9212d09422f0b8a77a519 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 20 Feb 2021 11:18:25 +0800 Subject: [PATCH 597/598] upgrade upppeteer version --- src/puppet-config.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/puppet-config.ts b/src/puppet-config.ts index 543cf0279..e6e822578 100644 --- a/src/puppet-config.ts +++ b/src/puppet-config.ts @@ -43,29 +43,29 @@ export const PUPPET_DEPENDENCIES = { /** * Wechaty Internal Puppets: dependency by package.json */ - 'wechaty-puppet-service' : '*', // https://www.npmjs.com/package/wechaty-puppet-service - 'wechaty-puppet-mock' : '*', // https://www.npmjs.com/package/wechaty-puppet-mock + 'wechaty-puppet-service' : '*', // https://www.npmjs.com/package/wechaty-puppet-service + 'wechaty-puppet-mock' : '*', // https://www.npmjs.com/package/wechaty-puppet-mock /** * WeChat External Puppets */ - 'wechaty-puppet-puppeteer' : '>=0.22.1', // https://www.npmjs.com/package/wechaty-puppet-puppeteer - 'wechaty-puppet-wechat4u' : '>=0.17.7', // https://www.npmjs.com/package/wechaty-puppet-wechat4u - 'wechaty-puppet-padlocal' : '>=0.2.31', // https://www.npmjs.com/package/wechaty-puppet-padlocal - 'wechaty-puppet-official-account' : '>=0.5.43', // https://www.npmjs.com/package/wechaty-puppet-official-account + 'wechaty-puppet-puppeteer' : '>=0.24', // https://www.npmjs.com/package/wechaty-puppet-puppeteer + 'wechaty-puppet-wechat4u' : '>=0.17', // https://www.npmjs.com/package/wechaty-puppet-wechat4u + 'wechaty-puppet-padlocal' : '>=0.2', // https://www.npmjs.com/package/wechaty-puppet-padlocal + 'wechaty-puppet-official-account' : '>=0.5', // https://www.npmjs.com/package/wechaty-puppet-official-account /** * Non-WeChat External Puppets */ - 'wechaty-puppet-gitter' : '>=0.4.7', // https://www.npmjs.com/package/wechaty-puppet-gitter - 'wechaty-puppet-lark' : '>=0.4.5', // https://www.npmjs.com/package/wechaty-puppet-lark - 'wechaty-puppet-whatsapp' : '>=0.2.2', // https://www.npmjs.com/package/wechaty-puppet-whatsapp + 'wechaty-puppet-gitter' : '>=0.4.7', // https://www.npmjs.com/package/wechaty-puppet-gitter + 'wechaty-puppet-lark' : '>=0.4.5', // https://www.npmjs.com/package/wechaty-puppet-lark + 'wechaty-puppet-whatsapp' : '>=0.2.2', // https://www.npmjs.com/package/wechaty-puppet-whatsapp /** * Scoped puppets (private) */ - '@juzibot/wechaty-puppet-donut': '^0.3', // https://www.npmjs.com/package/wechaty-puppet-donut (to be published) - '@juzibot/wechaty-puppet-wxwork': '*', // https://www.npmjs.com/package/wechaty-puppet-wxwork (to be published) + '@juzibot/wechaty-puppet-donut' : '*', // https://www.npmjs.com/package/wechaty-puppet-donut (to be published) + '@juzibot/wechaty-puppet-wxwork' : '*', // https://www.npmjs.com/package/wechaty-puppet-wxwork (to be published) } export type PuppetModuleName = keyof typeof PUPPET_DEPENDENCIES From 5a79c4751cd2df870c252087de7792dd8833a73c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huan=20LI=20=28=E6=9D=8E=E5=8D=93=E6=A1=93=29?= Date: Sat, 20 Feb 2021 11:18:37 +0800 Subject: [PATCH 598/598] 0.57.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d948ceeec..b4f7fc4e5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.57.10", + "version": "0.57.11", "description": "Wechaty is a RPA SDK for Chatbot Makers.", "main": "dist/src/mod.js", "typings": "dist/src/mod.d.ts",
Wechaty

Main bot class.

-

A Bot is a wechat client depends on which puppet you use. +

A Bot is a WeChat client depends on which puppet you use. It may equals

See more:

    @@ -26,7 +26,7 @@ If you want to know how to get contact, see Contact

Room
-

All wechat rooms(groups) will be encapsulated as a Room.

+

All WeChat rooms(groups) will be encapsulated as a Room.

Examples/Room-Bot

Contact
@@ -57,12 +57,46 @@ If you want to know how to get contact, see Contact