@juzi/wechaty 1.0.162 → 1.0.164

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 (132) hide show
  1. package/dist/cjs/src/io.spec.js +4 -1
  2. package/dist/cjs/src/io.spec.js.map +1 -1
  3. package/dist/cjs/src/mods/impls.d.ts +3 -3
  4. package/dist/cjs/src/mods/impls.d.ts.map +1 -1
  5. package/dist/cjs/src/mods/impls.js +2 -1
  6. package/dist/cjs/src/mods/impls.js.map +1 -1
  7. package/dist/cjs/src/mods/users.d.ts +1 -1
  8. package/dist/cjs/src/mods/users.d.ts.map +1 -1
  9. package/dist/cjs/src/package-json.d.ts.map +1 -1
  10. package/dist/cjs/src/package-json.js +4 -3
  11. package/dist/cjs/src/package-json.js.map +1 -1
  12. package/dist/cjs/src/sayable/deliver-sayable.d.ts.map +1 -1
  13. package/dist/cjs/src/sayable/deliver-sayable.js +6 -0
  14. package/dist/cjs/src/sayable/deliver-sayable.js.map +1 -1
  15. package/dist/cjs/src/sayable/message-to-sayable.d.ts.map +1 -1
  16. package/dist/cjs/src/sayable/message-to-sayable.js +2 -0
  17. package/dist/cjs/src/sayable/message-to-sayable.js.map +1 -1
  18. package/dist/cjs/src/sayable/payload-to-sayable.d.ts.map +1 -1
  19. package/dist/cjs/src/sayable/payload-to-sayable.js +2 -0
  20. package/dist/cjs/src/sayable/payload-to-sayable.js.map +1 -1
  21. package/dist/cjs/src/sayable/sayable-to-payload.d.ts.map +1 -1
  22. package/dist/cjs/src/sayable/sayable-to-payload.js +3 -0
  23. package/dist/cjs/src/sayable/sayable-to-payload.js.map +1 -1
  24. package/dist/cjs/src/sayable/types.d.ts +2 -2
  25. package/dist/cjs/src/sayable/types.d.ts.map +1 -1
  26. package/dist/cjs/src/sayable/types.js.map +1 -1
  27. package/dist/cjs/src/user-modules/email.d.ts +72 -0
  28. package/dist/cjs/src/user-modules/email.d.ts.map +1 -0
  29. package/dist/cjs/src/user-modules/email.js +77 -0
  30. package/dist/cjs/src/user-modules/email.js.map +1 -0
  31. package/dist/cjs/src/user-modules/email.spec.d.ts +3 -0
  32. package/dist/cjs/src/user-modules/email.spec.d.ts.map +1 -0
  33. package/dist/cjs/src/user-modules/email.spec.js +73 -0
  34. package/dist/cjs/src/user-modules/email.spec.js.map +1 -0
  35. package/dist/cjs/src/user-modules/message.d.ts +4 -1
  36. package/dist/cjs/src/user-modules/message.d.ts.map +1 -1
  37. package/dist/cjs/src/user-modules/message.js +15 -3
  38. package/dist/cjs/src/user-modules/message.js.map +1 -1
  39. package/dist/cjs/src/user-modules/mod.d.ts +4 -3
  40. package/dist/cjs/src/user-modules/mod.d.ts.map +1 -1
  41. package/dist/cjs/src/user-modules/mod.js +3 -1
  42. package/dist/cjs/src/user-modules/mod.js.map +1 -1
  43. package/dist/cjs/src/wechaty/wechaty-base.d.ts +10 -0
  44. package/dist/cjs/src/wechaty/wechaty-base.d.ts.map +1 -1
  45. package/dist/cjs/src/wechaty/wechaty-impl.spec.js +16 -14
  46. package/dist/cjs/src/wechaty/wechaty-impl.spec.js.map +1 -1
  47. package/dist/cjs/src/wechaty-mixins/login-mixin.d.ts +18 -3
  48. package/dist/cjs/src/wechaty-mixins/login-mixin.d.ts.map +1 -1
  49. package/dist/cjs/src/wechaty-mixins/misc-mixin.d.ts +6 -0
  50. package/dist/cjs/src/wechaty-mixins/misc-mixin.d.ts.map +1 -1
  51. package/dist/cjs/src/wechaty-mixins/plugin-mixin.d.ts +8 -0
  52. package/dist/cjs/src/wechaty-mixins/plugin-mixin.d.ts.map +1 -1
  53. package/dist/cjs/src/wechaty-mixins/puppet-mixin.d.ts +4 -0
  54. package/dist/cjs/src/wechaty-mixins/puppet-mixin.d.ts.map +1 -1
  55. package/dist/cjs/src/wechaty-mixins/wechatify-user-module-mixin.d.ts +4 -2
  56. package/dist/cjs/src/wechaty-mixins/wechatify-user-module-mixin.d.ts.map +1 -1
  57. package/dist/cjs/src/wechaty-mixins/wechatify-user-module-mixin.js +3 -0
  58. package/dist/cjs/src/wechaty-mixins/wechatify-user-module-mixin.js.map +1 -1
  59. package/dist/esm/src/io.spec.js +4 -1
  60. package/dist/esm/src/io.spec.js.map +1 -1
  61. package/dist/esm/src/mods/impls.d.ts +3 -3
  62. package/dist/esm/src/mods/impls.d.ts.map +1 -1
  63. package/dist/esm/src/mods/impls.js +1 -1
  64. package/dist/esm/src/mods/impls.js.map +1 -1
  65. package/dist/esm/src/mods/users.d.ts +1 -1
  66. package/dist/esm/src/mods/users.d.ts.map +1 -1
  67. package/dist/esm/src/package-json.d.ts.map +1 -1
  68. package/dist/esm/src/package-json.js +4 -3
  69. package/dist/esm/src/package-json.js.map +1 -1
  70. package/dist/esm/src/sayable/deliver-sayable.d.ts.map +1 -1
  71. package/dist/esm/src/sayable/deliver-sayable.js +7 -1
  72. package/dist/esm/src/sayable/deliver-sayable.js.map +1 -1
  73. package/dist/esm/src/sayable/message-to-sayable.d.ts.map +1 -1
  74. package/dist/esm/src/sayable/message-to-sayable.js +2 -0
  75. package/dist/esm/src/sayable/message-to-sayable.js.map +1 -1
  76. package/dist/esm/src/sayable/payload-to-sayable.d.ts.map +1 -1
  77. package/dist/esm/src/sayable/payload-to-sayable.js +2 -0
  78. package/dist/esm/src/sayable/payload-to-sayable.js.map +1 -1
  79. package/dist/esm/src/sayable/sayable-to-payload.d.ts.map +1 -1
  80. package/dist/esm/src/sayable/sayable-to-payload.js +4 -1
  81. package/dist/esm/src/sayable/sayable-to-payload.js.map +1 -1
  82. package/dist/esm/src/sayable/types.d.ts +2 -2
  83. package/dist/esm/src/sayable/types.d.ts.map +1 -1
  84. package/dist/esm/src/sayable/types.js.map +1 -1
  85. package/dist/esm/src/user-modules/email.d.ts +72 -0
  86. package/dist/esm/src/user-modules/email.d.ts.map +1 -0
  87. package/dist/esm/src/user-modules/email.js +74 -0
  88. package/dist/esm/src/user-modules/email.js.map +1 -0
  89. package/dist/esm/src/user-modules/email.spec.d.ts +3 -0
  90. package/dist/esm/src/user-modules/email.spec.d.ts.map +1 -0
  91. package/dist/esm/src/user-modules/email.spec.js +71 -0
  92. package/dist/esm/src/user-modules/email.spec.js.map +1 -0
  93. package/dist/esm/src/user-modules/message.d.ts +4 -1
  94. package/dist/esm/src/user-modules/message.d.ts.map +1 -1
  95. package/dist/esm/src/user-modules/message.js +15 -3
  96. package/dist/esm/src/user-modules/message.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/wechaty/wechaty-base.d.ts +10 -0
  102. package/dist/esm/src/wechaty/wechaty-base.d.ts.map +1 -1
  103. package/dist/esm/src/wechaty/wechaty-impl.spec.js +16 -14
  104. package/dist/esm/src/wechaty/wechaty-impl.spec.js.map +1 -1
  105. package/dist/esm/src/wechaty-mixins/login-mixin.d.ts +18 -3
  106. package/dist/esm/src/wechaty-mixins/login-mixin.d.ts.map +1 -1
  107. package/dist/esm/src/wechaty-mixins/misc-mixin.d.ts +6 -0
  108. package/dist/esm/src/wechaty-mixins/misc-mixin.d.ts.map +1 -1
  109. package/dist/esm/src/wechaty-mixins/plugin-mixin.d.ts +8 -0
  110. package/dist/esm/src/wechaty-mixins/plugin-mixin.d.ts.map +1 -1
  111. package/dist/esm/src/wechaty-mixins/puppet-mixin.d.ts +4 -0
  112. package/dist/esm/src/wechaty-mixins/puppet-mixin.d.ts.map +1 -1
  113. package/dist/esm/src/wechaty-mixins/wechatify-user-module-mixin.d.ts +4 -2
  114. package/dist/esm/src/wechaty-mixins/wechatify-user-module-mixin.d.ts.map +1 -1
  115. package/dist/esm/src/wechaty-mixins/wechatify-user-module-mixin.js +4 -1
  116. package/dist/esm/src/wechaty-mixins/wechatify-user-module-mixin.js.map +1 -1
  117. package/package.json +3 -2
  118. package/src/io.spec.ts +4 -1
  119. package/src/mods/impls.ts +3 -0
  120. package/src/mods/users.ts +1 -0
  121. package/src/package-json.ts +4 -3
  122. package/src/sayable/deliver-sayable.ts +9 -0
  123. package/src/sayable/message-to-sayable.ts +3 -0
  124. package/src/sayable/payload-to-sayable.ts +3 -0
  125. package/src/sayable/sayable-to-payload.ts +3 -0
  126. package/src/sayable/types.ts +2 -0
  127. package/src/user-modules/email.spec.ts +82 -0
  128. package/src/user-modules/email.ts +130 -0
  129. package/src/user-modules/message.ts +23 -3
  130. package/src/user-modules/mod.ts +8 -0
  131. package/src/wechaty/wechaty-impl.spec.ts +3 -0
  132. package/src/wechaty-mixins/wechatify-user-module-mixin.ts +6 -0
@@ -4,10 +4,10 @@
4
4
  */
5
5
  import type { PackageJsonWechaty } from './config'
6
6
 
7
- export const GIT_COMMIT_HASH: string = 'a227e6b177eed32833bff79d6f6dc09a7b47b107'
7
+ export const GIT_COMMIT_HASH: string = '2c311276c0c88cacc69d0844f82d3240ae112408'
8
8
  export const packageJson: PackageJsonWechaty = {
9
9
  "name": "@juzi/wechaty",
10
- "version": "1.0.162",
10
+ "version": "1.0.164",
11
11
  "description": "Wechaty is a RPA SDK for Chatbot Makers.",
12
12
  "type": "module",
13
13
  "exports": {
@@ -116,6 +116,7 @@ export const packageJson: PackageJsonWechaty = {
116
116
  },
117
117
  "homepage": "https://github.com/wechaty/",
118
118
  "dependencies": {
119
+ "@juzi/wechaty-puppet": "^1.0.153",
119
120
  "@juzi/wechaty-puppet-service": "1.0.124",
120
121
  "clone-class": "^1.1.1",
121
122
  "cmd-ts": "^0.10.0",
@@ -139,7 +140,7 @@ export const packageJson: PackageJsonWechaty = {
139
140
  "@chatie/eslint-config": "^1.0.4",
140
141
  "@chatie/semver": "^0.4.7",
141
142
  "@chatie/tsconfig": "^4.6.3",
142
- "@juzi/wechaty-puppet": "^1.0.148",
143
+ "@juzi/wechaty-puppet": "^1.0.152",
143
144
  "@juzi/wechaty-puppet-mock": "^1.0.1",
144
145
  "@swc/core": "1.3.44",
145
146
  "@swc/helpers": "^0.3.6",
@@ -6,6 +6,7 @@ import {
6
6
  MessageImpl,
7
7
  DelayImpl,
8
8
  UrlLinkImpl,
9
+ EmailImpl,
9
10
  MiniProgramImpl,
10
11
  PostImpl,
11
12
  LocationImpl,
@@ -77,6 +78,14 @@ const deliverSayableConversationPuppet = (puppet: PUPPET.impls.PuppetInterface)
77
78
  conversationId,
78
79
  sayable.payload,
79
80
  )
81
+ } else if (EmailImpl.validInstance(sayable)) {
82
+ /**
83
+ * 4.1. Email Message
84
+ */
85
+ msgId = await puppet.messageSendEmail(
86
+ conversationId,
87
+ sayable.payload,
88
+ )
80
89
  } else if (MiniProgramImpl.validInstance(sayable)) {
81
90
  /**
82
91
  * 5. Mini Program
@@ -31,6 +31,9 @@ async function messageToSayable (
31
31
  case PUPPET.types.Message.Url:
32
32
  return message.toUrlLink()
33
33
 
34
+ case PUPPET.types.Message.Email:
35
+ return message.toEmail()
36
+
34
37
  case PUPPET.types.Message.MiniProgram:
35
38
  return message.toMiniProgram()
36
39
 
@@ -38,6 +38,9 @@ const payloadToSayableWechaty: (w: WechatyInterface) => (p: PUPPET.payloads.Saya
38
38
  case PUPPET.types.Sayable.Url:
39
39
  return new wechaty.UrlLink(sayable.payload)
40
40
 
41
+ case PUPPET.types.Sayable.Email:
42
+ return new wechaty.Email(sayable.payload)
43
+
41
44
  case PUPPET.types.Sayable.Post:
42
45
  return new wechaty.Post(sayable.payload)
43
46
 
@@ -8,6 +8,7 @@ import {
8
8
  MessageImpl,
9
9
  MiniProgramImpl,
10
10
  UrlLinkImpl,
11
+ EmailImpl,
11
12
  ContactImpl,
12
13
  PostImpl,
13
14
  ChannelImpl,
@@ -47,6 +48,8 @@ async function sayableToPayload (sayable: Sayable): Promise<undefined | PUPPET.p
47
48
  return PUPPET.payloads.sayable.post(sayable.payload)
48
49
  } else if (UrlLinkImpl.validInstance(sayable)) {
49
50
  return PUPPET.payloads.sayable.url(sayable.payload)
51
+ } else if (EmailImpl.validInstance(sayable)) {
52
+ return PUPPET.payloads.sayable.email(sayable.payload)
50
53
  } else if (ChannelImpl.validInstance(sayable)) {
51
54
  return PUPPET.payloads.sayable.channel(sayable.payload)
52
55
  } else if (ChannelCardImpl.validInstance(sayable)) {
@@ -29,6 +29,7 @@ import {
29
29
  MiniProgramInterface,
30
30
  PostInterface,
31
31
  UrlLinkInterface,
32
+ EmailInterface,
32
33
  ChannelInterface,
33
34
  ContactImpl,
34
35
  MessageImpl,
@@ -55,6 +56,7 @@ type Sayable =
55
56
  | PostInterface
56
57
  | string
57
58
  | UrlLinkInterface
59
+ | EmailInterface
58
60
  | ChannelInterface
59
61
  | ChannelCardInterface
60
62
  | ConsultCardInterface
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env -S node --no-warnings --loader ts-node/esm
2
+ /**
3
+ * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty
4
+ *
5
+ * @copyright 2016 Huan LI (李卓桓) <https://github.com/huan>, and
6
+ * Wechaty Contributors <https://github.com/wechaty>.
7
+ *
8
+ * Licensed under the Apache License, Version 2.0 (the "License");
9
+ * you may not use this file except in compliance with the License.
10
+ * You may obtain a copy of the License at
11
+ *
12
+ * http://www.apache.org/licenses/LICENSE-2.0
13
+ *
14
+ * Unless required by applicable law or agreed to in writing, software
15
+ * distributed under the License is distributed on an "AS IS" BASIS,
16
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ * See the License for the specific language governing permissions and
18
+ * limitations under the License.
19
+ *
20
+ */
21
+ import { test } from 'tstest'
22
+ import type * as PUPPET from '@juzi/wechaty-puppet'
23
+ import { log } from '@juzi/wechaty-puppet'
24
+
25
+ import type { Wechaty } from '../mods/mod.js'
26
+
27
+ import { MessageImpl } from './message.js'
28
+ import { wechatifyUserModule } from './mod.js'
29
+ import { EmailImpl } from './email.js'
30
+
31
+ const wechaty = {
32
+ log,
33
+ puppet: {} as any,
34
+ } as any as Wechaty
35
+
36
+ const EmailTest = wechatifyUserModule(EmailImpl)(wechaty)
37
+
38
+ const PAYLOAD: PUPPET.payloads.Email = {
39
+ attachments : [ { filename: 'report.pdf', contentType: 'application/pdf', size: 1024 } ],
40
+ cc : [ { address: 'cc@example.com' } ],
41
+ from : { address: 'alice@example.com', name: 'Alice' },
42
+ html : '<p>hello</p>',
43
+ inReplyTo : '<parent@example.com>',
44
+ mimeMessageId : '<abc@example.com>',
45
+ replyTo : [ { address: 'reply@example.com' } ],
46
+ subject : 'Hello World',
47
+ text : 'hello',
48
+ to : [ { address: 'bob@example.com', name: 'Bob' } ],
49
+ }
50
+
51
+ test('Email getters expose the payload', async t => {
52
+ const email = new EmailTest(PAYLOAD)
53
+
54
+ t.equal(email.subject(), PAYLOAD.subject, 'should expose subject')
55
+ t.same(email.from(), PAYLOAD.from, 'should expose from')
56
+ t.same(email.to(), PAYLOAD.to, 'should expose to')
57
+ t.same(email.cc(), PAYLOAD.cc, 'should expose cc')
58
+ t.same(email.replyTo(), PAYLOAD.replyTo, 'should expose replyTo')
59
+ t.equal(email.text(), PAYLOAD.text, 'should expose text')
60
+ t.equal(email.html(), PAYLOAD.html, 'should expose html')
61
+ t.equal(email.mimeMessageId(), PAYLOAD.mimeMessageId, 'should expose mimeMessageId')
62
+ t.equal(email.inReplyTo(), PAYLOAD.inReplyTo, 'should expose inReplyTo')
63
+ t.same(email.attachments(), PAYLOAD.attachments, 'should expose attachments metadata')
64
+ })
65
+
66
+ test('Email absent optional fields are undefined', async t => {
67
+ const email = new EmailTest({
68
+ from : { address: 'alice@example.com' },
69
+ subject : 'Bare',
70
+ to : [ { address: 'bob@example.com' } ],
71
+ })
72
+
73
+ t.equal(email.cc(), undefined, 'should return undefined for absent cc')
74
+ t.equal(email.bcc(), undefined, 'should return undefined for absent bcc')
75
+ t.equal(email.html(), undefined, 'should return undefined for absent html')
76
+ })
77
+
78
+ test('Email.valid()', async t => {
79
+ const email = new EmailTest(PAYLOAD)
80
+ t.ok(EmailImpl.valid(email), 'should pass the validation of EmailImpl')
81
+ t.notOk(MessageImpl.valid(email), 'should not pass the validation of MessageImpl')
82
+ })
@@ -0,0 +1,130 @@
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 agreed 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 language governing permissions and
17
+ * limitations under the License.
18
+ *
19
+ */
20
+ import type * as PUPPET from '@juzi/wechaty-puppet'
21
+ import type { Constructor } from 'clone-class'
22
+
23
+ import { validationMixin } from '../user-mixins/validation.js'
24
+ import { wechatifyMixinBase } from '../user-mixins/wechatify.js'
25
+
26
+ class EmailMixin extends wechatifyMixinBase() {
27
+
28
+ /**
29
+ *
30
+ * Create from payload
31
+ *
32
+ */
33
+ static create (
34
+ payload: PUPPET.payloads.Email,
35
+ ): EmailInterface {
36
+ this.log.verbose('Email', 'create()')
37
+ return new this(payload)
38
+ }
39
+
40
+ /*
41
+ * @hideconstructor
42
+ */
43
+ constructor (
44
+ public readonly payload: PUPPET.payloads.Email,
45
+ ) {
46
+ super()
47
+ this.log.verbose('Email', 'constructor()')
48
+ }
49
+
50
+ override toString (): string {
51
+ return `Email<${this.payload.subject}>`
52
+ }
53
+
54
+ subject (): string {
55
+ return this.payload.subject
56
+ }
57
+
58
+ from (): PUPPET.payloads.EmailAddress {
59
+ return this.payload.from
60
+ }
61
+
62
+ to (): PUPPET.payloads.EmailAddress[] {
63
+ return this.payload.to
64
+ }
65
+
66
+ cc (): undefined | PUPPET.payloads.EmailAddress[] {
67
+ return this.payload.cc
68
+ }
69
+
70
+ bcc (): undefined | PUPPET.payloads.EmailAddress[] {
71
+ return this.payload.bcc
72
+ }
73
+
74
+ date (): undefined | number {
75
+ return this.payload.date
76
+ }
77
+
78
+ mimeMessageId (): undefined | string {
79
+ return this.payload.mimeMessageId
80
+ }
81
+
82
+ inReplyTo (): undefined | string {
83
+ return this.payload.inReplyTo
84
+ }
85
+
86
+ references (): undefined | string[] {
87
+ return this.payload.references
88
+ }
89
+
90
+ replyTo (): undefined | PUPPET.payloads.EmailAddress[] {
91
+ return this.payload.replyTo
92
+ }
93
+
94
+ sender (): undefined | PUPPET.payloads.EmailAddress {
95
+ return this.payload.sender
96
+ }
97
+
98
+ headers (): undefined | { [name: string]: string } {
99
+ return this.payload.headers
100
+ }
101
+
102
+ text (): undefined | string {
103
+ return this.payload.text
104
+ }
105
+
106
+ html (): undefined | string {
107
+ return this.payload.html
108
+ }
109
+
110
+ attachments (): undefined | PUPPET.payloads.EmailAttachment[] {
111
+ return this.payload.attachments
112
+ }
113
+
114
+ }
115
+
116
+ class EmailImpl extends validationMixin(EmailMixin)<EmailInterface>() {}
117
+ interface EmailInterface extends EmailImpl {}
118
+
119
+ type EmailConstructor = Constructor<
120
+ EmailInterface,
121
+ typeof EmailImpl
122
+ >
123
+
124
+ export type {
125
+ EmailConstructor,
126
+ EmailInterface,
127
+ }
128
+ export {
129
+ EmailImpl,
130
+ }
@@ -55,6 +55,9 @@ import type {
55
55
  import type {
56
56
  UrlLinkInterface,
57
57
  } from './url-link.js'
58
+ import type {
59
+ EmailInterface,
60
+ } from './email.js'
58
61
  import type {
59
62
  MiniProgramInterface,
60
63
  } from './mini-program.js'
@@ -1384,6 +1387,7 @@ class MessageMixin extends MixinBase implements SayableSayer {
1384
1387
  * > Tips:
1385
1388
  * This function is depending on the Puppet Implementation, see [puppet-compatible-table](https://github.com/wechaty/wechaty/wiki/Puppet#3-puppet-compatible-table)
1386
1389
  *
1390
+ * @param {number} [index] For an Email message, pick the N-th attachment (0-based). Ignored by other message types.
1387
1391
  * @returns {Promise<FileBoxInterface>}
1388
1392
  *
1389
1393
  * @example <caption>Save media file from a message</caption>
@@ -1391,12 +1395,12 @@ class MessageMixin extends MixinBase implements SayableSayer {
1391
1395
  * const fileName = fileBox.name
1392
1396
  * fileBox.toFile(fileName)
1393
1397
  */
1394
- async toFileBox (): Promise<FileBoxInterface> {
1395
- this.log.verbose('Message', 'toFileBox()')
1398
+ async toFileBox (index?: number): Promise<FileBoxInterface> {
1399
+ this.log.verbose('Message', 'toFileBox(%s)', index ?? '')
1396
1400
  if (this.type() === PUPPET.types.Message.Text) {
1397
1401
  throw new Error('text message no file')
1398
1402
  }
1399
- const fileBox = await this.wechaty.puppet.messageFile(this.id)
1403
+ const fileBox = await this.wechaty.puppet.messageFile(this.id, index)
1400
1404
  return fileBox
1401
1405
  }
1402
1406
 
@@ -1495,6 +1499,22 @@ class MessageMixin extends MixinBase implements SayableSayer {
1495
1499
  return new this.wechaty.UrlLink(urlPayload)
1496
1500
  }
1497
1501
 
1502
+ async toEmail (): Promise<EmailInterface> {
1503
+ this.log.verbose('Message', 'toEmail()')
1504
+
1505
+ if (!this.payload) {
1506
+ throw new Error('no payload')
1507
+ }
1508
+
1509
+ if (this.type() !== PUPPET.types.Message.Email) {
1510
+ throw new Error('message not an Email')
1511
+ }
1512
+
1513
+ const emailPayload = await this.wechaty.puppet.messageEmail(this.id)
1514
+
1515
+ return new this.wechaty.Email(emailPayload)
1516
+ }
1517
+
1498
1518
  async toMiniProgram (): Promise<MiniProgramInterface> {
1499
1519
  this.log.verbose('Message', 'toMiniProgram()')
1500
1520
 
@@ -102,6 +102,11 @@ import {
102
102
  UrlLinkInterface,
103
103
  UrlLinkConstructor,
104
104
  } from './url-link.js'
105
+ import {
106
+ EmailImpl,
107
+ EmailInterface,
108
+ EmailConstructor,
109
+ } from './email.js'
105
110
  import {
106
111
  DelayImpl,
107
112
  DelayInterface,
@@ -193,6 +198,7 @@ export type {
193
198
  TagGroupInterface,
194
199
  DelayInterface,
195
200
  UrlLinkInterface,
201
+ EmailInterface,
196
202
  ChannelInterface,
197
203
  ChannelCardInterface,
198
204
  ConsultCardInterface,
@@ -226,6 +232,7 @@ export type {
226
232
  TagConstructor,
227
233
  TagGroupConstructor,
228
234
  UrlLinkConstructor,
235
+ EmailConstructor,
229
236
  ChannelConstructor,
230
237
  ChannelCardConstructor,
231
238
  ConsultCardConstructor,
@@ -261,6 +268,7 @@ export {
261
268
  TagImpl,
262
269
  TagGroupImpl,
263
270
  UrlLinkImpl,
271
+ EmailImpl,
264
272
  ChannelImpl,
265
273
  ChannelCardImpl,
266
274
  ConsultCardImpl,
@@ -20,6 +20,7 @@ import type {
20
20
  TagConstructor,
21
21
  TagGroupConstructor,
22
22
  UrlLinkConstructor,
23
+ EmailConstructor,
23
24
  MessageInterface,
24
25
  ChannelConstructor,
25
26
  ChannelCardConstructor,
@@ -62,6 +63,7 @@ test('Wechaty interface', async t => {
62
63
  Tag : TagConstructor
63
64
  TagGroup : TagGroupConstructor
64
65
  UrlLink : UrlLinkConstructor
66
+ Email : EmailConstructor
65
67
  Channel : ChannelConstructor
66
68
  ChannelCard : ChannelCardConstructor
67
69
  ConsultCard : ConsultCardConstructor
@@ -94,6 +96,7 @@ test('Wechaty interface', async t => {
94
96
  = this.Tag
95
97
  = this.TagGroup
96
98
  = this.UrlLink
99
+ = this.Email
97
100
  = this.Channel
98
101
  = this.ChannelCard
99
102
  = this.ConsultCard
@@ -17,6 +17,7 @@ import {
17
17
  TagImpl,
18
18
  TagGroupImpl,
19
19
  UrlLinkImpl,
20
+ EmailImpl,
20
21
  ChannelImpl,
21
22
  ChannelCardImpl,
22
23
  ConsultCardImpl,
@@ -46,6 +47,7 @@ import {
46
47
  TagConstructor,
47
48
  TagGroupConstructor,
48
49
  UrlLinkConstructor,
50
+ EmailConstructor,
49
51
  ChannelConstructor,
50
52
  ChannelCardConstructor,
51
53
  ConsultCardConstructor,
@@ -91,6 +93,7 @@ const wechatifyUserModuleMixin = <MixinBase extends typeof WechatySkeleton> (mix
91
93
  __wechatifiedTag? : TagConstructor
92
94
  __wechatifiedTagGroup? : TagGroupConstructor
93
95
  __wechatifiedUrlLink? : UrlLinkConstructor
96
+ __wechatifiedEmail? : EmailConstructor
94
97
  __wechatifiedChannel? : ChannelConstructor
95
98
  __wechatifiedChannelCard? : ChannelCardConstructor
96
99
  __wechatifiedConsultCard? : ConsultCardConstructor
@@ -120,6 +123,7 @@ const wechatifyUserModuleMixin = <MixinBase extends typeof WechatySkeleton> (mix
120
123
  get Tag () : TagConstructor { return guardWechatify(this.__wechatifiedTag) }
121
124
  get TagGroup () : TagGroupConstructor { return guardWechatify(this.__wechatifiedTagGroup) }
122
125
  get UrlLink () : UrlLinkConstructor { return guardWechatify(this.__wechatifiedUrlLink) }
126
+ get Email () : EmailConstructor { return guardWechatify(this.__wechatifiedEmail) }
123
127
  get Channel () : ChannelConstructor { return guardWechatify(this.__wechatifiedChannel) }
124
128
  get ChannelCard () : ChannelCardConstructor { return guardWechatify(this.__wechatifiedChannelCard) }
125
129
  get ConsultCard () : ConsultCardConstructor { return guardWechatify(this.__wechatifiedConsultCard) }
@@ -169,6 +173,7 @@ const wechatifyUserModuleMixin = <MixinBase extends typeof WechatySkeleton> (mix
169
173
  this.__wechatifiedTag = wechatifyUserModule(TagImpl)(this as any)
170
174
  this.__wechatifiedTagGroup = wechatifyUserModule(TagGroupImpl)(this as any)
171
175
  this.__wechatifiedUrlLink = wechatifyUserModule(UrlLinkImpl)(this as any)
176
+ this.__wechatifiedEmail = wechatifyUserModule(EmailImpl)(this as any)
172
177
  this.__wechatifiedChannel = wechatifyUserModule(ChannelImpl)(this as any)
173
178
  this.__wechatifiedChannelCard = wechatifyUserModule(ChannelCardImpl)(this as any)
174
179
  this.__wechatifiedConsultCard = wechatifyUserModule(ConsultCardImpl)(this as any)
@@ -218,6 +223,7 @@ type ProtectedPropertyWechatifyUserModuleMixin =
218
223
  | '__wechatifiedTag'
219
224
  | '__wechatifiedTagGroup'
220
225
  | '__wechatifiedUrlLink'
226
+ | '__wechatifiedEmail'
221
227
  | '__wechatifiedChannel'
222
228
  | '__wechatifiedChannelCard'
223
229
  | '__wechatifiedConsultCard'