From 27b95f49a987490f3a9af23381c9caa9476d027b Mon Sep 17 00:00:00 2001 From: Yuan Gao Date: Sat, 11 Aug 2018 03:22:16 +0800 Subject: [PATCH] add receive and send link prototype (#1538) * add receive and send link prototype * add UrlLink class * 0.19.140 * code clean * 0.19.141 --- package.json | 4 ++-- src/user/contact.ts | 48 ++++++++++++++++++++++--------------- src/user/index.ts | 1 + src/user/message.ts | 55 +++++++++++++++++++++++++++++++++++-------- src/user/room.ts | 37 ++++++++++++++++++----------- src/user/url-link.ts | 56 ++++++++++++++++++++++++++++++++++++++++++++ src/wechaty.ts | 28 ++++++++++++++-------- 7 files changed, 174 insertions(+), 55 deletions(-) create mode 100644 src/user/url-link.ts diff --git a/package.json b/package.json index 75a1956c..66e3dabb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty", - "version": "0.19.139", + "version": "0.19.141", "description": "Wechaty is a Bot SDK for Wechat Personal Account", "main": "dist/src/index.js", "typings": "dist/src/index.d.ts", @@ -91,7 +91,7 @@ "read-pkg-up": "^4.0.0", "state-switch": "^0.6.2", "watchdog": "^0.8.1", - "wechaty-puppet": "^0.11.3", + "wechaty-puppet": "^0.13.6", "ws": "^6.0.0" }, "devDependencies": { diff --git a/src/user/contact.ts b/src/user/contact.ts index bbefd0bf..f7a35b5a 100644 --- a/src/user/contact.ts +++ b/src/user/contact.ts @@ -20,9 +20,16 @@ import { instanceToClass } from 'clone-class' import { FileBox } from 'file-box' +import { + ContactGender, + ContactPayload, + ContactQueryFilter, + ContactType, +} from 'wechaty-puppet' + import { Accessory, -} from '../accessory' +} from '../accessory' import { log, qrCodeForChatie, @@ -30,14 +37,9 @@ import { } from '../config' import { Sayable, -} from '../types' +} from '../types' -import { - ContactGender, - ContactPayload, - ContactQueryFilter, - ContactType, -} from 'wechaty-puppet' +import { UrlLink } from './url-link' export const POOL = Symbol('pool') @@ -306,15 +308,16 @@ export class Contact extends Accessory implements Sayable { return `Contact<${identity}>` } - public async say (text: string): Promise + public async say (text: string) : Promise public async say (file: FileBox) : Promise public async say (contact: Contact) : Promise + public async say (url: UrlLink) : Promise /** * > Tips: * This function is depending on the Puppet Implementation, see [puppet-compatible-table](https://github.com/Chatie/wechaty/wiki/Puppet#3-puppet-compatible-table) * - * @param {(string | Contact | FileBox)} textOrContactOrFile + * @param {(string | Contact | FileBox)} textOrContactOrFileOrUrl * send text, Contact, or file to contact.
* You can use {@link https://www.npmjs.com/package/file-box|FileBox} to send file * @returns {Promise} @@ -340,32 +343,39 @@ export class Contact extends Accessory implements Sayable { * const contactCard = bot.Contact.load('contactId') * await contact.say(contactCard) */ - public async say (textOrContactOrFile: string | Contact | FileBox): Promise { - log.verbose('Contact', 'say(%s)', textOrContactOrFile) + public async say (textOrContactOrFileOrUrl: string | Contact | FileBox | UrlLink): Promise { + log.verbose('Contact', 'say(%s)', textOrContactOrFileOrUrl) - if (typeof textOrContactOrFile === 'string') { + if (typeof textOrContactOrFileOrUrl === 'string') { /** * 1. Text */ await this.puppet.messageSendText({ contactId: this.id, - }, textOrContactOrFile) - } else if (textOrContactOrFile instanceof Contact) { + }, textOrContactOrFileOrUrl) + } else if (textOrContactOrFileOrUrl instanceof Contact) { /** * 2. Contact */ await this.puppet.messageSendContact({ contactId: this.id, - }, textOrContactOrFile.id) - } else if (textOrContactOrFile instanceof FileBox) { + }, textOrContactOrFileOrUrl.id) + } else if (textOrContactOrFileOrUrl instanceof FileBox) { /** * 3. File */ await this.puppet.messageSendFile({ contactId: this.id, - }, textOrContactOrFile) + }, textOrContactOrFileOrUrl) + } else if (textOrContactOrFileOrUrl instanceof UrlLink) { + /** + * 4. Link Message + */ + await this.puppet.messageSendUrl({ + contactId : this.id + }, textOrContactOrFileOrUrl.payload) } else { - throw new Error('unsupported') + throw new Error('unsupported arg: ' + textOrContactOrFileOrUrl) } } diff --git a/src/user/index.ts b/src/user/index.ts index 9de72bc2..89eeee77 100644 --- a/src/user/index.ts +++ b/src/user/index.ts @@ -7,3 +7,4 @@ export * from './moment' export * from './money' export * from './room' export * from './room-invitation' +export * from './url-link' diff --git a/src/user/message.ts b/src/user/message.ts index e35ac740..e4897920 100644 --- a/src/user/message.ts +++ b/src/user/message.ts @@ -43,6 +43,9 @@ import { import { Room, } from './room' +import { + UrlLink, +} from './url-link' import { MessagePayload, @@ -180,7 +183,7 @@ export class Message extends Accessory implements Sayable { if (!this.payload) { throw new Error('no payload') } - const filename = this.payload.filename + // const filename = this.puppet.messagefile payload.filename // if (!filename) { // throw new Error( // 'no file for message id: ' + this.id @@ -188,7 +191,7 @@ export class Message extends Accessory implements Sayable { // + '(' + this.payload.type + ')', // ) // } - msgStrList.push(`<${filename || 'unknown file name'}>`) + // msgStrList.push(`<${filename || 'unknown file name'}>`) } return msgStrList.join('') @@ -327,6 +330,7 @@ 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 (...args: never[]): Promise /** @@ -376,11 +380,11 @@ export class Message extends Accessory implements Sayable { * .start() */ public async say ( - textOrContactOrFile : string | Contact | FileBox, + textOrContactOrFileOrUrl : string | Contact | FileBox | UrlLink, mention? : Contact | Contact[], ): Promise { log.verbose('Message', 'say(%s%s)', - textOrContactOrFile.toString(), + textOrContactOrFileOrUrl, mention ? ', ' + mention : '', @@ -397,29 +401,39 @@ export class Message extends Accessory implements Sayable { : [mention] : [] - if (typeof textOrContactOrFile === 'string') { + if (typeof textOrContactOrFileOrUrl === 'string') { await this.sayText( - textOrContactOrFile, + textOrContactOrFileOrUrl, from || undefined, room || undefined, mentionList, ) - } else if (textOrContactOrFile instanceof Contact) { + } else if (textOrContactOrFileOrUrl instanceof Contact) { /** * Contact Card */ await this.puppet.messageSendContact({ contactId : from && from.id || undefined, roomId : room && room.id || undefined, - }, textOrContactOrFile.id) - } else { + }, textOrContactOrFileOrUrl.id) + } else if (textOrContactOrFileOrUrl instanceof FileBox) { /** * File Message */ await this.puppet.messageSendFile({ contactId : from && from.id || undefined, roomId : room && room.id || undefined, - }, textOrContactOrFile) + }, textOrContactOrFileOrUrl) + } else if (textOrContactOrFileOrUrl instanceof UrlLink) { + /** + * Link Message + */ + await this.puppet.messageSendUrl({ + contactId : from && from.id || undefined, + roomId : room && room.id || undefined, + }, textOrContactOrFileOrUrl.payload) + } else { + throw new Error('unknown msg: ' + textOrContactOrFileOrUrl) } } @@ -461,6 +475,7 @@ export class Message extends Accessory implements Sayable { * - MessageType.Image
* - MessageType.Text
* - MessageType.Video
+ * - MessageType.Url
* @returns {MessageType} * * @example @@ -789,4 +804,24 @@ export class Message extends Accessory implements Sayable { return contact } + public async toUrl (): Promise { + log.verbose('Message', 'toUrl()') + + if (!this.payload) { + throw new Error('no payload') + } + + if (this.type() !== Message.Type.Url) { + throw new Error('message not a Url Link') + } + + const urlPayload = await this.puppet.messageUrl(this.id) + + if (!urlPayload) { + throw new Error(`no url payload for message ${this.id}`) + } + + return new UrlLink(urlPayload) + } + } diff --git a/src/user/room.ts b/src/user/room.ts index 7844a6f5..3022d641 100644 --- a/src/user/room.ts +++ b/src/user/room.ts @@ -26,7 +26,7 @@ import { import { Accessory, -} from '../accessory' +} from '../accessory' import { // config, FOUR_PER_EM_SPACE, @@ -35,10 +35,11 @@ import { } from '../config' import { Sayable, -} from '../types' +} from '../types' import { Contact } from './contact' import { RoomInvitation } from './room-invitation' +import { UrlLink } from './url-link' export const ROOM_EVENT_DICT = { invite: 'tbw', @@ -359,6 +360,7 @@ export class Room extends Accessory implements Sayable { public say (text: string, mention: Contact) : Promise public say (text: string, mention: Contact[]) : Promise public say (file: FileBox) : Promise + public say (url: UrlLink) : Promise public say (...args: never[]): never @@ -367,7 +369,7 @@ export class Room extends Accessory implements Sayable { * > Tips: * This function is depending on the Puppet Implementation, see [puppet-compatible-table](https://github.com/Chatie/wechaty/wiki/Puppet#3-puppet-compatible-table) * - * @param {(string | Contact | FileBox)} textOrContactOrFile - Send `text` or `media file` inside Room.
+ * @param {(string | Contact | FileBox)} textOrContactOrFileOrUrl - Send `text` or `media file` inside Room.
* You can use {@link https://www.npmjs.com/package/file-box|FileBox} to send file * @param {(Contact | Contact[])} [mention] - Optional parameter, send content inside Room, and mention @replyTo contact or contactList. * @returns {Promise} @@ -398,11 +400,11 @@ export class Room extends Accessory implements Sayable { * await room.say('Hello world!', contact) */ public async say ( - textOrContactOrFile : string | Contact | FileBox, - mention? : Contact | Contact[], + textOrContactOrFileOrUrl : string | Contact | FileBox | UrlLink, + mention? : Contact | Contact[], ): Promise { log.verbose('Room', 'say(%s, %s)', - textOrContactOrFile, + textOrContactOrFileOrUrl, Array.isArray(mention) ? mention.map(c => c.name()).join(', ') : mention ? mention.name() : '', @@ -411,31 +413,38 @@ export class Room extends Accessory implements Sayable { const replyToList: Contact[] = [].concat(mention as any || []) - if (typeof textOrContactOrFile === 'string') { + if (typeof textOrContactOrFileOrUrl === 'string') { if (replyToList.length > 0) { // const AT_SEPRATOR = String.fromCharCode(8197) const AT_SEPRATOR = FOUR_PER_EM_SPACE const mentionList = replyToList.map(c => '@' + c.name()).join(AT_SEPRATOR) - text = mentionList + ' ' + textOrContactOrFile + text = mentionList + ' ' + textOrContactOrFileOrUrl } else { - text = textOrContactOrFile + text = textOrContactOrFileOrUrl } await this.puppet.messageSendText({ contactId : replyToList.length && replyToList[0].id || undefined, roomId : this.id, }, text) - } else if (textOrContactOrFile instanceof FileBox) { + } else if (textOrContactOrFileOrUrl instanceof FileBox) { await this.puppet.messageSendFile({ roomId: this.id, - }, textOrContactOrFile) - } else if (textOrContactOrFile instanceof Contact) { + }, textOrContactOrFileOrUrl) + } else if (textOrContactOrFileOrUrl instanceof Contact) { await this.puppet.messageSendContact({ roomId: this.id, - }, textOrContactOrFile.id) + }, textOrContactOrFileOrUrl.id) + } else if (textOrContactOrFileOrUrl instanceof UrlLink) { + /** + * 4. Link Message + */ + await this.puppet.messageSendUrl({ + contactId : this.id + }, textOrContactOrFileOrUrl.payload) } else { - throw new Error('arg unsupported') + throw new Error('arg unsupported: ' + textOrContactOrFileOrUrl) } } diff --git a/src/user/url-link.ts b/src/user/url-link.ts new file mode 100644 index 00000000..3a942781 --- /dev/null +++ b/src/user/url-link.ts @@ -0,0 +1,56 @@ +import { + UrlLinkPayload, +} from 'wechaty-puppet' + +import { + log, +} from '../config' + +export class UrlLink { + + /** + * + * Create from URL + * + */ + public static async create (url: string): Promise { + log.verbose('UrlLink', 'create(%s)', url) + + // TODO: get title/description/thumbnailUrl from url automatically + const payload: UrlLinkPayload = { + description : 'todo', + thumbnailUrl : 'todo', + title : 'todo', + url, + } + + return new UrlLink(payload) + } + + constructor ( + public readonly payload: UrlLinkPayload, + ) { + log.verbose('UrlLink', 'constructor()') + } + + public toString (): string { + return `UrlLink<${this.payload.url}>` + } + + public url (): string { + return this.payload.url + } + + public title (): string { + return this.payload.title + } + + public thumbnailUrl (): undefined | string { + return this.payload.thumbnailUrl + } + + public description (): undefined | string { + return this.payload.description + } + +} diff --git a/src/wechaty.ts b/src/wechaty.ts index a5f6dbc6..29215404 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -81,6 +81,7 @@ import { Message, Room, RoomInvitation, + UrlLink, } from './user/' export const WECHATY_EVENT_DICT = { @@ -159,6 +160,7 @@ export class Wechaty extends Accessory implements Sayable { public readonly Message : typeof Message public readonly RoomInvitation: typeof RoomInvitation public readonly Room : typeof Room + public readonly UrlLink : typeof UrlLink /** * Get the global instance of Wechaty @@ -269,6 +271,9 @@ export class Wechaty extends Accessory implements Sayable { this.Message = cloneClass(Message) this.Room = cloneClass(Room) this.RoomInvitation = cloneClass(RoomInvitation) + + // No need to set puppet/wechaty, so no need to clone + this.UrlLink = UrlLink } /** @@ -970,6 +975,7 @@ export class Wechaty extends Accessory implements Sayable { public async say (text: string) : Promise public async say (contact: Contact) : Promise public async say (file: FileBox) : Promise + public async say (url: UrlLink) : Promise public async say (...args: never[]): Promise @@ -978,7 +984,7 @@ export class Wechaty extends Accessory implements Sayable { * > Tips: * This function is depending on the Puppet Implementation, see [puppet-compatible-table](https://github.com/Chatie/wechaty/wiki/Puppet#3-puppet-compatible-table) * - * @param {(string | Contact | FileBox)} textOrContactOrFile + * @param {(string | Contact | FileBox)} textOrContactOrFileOrUrl * send text, Contact, or file to bot.
* You can use {@link https://www.npmjs.com/package/file-box|FileBox} to send file * @@ -1007,18 +1013,20 @@ export class Wechaty extends Accessory implements Sayable { * await bot.say(fileBox) */ - public async say (textOrContactOrFile: string | Contact | FileBox): Promise { - log.verbose('Wechaty', 'say(%s)', textOrContactOrFile) + public async say (textOrContactOrFileOrUrl: string | Contact | FileBox | UrlLink): Promise { + log.verbose('Wechaty', 'say(%s)', textOrContactOrFileOrUrl) // Make Typescript Happy: - if (typeof textOrContactOrFile === 'string') { - await this.userSelf().say(textOrContactOrFile) - } else if (textOrContactOrFile instanceof Contact) { - await this.userSelf().say(textOrContactOrFile) - } else if (textOrContactOrFile instanceof FileBox) { - await this.userSelf().say(textOrContactOrFile) + if (typeof textOrContactOrFileOrUrl === 'string') { + await this.userSelf().say(textOrContactOrFileOrUrl) + } else if (textOrContactOrFileOrUrl instanceof Contact) { + await this.userSelf().say(textOrContactOrFileOrUrl) + } else if (textOrContactOrFileOrUrl instanceof FileBox) { + await this.userSelf().say(textOrContactOrFileOrUrl) + } else if (textOrContactOrFileOrUrl instanceof UrlLink) { + await this.userSelf().say(textOrContactOrFileOrUrl) } else { - throw new Error('unsupported') + throw new Error('unsupported: ' + textOrContactOrFileOrUrl) } } -- GitLab