提交 7e6dc0f1 编写于 作者: L lijiarui 提交者: Huan (李卓桓)

change doc order # 774 (#798)

* change doc order # 774

* @private all deprecated APIs.

* change the links inside README.md from Wiki to /docs/index.md

* recover readme as original

* modify wrong change
上级 cacd44ff
此差异已折叠。
/**
*
* Wechaty - https://github.com/chatie/wechaty
*
* @copyright 2016-2017 Huan LI <zixia@zixia.net>
......@@ -179,23 +180,175 @@ export class Contact implements Sayable {
}
/**
* Get the weixin number from a contact.
* The way to search Contact
*
* Sometimes cannot get weixin number due to weixin security mechanism, not recommend.
* @typedef ContactQueryFilter
* @property {string} name - The name-string set by user-self, should be called name
* @property {string} alias - The name-string set by bot for others, should be called alias
* [More Detail]{@link https://github.com/Chatie/wechaty/issues/365}
*/
/**
* Try to find a contact by filter: {name: string | RegExp} / {alias: string | RegExp}
*
* @deprecated
* @returns {string | null}
* Find contact by name or alias, if the result more than one, return the first one.
*
* @static
* @param {ContactQueryFilter} query
* @returns {(Promise<Contact | null>)} If can find the contact, return Contact, or return null
* @example
* const weixin = contact.weixin()
* const contactFindByName = await Contact.find({ name:"ruirui"} )
* const contactFindByAlias = await Contact.find({ alias:"lijiarui"} )
*/
public weixin(): string | null {
const wxId = this.obj && this.obj.weixin || null
if (!wxId) {
log.info('Contact', `weixin() is not able to always work, it's limited by Tencent API`)
log.info('Contact', 'weixin() If you want to track a contact between sessions, see FAQ at')
log.info('Contact', 'https://github.com/Chatie/wechaty/wiki/FAQ#1-how-to-get-the-permanent-id-for-a-contact')
public static async find(query: ContactQueryFilter): Promise<Contact | null> {
log.verbose('Contact', 'find(%s)', JSON.stringify(query))
const contactList = await Contact.findAll(query)
if (!contactList || !contactList.length) {
return null
}
return wxId
if (contactList.length > 1) {
log.warn('Contact', 'function find(%s) get %d contacts, use the first one by default', JSON.stringify(query), contactList.length)
}
return contactList[0]
}
/**
* 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
*
* @static
* @param {ContactQueryFilter} [queryArg]
* @returns {Promise<Contact[]>}
* @example
* 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'
*/
public static async findAll(queryArg?: ContactQueryFilter): Promise<Contact[]> {
let query: ContactQueryFilter
if (queryArg) {
if (queryArg.remark) {
log.warn('Contact', 'Contact.findAll({remark:%s}) DEPRECATED, use Contact.findAll({alias:%s}) instead.', queryArg.remark, queryArg.remark)
query = { alias: queryArg.remark}
} else {
query = queryArg
}
} else {
query = { name: /.*/ }
}
// log.verbose('Cotnact', 'findAll({ name: %s })', query.name)
log.verbose('Cotnact', 'findAll({ %s })',
Object.keys(query)
.map(k => `${k}: ${query[k]}`)
.join(', '),
)
if (Object.keys(query).length !== 1) {
throw new Error('query only support one key. multi key support is not availble now.')
}
let filterKey = Object.keys(query)[0]
let filterValue: string | RegExp = query[filterKey]
const keyMap = {
name: 'NickName',
alias: 'RemarkName',
}
filterKey = keyMap[filterKey]
if (!filterKey) {
throw new Error('unsupport filter key')
}
if (!filterValue) {
throw new Error('filterValue not found')
}
/**
* must be string because we need inject variable value
* into code as variable name
*/
let filterFunction: string
if (filterValue instanceof RegExp) {
filterFunction = `(function (c) { return ${filterValue.toString()}.test(c.${filterKey}) })`
} else if (typeof filterValue === 'string') {
filterValue = filterValue.replace(/'/g, '\\\'')
filterFunction = `(function (c) { return c.${filterKey} === '${filterValue}' })`
} else {
throw new Error('unsupport name type')
}
try {
const contactList = await config.puppetInstance()
.contactFind(filterFunction)
await Promise.all(contactList.map(c => c.ready()))
return contactList
} catch (e) {
log.error('Contact', 'findAll() rejected: %s', e.message)
return [] // fail safe
}
}
/**
* Sent Text to contact
*
* @param {string} text
*/
public async say(text: string)
/**
* Send Media File to Contact
*
* @param {MediaMessage} mediaMessage
* @memberof Contact
*/
public async say(mediaMessage: MediaMessage)
/**
* Send Text or Media File to Contact.
*
* @param {(string | MediaMessage)} textOrMedia
* @returns {Promise<boolean>}
* @example
* const contact = await Contact.find({name: 'lijiarui'}) // change 'lijiarui' to any of your contact name in wechat
* await contact.say('welcome to wechaty!')
* await contact.say(new MediaMessage(__dirname + '/wechaty.png') // put the filePath you want to send here
*/
public async say(textOrMedia: string | MediaMessage): Promise<boolean> {
const content = textOrMedia instanceof MediaMessage ? textOrMedia.filename() : textOrMedia
log.verbose('Contact', 'say(%s)', content)
const bot = Wechaty.instance()
const user = bot.self()
if (!user) {
throw new Error('no user')
}
let m
if (typeof textOrMedia === 'string') {
m = new Message()
m.content(textOrMedia)
} else if (textOrMedia instanceof MediaMessage) {
m = textOrMedia
} else {
throw new Error('not support args')
}
m.from(user)
m.to(this)
log.silly('Contact', 'say() from: %s to: %s content: %s', user.name(), this.name(), content)
return await bot.send(m)
}
/**
......@@ -207,6 +360,70 @@ export class Contact implements Sayable {
*/
public name() { return UtilLib.plainText(this.obj && this.obj.name || '') }
public alias(): string | null
public alias(newAlias: string): Promise<boolean>
public alias(empty: 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).
* @param {(none | string | null)} newAlias
* @returns {(string | null | Promise<boolean>)}
* @example <caption> GET the alias for a contact, return {(string | null)}</caption>
* 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 <caption>SET the alias for a contact</caption>
* const ret = await contact.alias('lijiarui')
* if (ret) {
* console.log(`change ${contact.name()}'s alias successfully!`)
* } else {
* console.log(`failed to change ${contact.name()} alias!`)
* }
*
* @example <caption>DELETE the alias for a contact</caption>
* const ret = await contact.alias(null)
* if (ret) {
* console.log(`delete ${contact.name()}'s alias successfully!`)
* } else {
* console.log(`failed to delete ${contact.name()}'s alias!`)
* }
*/
public alias(newAlias?: string|null): Promise<boolean> | string | null {
log.silly('Contact', 'alias(%s)', newAlias || '')
if (newAlias === undefined) {
return this.obj && this.obj.alias || null
}
return config.puppetInstance()
.contactAlias(this, newAlias)
.then(ret => {
if (ret) {
if (this.obj) {
this.obj.alias = newAlias
} else {
log.error('Contact', 'alias() without this.obj?')
}
} else {
log.warn('Contact', 'alias(%s) fail', newAlias)
}
return ret
})
.catch(e => {
log.error('Contact', 'alias(%s) rejected: %s', newAlias, e.message)
Raven.captureException(e)
return false // fail safe
})
}
/**
* Check if contact is stranger
*
......@@ -446,165 +663,6 @@ export class Contact implements Sayable {
return selfId === userId
}
/**
* The way to search Contact
*
* @typedef ContactQueryFilter
* @property {string} name - The name-string set by user-self, should be called name
* @property {string} alias - The name-string set by bot for others, should be called alias
* [More Detail]{@link https://github.com/Chatie/wechaty/issues/365}
*/
/**
* 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
*
* @static
* @param {ContactQueryFilter} [queryArg]
* @returns {Promise<Contact[]>}
* @example
* 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'
*/
public static async findAll(queryArg?: ContactQueryFilter): Promise<Contact[]> {
let query: ContactQueryFilter
if (queryArg) {
if (queryArg.remark) {
log.warn('Contact', 'Contact.findAll({remark:%s}) DEPRECATED, use Contact.findAll({alias:%s}) instead.', queryArg.remark, queryArg.remark)
query = { alias: queryArg.remark}
} else {
query = queryArg
}
} else {
query = { name: /.*/ }
}
// log.verbose('Cotnact', 'findAll({ name: %s })', query.name)
log.verbose('Cotnact', 'findAll({ %s })',
Object.keys(query)
.map(k => `${k}: ${query[k]}`)
.join(', '),
)
if (Object.keys(query).length !== 1) {
throw new Error('query only support one key. multi key support is not availble now.')
}
let filterKey = Object.keys(query)[0]
let filterValue: string | RegExp = query[filterKey]
const keyMap = {
name: 'NickName',
alias: 'RemarkName',
}
filterKey = keyMap[filterKey]
if (!filterKey) {
throw new Error('unsupport filter key')
}
if (!filterValue) {
throw new Error('filterValue not found')
}
/**
* must be string because we need inject variable value
* into code as variable name
*/
let filterFunction: string
if (filterValue instanceof RegExp) {
filterFunction = `(function (c) { return ${filterValue.toString()}.test(c.${filterKey}) })`
} else if (typeof filterValue === 'string') {
filterValue = filterValue.replace(/'/g, '\\\'')
filterFunction = `(function (c) { return c.${filterKey} === '${filterValue}' })`
} else {
throw new Error('unsupport name type')
}
try {
const contactList = await config.puppetInstance()
.contactFind(filterFunction)
await Promise.all(contactList.map(c => c.ready()))
return contactList
} catch (e) {
log.error('Contact', 'findAll() rejected: %s', e.message)
return [] // fail safe
}
}
public alias(): string | null
public alias(newAlias: string): Promise<boolean>
public alias(empty: 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).
* @param {(none | string | null)} newAlias
* @returns {(string | null | Promise<boolean>)}
* @example <caption> GET the alias for a contact, return {(string | null)}</caption>
* 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 <caption>SET the alias for a contact</caption>
* const ret = await contact.alias('lijiarui')
* if (ret) {
* console.log(`change ${contact.name()}'s alias successfully!`)
* } else {
* console.log(`failed to change ${contact.name()} alias!`)
* }
*
* @example <caption>DELETE the alias for a contact</caption>
* const ret = await contact.alias(null)
* if (ret) {
* console.log(`delete ${contact.name()}'s alias successfully!`)
* } else {
* console.log(`failed to delete ${contact.name()}'s alias!`)
* }
*/
public alias(newAlias?: string|null): Promise<boolean> | string | null {
log.silly('Contact', 'alias(%s)', newAlias || '')
if (newAlias === undefined) {
return this.obj && this.obj.alias || null
}
return config.puppetInstance()
.contactAlias(this, newAlias)
.then(ret => {
if (ret) {
if (this.obj) {
this.obj.alias = newAlias
} else {
log.error('Contact', 'alias() without this.obj?')
}
} else {
log.warn('Contact', 'alias(%s) fail', newAlias)
}
return ret
})
.catch(e => {
log.error('Contact', 'alias(%s) rejected: %s', newAlias, e.message)
Raven.captureException(e)
return false // fail safe
})
}
/**
* @private
*/
......@@ -623,32 +681,6 @@ export class Contact implements Sayable {
}
}
/**
* 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.
*
* @static
* @param {ContactQueryFilter} query
* @returns {(Promise<Contact | null>)} If can find the contact, return Contact, or return null
* @example
* const contactFindByName = await Contact.find({ name:"ruirui"} )
* const contactFindByAlias = await Contact.find({ alias:"lijiarui"} )
*/
public static async find(query: ContactQueryFilter): Promise<Contact | null> {
log.verbose('Contact', 'find(%s)', JSON.stringify(query))
const contactList = await Contact.findAll(query)
if (!contactList || !contactList.length) {
return null
}
if (contactList.length > 1) {
log.warn('Contact', 'function find(%s) get %d contacts, use the first one by default', JSON.stringify(query), contactList.length)
}
return contactList[0]
}
/**
* @private
*/
......@@ -664,54 +696,23 @@ export class Contact implements Sayable {
}
/**
* Sent Text to contact
*
* @param {string} text
*/
public async say(text: string)
/**
* Send Media File to Contact
* Get the weixin number from a contact.
*
* @param {MediaMessage} mediaMessage
* @memberof Contact
*/
public async say(mediaMessage: MediaMessage)
/**
* Send Text or Media File to Contact.
* Sometimes cannot get weixin number due to weixin security mechanism, not recommend.
*
* @param {(string | MediaMessage)} textOrMedia
* @returns {Promise<boolean>}
* @private
* @returns {string | null}
* @example
* const contact = await Contact.find({name: 'lijiarui'}) // change 'lijiarui' to any of your contact name in wechat
* await contact.say('welcome to wechaty!')
* await contact.say(new MediaMessage(__dirname + '/wechaty.png') // put the filePath you want to send here
* const weixin = contact.weixin()
*/
public async say(textOrMedia: string | MediaMessage): Promise<boolean> {
const content = textOrMedia instanceof MediaMessage ? textOrMedia.filename() : textOrMedia
log.verbose('Contact', 'say(%s)', content)
const bot = Wechaty.instance()
const user = bot.self()
if (!user) {
throw new Error('no user')
}
let m
if (typeof textOrMedia === 'string') {
m = new Message()
m.content(textOrMedia)
} else if (textOrMedia instanceof MediaMessage) {
m = textOrMedia
} else {
throw new Error('not support args')
public weixin(): string | null {
const wxId = this.obj && this.obj.weixin || null
if (!wxId) {
log.info('Contact', `weixin() is not able to always work, it's limited by Tencent API`)
log.info('Contact', 'weixin() If you want to track a contact between sessions, see FAQ at')
log.info('Contact', 'https://github.com/Chatie/wechaty/wiki/FAQ#1-how-to-get-the-permanent-id-for-a-contact')
}
m.from(user)
m.to(this)
log.silly('Contact', 'say() from: %s to: %s content: %s', user.name(), this.name(), content)
return await bot.send(m)
return wxId
}
}
......
......@@ -315,16 +315,6 @@ export class Message implements Sayable {
*/
public obj = <MsgObj>{}
/**
* Please notice that when we are running Wechaty,
* if you use the browser that controlled by Wechaty to send attachment files,
* you will get a zero sized file, because it is not an attachment from the network,
* but a local data, which is not supported by Wechaty yet.
*/
public readyStream(): Promise<Readable> {
throw Error('abstract method')
}
/**
* @private
*/
......@@ -428,6 +418,74 @@ export class Message implements Sayable {
return '{' + this.type() + '}' + content
}
public say(text: string, replyTo?: Contact | Contact[]): Promise<any>
public say(mediaMessage: MediaMessage, replyTo?: Contact | Contact[]): Promise<any>
/**
* Reply a Text or Media File message to the sender.
*
* @see {@link https://github.com/Chatie/wechaty/blob/master/example/ding-dong-bot.ts|Example/ding-dong-bot}
* @param {(string | MediaMessage)} textOrMedia
* @param {(Contact|Contact[])} [replyTo]
* @returns {Promise<any>}
*
* @example
* const bot = Wechaty.instance()
* bot
* .on('message', async m => {
* if (/^ding$/i.test(m.content())) {
* await m.say('hello world')
* console.log('Bot REPLY: hello world')
* await m.say(new MediaMessage(__dirname + '/wechaty.png'))
* console.log('Bot REPLY: Image')
* }
* })
*/
public say(textOrMedia: string | MediaMessage, replyTo?: Contact|Contact[]): Promise<any> {
/* tslint:disable:no-use-before-declare */
const content = textOrMedia instanceof MediaMessage ? textOrMedia.filename() : textOrMedia
log.verbose('Message', 'say(%s, %s)', content, replyTo)
let m
if (typeof textOrMedia === 'string') {
m = new Message()
const room = this.room()
if (room) {
m.room(room)
}
if (!replyTo) {
m.to(this.from())
m.content(textOrMedia)
} else if (this.room()) {
let mentionList
if (Array.isArray(replyTo)) {
m.to(replyTo[0])
mentionList = replyTo.map(c => '@' + c.name()).join(' ')
} else {
m.to(replyTo)
mentionList = '@' + replyTo.name()
}
m.content(mentionList + ' ' + textOrMedia)
}
/* tslint:disable:no-use-before-declare */
} else if (textOrMedia instanceof MediaMessage) {
m = textOrMedia
const room = this.room()
if (room) {
m.room(room)
}
if (!replyTo) {
m.to(this.from())
}
}
return config.puppetInstance()
.send(m)
}
/**
* @private
*/
......@@ -463,47 +521,6 @@ export class Message implements Sayable {
return loadedContact
}
// public to(room: Room): void
// public to(): Contact|Room
// public to(contact?: Contact|Room|string): Contact|Room|void {
/**
* @private
*/
public to(contact: Contact): void
/**
* @private
*/
public to(id: string): void
public to(): Contact|null // if to is not set, then room must had set
/**
* 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.
* @returns {(Contact|null)}
*/
public to(contact?: Contact|string): Contact|Room|null|void {
if (contact) {
if (contact instanceof Contact) {
this.obj.to = contact.id
} else if (typeof contact === 'string') {
this.obj.to = contact
} else {
throw new Error('unsupport to param ' + typeof contact)
}
return
}
// no parameter
if (!this.obj.to) {
return null
}
return Contact.load(this.obj.to)
}
/**
* @private
*/
......@@ -797,82 +814,67 @@ export class Message implements Sayable {
])
}
// DEPRECATED: TypeScript ENUM did this for us 201705
// public static initType() {
// Object.keys(Message.TYPE).forEach(k => {
// const v = Message.TYPE[k]
// Message.TYPE[v] = k // Message.Type[1] = 'TEXT'
// })
// }
public say(text: string, replyTo?: Contact | Contact[]): Promise<any>
// public to(room: Room): void
// public to(): Contact|Room
// public to(contact?: Contact|Room|string): Contact|Room|void {
public say(mediaMessage: MediaMessage, replyTo?: Contact | Contact[]): Promise<any>
/**
* @private
*/
public to(contact: Contact): void
/**
* Reply a Text or Media File message to the sender.
*
* @see {@link https://github.com/Chatie/wechaty/blob/master/example/ding-dong-bot.ts|Example/ding-dong-bot}
* @param {(string | MediaMessage)} textOrMedia
* @param {(Contact|Contact[])} [replyTo]
* @returns {Promise<any>}
*
* @example
* const bot = Wechaty.instance()
* bot
* .on('message', async m => {
* if (/^ding$/i.test(m.content())) {
* await m.say('hello world')
* console.log('Bot REPLY: hello world')
* await m.say(new MediaMessage(__dirname + '/wechaty.png'))
* console.log('Bot REPLY: Image')
* }
* })
* @private
*/
public say(textOrMedia: string | MediaMessage, replyTo?: Contact|Contact[]): Promise<any> {
/* tslint:disable:no-use-before-declare */
const content = textOrMedia instanceof MediaMessage ? textOrMedia.filename() : textOrMedia
log.verbose('Message', 'say(%s, %s)', content, replyTo)
let m
if (typeof textOrMedia === 'string') {
m = new Message()
const room = this.room()
if (room) {
m.room(room)
}
public to(id: string): void
if (!replyTo) {
m.to(this.from())
m.content(textOrMedia)
public to(): Contact|null // if to is not set, then room must had set
} else if (this.room()) {
let mentionList
if (Array.isArray(replyTo)) {
m.to(replyTo[0])
mentionList = replyTo.map(c => '@' + c.name()).join(' ')
} else {
m.to(replyTo)
mentionList = '@' + replyTo.name()
}
m.content(mentionList + ' ' + textOrMedia)
}
/* tslint:disable:no-use-before-declare */
} else if (textOrMedia instanceof MediaMessage) {
m = textOrMedia
const room = this.room()
if (room) {
m.room(room)
/**
* 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.
* @returns {(Contact|null)}
*/
public to(contact?: Contact|string): Contact|Room|null|void {
if (contact) {
if (contact instanceof Contact) {
this.obj.to = contact.id
} else if (typeof contact === 'string') {
this.obj.to = contact
} else {
throw new Error('unsupport to param ' + typeof contact)
}
return
}
if (!replyTo) {
m.to(this.from())
}
// no parameter
if (!this.obj.to) {
return null
}
return Contact.load(this.obj.to)
}
return config.puppetInstance()
.send(m)
/**
* Please notice that when we are running Wechaty,
* if you use the browser that controlled by Wechaty to send attachment files,
* you will get a zero sized file, because it is not an attachment from the network,
* but a local data, which is not supported by Wechaty yet.
*
* @returns {Promise<Readable>}
*/
public readyStream(): Promise<Readable> {
throw Error('abstract method')
}
// DEPRECATED: TypeScript ENUM did this for us 201705
// public static initType() {
// Object.keys(Message.TYPE).forEach(k => {
// const v = Message.TYPE[k]
// Message.TYPE[v] = k // Message.Type[1] = 'TEXT'
// })
// }
}
// Message.initType()
......
/**
*
* Wechaty - https://github.com/chatie/wechaty
*
* @copyright 2016-2017 Huan LI <zixia@zixia.net>
......@@ -114,20 +115,6 @@ export class Room extends EventEmitter implements Sayable {
return !!(this.obj && this.obj.memberList && this.obj.memberList.length)
}
/**
* Force reload data for Room
*
* @returns {Promise<void>}
*/
public async refresh(): Promise<void> {
if (this.isReady()) {
this.dirtyObj = this.obj
}
this.obj = null
await this.ready()
return
}
/**
* @private
*/
......@@ -182,6 +169,67 @@ export class Room extends EventEmitter implements Sayable {
}
}
public say(mediaMessage: MediaMessage)
public say(content: string)
public say(content: string, replyTo: Contact)
public say(content: string, replyTo: Contact[])
/**
* Send message inside Room, if set [replyTo], wechaty will mention the contact as well.
*
* @param {(string | MediaMessage)} textOrMedia - Send `text` or `media file` inside Room.
* @param {(Contact | Contact[])} [replyTo] - Optional parameter, send content inside Room, and mention @replyTo contact or contactList.
* @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
*
* @example <caption>Send text inside Room</caption>
* const room = await Room.find({name: 'wechaty'}) // change 'wechaty' to any of your room in wechat
* await room.say('Hello world!')
*
* @example <caption>Send media file inside Room</caption>
* 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 <caption>Send text inside Room, and mention @replyTo contact</caption>
* 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)
*/
public say(textOrMedia: string | MediaMessage, replyTo?: Contact|Contact[]): Promise<boolean> {
const content = textOrMedia instanceof MediaMessage ? textOrMedia.filename() : textOrMedia
log.verbose('Room', 'say(%s, %s)',
content,
Array.isArray(replyTo)
? replyTo.map(c => c.name()).join(', ')
: replyTo ? replyTo.name() : '',
)
let m
if (typeof textOrMedia === 'string') {
m = new Message()
const replyToList: Contact[] = [].concat(replyTo as any || [])
if (replyToList.length > 0) {
const AT_SEPRATOR = String.fromCharCode(8197)
const mentionList = replyToList.map(c => '@' + c.name()).join(AT_SEPRATOR)
m.content(mentionList + ' ' + content)
} else {
m.content(content)
}
// m.to(replyToList[0])
} else
m = textOrMedia
m.room(this)
return config.puppetInstance()
.send(m)
}
public on(event: 'leave', listener: (this: Room, leaver: Contact) => void): this
public on(event: 'join' , listener: (this: Room, inviteeList: Contact[] , inviter: Contact) => void): this
......@@ -247,67 +295,6 @@ export class Room extends EventEmitter implements Sayable {
return this
}
public say(mediaMessage: MediaMessage)
public say(content: string)
public say(content: string, replyTo: Contact)
public say(content: string, replyTo: Contact[])
/**
* Send message inside Room, if set [replyTo], wechaty will mention the contact as well.
*
* @param {(string | MediaMessage)} textOrMedia - Send `text` or `media file` inside Room.
* @param {(Contact | Contact[])} [replyTo] - Optional parameter, send content inside Room, and mention @replyTo contact or contactList.
* @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
*
* @example <caption>Send text inside Room</caption>
* const room = await Room.find({name: 'wechaty'}) // change 'wechaty' to any of your room in wechat
* await room.say('Hello world!')
*
* @example <caption>Send media file inside Room</caption>
* 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 <caption>Send text inside Room, and mention @replyTo contact</caption>
* 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)
*/
public say(textOrMedia: string | MediaMessage, replyTo?: Contact|Contact[]): Promise<boolean> {
const content = textOrMedia instanceof MediaMessage ? textOrMedia.filename() : textOrMedia
log.verbose('Room', 'say(%s, %s)',
content,
Array.isArray(replyTo)
? replyTo.map(c => c.name()).join(', ')
: replyTo ? replyTo.name() : '',
)
let m
if (typeof textOrMedia === 'string') {
m = new Message()
const replyToList: Contact[] = [].concat(replyTo as any || [])
if (replyToList.length > 0) {
const AT_SEPRATOR = String.fromCharCode(8197)
const mentionList = replyToList.map(c => '@' + c.name()).join(AT_SEPRATOR)
m.content(mentionList + ' ' + content)
} else {
m.content(content)
}
// m.to(replyToList[0])
} else
m = textOrMedia
m.room(this)
return config.puppetInstance()
.send(m)
}
/**
* @private
*/
......@@ -608,30 +595,6 @@ export class Room extends EventEmitter implements Sayable {
.length > 0
}
/**
* @deprecated
* Get room's owner from the room.
* Not recommend, because cannot always get the owner
* @returns {(Contact | null)}
*/
public owner(): Contact | null {
const ownerUin = this.obj && this.obj.ownerUin
const user = config.puppetInstance()
.user
if (user && user.get('uin') === ownerUin) {
return user
}
if (this.rawObj.ChatRoomOwner) {
return Contact.load(this.rawObj.ChatRoomOwner)
}
log.info('Room', 'owner() is limited by Tencent API, sometimes work sometimes not')
return null
}
public memberAll(filter: MemberQueryFilter): Contact[]
public memberAll(name: string): Contact[]
......@@ -910,6 +873,44 @@ export class Room extends EventEmitter implements Sayable {
return roomList[0]
}
/**
* Force reload data for Room
*
* @returns {Promise<void>}
*/
public async refresh(): Promise<void> {
if (this.isReady()) {
this.dirtyObj = this.obj
}
this.obj = null
await this.ready()
return
}
/**
* @private
* Get room's owner from the room.
* Not recommend, because cannot always get the owner
* @returns {(Contact | null)}
*/
public owner(): Contact | null {
const ownerUin = this.obj && this.obj.ownerUin
const user = config.puppetInstance()
.user
if (user && user.get('uin') === ownerUin) {
return user
}
if (this.rawObj.ChatRoomOwner) {
return Contact.load(this.rawObj.ChatRoomOwner)
}
log.info('Room', 'owner() is limited by Tencent API, sometimes work sometimes not')
return null
}
/**
* @private
*/
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册