From 116c8efea03e36da57238ef463a87594d641e0e6 Mon Sep 17 00:00:00 2001 From: Huan LI Date: Sat, 9 Jun 2018 21:51:35 +0800 Subject: [PATCH] support to change user self avatar (#1298) --- src/contact.ts | 41 ++++++++++++++++-------- src/puppet-mock/puppet-mock.ts | 24 +++++++++++++- src/puppet-padchat/puppet-padchat.ts | 34 +++++++++++++++++--- src/puppet-puppeteer/puppet-puppeteer.ts | 19 ++++++++++- src/puppet-wechat4u/puppet-wechat4u.ts | 18 ++++++++++- src/puppet/puppet.spec.ts | 9 ++++-- src/puppet/puppet.ts | 9 ++++-- src/wechaty.ts | 28 +++++++++------- 8 files changed, 146 insertions(+), 36 deletions(-) diff --git a/src/contact.ts b/src/contact.ts index fb85716b..d8158974 100644 --- a/src/contact.ts +++ b/src/contact.ts @@ -604,29 +604,42 @@ export class Contact extends Accessory implements Sayable { public weixin(): null | string { return this.payload && this.payload.weixin || null } +} + +export class ContactSelf extends Contact { + constructor( + id: string, + ) { + super(id) + } + + public async avatar() : Promise + public async avatar(file: FileBox) : Promise + + public async avatar(file?: FileBox): Promise { + log.verbose('Contact', 'avatar(%s)', file ? file.name : '') + + if (!file) { + return await super.avatar() + } + + if (this.id !== this.puppet.selfId()) { + throw new Error('set avatar only available for user self') + } + + await this.puppet.contactAvatar(this.id, file) + } - /** - * - * Need a new class for manage user profile - * - */ - // TODO: public async qrcode(): Promise { log.verbose('Contact', 'qrcode()') - if (!this.self()) { + if (this.id !== this.puppet.selfId()) { throw new Error('only can get qrcode for the login userself') } - return 'url of qrcode data for this contact(self only)' + return await this.puppet.contactQrCode(this.id) } - public async setAvatar(file: FileBox): Promise { - log.verbose('Contact', 'setAvatar(%s)', file.name) - - // should not in contact class ? - // too many methods that can only use on the login-ed userself. - } } export default Contact diff --git a/src/puppet-mock/puppet-mock.ts b/src/puppet-mock/puppet-mock.ts index 937a1971..a6df100a 100644 --- a/src/puppet-mock/puppet-mock.ts +++ b/src/puppet-mock/puppet-mock.ts @@ -153,9 +153,31 @@ export class PuppetMock extends Puppet { return [] } - public async contactAvatar(contactId: string): Promise { + public async contactQrCode(contactId: string): Promise { + if (contactId !== this.selfId()) { + throw new Error('can not set avatar for others') + } + + throw new Error('not supported') + // return await this.bridge.WXqr + } + + public async contactAvatar(contactId: string) : Promise + public async contactAvatar(contactId: string, file: FileBox) : Promise + + public async contactAvatar(contactId: string, file?: FileBox): Promise { log.verbose('PuppetMock', 'contactAvatar(%s)', contactId) + /** + * 1. set + */ + if (file) { + return + } + + /** + * 2. get + */ const WECHATY_ICON_PNG = path.resolve('../../docs/images/wechaty-icon.png') return FileBox.fromFile(WECHATY_ICON_PNG) } diff --git a/src/puppet-padchat/puppet-padchat.ts b/src/puppet-padchat/puppet-padchat.ts index e6d4d024..cb581063 100644 --- a/src/puppet-padchat/puppet-padchat.ts +++ b/src/puppet-padchat/puppet-padchat.ts @@ -315,17 +315,43 @@ export class PuppetPadchat extends Puppet { return contactIdList } - public async contactAvatar(contactId: string): Promise { - log.verbose('PuppetPadchat', 'contactAvatar(%s)', contactId) + public async contactAvatar(contactId: string) : Promise + public async contactAvatar(contactId: string, file: FileBox) : Promise + public async contactAvatar(contactId: string, file?: FileBox): Promise { + log.verbose('PuppetPadchat', 'contactAvatar(%s, %s)', contactId, file ? file.name : '') + + /** + * 1. set avatar for user self + */ + if (file) { + if (contactId !== this.selfId()) { + throw new Error('can not set avatar for others') + } + await this.bridge.WXSetHeadImage(await file.toBase64()) + return + } + + /** + * 2. get avatar + */ const payload = await this.contactPayload(contactId) if (!payload.avatar) { throw new Error('no avatar') } - const file = FileBox.fromUrl(payload.avatar) - return file + const fileBox = FileBox.fromUrl(payload.avatar) + return fileBox + } + + public async contactQrCode(contactId: string): Promise { + if (contactId !== this.selfId()) { + throw new Error('can not set avatar for others') + } + + throw new Error('not supported') + // return await this.bridge.WXqr } public async contactRawPayload(contactId: string): Promise { diff --git a/src/puppet-puppeteer/puppet-puppeteer.ts b/src/puppet-puppeteer/puppet-puppeteer.ts index 62a905ae..4692c0c9 100644 --- a/src/puppet-puppeteer/puppet-puppeteer.ts +++ b/src/puppet-puppeteer/puppet-puppeteer.ts @@ -729,8 +729,16 @@ export class PuppetPuppeteer extends Puppet { } } - public async contactAvatar(contactId: string): Promise { + public async contactAvatar(contactId: string) : Promise + public async contactAvatar(contactId: string, file: FileBox) : Promise + + public async contactAvatar(contactId: string, file?: FileBox): Promise { log.verbose('PuppetPuppeteer', 'contactAvatar(%s)', contactId) + + if (file) { + throw new Error('not support') + } + const payload = await this.contactPayload(contactId) if (!payload.avatar) { throw new Error('Can not get avatar: no payload.avatar!') @@ -767,6 +775,15 @@ export class PuppetPuppeteer extends Puppet { } } + public async contactQrCode(contactId: string): Promise { + if (contactId !== this.selfId()) { + throw new Error('can not set avatar for others') + } + + throw new Error('not supported') + // return await this.bridge.WXqr + } + public contactAlias(contactId: string) : Promise public contactAlias(contactId: string, alias: string | null): Promise diff --git a/src/puppet-wechat4u/puppet-wechat4u.ts b/src/puppet-wechat4u/puppet-wechat4u.ts index e0262861..d7c7c360 100644 --- a/src/puppet-wechat4u/puppet-wechat4u.ts +++ b/src/puppet-wechat4u/puppet-wechat4u.ts @@ -316,9 +316,25 @@ export class PuppetWechat4u extends Puppet { return idList } - public async contactAvatar(contactId: string): Promise { + public async contactQrCode(contactId: string): Promise { + if (contactId !== this.selfId()) { + throw new Error('can not set avatar for others') + } + + throw new Error('not supported') + // return await this.bridge.WXqr + } + + public async contactAvatar(contactId: string) : Promise + public async contactAvatar(contactId: string, file: FileBox) : Promise + + public async contactAvatar(contactId: string, file?: FileBox): Promise { log.verbose('PuppetWechat4u', 'contactAvatar(%s)', contactId) + if (file) { + throw new Error('not supported') + } + const rawPayload = await this.contactRawPayload(contactId) const res = await this.wechat4u.getHeadImg(rawPayload.HeadImgUrl) diff --git a/src/puppet/puppet.spec.ts b/src/puppet/puppet.spec.ts index d5996985..90215033 100755 --- a/src/puppet/puppet.spec.ts +++ b/src/puppet/puppet.spec.ts @@ -52,8 +52,13 @@ class PuppetTest extends Puppet { public async contactAlias(contactId: string) : Promise public async contactAlias(contactId: string, alias: string | null) : Promise public async contactAlias(contactId: string, alias?: string|null) : Promise { return {contactId, alias} as any } - public async contactAvatar(contactId: string) : Promise { return {contactId} as any } - public async contactList() : Promise { return {} as any } + + public async contactAvatar(contactId: string) : Promise + public async contactAvatar(contactId: string, file: FileBox) : Promise + public async contactAvatar(contactId: string, file?: FileBox) : Promise { return {contactId, file} as any } + + public async contactList() : Promise { return {} as any } + public async contactQrCode(contactId: string) : Promise { return {contactId} as any } public async contactRawPayload(id: string) : Promise { return {id} as any } public async contactRawPayloadParser(rawPayload: any) : Promise { return {rawPayload} as any } diff --git a/src/puppet/puppet.ts b/src/puppet/puppet.ts index 383ce28c..da22cbc9 100644 --- a/src/puppet/puppet.ts +++ b/src/puppet/puppet.ts @@ -355,8 +355,13 @@ export abstract class Puppet extends EventEmitter implements Sayable { public abstract async contactAlias(contactId: string) : Promise public abstract async contactAlias(contactId: string, alias: string | null) : Promise // public abstract async contactAlias(contactId: string, alias?: string|null) : Promise - public abstract async contactAvatar(contactId: string) : Promise - public abstract async contactList() : Promise + + public abstract async contactAvatar(contactId: string) : Promise + public abstract async contactAvatar(contactId: string, file: FileBox) : Promise + + public abstract async contactList() : Promise + + public abstract async contactQrCode(contactId: string) : Promise public abstract async contactRawPayload(contactId: string) : Promise public abstract async contactRawPayloadParser(rawPayload: any) : Promise diff --git a/src/wechaty.ts b/src/wechaty.ts index b39c4fae..80d6b7ce 100644 --- a/src/wechaty.ts +++ b/src/wechaty.ts @@ -59,6 +59,7 @@ import { import { Contact, + ContactSelf, } from './contact' import { FriendRequest, @@ -137,6 +138,8 @@ export class Wechaty extends Accessory implements Sayable { // tslint:disable-next-line:variable-name public readonly Contact : typeof Contact // tslint:disable-next-line:variable-name + public readonly ContactSelf : typeof ContactSelf + // tslint:disable-next-line:variable-name public readonly FriendRequest : typeof FriendRequest // tslint:disable-next-line:variable-name public readonly Message : typeof Message @@ -193,6 +196,7 @@ export class Wechaty extends Accessory implements Sayable { */ // TODO: make Message & Room constructor private??? this.Contact = cloneClass(Contact) + this.ContactSelf = cloneClass(ContactSelf) this.FriendRequest = cloneClass(FriendRequest) this.Message = cloneClass(Message) this.Room = cloneClass(Room) @@ -244,8 +248,8 @@ export class Wechaty extends Accessory implements Sayable { public emit(event: 'error' , error: Error) : boolean public emit(event: 'friend' , request: FriendRequest) : boolean public emit(event: 'heartbeat' , data: any) : boolean - public emit(event: 'logout' , user: Contact) : boolean - public emit(event: 'login' , user: Contact) : boolean + public emit(event: 'logout' , user: ContactSelf) : boolean + public emit(event: 'login' , user: ContactSelf) : boolean public emit(event: 'message' , message: Message) : boolean public emit(event: 'room-join' , room: Room, inviteeList : Contact[], inviter : Contact) : boolean public emit(event: 'room-leave' , room: Room, leaverList : Contact[], remover? : Contact) : boolean @@ -267,8 +271,8 @@ export class Wechaty extends Accessory implements Sayable { public on(event: 'error' , listener: string | ((this: Wechaty, error: Error) => void)) : this public on(event: 'friend' , listener: string | ((this: Wechaty, request: FriendRequest) => void)) : this public on(event: 'heartbeat' , listener: string | ((this: Wechaty, data: any) => void)) : this - public on(event: 'logout' , listener: string | ((this: Wechaty, user: Contact) => void)) : this - public on(event: 'login' , listener: string | ((this: Wechaty, user: Contact) => void)) : this + public on(event: 'logout' , listener: string | ((this: Wechaty, user: ContactSelf) => void)) : this + public on(event: 'login' , listener: string | ((this: Wechaty, user: ContactSelf) => void)) : this public on(event: 'message' , listener: string | ((this: Wechaty, message: Message) => void)) : this public on(event: 'room-join' , listener: string | ((this: Wechaty, room: Room, inviteeList: Contact[], inviter: Contact) => void)) : this public on(event: 'room-leave' , listener: string | ((this: Wechaty, room: Room, leaverList: Contact[], remover?: Contact) => void)) : this @@ -300,8 +304,8 @@ export class Wechaty extends Accessory implements Sayable { * @desc Wechaty Class Event Function * @typedef WechatyEventFunction * @property {Function} error -(this: Wechaty, error: Error) => void callback function - * @property {Function} login -(this: Wechaty, user: Contact)=> void - * @property {Function} logout -(this: Wechaty, user: Contact) => void + * @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. @@ -335,12 +339,12 @@ export class Wechaty extends Accessory implements Sayable { * }) * * @example Event:login - * bot.on('login', (user: Contact) => { + * bot.on('login', (user: ContactSelf) => { * console.log(`user ${user} login`) * }) * * @example Event:logout - * bot.on('logout', (user: Contact) => { + * bot.on('logout', (user: ContactSelf) => { * console.log(`user ${user} logout`) * }) * @@ -562,7 +566,7 @@ export class Wechaty extends Accessory implements Sayable { case 'login': puppet.removeAllListeners('login') puppet.on('login', async contactId => { - const contact = this.Contact.load(contactId) + const contact = this.ContactSelf.load(contactId) await contact.ready() this.emit('login', contact) }) @@ -571,7 +575,7 @@ export class Wechaty extends Accessory implements Sayable { case 'logout': puppet.removeAllListeners('logout') puppet.on('logout', async contactId => { - const contact = this.Contact.load(contactId) + const contact = this.ContactSelf.load(contactId) await contact.ready() this.emit('logout', contact) }) @@ -661,6 +665,7 @@ export class Wechaty extends Accessory implements Sayable { * 1. Set Wechaty */ this.Contact.wechaty = this + this.ContactSelf.wechaty = this this.FriendRequest.wechaty = this this.Message.wechaty = this this.Room.wechaty = this @@ -669,6 +674,7 @@ export class Wechaty extends Accessory implements Sayable { * 2. Set Puppet */ this.Contact.puppet = puppet + this.ContactSelf.puppet = puppet this.FriendRequest.puppet = puppet this.Message.puppet = puppet this.Room.puppet = puppet @@ -811,7 +817,7 @@ export class Wechaty extends Accessory implements Sayable { */ public userSelf(): Contact { const userId = this.puppet.selfId() - const user = this.Contact.load(userId) + const user = this.ContactSelf.load(userId) return user } -- GitLab