@juzi/wechaty-puppet-service 1.0.128 → 1.0.130
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.
- package/dist/cjs/src/client/puppet-service.d.ts +2 -0
- package/dist/cjs/src/client/puppet-service.d.ts.map +1 -1
- package/dist/cjs/src/client/puppet-service.js +45 -0
- package/dist/cjs/src/client/puppet-service.js.map +1 -1
- package/dist/cjs/src/client/puppet-service.spec.js +107 -0
- package/dist/cjs/src/client/puppet-service.spec.js.map +1 -1
- package/dist/cjs/src/package-json.js +4 -4
- package/dist/cjs/src/server/event-stream-manager.d.ts.map +1 -1
- package/dist/cjs/src/server/event-stream-manager.js +21 -0
- package/dist/cjs/src/server/event-stream-manager.js.map +1 -1
- package/dist/cjs/src/server/event-stream-manager.spec.d.ts +3 -0
- package/dist/cjs/src/server/event-stream-manager.spec.d.ts.map +1 -0
- package/dist/cjs/src/server/event-stream-manager.spec.js +22 -0
- package/dist/cjs/src/server/event-stream-manager.spec.js.map +1 -0
- package/dist/cjs/src/server/puppet-implementation.d.ts.map +1 -1
- package/dist/cjs/src/server/puppet-implementation.js +44 -0
- package/dist/cjs/src/server/puppet-implementation.js.map +1 -1
- package/dist/cjs/src/server/puppet-implementation.spec.js +98 -0
- package/dist/cjs/src/server/puppet-implementation.spec.js.map +1 -1
- package/dist/esm/src/client/puppet-service.d.ts +2 -0
- package/dist/esm/src/client/puppet-service.d.ts.map +1 -1
- package/dist/esm/src/client/puppet-service.js +45 -0
- package/dist/esm/src/client/puppet-service.js.map +1 -1
- package/dist/esm/src/client/puppet-service.spec.js +107 -0
- package/dist/esm/src/client/puppet-service.spec.js.map +1 -1
- package/dist/esm/src/package-json.js +4 -4
- package/dist/esm/src/server/event-stream-manager.d.ts.map +1 -1
- package/dist/esm/src/server/event-stream-manager.js +21 -0
- package/dist/esm/src/server/event-stream-manager.js.map +1 -1
- package/dist/esm/src/server/event-stream-manager.spec.d.ts +3 -0
- package/dist/esm/src/server/event-stream-manager.spec.d.ts.map +1 -0
- package/dist/esm/src/server/event-stream-manager.spec.js +20 -0
- package/dist/esm/src/server/event-stream-manager.spec.js.map +1 -0
- package/dist/esm/src/server/puppet-implementation.d.ts.map +1 -1
- package/dist/esm/src/server/puppet-implementation.js +44 -0
- package/dist/esm/src/server/puppet-implementation.js.map +1 -1
- package/dist/esm/src/server/puppet-implementation.spec.js +98 -0
- package/dist/esm/src/server/puppet-implementation.spec.js.map +1 -1
- package/package.json +4 -4
- package/src/client/puppet-service.spec.ts +147 -0
- package/src/client/puppet-service.ts +57 -0
- package/src/package-json.ts +4 -4
- package/src/server/event-stream-manager.spec.ts +30 -0
- package/src/server/event-stream-manager.ts +21 -0
- package/src/server/puppet-implementation.spec.ts +127 -0
- package/src/server/puppet-implementation.ts +50 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juzi/wechaty-puppet-service",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.130",
|
|
4
4
|
"description": "Puppet Service for Wechaty",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"@chatie/eslint-config": "^1.0.4",
|
|
52
52
|
"@chatie/semver": "^0.4.7",
|
|
53
53
|
"@chatie/tsconfig": "^4.6.3",
|
|
54
|
-
"@juzi/wechaty-puppet": "^1.0.
|
|
54
|
+
"@juzi/wechaty-puppet": "^1.0.157",
|
|
55
55
|
"@juzi/wechaty-puppet-mock": "^1.0.1",
|
|
56
56
|
"@swc/core": "1.3.39",
|
|
57
57
|
"@types/google-protobuf": "^3.15.5",
|
|
@@ -71,10 +71,10 @@
|
|
|
71
71
|
"why-is-node-running": "^2.2.1"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|
|
74
|
-
"@juzi/wechaty-puppet": "^1.0.
|
|
74
|
+
"@juzi/wechaty-puppet": "^1.0.157"
|
|
75
75
|
},
|
|
76
76
|
"dependencies": {
|
|
77
|
-
"@juzi/wechaty-grpc": "^1.0.
|
|
77
|
+
"@juzi/wechaty-grpc": "^1.0.109",
|
|
78
78
|
"clone-class": "^1.1.1",
|
|
79
79
|
"ducks": "^1.0.2",
|
|
80
80
|
"file-box": "^1.5.5",
|
|
@@ -154,6 +154,153 @@ test('callInviteWithMedia rejects when the server returns an empty call_id', asy
|
|
|
154
154
|
)
|
|
155
155
|
})
|
|
156
156
|
|
|
157
|
+
let orgBroadcastTestId = 0
|
|
158
|
+
|
|
159
|
+
function createOrgBroadcastPuppet (
|
|
160
|
+
payloadResponse?: grpcPuppet.OrgBroadcastPayloadResponse,
|
|
161
|
+
): { puppet: PuppetService, executeRequestList: grpcPuppet.OrgBroadcastExecuteRequest[] } {
|
|
162
|
+
const puppet = new PuppetService({
|
|
163
|
+
token: `org-broadcast-test-${orgBroadcastTestId++}`,
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
const executeRequestList: grpcPuppet.OrgBroadcastExecuteRequest[] = []
|
|
167
|
+
|
|
168
|
+
;(puppet as any)._grpcManager = {
|
|
169
|
+
client: {
|
|
170
|
+
orgBroadcastExecute: (
|
|
171
|
+
request : grpcPuppet.OrgBroadcastExecuteRequest,
|
|
172
|
+
callback : (error: null | Error, response: grpcPuppet.OrgBroadcastExecuteResponse) => void,
|
|
173
|
+
) => {
|
|
174
|
+
executeRequestList.push(request)
|
|
175
|
+
callback(null, new grpcPuppet.OrgBroadcastExecuteResponse())
|
|
176
|
+
},
|
|
177
|
+
orgBroadcastPayload: (
|
|
178
|
+
request : grpcPuppet.OrgBroadcastPayloadRequest,
|
|
179
|
+
callback : (error: null | Error, response?: grpcPuppet.OrgBroadcastPayloadResponse) => void,
|
|
180
|
+
) => {
|
|
181
|
+
void request
|
|
182
|
+
callback(null, payloadResponse)
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return { puppet, executeRequestList }
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
test('orgBroadcastPayload maps every response field onto OrgBroadcastPayload', async t => {
|
|
191
|
+
const roomTarget = new grpcPuppet.OrgBroadcastTarget()
|
|
192
|
+
roomTarget.setRoomId('R:room-1')
|
|
193
|
+
roomTarget.setStatus(grpcPuppet.OrgBroadcastTargetStatus.ORG_BROADCAST_TARGET_STATUS_UNCONFIRMED)
|
|
194
|
+
|
|
195
|
+
const sentRoomTarget = new grpcPuppet.OrgBroadcastTarget()
|
|
196
|
+
sentRoomTarget.setRoomId('R:room-2')
|
|
197
|
+
sentRoomTarget.setStatus(grpcPuppet.OrgBroadcastTargetStatus.ORG_BROADCAST_TARGET_STATUS_SENT)
|
|
198
|
+
|
|
199
|
+
const response = new grpcPuppet.OrgBroadcastPayloadResponse()
|
|
200
|
+
response.setId('4728994241730369413')
|
|
201
|
+
response.setSendType(2)
|
|
202
|
+
response.setConversationType(1)
|
|
203
|
+
response.setCreatorId('creator-1')
|
|
204
|
+
response.setExecTime(1758600000000)
|
|
205
|
+
response.setStatus(3)
|
|
206
|
+
response.setCanCancel(true)
|
|
207
|
+
response.setAllowSelect(true)
|
|
208
|
+
response.setSent(false)
|
|
209
|
+
response.setTotalCount(7)
|
|
210
|
+
response.setSentCount(5)
|
|
211
|
+
response.setContentListJson('[{"contentType":2}]')
|
|
212
|
+
response.setTargetsList([ roomTarget, sentRoomTarget ])
|
|
213
|
+
|
|
214
|
+
const { puppet } = createOrgBroadcastPuppet(response)
|
|
215
|
+
const payload = await puppet.orgBroadcastPayload('4728994241730369413')
|
|
216
|
+
|
|
217
|
+
t.same(payload, {
|
|
218
|
+
id : '4728994241730369413',
|
|
219
|
+
sendType : 2,
|
|
220
|
+
conversationType : 1,
|
|
221
|
+
creatorId : 'creator-1',
|
|
222
|
+
execTime : 1758600000000,
|
|
223
|
+
status : 3,
|
|
224
|
+
canCancel : true,
|
|
225
|
+
allowSelect : true,
|
|
226
|
+
sent : false,
|
|
227
|
+
totalCount : 7,
|
|
228
|
+
sentCount : 5,
|
|
229
|
+
contentListJson : '[{"contentType":2}]',
|
|
230
|
+
targets : [
|
|
231
|
+
{ contactId: undefined, roomId: 'R:room-1', status: 4 },
|
|
232
|
+
{ contactId: undefined, roomId: 'R:room-2', status: 1 },
|
|
233
|
+
],
|
|
234
|
+
}, 'maps every field and drops the empty contact_id of room targets')
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
test('orgBroadcastPayload maps empty creator_id and contact targets', async t => {
|
|
238
|
+
const contactTarget = new grpcPuppet.OrgBroadcastTarget()
|
|
239
|
+
contactTarget.setContactId('contact-1')
|
|
240
|
+
|
|
241
|
+
const response = new grpcPuppet.OrgBroadcastPayloadResponse()
|
|
242
|
+
response.setId('org-broadcast-2')
|
|
243
|
+
response.setTargetsList([ contactTarget ])
|
|
244
|
+
|
|
245
|
+
const { puppet } = createOrgBroadcastPuppet(response)
|
|
246
|
+
const payload = await puppet.orgBroadcastPayload('org-broadcast-2')
|
|
247
|
+
|
|
248
|
+
t.equal(payload.creatorId, undefined, 'maps an empty creator_id to undefined')
|
|
249
|
+
t.same(payload.targets, [ { contactId: 'contact-1', roomId: undefined, status: 0 } ], 'drops the empty room_id of contact targets')
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
test('orgBroadcastExecute sends all targets as an empty target_ids when targetIds is omitted', async t => {
|
|
253
|
+
const { puppet, executeRequestList } = createOrgBroadcastPuppet()
|
|
254
|
+
|
|
255
|
+
await puppet.orgBroadcastExecute('org-broadcast-1')
|
|
256
|
+
|
|
257
|
+
t.equal(executeRequestList.length, 1, 'sends exactly one request')
|
|
258
|
+
t.equal(executeRequestList[0]!.getId(), 'org-broadcast-1', 'maps orgBroadcastId onto id')
|
|
259
|
+
t.same(executeRequestList[0]!.getTargetIdsList(), [], 'leaves target_ids empty')
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
test('orgBroadcastExecute forwards the selected targets', async t => {
|
|
263
|
+
const { puppet, executeRequestList } = createOrgBroadcastPuppet()
|
|
264
|
+
|
|
265
|
+
await puppet.orgBroadcastExecute('org-broadcast-1', [ 'contact-1', 'contact-2' ])
|
|
266
|
+
|
|
267
|
+
t.same(executeRequestList[0]!.getTargetIdsList(), [ 'contact-1', 'contact-2' ], 'maps targetIds onto target_ids')
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
test('orgBroadcastExecute rejects an explicit empty targetIds instead of sending to all targets', async t => {
|
|
271
|
+
const { puppet, executeRequestList } = createOrgBroadcastPuppet()
|
|
272
|
+
|
|
273
|
+
await t.rejects(
|
|
274
|
+
puppet.orgBroadcastExecute('org-broadcast-1', []),
|
|
275
|
+
/targetIds is empty/,
|
|
276
|
+
'does not turn an empty selection into sending to all targets',
|
|
277
|
+
)
|
|
278
|
+
t.equal(executeRequestList.length, 0, 'never reaches the server')
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
test('org broadcast grpc events are emitted as puppet events', async t => {
|
|
282
|
+
const { puppet } = createOrgBroadcastPuppet()
|
|
283
|
+
|
|
284
|
+
const createdSpy = sinon.spy()
|
|
285
|
+
const sentSpy = sinon.spy()
|
|
286
|
+
puppet.on('org-broadcast-created', createdSpy)
|
|
287
|
+
puppet.on('org-broadcast-sent', sentSpy)
|
|
288
|
+
|
|
289
|
+
const createdEvent = new grpcPuppet.EventResponse()
|
|
290
|
+
createdEvent.setType(grpcPuppet.EventType.EVENT_TYPE_ORG_BROADCAST_CREATED)
|
|
291
|
+
createdEvent.setPayload(JSON.stringify({ orgBroadcastId: 'org-broadcast-1', messageId: 'message-1' }))
|
|
292
|
+
|
|
293
|
+
const sentEvent = new grpcPuppet.EventResponse()
|
|
294
|
+
sentEvent.setType(grpcPuppet.EventType.EVENT_TYPE_ORG_BROADCAST_SENT)
|
|
295
|
+
sentEvent.setPayload(JSON.stringify({ orgBroadcastId: 'org-broadcast-1' }))
|
|
296
|
+
|
|
297
|
+
await (puppet as any).onGrpcStreamEvent(createdEvent)
|
|
298
|
+
await (puppet as any).onGrpcStreamEvent(sentEvent)
|
|
299
|
+
|
|
300
|
+
t.same(createdSpy.args[0], [ { orgBroadcastId: 'org-broadcast-1', messageId: 'message-1' } ], 'emits org-broadcast-created')
|
|
301
|
+
t.same(sentSpy.args[0], [ { orgBroadcastId: 'org-broadcast-1' } ], 'emits org-broadcast-sent')
|
|
302
|
+
})
|
|
303
|
+
|
|
157
304
|
test('version()', async t => {
|
|
158
305
|
const puppet = new PuppetService({
|
|
159
306
|
token: 'test',
|
|
@@ -429,9 +429,18 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
429
429
|
case grpcPuppet.EventType.EVENT_TYPE_VERIFY_SLIDE:
|
|
430
430
|
this.emit('verify-slide', JSON.parse(payload) as PUPPET.payloads.EventVerifySlide)
|
|
431
431
|
break
|
|
432
|
+
case grpcPuppet.EventType.EVENT_TYPE_SAME_NET_VERIFY:
|
|
433
|
+
this.emit('same-net-verify', JSON.parse(payload) as PUPPET.payloads.EventSameNetVerify)
|
|
434
|
+
break
|
|
432
435
|
case grpcPuppet.EventType.EVENT_TYPE_CALL:
|
|
433
436
|
this.emit('call', JSON.parse(payload) as PUPPET.payloads.EventCall)
|
|
434
437
|
break
|
|
438
|
+
case grpcPuppet.EventType.EVENT_TYPE_ORG_BROADCAST_CREATED:
|
|
439
|
+
this.emit('org-broadcast-created', JSON.parse(payload) as PUPPET.payloads.EventOrgBroadcastCreated)
|
|
440
|
+
break
|
|
441
|
+
case grpcPuppet.EventType.EVENT_TYPE_ORG_BROADCAST_SENT:
|
|
442
|
+
this.emit('org-broadcast-sent', JSON.parse(payload) as PUPPET.payloads.EventOrgBroadcastSent)
|
|
443
|
+
break
|
|
435
444
|
|
|
436
445
|
default:
|
|
437
446
|
// Huan(202003): in default, the `type` type should be `never`, please check.
|
|
@@ -3725,6 +3734,54 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
3725
3734
|
return result
|
|
3726
3735
|
}
|
|
3727
3736
|
|
|
3737
|
+
override async orgBroadcastPayload (orgBroadcastId: string): Promise<PUPPET.payloads.OrgBroadcast> {
|
|
3738
|
+
this.log.verbose('PuppetService', 'orgBroadcastPayload(%s)', orgBroadcastId)
|
|
3739
|
+
|
|
3740
|
+
const request = new grpcPuppet.OrgBroadcastPayloadRequest()
|
|
3741
|
+
request.setId(orgBroadcastId)
|
|
3742
|
+
|
|
3743
|
+
const response = await util.promisify(
|
|
3744
|
+
this.grpcManager.client.orgBroadcastPayload.bind(this.grpcManager.client),
|
|
3745
|
+
)(request)
|
|
3746
|
+
|
|
3747
|
+
return {
|
|
3748
|
+
id : response.getId(),
|
|
3749
|
+
sendType : response.getSendType(),
|
|
3750
|
+
conversationType : response.getConversationType() as PUPPET.types.OrgBroadcastConversationType,
|
|
3751
|
+
creatorId : response.getCreatorId() || undefined,
|
|
3752
|
+
execTime : response.getExecTime(),
|
|
3753
|
+
status : response.getStatus(),
|
|
3754
|
+
canCancel : response.getCanCancel(),
|
|
3755
|
+
allowSelect : response.getAllowSelect(),
|
|
3756
|
+
sent : response.getSent(),
|
|
3757
|
+
totalCount : response.getTotalCount(),
|
|
3758
|
+
sentCount : response.getSentCount(),
|
|
3759
|
+
contentListJson : response.getContentListJson(),
|
|
3760
|
+
targets : response.getTargetsList().map(targetPb => ({
|
|
3761
|
+
contactId : targetPb.getContactId() || undefined,
|
|
3762
|
+
roomId : targetPb.getRoomId() || undefined,
|
|
3763
|
+
status : targetPb.getStatus() as number as PUPPET.types.OrgBroadcastTargetStatus,
|
|
3764
|
+
})),
|
|
3765
|
+
}
|
|
3766
|
+
}
|
|
3767
|
+
|
|
3768
|
+
override async orgBroadcastExecute (orgBroadcastId: string, targetIds?: string[]): Promise<void> {
|
|
3769
|
+
this.log.verbose('PuppetService', 'orgBroadcastExecute(%s, %s)', orgBroadcastId, targetIds?.length)
|
|
3770
|
+
|
|
3771
|
+
// on the wire an empty target_ids means all targets, so an explicit empty list must not pass through
|
|
3772
|
+
if (targetIds && targetIds.length === 0) {
|
|
3773
|
+
throw new Error('targetIds is empty, omit it to send to all targets of the org broadcast')
|
|
3774
|
+
}
|
|
3775
|
+
|
|
3776
|
+
const request = new grpcPuppet.OrgBroadcastExecuteRequest()
|
|
3777
|
+
request.setId(orgBroadcastId)
|
|
3778
|
+
request.setTargetIdsList(targetIds ?? [])
|
|
3779
|
+
|
|
3780
|
+
await util.promisify(
|
|
3781
|
+
this.grpcManager.client.orgBroadcastExecute.bind(this.grpcManager.client),
|
|
3782
|
+
)(request)
|
|
3783
|
+
}
|
|
3784
|
+
|
|
3728
3785
|
healthCheckInterval?: NodeJS.Timeout
|
|
3729
3786
|
startHealthCheck () {
|
|
3730
3787
|
this.healthCheckInterval = setInterval(() => {
|
package/src/package-json.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import type { PackageJson } from 'type-fest'
|
|
5
5
|
export const packageJson: PackageJson = {
|
|
6
6
|
"name": "@juzi/wechaty-puppet-service",
|
|
7
|
-
"version": "1.0.
|
|
7
|
+
"version": "1.0.130",
|
|
8
8
|
"description": "Puppet Service for Wechaty",
|
|
9
9
|
"type": "module",
|
|
10
10
|
"exports": {
|
|
@@ -55,7 +55,7 @@ export const packageJson: PackageJson = {
|
|
|
55
55
|
"@chatie/eslint-config": "^1.0.4",
|
|
56
56
|
"@chatie/semver": "^0.4.7",
|
|
57
57
|
"@chatie/tsconfig": "^4.6.3",
|
|
58
|
-
"@juzi/wechaty-puppet": "^1.0.
|
|
58
|
+
"@juzi/wechaty-puppet": "^1.0.157",
|
|
59
59
|
"@juzi/wechaty-puppet-mock": "^1.0.1",
|
|
60
60
|
"@swc/core": "1.3.39",
|
|
61
61
|
"@types/google-protobuf": "^3.15.5",
|
|
@@ -75,10 +75,10 @@ export const packageJson: PackageJson = {
|
|
|
75
75
|
"why-is-node-running": "^2.2.1"
|
|
76
76
|
},
|
|
77
77
|
"peerDependencies": {
|
|
78
|
-
"@juzi/wechaty-puppet": "^1.0.
|
|
78
|
+
"@juzi/wechaty-puppet": "^1.0.157"
|
|
79
79
|
},
|
|
80
80
|
"dependencies": {
|
|
81
|
-
"@juzi/wechaty-grpc": "^1.0.
|
|
81
|
+
"@juzi/wechaty-grpc": "^1.0.109",
|
|
82
82
|
"clone-class": "^1.1.1",
|
|
83
83
|
"ducks": "^1.0.2",
|
|
84
84
|
"file-box": "^1.5.5",
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env -S node --no-warnings --loader ts-node/esm
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
sinon,
|
|
5
|
+
test,
|
|
6
|
+
} from 'tstest'
|
|
7
|
+
|
|
8
|
+
import { puppet as grpcPuppet } from '@juzi/wechaty-grpc'
|
|
9
|
+
import { PuppetMock } from '@juzi/wechaty-puppet-mock'
|
|
10
|
+
|
|
11
|
+
import { EventStreamManager } from './event-stream-manager.js'
|
|
12
|
+
|
|
13
|
+
test('org broadcast puppet events are forwarded as their own grpc event types', async t => {
|
|
14
|
+
const puppet = new PuppetMock() as any
|
|
15
|
+
const manager = new EventStreamManager(puppet)
|
|
16
|
+
|
|
17
|
+
const write = sinon.spy()
|
|
18
|
+
;(manager as any).eventStream = { write }
|
|
19
|
+
manager.connectPuppetEventToStreamingCall()
|
|
20
|
+
|
|
21
|
+
puppet.emit('org-broadcast-created', { orgBroadcastId: 'org-broadcast-1', messageId: 'message-1' })
|
|
22
|
+
puppet.emit('org-broadcast-sent', { orgBroadcastId: 'org-broadcast-1' })
|
|
23
|
+
|
|
24
|
+
const [ created, sent ] = write.args.map(args => args[0] as grpcPuppet.EventResponse)
|
|
25
|
+
|
|
26
|
+
t.equal(created?.getType(), grpcPuppet.EventType.EVENT_TYPE_ORG_BROADCAST_CREATED, 'forwards org-broadcast-created as EVENT_TYPE_ORG_BROADCAST_CREATED')
|
|
27
|
+
t.same(JSON.parse(created!.getPayload()), { orgBroadcastId: 'org-broadcast-1', messageId: 'message-1' }, 'keeps the created payload')
|
|
28
|
+
t.equal(sent?.getType(), grpcPuppet.EventType.EVENT_TYPE_ORG_BROADCAST_SENT, 'forwards org-broadcast-sent as EVENT_TYPE_ORG_BROADCAST_SENT')
|
|
29
|
+
t.same(JSON.parse(sent!.getPayload()), { orgBroadcastId: 'org-broadcast-1' }, 'keeps the sent payload')
|
|
30
|
+
})
|
|
@@ -322,6 +322,13 @@ class EventStreamManager {
|
|
|
322
322
|
this.offCallbackList.push(off)
|
|
323
323
|
break
|
|
324
324
|
}
|
|
325
|
+
case 'same-net-verify': {
|
|
326
|
+
const listener = (payload: PUPPET.payloads.EventSameNetVerify) => this.grpcEmit(grpcPuppet.EventType.EVENT_TYPE_SAME_NET_VERIFY, payload)
|
|
327
|
+
this.puppet.on('same-net-verify', listener)
|
|
328
|
+
const off = () => this.puppet.off('same-net-verify', listener)
|
|
329
|
+
this.offCallbackList.push(off)
|
|
330
|
+
break
|
|
331
|
+
}
|
|
325
332
|
case 'call': {
|
|
326
333
|
const listener = (payload: PUPPET.payloads.EventCall) => this.grpcEmit(grpcPuppet.EventType.EVENT_TYPE_CALL, payload)
|
|
327
334
|
this.puppet.on('call', listener)
|
|
@@ -329,6 +336,20 @@ class EventStreamManager {
|
|
|
329
336
|
this.offCallbackList.push(off)
|
|
330
337
|
break
|
|
331
338
|
}
|
|
339
|
+
case 'org-broadcast-created': {
|
|
340
|
+
const listener = (payload: PUPPET.payloads.EventOrgBroadcastCreated) => this.grpcEmit(grpcPuppet.EventType.EVENT_TYPE_ORG_BROADCAST_CREATED, payload)
|
|
341
|
+
this.puppet.on('org-broadcast-created', listener)
|
|
342
|
+
const off = () => this.puppet.off('org-broadcast-created', listener)
|
|
343
|
+
this.offCallbackList.push(off)
|
|
344
|
+
break
|
|
345
|
+
}
|
|
346
|
+
case 'org-broadcast-sent': {
|
|
347
|
+
const listener = (payload: PUPPET.payloads.EventOrgBroadcastSent) => this.grpcEmit(grpcPuppet.EventType.EVENT_TYPE_ORG_BROADCAST_SENT, payload)
|
|
348
|
+
this.puppet.on('org-broadcast-sent', listener)
|
|
349
|
+
const off = () => this.puppet.off('org-broadcast-sent', listener)
|
|
350
|
+
this.offCallbackList.push(off)
|
|
351
|
+
break
|
|
352
|
+
}
|
|
332
353
|
case 'reset':
|
|
333
354
|
// the `reset` event should be dealed internally, should not send out
|
|
334
355
|
break
|
|
@@ -119,3 +119,130 @@ test('callInviteWithMedia rejects an empty callId returned by the puppet', async
|
|
|
119
119
|
|
|
120
120
|
t.match(error?.message, /empty callId/, 'does not pass an unusable empty callId back on the wire')
|
|
121
121
|
})
|
|
122
|
+
|
|
123
|
+
function invokeOrgBroadcast<Req, Res> (
|
|
124
|
+
puppet : any,
|
|
125
|
+
method : 'orgBroadcastPayload' | 'orgBroadcastExecute',
|
|
126
|
+
request : Req,
|
|
127
|
+
): Promise<{ error: null | Error, response: null | Res }> {
|
|
128
|
+
const impl = puppetImplementation(puppet, FileBox)
|
|
129
|
+
|
|
130
|
+
return new Promise(resolve => {
|
|
131
|
+
void (impl[method] as any)(
|
|
132
|
+
{ request } as any,
|
|
133
|
+
((error: any, response: any) => resolve({ error, response })) as any,
|
|
134
|
+
)
|
|
135
|
+
})
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
test('orgBroadcastPayload serializes every payload field onto the response', async t => {
|
|
139
|
+
const puppet = new PuppetMock() as any
|
|
140
|
+
const stub = sinon.stub().resolves({
|
|
141
|
+
id : 'org-broadcast-1',
|
|
142
|
+
sendType : 2,
|
|
143
|
+
conversationType : 1,
|
|
144
|
+
creatorId : 'creator-1',
|
|
145
|
+
execTime : 1758600000000,
|
|
146
|
+
status : 3,
|
|
147
|
+
canCancel : true,
|
|
148
|
+
allowSelect : true,
|
|
149
|
+
sent : false,
|
|
150
|
+
totalCount : 7,
|
|
151
|
+
sentCount : 5,
|
|
152
|
+
contentListJson : '[{"contentType":2}]',
|
|
153
|
+
targets : [ { roomId: 'R:1', status: 4 }, { roomId: 'R:2', status: 1 } ],
|
|
154
|
+
})
|
|
155
|
+
puppet.orgBroadcastPayload = stub
|
|
156
|
+
|
|
157
|
+
const request = new grpcPuppet.OrgBroadcastPayloadRequest()
|
|
158
|
+
request.setId('org-broadcast-1')
|
|
159
|
+
|
|
160
|
+
const { error, response } = await invokeOrgBroadcast<grpcPuppet.OrgBroadcastPayloadRequest, grpcPuppet.OrgBroadcastPayloadResponse>(puppet, 'orgBroadcastPayload', request)
|
|
161
|
+
|
|
162
|
+
t.equal(error, null, 'returns without error')
|
|
163
|
+
t.same(stub.args[0], [ 'org-broadcast-1' ], 'passes the id to the puppet')
|
|
164
|
+
t.same(response?.toObject(), {
|
|
165
|
+
id : 'org-broadcast-1',
|
|
166
|
+
sendType : 2,
|
|
167
|
+
conversationType: 1,
|
|
168
|
+
creatorId : 'creator-1',
|
|
169
|
+
execTime : 1758600000000,
|
|
170
|
+
status : 3,
|
|
171
|
+
canCancel : true,
|
|
172
|
+
allowSelect : true,
|
|
173
|
+
sent : false,
|
|
174
|
+
totalCount : 7,
|
|
175
|
+
sentCount : 5,
|
|
176
|
+
contentListJson : '[{"contentType":2}]',
|
|
177
|
+
targetsList : [
|
|
178
|
+
{ contactId: '', roomId: 'R:1', status: 4 },
|
|
179
|
+
{ contactId: '', roomId: 'R:2', status: 1 },
|
|
180
|
+
],
|
|
181
|
+
}, 'serializes every field')
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
test('orgBroadcastPayload serializes a missing creatorId and contact targets as empty strings', async t => {
|
|
185
|
+
const puppet = new PuppetMock() as any
|
|
186
|
+
puppet.orgBroadcastPayload = sinon.stub().resolves({
|
|
187
|
+
id : 'org-broadcast-2',
|
|
188
|
+
sendType : 0,
|
|
189
|
+
conversationType : 0,
|
|
190
|
+
execTime : 0,
|
|
191
|
+
status : 0,
|
|
192
|
+
canCancel : false,
|
|
193
|
+
allowSelect : false,
|
|
194
|
+
sent : false,
|
|
195
|
+
totalCount : 1,
|
|
196
|
+
sentCount : 0,
|
|
197
|
+
contentListJson : '[]',
|
|
198
|
+
targets : [ { contactId: 'contact-1', status: 0 } ],
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
const request = new grpcPuppet.OrgBroadcastPayloadRequest()
|
|
202
|
+
request.setId('org-broadcast-2')
|
|
203
|
+
|
|
204
|
+
const { response } = await invokeOrgBroadcast<grpcPuppet.OrgBroadcastPayloadRequest, grpcPuppet.OrgBroadcastPayloadResponse>(puppet, 'orgBroadcastPayload', request)
|
|
205
|
+
|
|
206
|
+
t.equal(response?.getCreatorId(), '', 'serializes a missing creatorId as empty')
|
|
207
|
+
t.same(response?.getTargetsList()[0]?.toObject(), { contactId: 'contact-1', roomId: '', status: 0 }, 'leaves room_id empty for a contact target')
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
test('orgBroadcastExecute turns an empty target_ids into sending to all targets', async t => {
|
|
211
|
+
const puppet = new PuppetMock() as any
|
|
212
|
+
const stub = sinon.stub().resolves()
|
|
213
|
+
puppet.orgBroadcastExecute = stub
|
|
214
|
+
|
|
215
|
+
const request = new grpcPuppet.OrgBroadcastExecuteRequest()
|
|
216
|
+
request.setId('org-broadcast-1')
|
|
217
|
+
|
|
218
|
+
const { error } = await invokeOrgBroadcast(puppet, 'orgBroadcastExecute', request)
|
|
219
|
+
|
|
220
|
+
t.equal(error, null, 'returns without error')
|
|
221
|
+
t.same(stub.args[0], [ 'org-broadcast-1', undefined ], 'omits targetIds')
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
test('orgBroadcastExecute forwards the selected target_ids', async t => {
|
|
225
|
+
const puppet = new PuppetMock() as any
|
|
226
|
+
const stub = sinon.stub().resolves()
|
|
227
|
+
puppet.orgBroadcastExecute = stub
|
|
228
|
+
|
|
229
|
+
const request = new grpcPuppet.OrgBroadcastExecuteRequest()
|
|
230
|
+
request.setId('org-broadcast-1')
|
|
231
|
+
request.setTargetIdsList([ 'contact-1' ])
|
|
232
|
+
|
|
233
|
+
await invokeOrgBroadcast(puppet, 'orgBroadcastExecute', request)
|
|
234
|
+
|
|
235
|
+
t.same(stub.args[0], [ 'org-broadcast-1', [ 'contact-1' ] ], 'passes targetIds through')
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
test('orgBroadcastExecute reports a puppet failure as a grpc error', async t => {
|
|
239
|
+
const puppet = new PuppetMock() as any
|
|
240
|
+
puppet.orgBroadcastExecute = sinon.stub().rejects(new Error('broadcast not found'))
|
|
241
|
+
|
|
242
|
+
const request = new grpcPuppet.OrgBroadcastExecuteRequest()
|
|
243
|
+
request.setId('org-broadcast-missing')
|
|
244
|
+
|
|
245
|
+
const { error } = await invokeOrgBroadcast(puppet, 'orgBroadcastExecute', request)
|
|
246
|
+
|
|
247
|
+
t.match(error?.message, /broadcast not found/, 'surfaces the puppet error')
|
|
248
|
+
})
|
|
@@ -3017,6 +3017,56 @@ function puppetImplementation (
|
|
|
3017
3017
|
}
|
|
3018
3018
|
},
|
|
3019
3019
|
|
|
3020
|
+
orgBroadcastPayload: async (call, callback) => {
|
|
3021
|
+
log.verbose('PuppetServiceImpl', 'orgBroadcastPayload()')
|
|
3022
|
+
|
|
3023
|
+
try {
|
|
3024
|
+
const orgBroadcastId = call.request.getId()
|
|
3025
|
+
const payload = await puppet.orgBroadcastPayload(orgBroadcastId)
|
|
3026
|
+
|
|
3027
|
+
const response = new grpcPuppet.OrgBroadcastPayloadResponse()
|
|
3028
|
+
response.setId(payload.id)
|
|
3029
|
+
response.setSendType(payload.sendType)
|
|
3030
|
+
response.setConversationType(payload.conversationType)
|
|
3031
|
+
response.setCreatorId(payload.creatorId ?? '')
|
|
3032
|
+
response.setExecTime(payload.execTime)
|
|
3033
|
+
response.setStatus(payload.status)
|
|
3034
|
+
response.setCanCancel(payload.canCancel)
|
|
3035
|
+
response.setAllowSelect(payload.allowSelect)
|
|
3036
|
+
response.setSent(payload.sent)
|
|
3037
|
+
response.setTotalCount(payload.totalCount)
|
|
3038
|
+
response.setSentCount(payload.sentCount)
|
|
3039
|
+
response.setContentListJson(payload.contentListJson)
|
|
3040
|
+
response.setTargetsList(payload.targets.map(target => {
|
|
3041
|
+
const targetPb = new grpcPuppet.OrgBroadcastTarget()
|
|
3042
|
+
targetPb.setContactId(target.contactId ?? '')
|
|
3043
|
+
targetPb.setRoomId(target.roomId ?? '')
|
|
3044
|
+
targetPb.setStatus(target.status as number as grpcPuppet.OrgBroadcastTargetStatusMap[keyof grpcPuppet.OrgBroadcastTargetStatusMap])
|
|
3045
|
+
return targetPb
|
|
3046
|
+
}))
|
|
3047
|
+
|
|
3048
|
+
return callback(null, response)
|
|
3049
|
+
} catch (e) {
|
|
3050
|
+
return grpcError('orgBroadcastPayload', e, callback)
|
|
3051
|
+
}
|
|
3052
|
+
},
|
|
3053
|
+
|
|
3054
|
+
orgBroadcastExecute: async (call, callback) => {
|
|
3055
|
+
log.verbose('PuppetServiceImpl', 'orgBroadcastExecute()')
|
|
3056
|
+
|
|
3057
|
+
try {
|
|
3058
|
+
const orgBroadcastId = call.request.getId()
|
|
3059
|
+
const targetIds = call.request.getTargetIdsList()
|
|
3060
|
+
|
|
3061
|
+
// an empty target_ids on the wire means all targets of the org broadcast
|
|
3062
|
+
await puppet.orgBroadcastExecute(orgBroadcastId, targetIds.length ? targetIds : undefined)
|
|
3063
|
+
|
|
3064
|
+
return callback(null, new grpcPuppet.OrgBroadcastExecuteResponse())
|
|
3065
|
+
} catch (e) {
|
|
3066
|
+
return grpcError('orgBroadcastExecute', e, callback)
|
|
3067
|
+
}
|
|
3068
|
+
},
|
|
3069
|
+
|
|
3020
3070
|
download: async (call) => {
|
|
3021
3071
|
log.verbose('PuppetServiceImpl', 'download()')
|
|
3022
3072
|
|