diff --git a/README.md b/README.md index b6536a54c3d610ef9e80d6cb27f4afe6fcbe92c6..b9cc8901774db9dff7b567e76a76ac744a466b47 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Wechaty.instance() // Global Instance .start() ``` -> **Notice: Wechaty requires Node.js version >= 8.5** +> **Notice: Wechaty requires Node.js version >= 10** This bot can log all messages to the console. @@ -56,12 +56,11 @@ You can find more examples from [Wiki](https://github.com/chatie/wechaty/wiki/Ex ## GETTING STARTED [![node](https://img.shields.io/node/v/wechaty.svg?maxAge=604800)](https://nodejs.org/) -[![Repo Size](https://reposs.herokuapp.com/?path=Chatie/wechaty)](https://github.com/chatie/wechaty) ### A Great Live Coding Tutorial
- +
The above 15 minute video tutorial is a good start point if you are new to Wechaty. diff --git a/docs/index.md b/docs/index.md index 9fa182fe028b8f4fb42f3ae15fc920f9169f1a15..3854c29f18134a4c803c510c53a7e69b65a10a24 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,6 +1,4 @@ -# Wechaty v0.15.26 Documentation -* https://blog.chatie.io - +# Wechaty v0.17.59 Documentation\n* https://blog.chatie.io\n ## Classes
@@ -9,6 +7,30 @@

The World's Shortest ChatBot Code: 6 lines of JavaScript

Wechaty Starter Project

+
Room
+

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

+

Room is Sayable, +Examples/Room-Bot

+
+
Contact
+

All wechat contacts(friend) will be encapsulated as a Contact.

+

Contact is Sayable, +Examples/Contact-Bot

+
+
Friendship
+

Send, receive friend request, and friend confirmation events.

+
    +
  1. send request
  2. +
  3. receive request(in friend event)
  4. +
  5. confirmation friendship(friend event)
  6. +
+

Examples/Friend-Bot

+
+
Message
+

All wechat messages will be encapsulated as a Message.

+

Message is Sayable, +Examples/Ding-Dong-Bot

+
## Typedefs @@ -20,6 +42,18 @@
WechatyEventFunction

Wechaty Class Event Function

+
RoomEventName
+

Room Class Event Type

+
+
RoomEventFunction
+

Room Class Event Function

+
+
MemberQueryFilter
+

The way to search member by Room.member()

+
+
ContactQueryFilter
+

The way to search Contact

+
@@ -36,6 +70,8 @@ Main bot class. * [Wechaty](#Wechaty) * _instance_ * [.Contact](#Wechaty+Contact) + * [.wechaty](#Wechaty+Contact.wechaty) + * [.puppet](#Wechaty+Contact.puppet) * [.version([forceNpm])](#Wechaty+version) ⇒ string * [.on(event, listener)](#Wechaty+on) ⇒ [Wechaty](#Wechaty) * [.start()](#Wechaty+start) ⇒ Promise.<void> @@ -43,8 +79,8 @@ Main bot class. * [.logout()](#Wechaty+logout) ⇒ Promise.<void> * [.logonoff()](#Wechaty+logonoff) ⇒ boolean * ~~[.self()](#Wechaty+self)~~ - * [.userSelf()](#Wechaty+userSelf) ⇒ Contact - * [.say(text)](#Wechaty+say) ⇒ Promise.<boolean> + * [.userSelf()](#Wechaty+userSelf) ⇒ [Contact](#Contact) + * [.say(textOrContactOrFile)](#Wechaty+say) ⇒ Promise.<boolean> * _static_ * [.instance()](#Wechaty.instance) @@ -53,12 +89,28 @@ Main bot class. ### wechaty.Contact Clone Classes for this bot and attach the `puppet` to the Class -Fixme: 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 **Kind**: instance property of [Wechaty](#Wechaty) + +* [.Contact](#Wechaty+Contact) + * [.wechaty](#Wechaty+Contact.wechaty) + * [.puppet](#Wechaty+Contact.puppet) + + + +#### Contact.wechaty +1. Set Wechaty + +**Kind**: static property of [Contact](#Wechaty+Contact) + + +#### Contact.puppet +2. Set Puppet + +**Kind**: static property of [Contact](#Wechaty+Contact) ### wechaty.version([forceNpm]) ⇒ string @@ -97,13 +149,13 @@ wechaty.on('scan', (url: string, code: number) => { ``` **Example** *(Event:login )* ```js -bot.on('login', (user: Contact) => { +bot.on('login', (user: ContactSelf) => { console.log(`user ${user} login`) }) ``` **Example** *(Event:logout )* ```js -bot.on('logout', (user: Contact) => { +bot.on('logout', (user: ContactSelf) => { console.log(`user ${user} logout`) }) ``` @@ -115,15 +167,16 @@ wechaty.on('message', (message: Message) => { ``` **Example** *(Event:friend )* ```js -bot.on('friend', (contact: Contact, request: FriendRequest) => { - if(request){ // 1. request to be friend from new contact +bot.on('friend', (request: Friendship) => { + if(request.type === Friendship.Type.RECEIVE){ // 1. receive new friend request from new contact + const contact = request.contact() let result = await request.accept() if(result){ console.log(`Request from ${contact.name()} is accept succesfully!`) } else{ console.log(`Request from ${contact.name()} failed to accept!`) } - } else { // 2. confirm friend ship + } else if (request.type === Friendship.Type.CONFIRM) { // 2. confirm friend ship console.log(`new friendship confirmed with ${contact.name()}`) } }) @@ -201,7 +254,7 @@ if (bot.logonoff()) { **Kind**: instance method of [Wechaty](#Wechaty) -### wechaty.userSelf() ⇒ Contact +### wechaty.userSelf() ⇒ [Contact](#Contact) Get current user **Kind**: instance method of [Wechaty](#Wechaty) @@ -212,14 +265,14 @@ console.log(`Bot is ${contact.name()}`) ``` -### wechaty.say(text) ⇒ Promise.<boolean> -Send message to filehelper +### wechaty.say(textOrContactOrFile) ⇒ Promise.<boolean> +Send message to userSelf **Kind**: instance method of [Wechaty](#Wechaty) | Param | Type | | --- | --- | -| text | string | +| textOrContactOrFile | string | @@ -237,63 +290,905 @@ Wechaty.instance() // Singleton .on('message', message => console.log(`Message: ${message}`)) .init() ``` - + -## AppMsgType : enum -Enum for AppMsgType values. +## Room +All wechat rooms(groups) will be encapsulated as a Room. -**Kind**: global enum -**Properties** +`Room` is `Sayable`, +[Examples/Room-Bot](https://github.com/Chatie/wechaty/blob/master/examples/room-bot.ts) -| Name | Type | Description | +**Kind**: global class + +* [Room](#Room) + * _instance_ + * [.say(textOrContactOrFile, [replyTo])](#Room+say) ⇒ Promise.<boolean> + * [.on(event, listener)](#Room+on) ⇒ this + * [.add(contact)](#Room+add) ⇒ Promise.<number> + * [.del(contact)](#Room+del) ⇒ Promise.<number> + * [.topic([newTopic])](#Room+topic) ⇒ Promise.<(string\|void)> + * [.qrcode()](#Room+qrcode) + * [.alias(contact)](#Room+alias) ⇒ string \| null + * [.roomAlias(contact)](#Room+roomAlias) ⇒ string \| null + * [.has(contact)](#Room+has) ⇒ boolean + * [.memberAll(query)](#Room+memberAll) ⇒ [Array.<Contact>](#Contact) + * [.member(queryArg)](#Room+member) ⇒ [Contact](#Contact) \| null + * [.memberList()](#Room+memberList) ⇒ [Array.<Contact>](#Contact) + * [.sync()](#Room+sync) ⇒ Promise.<void> + * _static_ + * [.create(contactList, [topic])](#Room.create) ⇒ [Promise.<Room>](#Room) + * [.findAll([query])](#Room.findAll) ⇒ Promise.<Array.<Room>> + * [.find(query)](#Room.find) ⇒ Promise.<(Room\|null)> + + + +### room.say(textOrContactOrFile, [replyTo]) ⇒ Promise.<boolean> +Send message inside Room, if set [replyTo], wechaty will mention the contact as well. + +**Kind**: instance method of [Room](#Room) +**Returns**: Promise.<boolean> - If bot send message successfully, it will return true. If the bot failed to send for blocking or any other reason, it will return false + +| Param | Type | Description | | --- | --- | --- | -| TEXT | number | AppMsgType.TEXT (1) for TEXT | -| IMG | number | AppMsgType.IMG (2) for IMG | -| AUDIO | number | AppMsgType.AUDIO (3) for AUDIO | -| VIDEO | number | AppMsgType.VIDEO (4) for VIDEO | -| URL | number | AppMsgType.URL (5) for URL | -| ATTACH | number | AppMsgType.ATTACH (6) for ATTACH | -| OPEN | number | AppMsgType.OPEN (7) for OPEN | -| EMOJI | number | AppMsgType.EMOJI (8) for EMOJI | -| VOICE_REMIND | number | AppMsgType.VOICE_REMIND (9) for VOICE_REMIND | -| SCAN_GOOD | number | AppMsgType.SCAN_GOOD (10) for SCAN_GOOD | -| GOOD | number | AppMsgType.GOOD (13) for GOOD | -| EMOTION | number | AppMsgType.EMOTION (15) for EMOTION | -| CARD_TICKET | number | AppMsgType.CARD_TICKET (16) for CARD_TICKET | -| REALTIME_SHARE_LOCATION | number | AppMsgType.REALTIME_SHARE_LOCATION (17) for REALTIME_SHARE_LOCATION | -| TRANSFERS | number | AppMsgType.TRANSFERS (2e3) for TRANSFERS | -| RED_ENVELOPES | number | AppMsgType.RED_ENVELOPES (2001) for RED_ENVELOPES | -| READER_TYPE | number | AppMsgType.READER_TYPE (100001) for READER_TYPE | - - - -## MsgType : enum -Enum for MsgType values. - -**Kind**: global enum -**Properties** +| textOrContactOrFile | string \| MediaMessage | Send `text` or `media file` inside Room. | +| [replyTo] | [Contact](#Contact) \| [Array.<Contact>](#Contact) | Optional parameter, send content inside Room, and mention @replyTo contact or contactList. | -| Name | Type | Description | +**Example** *(Send text inside Room)* +```js +const room = await Room.find({name: 'wechaty'}) // change 'wechaty' to any of your room in wechat +await room.say('Hello world!') +``` +**Example** *(Send media file inside Room)* +```js +const room = await Room.find({name: 'wechaty'}) // change 'wechaty' to any of your room in wechat +await room.say(new MediaMessage('/test.jpg')) // put the filePath you want to send here +``` +**Example** *(Send text inside Room, and mention @replyTo contact)* +```js +const contact = await Contact.find({name: 'lijiarui'}) // change 'lijiarui' to any of the room member +const room = await Room.find({name: 'wechaty'}) // change 'wechaty' to any of your room in wechat +await room.say('Hello world!', contact) +``` + + +### room.on(event, listener) ⇒ this +**Kind**: instance method of [Room](#Room) +**Returns**: this - - this for chain + +| Param | Type | Description | | --- | --- | --- | -| TEXT | number | MsgType.TEXT (1) for TEXT | -| IMAGE | number | MsgType.IMAGE (3) for IMAGE | -| VOICE | number | MsgType.VOICE (34) for VOICE | -| VERIFYMSG | number | MsgType.VERIFYMSG (37) for VERIFYMSG | -| POSSIBLEFRIEND_MSG | number | MsgType.POSSIBLEFRIEND_MSG (40) for POSSIBLEFRIEND_MSG | -| SHARECARD | number | MsgType.SHARECARD (42) for SHARECARD | -| VIDEO | number | MsgType.VIDEO (43) for VIDEO | -| EMOTICON | number | MsgType.EMOTICON (47) for EMOTICON | -| LOCATION | number | MsgType.LOCATION (48) for LOCATION | -| APP | number | MsgType.APP (49) for APP | -| VOIPMSG | number | MsgType.VOIPMSG (50) for VOIPMSG | -| STATUSNOTIFY | number | MsgType.STATUSNOTIFY (51) for STATUSNOTIFY | -| VOIPNOTIFY | number | MsgType.VOIPNOTIFY (52) for VOIPNOTIFY | -| VOIPINVITE | number | MsgType.VOIPINVITE (53) for VOIPINVITE | -| MICROVIDEO | number | MsgType.MICROVIDEO (62) for MICROVIDEO | -| SYSNOTICE | number | MsgType.SYSNOTICE (9999) for SYSNOTICE | -| SYS | number | MsgType.SYS (10000) for SYS | -| RECALLED | number | MsgType.RECALLED (10002) for RECALLED | +| event | [RoomEventName](#RoomEventName) | Emit WechatyEvent | +| listener | [RoomEventFunction](#RoomEventFunction) | Depends on the WechatyEvent | + +**Example** *(Event:join )* +```js +const room = await Room.find({topic: 'event-room'}) // change `event-room` to any room topic in your wechat +if (room) { + room.on('join', (room: Room, inviteeList: Contact[], inviter: Contact) => { + const nameList = inviteeList.map(c => c.name()).join(',') + console.log(`Room ${room.topic()} got new member ${nameList}, invited by ${inviter}`) + }) +} +``` +**Example** *(Event:leave )* +```js +const room = await Room.find({topic: 'event-room'}) // change `event-room` to any room topic in your wechat +if (room) { + room.on('leave', (room: Room, leaverList: Contact[]) => { + const nameList = leaverList.map(c => c.name()).join(',') + console.log(`Room ${room.topic()} lost member ${nameList}`) + }) +} +``` +**Example** *(Event:topic )* +```js +const room = await Room.find({topic: 'event-room'}) // change `event-room` to any room topic in your wechat +if (room) { + room.on('topic', (room: Room, topic: string, oldTopic: string, changer: Contact) => { + console.log(`Room ${room.topic()} topic changed from ${oldTopic} to ${topic} by ${changer.name()}`) + }) +} +``` + + +### room.add(contact) ⇒ Promise.<number> +Add contact in a room + +**Kind**: instance method of [Room](#Room) + +| Param | Type | +| --- | --- | +| contact | [Contact](#Contact) | + +**Example** +```js +const contact = await Contact.find({name: 'lijiarui'}) // change 'lijiarui' to any contact in your wechat +const room = await Room.find({topic: 'wechat'}) // change 'wechat' to any room topic in your wechat +if (room) { + const result = await room.add(contact) + if (result) { + console.log(`add ${contact.name()} to ${room.topic()} successfully! `) + } else{ + console.log(`failed to add ${contact.name()} to ${room.topic()}! `) + } +} +``` + + +### room.del(contact) ⇒ Promise.<number> +Delete a contact from the room +It works only when the bot is the owner of the room + +**Kind**: instance method of [Room](#Room) + +| Param | Type | +| --- | --- | +| contact | [Contact](#Contact) | + +**Example** +```js +const room = await Room.find({topic: 'wechat'}) // change 'wechat' to any room topic in your wechat +const contact = await Contact.find({name: 'lijiarui'}) // change 'lijiarui' to any room member in the room you just set +if (room) { + const result = await room.del(contact) + if (result) { + console.log(`remove ${contact.name()} from ${room.topic()} successfully! `) + } else{ + console.log(`failed to remove ${contact.name()} from ${room.topic()}! `) + } +} +``` + + +### room.topic([newTopic]) ⇒ Promise.<(string\|void)> +SET/GET topic from the room + +**Kind**: instance method of [Room](#Room) + +| Param | Type | Description | +| --- | --- | --- | +| [newTopic] | string | If set this para, it will change room topic. | + +**Example** *(When you say anything in a room, it will get room topic. )* +```js +const bot = Wechaty.instance() +bot +.on('message', async m => { + const room = m.room() + if (room) { + const topic = await room.topic() + console.log(`room topic is : ${topic}`) + } +}) +``` +**Example** *(When you say anything in a room, it will change room topic. )* +```js +const bot = Wechaty.instance() +bot +.on('message', async m => { + const room = m.room() + if (room) { + const oldTopic = room.topic() + room.topic('change topic to wechaty!') + console.log(`room topic change from ${oldTopic} to ${room.topic()}`) + } +}) +``` + + +### room.qrcode() +Room QR Code + +**Kind**: instance method of [Room](#Room) + + +### room.alias(contact) ⇒ string \| null +Return contact's roomAlias in the room, the same as roomAlias + +**Kind**: instance method of [Room](#Room) +**Returns**: string \| null - - If a contact has an alias in room, return string, otherwise return null + +| Param | Type | +| --- | --- | +| contact | [Contact](#Contact) | + +**Example** +```js +const bot = Wechaty.instance() +bot +.on('message', async m => { + const room = m.room() + const contact = m.from() + if (room) { + const alias = room.alias(contact) + console.log(`${contact.name()} alias is ${alias}`) + } +}) +``` + + +### room.roomAlias(contact) ⇒ string \| null +Same as function alias + +**Kind**: instance method of [Room](#Room) + +| Param | Type | +| --- | --- | +| contact | [Contact](#Contact) | + + + +### room.has(contact) ⇒ boolean +Check if the room has member `contact`, the return is a Promise and must be `await`-ed + +**Kind**: instance method of [Room](#Room) +**Returns**: boolean - Return `true` if has contact, else return `false`. + +| Param | Type | +| --- | --- | +| contact | [Contact](#Contact) | + +**Example** *(Check whether 'lijiarui' is in the room 'wechaty')* +```js +const contact = await Contact.find({name: 'lijiarui'}) // change 'lijiarui' to any of contact in your wechat +const room = await 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 ${room.topic()}!`) + } else { + console.log(`${contact.name()} is not in the room ${room.topic()} !`) + } +} +``` + + +### room.memberAll(query) ⇒ [Array.<Contact>](#Contact) +Find all contacts in a room + +#### definition +- `name` the name-string set by user-self, should be called name, equal to `Contact.name()` +- `roomAlias` the name-string set by user-self in the room, should be called roomAlias +- `contactAlias` the name-string set by bot for others, should be called alias, equal to `Contact.alias()` + +**Kind**: instance method of [Room](#Room) + +| Param | Type | Description | +| --- | --- | --- | +| query | RoomMemberQueryFilter \| string | When use memberAll(name:string), return all matched members, including name, roomAlias, contactAlias | + + + +### room.member(queryArg) ⇒ [Contact](#Contact) \| null +Find all contacts in a room, if get many, return the first one. + +**Kind**: instance method of [Room](#Room) + +| Param | Type | Description | +| --- | --- | --- | +| queryArg | RoomMemberQueryFilter \| string | When use member(name:string), return all matched members, including name, roomAlias, contactAlias | + +**Example** *(Find member by name)* +```js +const room = await Room.find({topic: 'wechaty'}) // change 'wechaty' to any room name in your wechat +if (room) { + const member = room.member('lijiarui') // change 'lijiarui' to any room member in your wechat + if (member) { + console.log(`${room.topic()} got the member: ${member.name()}`) + } else { + console.log(`cannot get member in room: ${room.topic()}`) + } +} +``` +**Example** *(Find member by MemberQueryFilter)* +```js +const room = await Room.find({topic: 'wechaty'}) // change 'wechaty' to any room name in your wechat +if (room) { + const member = room.member({name: 'lijiarui'}) // change 'lijiarui' to any room member in your wechat + if (member) { + console.log(`${room.topic()} got the member: ${member.name()}`) + } else { + console.log(`cannot get member in room: ${room.topic()}`) + } +} +``` + + +### room.memberList() ⇒ [Array.<Contact>](#Contact) +Get all room member from the room + +**Kind**: instance method of [Room](#Room) + + +### room.sync() ⇒ Promise.<void> +Sync data for Room + +**Kind**: instance method of [Room](#Room) + + +### Room.create(contactList, [topic]) ⇒ [Promise.<Room>](#Room) +Create a new room. + +**Kind**: static method of [Room](#Room) + +| Param | Type | +| --- | --- | +| contactList | [Array.<Contact>](#Contact) | +| [topic] | string | + +**Example** *(Creat a room with 'lijiarui' and 'juxiaomi', 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 contactList = [helperContactA, helperContactB] +console.log('Bot', 'contactList: %s', contactList.join(',')) +const room = await Room.create(contactList, 'ding') +console.log('Bot', 'createDingRoom() new ding room created: %s', room) +await room.topic('ding - created') +await room.say('ding - created') +``` + + +### Room.findAll([query]) ⇒ Promise.<Array.<Room>> +Find room by topic, return all the matched room + +**Kind**: static method of [Room](#Room) + +| Param | Type | +| --- | --- | +| [query] | RoomQueryFilter | + +**Example** +```js +const roomList = await Room.findAll() // get the room list of the bot +const roomList = await Room.findAll({name: 'wechaty'}) // find all of the rooms with name 'wechaty' +``` + + +### Room.find(query) ⇒ Promise.<(Room\|null)> +Try to find a room by filter: {topic: string | RegExp}. If get many, return the first one. + +**Kind**: static method of [Room](#Room) +**Returns**: Promise.<(Room\|null)> - If can find the room, return Room, or return null + +| Param | Type | +| --- | --- | +| query | RoomQueryFilter | + + + +## Contact +All wechat contacts(friend) will be encapsulated as a Contact. + +`Contact` is `Sayable`, +[Examples/Contact-Bot](https://github.com/Chatie/wechaty/blob/master/examples/contact-bot.ts) + +**Kind**: global class + +* [Contact](#Contact) + * _instance_ + * [.payload](#Contact+payload) + * [.name()](#Contact+name) ⇒ string + * [.alias(newAlias)](#Contact+alias) ⇒ string \| null \| Promise.<boolean> + * ~~[.stranger()](#Contact+stranger) ⇒ boolean \| null~~ + * [.friend()](#Contact+friend) ⇒ boolean \| null + * ~~[.official()](#Contact+official) ⇒ boolean \| null~~ + * ~~[.personal()](#Contact+personal) ⇒ boolean~~ + * [.type()](#Contact+type) ⇒ + * [.star()](#Contact+star) ⇒ boolean \| null + * [.gender()](#Contact+gender) ⇒ ContactGender.Male(2) \| Gender.Female(1) \| Gender.Unknown(0) + * [.province()](#Contact+province) ⇒ string \| null + * [.city()](#Contact+city) ⇒ string \| null + * [.avatar()](#Contact+avatar) ⇒ Promise.<FileBox> + * ~~[.refresh()](#Contact+refresh) ⇒ Promise.<this>~~ + * [.sync()](#Contact+sync) ⇒ Promise.<this> + * [.self()](#Contact+self) ⇒ boolean + * _static_ + * [.find(query)](#Contact.find) ⇒ Promise.<(Contact\|null)> + * [.findAll([queryArg])](#Contact.findAll) ⇒ Promise.<Array.<Contact>> + + + +### contact.payload +Instance properties + +**Kind**: instance property of [Contact](#Contact) + + +### contact.name() ⇒ string +Get the name from a contact + +**Kind**: instance method of [Contact](#Contact) +**Example** +```js +const name = contact.name() +``` + + +### contact.alias(newAlias) ⇒ string \| null \| Promise.<boolean> +GET / SET / DELETE the alias for a contact + +Tests show it will failed if set alias too frequently(60 times in one minute). + +**Kind**: instance method of [Contact](#Contact) + +| Param | Type | +| --- | --- | +| newAlias | none \| string \| null | + +**Example** *( GET the alias for a contact, return {(string | null)})* +```js +const alias = contact.alias() +if (alias === null) { + console.log('You have not yet set any alias for contact ' + contact.name()) +} else { + console.log('You have already set an alias for contact ' + contact.name() + ':' + alias) +} +``` +**Example** *(SET the alias for a contact)* +```js +try { + await contact.alias('lijiarui') + console.log(`change ${contact.name()}'s alias successfully!`) +} catch (e) { + console.log(`failed to change ${contact.name()} alias!`) +} +``` +**Example** *(DELETE the alias for a contact)* +```js +try { + const oldAlias = await contact.alias(null) + console.log(`delete ${contact.name()}'s alias successfully!`) + console.log('old alias is ${oldAlias}`) +} catch (e) { + console.log(`failed to delete ${contact.name()}'s alias!`) +} +``` + + +### ~~contact.stranger() ⇒ boolean \| null~~ +***Deprecated*** + +Check if contact is stranger + +**Kind**: instance method of [Contact](#Contact) +**Returns**: boolean \| null - - True for not friend of the bot, False for friend of the bot, null for unknown. +**Example** +```js +const isStranger = contact.stranger() +``` + + +### contact.friend() ⇒ boolean \| null +Check if contact is friend + +**Kind**: instance method of [Contact](#Contact) +**Returns**: boolean \| null - - True for friend of the bot, False for not friend of the bot, null for unknown. +**Example** +```js +const isFriend = contact.friend() +``` + + +### ~~contact.official() ⇒ boolean \| null~~ +***Deprecated*** + +Check if it's a offical account + +**Kind**: instance method of [Contact](#Contact) +**Returns**: boolean \| null - - True for official account, Flase for contact is not a official account, null for unknown +**See** + +- [webwxApp.js#L324](https://github.com/Chatie/webwx-app-tracker/blob/7c59d35c6ea0cff38426a4c5c912a086c4c512b2/formatted/webwxApp.js#L3243) +- [Urinx/WeixinBot/README](https://github.com/Urinx/WeixinBot/blob/master/README.md) +**Example** +```js +const isOfficial = contact.official() +``` + + +### ~~contact.personal() ⇒ boolean~~ +***Deprecated*** + +Check if it's a personal account + +**Kind**: instance method of [Contact](#Contact) +**Returns**: boolean - - True for personal account, Flase for contact is not a personal account +**Example** +```js +const isPersonal = contact.personal() +``` + + +### contact.type() ⇒ +Return the type of the Contact + +**Kind**: instance method of [Contact](#Contact) +**Returns**: ContactType - Contact.Type.PERSONAL for personal account, Contact.Type.OFFICIAL for official account +**Example** +```js +const isOfficial = contact.type() === Contact.Type.OFFICIAL +``` + + +### contact.star() ⇒ boolean \| null +Check if the contact is star contact. + +**Kind**: instance method of [Contact](#Contact) +**Returns**: boolean \| null - - True for star friend, False for no star friend. +**Example** +```js +const isStar = contact.star() +``` + + +### contact.gender() ⇒ ContactGender.Male(2) \| Gender.Female(1) \| Gender.Unknown(0) +Contact gender + +**Kind**: instance method of [Contact](#Contact) +**Example** +```js +const gender = contact.gender() +``` + + +### contact.province() ⇒ string \| null +Get the region 'province' from a contact + +**Kind**: instance method of [Contact](#Contact) +**Example** +```js +const province = contact.province() +``` + + +### contact.city() ⇒ string \| null +Get the region 'city' from a contact + +**Kind**: instance method of [Contact](#Contact) +**Example** +```js +const city = contact.city() +``` + + +### contact.avatar() ⇒ Promise.<FileBox> +Get avatar picture file stream + +**Kind**: instance method of [Contact](#Contact) +**Example** +```js +const avatarFileName = contact.name() + `.jpg` +const fileBox = await contact.avatar() +const avatarWriteStream = createWriteStream(avatarFileName) +fileBox.pipe(avatarWriteStream) +log.info('Bot', 'Contact: %s: %s with avatar file: %s', contact.weixin(), contact.name(), avatarFileName) +``` + + +### ~~contact.refresh() ⇒ Promise.<this>~~ +***Deprecated*** + +Force reload(re-ready()) data for Contact + +**Kind**: instance method of [Contact](#Contact) +**Example** +```js +await contact.refresh() +``` + + +### contact.sync() ⇒ Promise.<this> +sycc data for Contact + +**Kind**: instance method of [Contact](#Contact) +**Example** +```js +await contact.sync() +``` + + +### contact.self() ⇒ boolean +Check if contact is self + +**Kind**: instance method of [Contact](#Contact) +**Returns**: boolean - True for contact is self, False for contact is others +**Example** +```js +const isSelf = contact.self() +``` + + +### Contact.find(query) ⇒ Promise.<(Contact\|null)> +Try to find a contact by filter: {name: string | RegExp} / {alias: string | RegExp} + +Find contact by name or alias, if the result more than one, return the first one. + +**Kind**: static method of [Contact](#Contact) +**Returns**: Promise.<(Contact\|null)> - If can find the contact, return Contact, or return null + +| Param | Type | +| --- | --- | +| query | [ContactQueryFilter](#ContactQueryFilter) | + +**Example** +```js +const contactFindByName = await Contact.find({ name:"ruirui"} ) +const contactFindByAlias = await Contact.find({ alias:"lijiarui"} ) +``` + + +### Contact.findAll([queryArg]) ⇒ Promise.<Array.<Contact>> +Find contact by `name` or `alias` + +If use Contact.findAll() get the contact list of the bot. + +#### definition +- `name` the name-string set by user-self, should be called name +- `alias` the name-string set by bot for others, should be called alias + +**Kind**: static method of [Contact](#Contact) + +| Param | Type | +| --- | --- | +| [queryArg] | [ContactQueryFilter](#ContactQueryFilter) | + +**Example** +```js +const contactList = await Contact.findAll() // get the contact list of the bot +const contactList = await Contact.findAll({name: 'ruirui'}) // find allof the contacts whose name is 'ruirui' +const contactList = await Contact.findAll({alias: 'lijiarui'}) // find all of the contacts whose alias is 'lijiarui' +``` + + +## Friendship +Send, receive friend request, and friend confirmation events. + +1. send request +2. receive request(in friend event) +3. confirmation friendship(friend event) + +[Examples/Friend-Bot](https://github.com/Chatie/wechaty/blob/master/examples/friend-bot.ts) + +**Kind**: global class + +* [Friendship](#Friendship) + * _instance_ + * [.payload](#Friendship+payload) + * [.ready()](#Friendship+ready) + * _static_ + * ~~[.send()](#Friendship.send)~~ + * [.add(contact, hello)](#Friendship.add) + + + +### friendship.payload +Instance Properties + +**Kind**: instance property of [Friendship](#Friendship) + + +### friendship.ready() +no `dirty` support because Friendship has no rawPayload(yet) + +**Kind**: instance method of [Friendship](#Friendship) + + +### ~~Friendship.send()~~ +***Deprecated*** + +**Kind**: static method of [Friendship](#Friendship) + + +### Friendship.add(contact, hello) +Send a Friend Request to a `contact` with message `hello`. + +**Kind**: static method of [Friendship](#Friendship) + +| Param | +| --- | +| contact | +| hello | + + + +## Message +All wechat messages will be encapsulated as a Message. + +`Message` is `Sayable`, +[Examples/Ding-Dong-Bot](https://github.com/Chatie/wechaty/blob/master/examples/ding-dong-bot.ts) + +**Kind**: global class + +* [Message](#Message) + * _instance_ + * [.payload](#Message+payload) + * [.from()](#Message+from) ⇒ [Contact](#Contact) + * [.to()](#Message+to) ⇒ [Contact](#Contact) \| null + * [.room()](#Message+room) ⇒ [Room](#Room) \| null + * ~~[.content()](#Message+content)~~ + * [.text()](#Message+text) ⇒ string + * [.say(textOrContactOrFile, [mention])](#Message+say) ⇒ Promise.<void> + * ~~[.file()](#Message+file)~~ + * [.type()](#Message+type) ⇒ WebMsgType + * [.self()](#Message+self) ⇒ boolean + * [.mention()](#Message+mention) ⇒ [Array.<Contact>](#Contact) + * [.mentioned()](#Message+mentioned) + * [.forward(to)](#Message+forward) ⇒ Promise.<void> + * [.age()](#Message+age) + * _static_ + * [.Type](#Message.Type) + * [.find()](#Message.find) + * [.findAll()](#Message.findAll) + * [.create()](#Message.create) + + + +### message.payload +Instance Properties + +**Kind**: instance property of [Message](#Message) + + +### message.from() ⇒ [Contact](#Contact) +Get the sender from a message. + +**Kind**: instance method of [Message](#Message) + + +### message.to() ⇒ [Contact](#Contact) \| 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. + +**Kind**: instance method of [Message](#Message) + + +### message.room() ⇒ [Room](#Room) \| null +Get the room from the message. +If the message is not in a room, then will return `null` + +**Kind**: instance method of [Message](#Message) + + +### ~~message.content()~~ +***Deprecated*** + +**Kind**: instance method of [Message](#Message) + + +### message.text() ⇒ string +Get the text content of the message + +**Kind**: instance method of [Message](#Message) + + +### message.say(textOrContactOrFile, [mention]) ⇒ Promise.<void> +Reply a Text or Media File message to the sender. + +**Kind**: instance method of [Message](#Message) +**See**: [Examples/ding-dong-bot](https://github.com/Chatie/wechaty/blob/master/examples/ding-dong-bot.ts) + +| Param | Type | +| --- | --- | +| textOrContactOrFile | string \| FileBox | +| [mention] | [Contact](#Contact) \| [Array.<Contact>](#Contact) | + +**Example** +```js +const bot = new Wechaty() +bot +.on('message', async m => { + if (/^ding$/i.test(m.text())) { + await m.say('hello world') + console.log('Bot REPLY: hello world') + await m.say(new bot.Message(__dirname + '/wechaty.png')) + console.log('Bot REPLY: Image') + } +}) +``` + + +### ~~message.file()~~ +***Deprecated*** + +**Kind**: instance method of [Message](#Message) + + +### message.type() ⇒ WebMsgType +Get the type from the message. + +If type is equal to `MsgType.RECALLED`, [Message#id](Message#id) is the msgId of the recalled message. + +**Kind**: instance method of [Message](#Message) +**See**: [MsgType](MsgType) + + +### message.self() ⇒ boolean +Check if a message is sent by self. + +**Kind**: instance method of [Message](#Message) +**Returns**: boolean - - Return `true` for send from self, `false` for send from others. +**Example** +```js +if (message.self()) { + console.log('this message is sent by myself!') +} +``` + + +### message.mention() ⇒ [Array.<Contact>](#Contact) +Get message mentioned contactList. + +Message event table as follows + +| | Web | Mac PC Client | iOS Mobile | android Mobile | +| :--- | :--: | :----: | :---: | :---: | +| [You were mentioned] tip ([有人@我]的提示) | ✘ | √ | √ | √ | +| Identify magic code (8197) by copy & paste in mobile | ✘ | √ | √ | ✘ | +| Identify magic code (8197) by programming | ✘ | ✘ | ✘ | ✘ | +| Identify two contacts with the same roomAlias by [You were mentioned] tip | ✘ | ✘ | √ | √ | + +**Kind**: instance method of [Message](#Message) +**Returns**: [Array.<Contact>](#Contact) - - Return message mentioned contactList +**Example** +```js +const contactList = message.mentioned() +console.log(contactList) +``` + + +### message.mentioned() +**Kind**: instance method of [Message](#Message) +**Deprecated:**: use mention() instead + + +### message.forward(to) ⇒ Promise.<void> +Forward the received message. + +**Kind**: instance method of [Message](#Message) + +| Param | Type | Description | +| --- | --- | --- | +| to | Sayable \| Array.<Sayable> | Room or Contact The recipient of the message, the room, or the contact | + + + +### message.age() +Message Age: + in seconds. + +**Kind**: instance method of [Message](#Message) + + +### Message.Type +Static Properties + +**Kind**: static property of [Message](#Message) + + +### Message.find() +**Kind**: static method of [Message](#Message) +**Todo** + +- [ ] add function + + + +### Message.findAll() +**Kind**: static method of [Message](#Message) +**Todo** + +- [ ] add function + + + +### Message.create() +Create a Mobile Terminated Message + +"mobile originated" or "mobile terminated" +https://www.tatango.com/resources/video-lessons/video-mo-mt-sms-messaging/ + +**Kind**: static method of [Message](#Message) ## WechatyEventName @@ -326,13 +1221,68 @@ Wechaty Class Event Function | Name | Type | Description | | --- | --- | --- | | error | function | (this: Wechaty, error: Error) => void callback function | -| login | function | (this: Wechaty, user: Contact)=> void | -| logout | function | (this: Wechaty, user: Contact) => void | +| 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:
| | heartbeat | function | (this: Wechaty, data: any) => void | -| friend | function | (this: Wechaty, friend: Contact, request?: FriendRequest) => void | +| friend | function | (this: Wechaty, request?: Friendship) => void | | message | function | (this: Wechaty, message: Message) => void | | room-join | function | (this: Wechaty, room: Room, inviteeList: Contact[], inviter: Contact) => void | -| room-topic | function | (this: Wechaty, room: Room, topic: string, oldTopic: string, changer: 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 | + + +## RoomEventName +Room Class Event Type + +**Kind**: global typedef +**Properties** + +| Name | Type | Description | +| --- | --- | --- | +| 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. | + + + +## RoomEventFunction +Room Class Event Function + +**Kind**: global typedef +**Properties** + +| Name | Type | Description | +| --- | --- | --- | +| room-join | function | (this: Room, inviteeList: Contact[] , inviter: Contact) => void | +| room-topic | function | (this: Room, topic: string, oldTopic: string, changer: Contact) => void | +| room-leave | function | (this: Room, leaver: Contact) => void | + + + +## MemberQueryFilter +The way to search member by Room.member() + +**Kind**: global typedef +**Properties** + +| Name | Type | Description | +| --- | --- | --- | +| 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/Chatie/wechaty/issues/365) | + + + +## ContactQueryFilter +The way to search Contact + +**Kind**: global typedef +**Properties** + +| Name | Type | Description | +| --- | --- | --- | +| 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/Chatie/wechaty/issues/365) | + diff --git a/scripts/generate-docs.sh b/scripts/generate-docs.sh index 0e9885a500f97a2b817e8b11649d94c69e427d8e..f5194fd5b51a2ce58fa0280a048eeeef248f39b4 100755 --- a/scripts/generate-docs.sh +++ b/scripts/generate-docs.sh @@ -3,7 +3,7 @@ set -e npm version -if ./scripts/development-release.ts; then +if [ "$1" != "dev" ] && ./scripts/development-release.ts; then echo "Current release is a development release, please only update the docs when there's a stable release." exit 1 else diff --git a/src/accessory.ts b/src/accessory.ts index 8cf984a237eb52c68843e2f72d1dc40a479a10fc..c43c20547ffe47a36a12788356db81fb1ed11df4 100644 --- a/src/accessory.ts +++ b/src/accessory.ts @@ -30,6 +30,9 @@ export abstract class Accessory extends EventEmitter { private static _puppet? : Puppet private static _wechaty? : Wechaty + /** + * @private + */ public static set puppet(puppet: Puppet) { log.silly('Accessory', '<%s> static set puppet = "%s"', this.name, @@ -42,6 +45,9 @@ export abstract class Accessory extends EventEmitter { this._puppet = puppet } + /** + * @private + */ public static get puppet(): Puppet { // log.silly('Accessory', '<%s> static get puppet()', // this.name, @@ -56,6 +62,9 @@ export abstract class Accessory extends EventEmitter { ) } + /** + * @private + */ public static set wechaty(wechaty: Wechaty) { log.silly('Accessory', '<%s> static set wechaty = "%s"', this.name, @@ -67,6 +76,9 @@ export abstract class Accessory extends EventEmitter { this._wechaty = wechaty } + /** + * @private + */ public static get wechaty(): Wechaty { // log.silly('Accessory', '<%s> static get wechaty()', // this.name, @@ -90,6 +102,9 @@ export abstract class Accessory extends EventEmitter { */ private _puppet? : Puppet + /** + * @private + */ public set puppet(puppet: Puppet) { log.silly('Accessory', '<%s> set puppet = "%s"', this[SYMBOL_NAME] || this, @@ -102,6 +117,8 @@ export abstract class Accessory extends EventEmitter { } /** + * @private + * * instance.puppet * * Needs to support different `puppet` between instances. @@ -130,6 +147,8 @@ export abstract class Accessory extends EventEmitter { } /** + * @private + * * instance.wechaty is for: * Contact.wechaty * FriendRequest.wechaty diff --git a/src/user/room.ts b/src/user/room.ts index 4361bf07a7630b985e04e9993e04d1860250bd1a..fac81f1fa07bb11bb20cc134638e7b7c90f526bd 100644 --- a/src/user/room.ts +++ b/src/user/room.ts @@ -221,7 +221,7 @@ export class Room extends Accessory implements Sayable { } /** - * + * @private * * Instance Properties * @@ -792,6 +792,7 @@ export class Room extends Accessory implements Sayable { /** * Force reload data for Room + * @private * @deprecated use sync() instead * @returns {Promise} */ diff --git a/src/wechaty.ts b/src/wechaty.ts index 3e07d1d3833283b0be178f22f8bd7e4de681fb32..ac5de67b065803c80d9f7bce5dd76d699872568d 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -136,14 +136,33 @@ export class Wechaty extends Accessory implements Sayable { */ public readonly id : string + /** + * @private + */ // tslint:disable-next-line:variable-name public readonly Contact : typeof Contact + + /** + * @private + */ // tslint:disable-next-line:variable-name public readonly ContactSelf : typeof ContactSelf + + /** + * @private + */ // tslint:disable-next-line:variable-name public readonly Friendship : typeof Friendship + + /** + * @private + */ // tslint:disable-next-line:variable-name public readonly Message : typeof Message + + /** + * @private + */ // tslint:disable-next-line:variable-name public readonly Room : typeof Room @@ -491,6 +510,8 @@ export class Wechaty extends Accessory implements Sayable { } /** + * @private + * * Init the Puppet */ private initPuppetResolver(puppet?: PuppetName | Puppet): Puppet { @@ -523,6 +544,8 @@ export class Wechaty extends Accessory implements Sayable { } /** + * @private + * * Plugin Version Range Check */ private initPuppetSemverSatisfy(versionRange: string) { @@ -719,6 +742,7 @@ export class Wechaty extends Accessory implements Sayable { } /** + * @private * @deprecated use start() instead */ public async init(): Promise {