@juzi/wechaty 1.0.17 → 1.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/dist/cjs/src/mods/impls.d.ts +3 -3
  2. package/dist/cjs/src/mods/impls.d.ts.map +1 -1
  3. package/dist/cjs/src/mods/impls.js +2 -1
  4. package/dist/cjs/src/mods/impls.js.map +1 -1
  5. package/dist/cjs/src/mods/users.d.ts +1 -1
  6. package/dist/cjs/src/mods/users.d.ts.map +1 -1
  7. package/dist/cjs/src/package-json.js +4 -4
  8. package/dist/cjs/src/pure-functions/update.d.ts +9 -0
  9. package/dist/cjs/src/pure-functions/update.d.ts.map +1 -0
  10. package/dist/cjs/src/pure-functions/update.js +73 -0
  11. package/dist/cjs/src/pure-functions/update.js.map +1 -0
  12. package/dist/cjs/src/schemas/contact-events.d.ts +4 -1
  13. package/dist/cjs/src/schemas/contact-events.d.ts.map +1 -1
  14. package/dist/cjs/src/schemas/contact-events.js.map +1 -1
  15. package/dist/cjs/src/schemas/room-events.d.ts +5 -1
  16. package/dist/cjs/src/schemas/room-events.d.ts.map +1 -1
  17. package/dist/cjs/src/schemas/room-events.js +1 -0
  18. package/dist/cjs/src/schemas/room-events.js.map +1 -1
  19. package/dist/cjs/src/schemas/update.d.ts +12 -0
  20. package/dist/cjs/src/schemas/update.d.ts.map +1 -0
  21. package/dist/cjs/src/schemas/update.js +3 -0
  22. package/dist/cjs/src/schemas/update.js.map +1 -0
  23. package/dist/cjs/src/schemas/wechaty-events.d.ts +5 -1
  24. package/dist/cjs/src/schemas/wechaty-events.d.ts.map +1 -1
  25. package/dist/cjs/src/schemas/wechaty-events.js +1 -0
  26. package/dist/cjs/src/schemas/wechaty-events.js.map +1 -1
  27. package/dist/cjs/src/user-modules/contact.d.ts +8 -9
  28. package/dist/cjs/src/user-modules/contact.d.ts.map +1 -1
  29. package/dist/cjs/src/user-modules/contact.js +46 -33
  30. package/dist/cjs/src/user-modules/contact.js.map +1 -1
  31. package/dist/cjs/src/user-modules/mod.d.ts +4 -3
  32. package/dist/cjs/src/user-modules/mod.d.ts.map +1 -1
  33. package/dist/cjs/src/user-modules/mod.js +3 -1
  34. package/dist/cjs/src/user-modules/mod.js.map +1 -1
  35. package/dist/cjs/src/user-modules/room.d.ts +2 -2
  36. package/dist/cjs/src/user-modules/room.d.ts.map +1 -1
  37. package/dist/cjs/src/user-modules/room.js +10 -3
  38. package/dist/cjs/src/user-modules/room.js.map +1 -1
  39. package/dist/cjs/src/user-modules/tag-group.d.ts +66 -0
  40. package/dist/cjs/src/user-modules/tag-group.d.ts.map +1 -0
  41. package/dist/cjs/src/user-modules/tag-group.js +98 -0
  42. package/dist/cjs/src/user-modules/tag-group.js.map +1 -0
  43. package/dist/cjs/src/user-modules/tag.d.ts +47 -11
  44. package/dist/cjs/src/user-modules/tag.d.ts.map +1 -1
  45. package/dist/cjs/src/user-modules/tag.js +109 -27
  46. package/dist/cjs/src/user-modules/tag.js.map +1 -1
  47. package/dist/cjs/src/wechaty/wechaty-base.d.ts +22 -12
  48. package/dist/cjs/src/wechaty/wechaty-base.d.ts.map +1 -1
  49. package/dist/cjs/src/wechaty/wechaty-impl.spec.js +5 -3
  50. package/dist/cjs/src/wechaty/wechaty-impl.spec.js.map +1 -1
  51. package/dist/cjs/src/wechaty-mixins/gerror-mixin.d.ts +1 -1
  52. package/dist/cjs/src/wechaty-mixins/io-mixin.d.ts +2 -2
  53. package/dist/cjs/src/wechaty-mixins/login-mixin.d.ts +11 -5
  54. package/dist/cjs/src/wechaty-mixins/login-mixin.d.ts.map +1 -1
  55. package/dist/cjs/src/wechaty-mixins/misc-mixin.d.ts +14 -14
  56. package/dist/cjs/src/wechaty-mixins/misc-mixin.d.ts.map +1 -1
  57. package/dist/cjs/src/wechaty-mixins/plugin-mixin.d.ts +14 -6
  58. package/dist/cjs/src/wechaty-mixins/plugin-mixin.d.ts.map +1 -1
  59. package/dist/cjs/src/wechaty-mixins/puppet-mixin.d.ts +10 -24
  60. package/dist/cjs/src/wechaty-mixins/puppet-mixin.d.ts.map +1 -1
  61. package/dist/cjs/src/wechaty-mixins/puppet-mixin.js +23 -0
  62. package/dist/cjs/src/wechaty-mixins/puppet-mixin.js.map +1 -1
  63. package/dist/cjs/src/wechaty-mixins/wechatify-user-module-mixin.d.ts +5 -3
  64. package/dist/cjs/src/wechaty-mixins/wechatify-user-module-mixin.d.ts.map +1 -1
  65. package/dist/cjs/src/wechaty-mixins/wechatify-user-module-mixin.js +3 -0
  66. package/dist/cjs/src/wechaty-mixins/wechatify-user-module-mixin.js.map +1 -1
  67. package/dist/esm/src/mods/impls.d.ts +3 -3
  68. package/dist/esm/src/mods/impls.d.ts.map +1 -1
  69. package/dist/esm/src/mods/impls.js +1 -1
  70. package/dist/esm/src/mods/impls.js.map +1 -1
  71. package/dist/esm/src/mods/users.d.ts +1 -1
  72. package/dist/esm/src/mods/users.d.ts.map +1 -1
  73. package/dist/esm/src/package-json.js +4 -4
  74. package/dist/esm/src/pure-functions/update.d.ts +9 -0
  75. package/dist/esm/src/pure-functions/update.d.ts.map +1 -0
  76. package/dist/esm/src/pure-functions/update.js +69 -0
  77. package/dist/esm/src/pure-functions/update.js.map +1 -0
  78. package/dist/esm/src/schemas/contact-events.d.ts +4 -1
  79. package/dist/esm/src/schemas/contact-events.d.ts.map +1 -1
  80. package/dist/esm/src/schemas/contact-events.js.map +1 -1
  81. package/dist/esm/src/schemas/room-events.d.ts +5 -1
  82. package/dist/esm/src/schemas/room-events.d.ts.map +1 -1
  83. package/dist/esm/src/schemas/room-events.js +1 -0
  84. package/dist/esm/src/schemas/room-events.js.map +1 -1
  85. package/dist/esm/src/schemas/update.d.ts +12 -0
  86. package/dist/esm/src/schemas/update.d.ts.map +1 -0
  87. package/dist/esm/src/schemas/update.js +2 -0
  88. package/dist/esm/src/schemas/update.js.map +1 -0
  89. package/dist/esm/src/schemas/wechaty-events.d.ts +5 -1
  90. package/dist/esm/src/schemas/wechaty-events.d.ts.map +1 -1
  91. package/dist/esm/src/schemas/wechaty-events.js +1 -0
  92. package/dist/esm/src/schemas/wechaty-events.js.map +1 -1
  93. package/dist/esm/src/user-modules/contact.d.ts +8 -9
  94. package/dist/esm/src/user-modules/contact.d.ts.map +1 -1
  95. package/dist/esm/src/user-modules/contact.js +46 -33
  96. package/dist/esm/src/user-modules/contact.js.map +1 -1
  97. package/dist/esm/src/user-modules/mod.d.ts +4 -3
  98. package/dist/esm/src/user-modules/mod.d.ts.map +1 -1
  99. package/dist/esm/src/user-modules/mod.js +2 -1
  100. package/dist/esm/src/user-modules/mod.js.map +1 -1
  101. package/dist/esm/src/user-modules/room.d.ts +2 -2
  102. package/dist/esm/src/user-modules/room.d.ts.map +1 -1
  103. package/dist/esm/src/user-modules/room.js +10 -3
  104. package/dist/esm/src/user-modules/room.js.map +1 -1
  105. package/dist/esm/src/user-modules/tag-group.d.ts +66 -0
  106. package/dist/esm/src/user-modules/tag-group.d.ts.map +1 -0
  107. package/dist/esm/src/user-modules/tag-group.js +95 -0
  108. package/dist/esm/src/user-modules/tag-group.js.map +1 -0
  109. package/dist/esm/src/user-modules/tag.d.ts +47 -11
  110. package/dist/esm/src/user-modules/tag.d.ts.map +1 -1
  111. package/dist/esm/src/user-modules/tag.js +109 -27
  112. package/dist/esm/src/user-modules/tag.js.map +1 -1
  113. package/dist/esm/src/wechaty/wechaty-base.d.ts +22 -12
  114. package/dist/esm/src/wechaty/wechaty-base.d.ts.map +1 -1
  115. package/dist/esm/src/wechaty/wechaty-impl.spec.js +5 -3
  116. package/dist/esm/src/wechaty/wechaty-impl.spec.js.map +1 -1
  117. package/dist/esm/src/wechaty-mixins/gerror-mixin.d.ts +1 -1
  118. package/dist/esm/src/wechaty-mixins/io-mixin.d.ts +2 -2
  119. package/dist/esm/src/wechaty-mixins/login-mixin.d.ts +11 -5
  120. package/dist/esm/src/wechaty-mixins/login-mixin.d.ts.map +1 -1
  121. package/dist/esm/src/wechaty-mixins/misc-mixin.d.ts +14 -14
  122. package/dist/esm/src/wechaty-mixins/misc-mixin.d.ts.map +1 -1
  123. package/dist/esm/src/wechaty-mixins/plugin-mixin.d.ts +14 -6
  124. package/dist/esm/src/wechaty-mixins/plugin-mixin.d.ts.map +1 -1
  125. package/dist/esm/src/wechaty-mixins/puppet-mixin.d.ts +10 -24
  126. package/dist/esm/src/wechaty-mixins/puppet-mixin.d.ts.map +1 -1
  127. package/dist/esm/src/wechaty-mixins/puppet-mixin.js +23 -0
  128. package/dist/esm/src/wechaty-mixins/puppet-mixin.js.map +1 -1
  129. package/dist/esm/src/wechaty-mixins/wechatify-user-module-mixin.d.ts +5 -3
  130. package/dist/esm/src/wechaty-mixins/wechatify-user-module-mixin.d.ts.map +1 -1
  131. package/dist/esm/src/wechaty-mixins/wechatify-user-module-mixin.js +4 -1
  132. package/dist/esm/src/wechaty-mixins/wechatify-user-module-mixin.js.map +1 -1
  133. package/package.json +3 -3
  134. package/src/mods/impls.ts +3 -0
  135. package/src/mods/users.ts +1 -0
  136. package/src/package-json.ts +4 -4
  137. package/src/pure-functions/update.ts +68 -0
  138. package/src/schemas/contact-events.ts +4 -0
  139. package/src/schemas/room-events.ts +5 -0
  140. package/src/schemas/update.ts +14 -0
  141. package/src/schemas/wechaty-events.ts +5 -1
  142. package/src/user-modules/contact.ts +57 -35
  143. package/src/user-modules/mod.ts +8 -0
  144. package/src/user-modules/room.ts +11 -4
  145. package/src/user-modules/tag-group.ts +151 -0
  146. package/src/user-modules/tag.ts +131 -14
  147. package/src/wechaty/wechaty-impl.spec.ts +3 -0
  148. package/src/wechaty-mixins/puppet-mixin.ts +24 -0
  149. package/src/wechaty-mixins/wechatify-user-module-mixin.ts +6 -0
@@ -6,13 +6,16 @@ import type {
6
6
  FriendshipInterface,
7
7
  MessageInterface,
8
8
  } from '../user-modules/mod.js'
9
+ import type { InfoUpdateInterface } from './update.js'
9
10
 
10
11
  type ContactEventListenerMessage = (this: ContactInterface, message: MessageInterface, date?: Date) => void | Promise<void>
11
12
  type ContactEventListenerFriendship = (friendship: FriendshipInterface) => void | Promise<void>
13
+ type ContactEventListenerUpdate = (info: InfoUpdateInterface) => void | Promise<void>
12
14
 
13
15
  interface ContactEventListeners {
14
16
  friendship : ContactEventListenerFriendship,
15
17
  message : ContactEventListenerMessage,
18
+ update : ContactEventListenerUpdate,
16
19
  }
17
20
 
18
21
  const ContactEventEmitter = EventEmitter as any as new () => TypedEventEmitter<
@@ -23,6 +26,7 @@ export type {
23
26
  ContactEventListeners,
24
27
  ContactEventListenerMessage,
25
28
  ContactEventListenerFriendship,
29
+ ContactEventListenerUpdate,
26
30
  }
27
31
  export {
28
32
  ContactEventEmitter,
@@ -7,12 +7,14 @@ import type {
7
7
  RoomInterface,
8
8
  RoomInvitationInterface,
9
9
  } from '../user-modules/mod.js'
10
+ import type { InfoUpdateInterface } from './update.js'
10
11
 
11
12
  export const ROOM_EVENT_DICT = {
12
13
  invite : 'tbw',
13
14
  join : 'tbw',
14
15
  leave : 'tbw',
15
16
  message : 'message that received in this room',
17
+ update : 'room info update',
16
18
  topic : 'tbw',
17
19
  }
18
20
  export type RoomEventName = keyof typeof ROOM_EVENT_DICT
@@ -102,6 +104,7 @@ type RoomEventListenerJoin = (this: RoomInterface, inviteeList: ContactInterf
102
104
  type RoomEventListenerLeave = (this: RoomInterface, leaverList: ContactInterface[], remover?: ContactInterface, date?: Date) => void | Promise<void>
103
105
  type RoomEventListenerMessage = (this: RoomInterface, message: MessageInterface, date?: Date) => void | Promise<void>
104
106
  type RoomEventListenerTopic = (this: RoomInterface, topic: string, oldTopic: string, changer: ContactInterface, date?: Date) => void | Promise<void>
107
+ type RoomEventListenerUpdate = (info: InfoUpdateInterface) => void | Promise<void>
105
108
 
106
109
  interface RoomEventListeners {
107
110
  invite : RoomEventListenerInvite
@@ -109,6 +112,7 @@ interface RoomEventListeners {
109
112
  leave : RoomEventListenerLeave
110
113
  message : RoomEventListenerMessage
111
114
  topic : RoomEventListenerTopic
115
+ update : RoomEventListenerUpdate
112
116
  }
113
117
 
114
118
  const RoomEventEmitter = EventEmitter as any as new () => TypedEventEmitter<
@@ -122,6 +126,7 @@ export type {
122
126
  RoomEventListenerLeave,
123
127
  RoomEventListenerMessage,
124
128
  RoomEventListenerTopic,
129
+ RoomEventListenerUpdate,
125
130
  }
126
131
  export {
127
132
  RoomEventEmitter,
@@ -0,0 +1,14 @@
1
+ /* eslint-disable valid-typeof */
2
+ import type * as PUPPET from '@juzi/wechaty-puppet'
3
+
4
+ export interface InfoUpdateInterface {
5
+ type: PUPPET.types.Payload,
6
+ id: string,
7
+ updates: InfoUpdateValuePair[],
8
+ }
9
+
10
+ export interface InfoUpdateValuePair {
11
+ key: string,
12
+ oldValue: string,
13
+ newValue: string
14
+ }
@@ -13,6 +13,7 @@ import type {
13
13
  MessageInterface,
14
14
  PostInterface,
15
15
  } from '../user-modules/mod.js'
16
+ import type { InfoUpdateInterface } from './update.js'
16
17
 
17
18
  const WECHATY_EVENT_DICT = {
18
19
  ...PUPPET.types.CHAT_EVENT_DICT,
@@ -23,6 +24,7 @@ const WECHATY_EVENT_DICT = {
23
24
  ready : 'All underlined data source are ready for use.',
24
25
  start : 'Will be emitted after the Wechaty had been started.',
25
26
  stop : 'Will be emitted after the Wechaty had been stopped.',
27
+ update : 'Will be emitted when some info has been changed.',
26
28
  } as const
27
29
 
28
30
  type WechatyEventName = keyof typeof WECHATY_EVENT_DICT
@@ -46,7 +48,7 @@ type WechatyEventListenerRoomLeave = (room: RoomInterface, leaverList: ContactI
46
48
  type WechatyEventListenerRoomTopic = (room: RoomInterface, newTopic: string, oldTopic: string, changer: ContactInterface, date?: Date) => void | Promise<void>
47
49
  type WechatyEventListenerScan = (qrcode: string, status: PUPPET.types.ScanStatus, data?: string) => void | Promise<void>
48
50
  type WechatyEventListenerStartStop = () => void | Promise<void>
49
-
51
+ type WechatyEventListenerUpdate = (info: InfoUpdateInterface) => void | Promise<void>
50
52
  /**
51
53
  * @desc Wechaty Class Event Type
52
54
  * @typedef WechatyEventName
@@ -219,6 +221,7 @@ interface WechatyEventListeners {
219
221
  scan : WechatyEventListenerScan
220
222
  start : WechatyEventListenerStartStop
221
223
  stop : WechatyEventListenerStartStop
224
+ update : WechatyEventListenerUpdate
222
225
  }
223
226
 
224
227
  const WechatyEventEmitter = EventEmitter as any as new () => TypedEventEmitter<
@@ -245,6 +248,7 @@ export type {
245
248
  WechatyEventListenerRoomTopic,
246
249
  WechatyEventListenerScan,
247
250
  WechatyEventListenerStartStop,
251
+ WechatyEventListenerUpdate,
248
252
  }
249
253
  export {
250
254
  WechatyEventEmitter,
@@ -207,30 +207,6 @@ class ContactMixin extends MixinBase implements SayableSayer {
207
207
  log.verbose('Contact', 'static delete(%s)', contact.id)
208
208
  }
209
209
 
210
- /**
211
- * Get tags for all contact
212
- *
213
- * @static
214
- * @returns {Promise<TagInterface[]>}
215
- * @example
216
- * const tags = await wechaty.Contact.tags()
217
- */
218
- static async tags (): Promise<TagInterface[]> {
219
- log.verbose('Contact', 'static tags() for %s', this)
220
-
221
- // TODO implement new tag methods
222
- // try {
223
- // const tagIdList = await this.wechaty.puppet.tagContactList()
224
- // const tagList = tagIdList.map(id => this.wechaty.Tag.load(id))
225
- // return tagList
226
- // } catch (e) {
227
- // this.wechaty.emitError(e)
228
- // log.error('Contact', 'static tags() exception: %s', (e as Error).message)
229
- // return []
230
- // }
231
- return []
232
- }
233
-
234
210
  /**
235
211
  *
236
212
  * Instance properties
@@ -674,17 +650,63 @@ class ContactMixin extends MixinBase implements SayableSayer {
674
650
  async tags (): Promise<TagInterface[]> {
675
651
  log.verbose('Contact', 'tags() for %s', this)
676
652
 
677
- // TODO: implement new tag methods
678
- // try {
679
- // const tagIdList = await this.wechaty.puppet.tagContactList(this.id)
680
- // const tagList = tagIdList.map(id => this.wechaty.Tag.load(id))
681
- // return tagList
682
- // } catch (e) {
683
- // this.wechaty.emitError(e)
684
- // log.error('Contact', 'tags() exception: %s', (e as Error).message)
685
- // return []
686
- // }
687
- return []
653
+ try {
654
+ const tagPayloadList = await this.wechaty.puppet.tagContactTagList(this.id)
655
+
656
+ let tagList = tagPayloadList.map(tag => this.wechaty.Tag.load(tag))
657
+ if (tagList.some(tag => typeof tag === 'undefined')) {
658
+ await this.wechaty.Tag.sync()
659
+ tagList = tagPayloadList.map(tag => this.wechaty.Tag.load(tag))
660
+ }
661
+ return tagList.filter(tag => !!tag) as TagInterface[]
662
+ } catch (e) {
663
+ this.wechaty.emitError(e)
664
+ log.error('Contact', 'tags() exception: %s', (e as Error).message)
665
+ return []
666
+ }
667
+ }
668
+
669
+ /**
670
+ * Add a Tag
671
+ */
672
+
673
+ async tag (tags: TagInterface | TagInterface[]): Promise<void> {
674
+ log.verbose('Contact', 'tag(%s) for %s', JSON.stringify(tags), this)
675
+
676
+ if (!Array.isArray(tags)) {
677
+ tags = [tags]
678
+ }
679
+
680
+ const tagIdentifiers = tags.map(tag => {
681
+ return {
682
+ id: tag.id(),
683
+ groupId: tag.groupId(),
684
+ }
685
+ })
686
+ await this.wechaty.puppet.tagContactTagAdd(tagIdentifiers, [this.id])
687
+
688
+ }
689
+
690
+ /**
691
+ * Remove a Tag
692
+ */
693
+
694
+ async tagRemove (tags: TagInterface | TagInterface[]): Promise<void> {
695
+ log.verbose('Contact', 'tagRemove(%s) for %s', JSON.stringify(tags), this)
696
+
697
+ if (!Array.isArray(tags)) {
698
+ tags = [tags]
699
+ }
700
+
701
+ const tagIdentifiers = tags.map(tag => {
702
+ return {
703
+ id: tag.id(),
704
+ groupId: tag.groupId(),
705
+ }
706
+ })
707
+
708
+ await this.wechaty.puppet.tagContactTagRemove(tagIdentifiers, [this.id])
709
+
688
710
  }
689
711
 
690
712
  /**
@@ -87,6 +87,11 @@ import {
87
87
  TagInterface,
88
88
  TagConstructor,
89
89
  } from './tag.js'
90
+ import {
91
+ TagGroupImpl,
92
+ TagGroupInterface,
93
+ TagGroupConstructor,
94
+ } from './tag-group.js'
90
95
  import {
91
96
  UrlLinkImpl,
92
97
  UrlLinkInterface,
@@ -120,6 +125,7 @@ export type {
120
125
  RoomInterface,
121
126
  RoomInvitationInterface,
122
127
  TagInterface,
128
+ TagGroupInterface,
123
129
  DelayInterface,
124
130
  UrlLinkInterface,
125
131
  ChannelInterface,
@@ -141,6 +147,7 @@ export type {
141
147
  RoomInvitationConstructor,
142
148
  DelayConstructor,
143
149
  TagConstructor,
150
+ TagGroupConstructor,
144
151
  UrlLinkConstructor,
145
152
  ChannelConstructor,
146
153
  }
@@ -163,6 +170,7 @@ export {
163
170
  RoomInvitationImpl,
164
171
  DelayImpl,
165
172
  TagImpl,
173
+ TagGroupImpl,
166
174
  UrlLinkImpl,
167
175
  ChannelImpl,
168
176
  }
@@ -728,9 +728,16 @@ class RoomMixin extends MixinBase implements SayableSayer {
728
728
  * }
729
729
  * }
730
730
  */
731
- async remove (contact: ContactInterface): Promise<void> {
732
- log.verbose('Room', 'del(%s)', contact)
733
- await this.wechaty.puppet.roomDel(this.id, contact.id)
731
+ async remove (contacts: ContactInterface | ContactInterface[]): Promise<void> {
732
+ log.verbose('Room', 'del(%s)', contacts)
733
+
734
+ let contactIds: string[]
735
+ if (Array.isArray(contacts)) {
736
+ contactIds = contacts.map(c => c.id)
737
+ } else {
738
+ contactIds = [contacts.id]
739
+ }
740
+ await this.wechaty.puppet.roomDel(this.id, contactIds)
734
741
  // this.delLocal(contact)
735
742
  }
736
743
 
@@ -738,7 +745,7 @@ class RoomMixin extends MixinBase implements SayableSayer {
738
745
  * Huan(202106): will be removed after Dec 31, 2023
739
746
  * @deprecated use remove(contact) instead.
740
747
  */
741
- async del (contact: ContactImpl): Promise<void> {
748
+ async del (contact: ContactImpl | ContactImpl[]): Promise<void> {
742
749
  log.warn('Room', 'del() is DEPRECATED, use remove() instead.\n%s', new Error().stack)
743
750
  return this.remove(contact)
744
751
  }
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty
3
+ *
4
+ * @copyright 2016 Huan LI (李卓桓) <https://github.com/huan>, and
5
+ * Wechaty Contributors <https://github.com/wechaty>.
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agGroupreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific languagGroupe governing permissions and
17
+ * limitations under the License.
18
+ *
19
+ */
20
+ import type * as PUPPET from '@juzi/wechaty-puppet'
21
+
22
+ import type { Constructor } from 'clone-class'
23
+ import { log } from '../config.js'
24
+
25
+ import { validationMixin } from '../user-mixins/validation.js'
26
+ import {
27
+ wechatifyMixinBase,
28
+ } from '../user-mixins/wechatify.js'
29
+ import type { TagInterface } from './tag.js'
30
+
31
+ class TagGroupMixin extends wechatifyMixinBase() {
32
+
33
+ /**
34
+ *
35
+ * Create
36
+ *
37
+ */
38
+ static create (payload: PUPPET.payloads.TagGroup): TagGroupInterface {
39
+ log.verbose('TagGroup', 'create()')
40
+
41
+ return new this(payload)
42
+ }
43
+
44
+ /**
45
+ * @hideconstructor
46
+ */
47
+ constructor (
48
+ public readonly payload: PUPPET.payloads.TagGroup,
49
+ ) {
50
+ super()
51
+ log.silly('TagGroup', 'constructor()')
52
+ }
53
+
54
+ id (): string {
55
+ return this.payload.id
56
+ }
57
+
58
+ name (): string {
59
+ return this.payload.name
60
+ }
61
+
62
+ private static pool: TagGroupInterface[] = []
63
+
64
+ static async list (forceSync = false): Promise<TagGroupInterface[]> {
65
+ log.verbose('TagGroup', 'list(%s)', forceSync)
66
+
67
+ if (this.pool.length > 0 && !forceSync) {
68
+ return this.pool
69
+ }
70
+
71
+ try {
72
+ const payloads = await this.wechaty.puppet.tagGroupList()
73
+ this.pool = payloads.map(payload => new this(payload))
74
+ return this.pool
75
+ } catch (e) {
76
+ this.wechaty.emitError(e)
77
+ log.error('TagGroup', 'list() exception: %s', (e as Error).message)
78
+ return []
79
+ }
80
+ }
81
+
82
+ static async sync (): Promise<void> {
83
+ log.verbose('TagGroup', 'sync()')
84
+
85
+ await this.list(true)
86
+ }
87
+
88
+ static load (tagGroupId: string): TagGroupInterface | undefined {
89
+ log.verbose('TagGroup', 'load(%s)', tagGroupId)
90
+
91
+ for (const item of this.pool) {
92
+ if (item.id() === tagGroupId) {
93
+ return item
94
+ }
95
+ }
96
+ return undefined
97
+ }
98
+
99
+ static async createTagGroup (name: string): Promise<TagGroupInterface | void> {
100
+ log.verbose('TagGroup', 'createTagGroup(%s, %s)', name)
101
+
102
+ try {
103
+ const payload = await this.wechaty.puppet.tagGroupAdd(name)
104
+ if (payload) {
105
+ const newTagGroup = new this(payload)
106
+ this.pool.push(newTagGroup)
107
+ return newTagGroup
108
+ }
109
+ } catch (e) {
110
+ this.wechaty.emitError(e)
111
+ log.error('Contact', 'createTag() exception: %s', (e as Error).message)
112
+ }
113
+ }
114
+
115
+ static async deleteTagGroup (tagGroup: TagGroupInterface): Promise<TagGroupInterface | void> {
116
+ log.verbose('TagGroup', 'deleteTagGroup(%s)', tagGroup)
117
+
118
+ try {
119
+ await this.wechaty.puppet.tagGroupDelete(tagGroup.id())
120
+ this.pool.splice(this.pool.indexOf(tagGroup), 1)
121
+ } catch (e) {
122
+ this.wechaty.emitError(e)
123
+ log.error('TagGroup', 'deleteTagGroup() exception: %s', (e as Error).message)
124
+ }
125
+ }
126
+
127
+ async tags (): Promise<TagInterface[]> {
128
+ return (await this.wechaty.Tag.list()).filter(tag => tag.groupId() === this.id())
129
+ }
130
+
131
+ override toString () {
132
+ return `<TagGroup#${this.name() || this.id()}>`
133
+ }
134
+
135
+ }
136
+
137
+ class TagGroupImpl extends validationMixin(TagGroupMixin)<TagGroupInterface>() { }
138
+ interface TagGroupInterface extends TagGroupImpl { }
139
+
140
+ type TagGroupConstructor = Constructor<
141
+ TagGroupInterface,
142
+ typeof TagGroupImpl
143
+ >
144
+
145
+ export type {
146
+ TagGroupConstructor,
147
+ TagGroupInterface,
148
+ }
149
+ export {
150
+ TagGroupImpl,
151
+ }
@@ -17,37 +17,154 @@
17
17
  * limitations under the License.
18
18
  *
19
19
  */
20
- import {
21
- log,
22
- } from '@juzi/wechaty-puppet'
20
+ import type * as PUPPET from '@juzi/wechaty-puppet'
21
+ import type { TagIdentifier } from '@juzi/wechaty-puppet/filters'
23
22
 
24
- import type { Constructor } from 'clone-class'
23
+ import type { Constructor } from 'clone-class'
24
+ import { log } from '../config.js'
25
25
 
26
- import {
27
- poolifyMixin,
28
- } from '../user-mixins/poolify.js'
29
26
  import { validationMixin } from '../user-mixins/validation.js'
30
27
  import {
31
28
  wechatifyMixinBase,
32
29
  } from '../user-mixins/wechatify.js'
30
+ import type { ContactInterface } from './contact.js'
31
+ import type { TagGroupInterface } from './tag-group.js'
32
+
33
+ class TagMixin extends wechatifyMixinBase() {
33
34
 
34
- const MixinBase = poolifyMixin(
35
- wechatifyMixinBase(),
36
- )<TagInterface>()
35
+ /**
36
+ *
37
+ * Create
38
+ *
39
+ */
40
+ static create (payload: PUPPET.payloads.Tag): TagInterface {
41
+ log.verbose('Tag', 'create()')
37
42
 
38
- class TagMixin extends MixinBase {
43
+ return new this(payload)
44
+ }
39
45
 
40
46
  /**
41
47
  * @hideconstructor
42
48
  */
43
49
  constructor (
44
- public readonly id: string,
50
+ public readonly payload: PUPPET.payloads.Tag,
45
51
  ) {
46
52
  super()
47
- log.silly('Tag', `constructor(${id})`)
53
+ log.silly('Tag', 'constructor()')
54
+ }
55
+
56
+ id (): string {
57
+ return this.payload.id
58
+ }
59
+
60
+ type (): PUPPET.types.Tag {
61
+ return this.payload.type
62
+ }
63
+
64
+ groupId (): string {
65
+ return this.payload.groupId || ''
66
+ }
67
+
68
+ name (): string {
69
+ return this.payload.name
70
+ }
71
+
72
+ group (): TagGroupInterface | undefined {
73
+ return this.wechaty.TagGroup.load(this.groupId())
74
+ }
75
+
76
+ private static pool: TagInterface[] = []
77
+
78
+ static async list (forceSync = false): Promise<TagInterface[]> {
79
+ log.verbose('Tag', 'list(%s)', forceSync)
80
+
81
+ if (this.pool.length > 0 && !forceSync) {
82
+ return this.pool
83
+ }
84
+
85
+ try {
86
+ const payloads = await this.wechaty.puppet.tagTagList()
87
+ this.pool = payloads.map(payload => new this(payload))
88
+ return this.pool
89
+ } catch (e) {
90
+ this.wechaty.emitError(e)
91
+ log.error('Tag', 'list() exception: %s', (e as Error).message)
92
+ return []
93
+ }
48
94
  }
49
95
 
50
- // TODO: implement new tag methods
96
+ static async sync (): Promise<void> {
97
+ log.verbose('Tag', 'sync()')
98
+
99
+ await this.list(true)
100
+ }
101
+
102
+ static load (tag: TagIdentifier): TagInterface | undefined {
103
+ log.verbose('TagGroup', 'load(%s)', tag)
104
+
105
+ for (const item of this.pool) {
106
+ if (item.id() === tag.id && (item.groupId() === tag.groupId || (!item.groupId() && !tag.groupId))) {
107
+ return item
108
+ }
109
+ }
110
+ return undefined
111
+ }
112
+
113
+ async contactList (): Promise<ContactInterface[]> {
114
+ log.verbose('Tag', 'contactList() for tag : %s', this)
115
+
116
+ const tag = { id: this.id(), groupId: this.groupId() } as TagIdentifier
117
+ const contactIds = await this.wechaty.puppet.tagTagContactList(tag)
118
+ const contactPromises = contactIds.map(id => this.wechaty.Contact.find({ id })) as Promise<ContactInterface>[]
119
+ return Promise.all(contactPromises)
120
+ }
121
+
122
+ async tag (contacts: ContactInterface | ContactInterface[]): Promise<void> {
123
+ log.verbose('Tag', 'tag(%s) for tag : %s', contacts, this)
124
+
125
+ const tag = { id: this.id(), groupId: this.groupId() } as TagIdentifier
126
+ let contactIds: string[]
127
+ if (Array.isArray(contacts)) {
128
+ contactIds = contacts.map(c => c.id)
129
+ } else {
130
+ contactIds = [contacts.id]
131
+ }
132
+ await this.wechaty.puppet.tagContactTagAdd([tag], contactIds)
133
+ }
134
+
135
+ static async createTag (name: string, tagGroup?: TagGroupInterface): Promise<TagInterface | void> {
136
+ log.verbose('Tag', 'createTag(%s, %s)', tagGroup, name)
137
+
138
+ try {
139
+ const payload = await this.wechaty.puppet.tagTagAdd(name, tagGroup?.name())
140
+ if (payload) {
141
+ const newTag = new this(payload)
142
+ this.pool.push(newTag)
143
+ return newTag
144
+ }
145
+ } catch (e) {
146
+ this.wechaty.emitError(e)
147
+ log.error('Contact', 'createTag() exception: %s', (e as Error).message)
148
+ }
149
+ }
150
+
151
+ static async deleteTag (tagInstance: TagInterface): Promise<void> {
152
+ log.verbose('Tag', 'deleteTag(%s, %s)', tagInstance)
153
+
154
+ const tag = { id: tagInstance.id(), groupId: tagInstance.groupId() } as TagIdentifier
155
+
156
+ try {
157
+ await this.wechaty.puppet.tagTagDelete(tag)
158
+ this.pool.splice(this.pool.indexOf(tagInstance), 1)
159
+ } catch (e) {
160
+ this.wechaty.emitError(e)
161
+ log.error('Tag', 'deleteTag() exception: %s', (e as Error).message)
162
+ }
163
+ }
164
+
165
+ override toString () {
166
+ return `<Tag#${this.name() || this.id()}>`
167
+ }
51
168
 
52
169
  }
53
170
 
@@ -17,6 +17,7 @@ import type {
17
17
  RoomConstructor,
18
18
  DelayConstructor,
19
19
  TagConstructor,
20
+ TagGroupConstructor,
20
21
  UrlLinkConstructor,
21
22
  MessageInterface,
22
23
  ChannelConstructor,
@@ -45,6 +46,7 @@ test('Wechaty interface', async t => {
45
46
  Room : RoomConstructor
46
47
  RoomInvitation : RoomInvitationConstructor
47
48
  Tag : TagConstructor
49
+ TagGroup : TagGroupConstructor
48
50
  UrlLink : UrlLinkConstructor
49
51
  Channel : ChannelConstructor
50
52
 
@@ -63,6 +65,7 @@ test('Wechaty interface', async t => {
63
65
  = this.Room
64
66
  = this.RoomInvitation
65
67
  = this.Tag
68
+ = this.TagGroup
66
69
  = this.UrlLink
67
70
  = this.Channel
68
71
  = {} as any
@@ -25,6 +25,8 @@ import type {
25
25
 
26
26
  import type { GErrorMixin } from './gerror-mixin.js'
27
27
  import type { IoMixin } from './io-mixin.js'
28
+ import type { InfoUpdateInterface } from '../schemas/update.js'
29
+ import { diffPayload } from '../pure-functions/update.js'
28
30
 
29
31
  const PUPPET_MEMORY_NAME = 'puppet'
30
32
 
@@ -438,12 +440,34 @@ const puppetMixin = <MixinBase extends WechatifyUserModuleMixin & GErrorMixin &
438
440
  switch (payloadType) {
439
441
  case PUPPET.types.Payload.Contact: {
440
442
  const contact = await this.Contact.find({ id: payloadId }) as unknown as undefined | ContactImpl
443
+ const oldPayload = JSON.parse(JSON.stringify(contact?.payload || {}))
441
444
  await contact?.ready(true)
445
+ const newPayload = JSON.parse(JSON.stringify(contact?.payload || {}))
446
+ const updateEvent: InfoUpdateInterface = {
447
+ type: payloadType,
448
+ id: payloadId,
449
+ updates: diffPayload(oldPayload, newPayload),
450
+ }
451
+ if (updateEvent.updates.length > 0) {
452
+ this.emit('update', updateEvent)
453
+ contact?.emit('update', updateEvent)
454
+ }
442
455
  break
443
456
  }
444
457
  case PUPPET.types.Payload.Room: {
445
458
  const room = await this.Room.find({ id: payloadId }) as unknown as undefined | RoomImpl
459
+ const oldPayload = JSON.parse(JSON.stringify(room?.payload || {}))
446
460
  await room?.ready(true)
461
+ const newPayload = JSON.parse(JSON.stringify(room?.payload || {}))
462
+ const updateEvent: InfoUpdateInterface = {
463
+ type: payloadType,
464
+ id: payloadId,
465
+ updates: diffPayload(oldPayload, newPayload),
466
+ }
467
+ if (updateEvent.updates.length > 0) {
468
+ this.emit('update', updateEvent)
469
+ room?.emit('update', updateEvent)
470
+ }
447
471
  break
448
472
  }
449
473
  case PUPPET.types.Payload.RoomMember: {