gifted-baileys 1.5.5 → 1.5.7
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/README.md +6 -1642
- package/WAProto/WAProto.proto +969 -88
- package/WAProto/index.d.ts +13199 -1260
- package/WAProto/index.js +124901 -74525
- package/lib/Defaults/baileys-version.json +3 -0
- package/lib/Defaults/index.d.ts +284 -0
- package/{src → lib}/Defaults/index.js +7 -14
- package/lib/Signal/libsignal.d.ts +3 -0
- package/lib/Signal/libsignal.js +161 -0
- package/lib/Socket/Client/abstract-socket-client.d.ts +15 -0
- package/lib/Socket/Client/index.d.ts +2 -0
- package/{src → lib}/Socket/Client/index.js +2 -3
- package/lib/Socket/Client/mobile-socket-client.d.ts +12 -0
- package/lib/Socket/Client/mobile-socket-client.js +65 -0
- package/lib/Socket/Client/types.d.ts +17 -0
- package/lib/Socket/Client/types.js +13 -0
- package/lib/Socket/Client/websocket.d.ts +12 -0
- package/lib/Socket/Client/websocket.js +62 -0
- package/lib/Socket/business.d.ts +170 -0
- package/{src → lib}/Socket/business.js +28 -33
- package/lib/Socket/chats.d.ts +81 -0
- package/{src → lib}/Socket/chats.js +174 -176
- package/lib/Socket/groups.d.ts +115 -0
- package/{src → lib}/Socket/groups.js +80 -68
- package/lib/Socket/index.d.ts +172 -0
- package/{src → lib}/Socket/index.js +4 -1
- package/lib/Socket/messages-recv.d.ts +158 -0
- package/{src → lib}/Socket/messages-recv.js +378 -211
- package/lib/Socket/messages-send.d.ts +155 -0
- package/{src → lib}/Socket/messages-send.js +452 -177
- package/lib/Socket/newsletter.d.ts +132 -0
- package/{src → lib}/Socket/newsletter.js +107 -98
- package/lib/Socket/registration.d.ts +264 -0
- package/{src → lib}/Socket/registration.js +56 -48
- package/lib/Socket/socket.d.ts +44 -0
- package/{src → lib}/Socket/socket.js +77 -77
- package/lib/Socket/usync.d.ts +37 -0
- package/lib/Socket/usync.js +70 -0
- package/lib/Store/index.d.ts +3 -0
- package/lib/Store/make-cache-manager-store.d.ts +14 -0
- package/{src → lib}/Store/make-cache-manager-store.js +25 -34
- package/lib/Store/make-in-memory-store.d.ts +118 -0
- package/{src → lib}/Store/make-in-memory-store.js +36 -32
- package/lib/Store/make-ordered-dictionary.d.ts +13 -0
- package/lib/Store/object-repository.d.ts +10 -0
- package/{src → lib}/Store/object-repository.js +1 -1
- package/lib/Types/Auth.d.ts +109 -0
- package/lib/Types/Call.d.ts +13 -0
- package/lib/Types/Chat.d.ts +107 -0
- package/{src/Types/Contact.ts → lib/Types/Contact.d.ts} +8 -9
- package/lib/Types/Events.d.ts +172 -0
- package/lib/Types/GroupMetadata.d.ts +56 -0
- package/lib/Types/Label.d.ts +46 -0
- package/{src/Types/LabelAssociation.ts → lib/Types/LabelAssociation.d.ts} +16 -22
- package/lib/Types/Message.d.ts +433 -0
- package/lib/Types/Newsletter.d.ts +92 -0
- package/lib/Types/Product.d.ts +78 -0
- package/lib/Types/Signal.d.ts +57 -0
- package/{src/Types/Socket.ts → lib/Types/Socket.d.ts} +61 -68
- package/lib/Types/State.d.ts +27 -0
- package/lib/Types/USync.d.ts +25 -0
- package/lib/Types/index.d.ts +66 -0
- package/lib/Utils/auth-utils.d.ts +18 -0
- package/{src → lib}/Utils/auth-utils.js +73 -90
- package/lib/Utils/baileys-event-stream.d.ts +16 -0
- package/lib/Utils/baileys-event-stream.js +63 -0
- package/lib/Utils/business.d.ts +22 -0
- package/{src → lib}/Utils/business.js +15 -43
- package/lib/Utils/chat-utils.d.ts +70 -0
- package/{src → lib}/Utils/chat-utils.js +87 -94
- package/lib/Utils/crypto.d.ts +40 -0
- package/{src → lib}/Utils/crypto.js +4 -2
- package/lib/Utils/decode-wa-message.d.ts +36 -0
- package/lib/Utils/decode-wa-message.js +226 -0
- package/lib/Utils/event-buffer.d.ts +35 -0
- package/{src → lib}/Utils/event-buffer.js +4 -13
- package/lib/Utils/generics.d.ts +88 -0
- package/{src → lib}/Utils/generics.js +67 -86
- package/lib/Utils/history.d.ts +19 -0
- package/{src → lib}/Utils/history.js +13 -39
- package/lib/Utils/index.d.ts +17 -0
- package/lib/Utils/link-preview.d.ts +21 -0
- package/{src → lib}/Utils/link-preview.js +17 -54
- package/lib/Utils/logger.d.ts +2 -0
- package/lib/Utils/lt-hash.d.ts +12 -0
- package/lib/Utils/make-mutex.d.ts +7 -0
- package/{src → lib}/Utils/make-mutex.js +4 -13
- package/lib/Utils/messages-media.d.ts +113 -0
- package/{src → lib}/Utils/messages-media.js +193 -255
- package/lib/Utils/messages.d.ts +77 -0
- package/{src → lib}/Utils/messages.js +588 -118
- package/lib/Utils/noise-handler.d.ts +20 -0
- package/lib/Utils/process-message.d.ts +41 -0
- package/{src → lib}/Utils/process-message.js +27 -30
- package/lib/Utils/signal.d.ts +33 -0
- package/{src → lib}/Utils/signal.js +25 -42
- package/lib/Utils/use-multi-file-auth-state.d.ts +12 -0
- package/{src → lib}/Utils/use-multi-file-auth-state.js +27 -28
- package/lib/Utils/validate-connection.d.ts +11 -0
- package/{src → lib}/Utils/validate-connection.js +40 -9
- package/lib/WABinary/constants.d.ts +27 -0
- package/lib/WABinary/decode.d.ts +6 -0
- package/lib/WABinary/encode.d.ts +2 -0
- package/{src → lib}/WABinary/encode.js +16 -10
- package/lib/WABinary/generic-utils.d.ts +14 -0
- package/lib/WABinary/index.d.ts +5 -0
- package/lib/WABinary/jid-utils.d.ts +31 -0
- package/lib/WABinary/types.d.ts +18 -0
- package/lib/WABinary/types.js +2 -0
- package/lib/WAM/BinaryInfo.d.ts +8 -0
- package/lib/WAM/constants.d.ts +38 -0
- package/lib/WAM/encode.d.ts +2 -0
- package/lib/WAM/index.d.ts +3 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +9 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +32 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +22 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +57 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +12 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +30 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +12 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +42 -0
- package/lib/WAUSync/Protocols/index.d.ts +4 -0
- package/lib/WAUSync/Protocols/index.js +20 -0
- package/lib/WAUSync/USyncQuery.d.ts +26 -0
- package/lib/WAUSync/USyncQuery.js +79 -0
- package/lib/WAUSync/USyncUser.d.ts +10 -0
- package/lib/WAUSync/USyncUser.js +22 -0
- package/lib/WAUSync/index.d.ts +3 -0
- package/lib/WAUSync/index.js +19 -0
- package/{src → lib}/index.js +1 -0
- package/package.json +26 -8
- package/LICENSE +0 -21
- package/src/Defaults/baileys-version.json +0 -3
- package/src/Defaults/index.ts +0 -131
- package/src/Signal/libsignal.js +0 -180
- package/src/Signal/libsignal.ts +0 -141
- package/src/Socket/Client/abstract-socket-client.ts +0 -19
- package/src/Socket/Client/index.ts +0 -3
- package/src/Socket/Client/mobile-socket-client.js +0 -78
- package/src/Socket/Client/mobile-socket-client.ts +0 -66
- package/src/Socket/Client/web-socket-client.js +0 -75
- package/src/Socket/Client/web-socket-client.ts +0 -57
- package/src/Socket/business.ts +0 -281
- package/src/Socket/chats.ts +0 -1030
- package/src/Socket/groups.ts +0 -356
- package/src/Socket/index.ts +0 -13
- package/src/Socket/messages-recv.ts +0 -985
- package/src/Socket/messages-send.ts +0 -871
- package/src/Socket/newsletter.ts +0 -282
- package/src/Socket/registration.ts +0 -250
- package/src/Socket/socket.ts +0 -777
- package/src/Store/index.ts +0 -3
- package/src/Store/make-cache-manager-store.ts +0 -100
- package/src/Store/make-in-memory-store.ts +0 -475
- package/src/Store/make-ordered-dictionary.ts +0 -86
- package/src/Store/object-repository.ts +0 -32
- package/src/Tests/test.app-state-sync.js +0 -204
- package/src/Tests/test.app-state-sync.ts +0 -207
- package/src/Tests/test.event-buffer.js +0 -270
- package/src/Tests/test.event-buffer.ts +0 -319
- package/src/Tests/test.key-store.js +0 -76
- package/src/Tests/test.key-store.ts +0 -92
- package/src/Tests/test.libsignal.js +0 -141
- package/src/Tests/test.libsignal.ts +0 -186
- package/src/Tests/test.media-download.js +0 -93
- package/src/Tests/test.media-download.ts +0 -76
- package/src/Tests/test.messages.js +0 -33
- package/src/Tests/test.messages.ts +0 -37
- package/src/Tests/utils.js +0 -34
- package/src/Tests/utils.ts +0 -36
- package/src/Types/Auth.ts +0 -113
- package/src/Types/Call.ts +0 -15
- package/src/Types/Chat.ts +0 -106
- package/src/Types/Events.ts +0 -93
- package/src/Types/GroupMetadata.ts +0 -53
- package/src/Types/Label.ts +0 -36
- package/src/Types/Message.ts +0 -288
- package/src/Types/Newsletter.ts +0 -98
- package/src/Types/Product.ts +0 -85
- package/src/Types/Signal.ts +0 -68
- package/src/Types/State.ts +0 -29
- package/src/Types/index.ts +0 -59
- package/src/Utils/auth-utils.ts +0 -222
- package/src/Utils/baileys-event-stream.js +0 -92
- package/src/Utils/baileys-event-stream.ts +0 -66
- package/src/Utils/business.ts +0 -275
- package/src/Utils/chat-utils.ts +0 -860
- package/src/Utils/crypto.ts +0 -131
- package/src/Utils/decode-wa-message.js +0 -211
- package/src/Utils/decode-wa-message.ts +0 -228
- package/src/Utils/event-buffer.ts +0 -613
- package/src/Utils/generics.ts +0 -434
- package/src/Utils/history.ts +0 -112
- package/src/Utils/index.ts +0 -17
- package/src/Utils/link-preview.ts +0 -122
- package/src/Utils/logger.ts +0 -3
- package/src/Utils/lt-hash.ts +0 -61
- package/src/Utils/make-mutex.ts +0 -44
- package/src/Utils/messages-media.ts +0 -847
- package/src/Utils/messages.ts +0 -956
- package/src/Utils/noise-handler.ts +0 -197
- package/src/Utils/process-message.ts +0 -414
- package/src/Utils/signal.ts +0 -177
- package/src/Utils/use-multi-file-auth-state.ts +0 -90
- package/src/Utils/validate-connection.ts +0 -238
- package/src/WABinary/constants.ts +0 -42
- package/src/WABinary/decode.ts +0 -265
- package/src/WABinary/encode.ts +0 -236
- package/src/WABinary/generic-utils.ts +0 -121
- package/src/WABinary/index.ts +0 -5
- package/src/WABinary/jid-utils.ts +0 -68
- package/src/WABinary/types.ts +0 -17
- package/src/WAM/BinaryInfo.ts +0 -12
- package/src/WAM/constants.ts +0 -15382
- package/src/WAM/encode.ts +0 -174
- package/src/WAM/index.ts +0 -3
- package/src/gifted +0 -1
- package/src/index.ts +0 -13
- /package/{src → lib}/Defaults/phonenumber-mcc.json +0 -0
- /package/{src → lib}/Socket/Client/abstract-socket-client.js +0 -0
- /package/{src → lib}/Store/index.js +0 -0
- /package/{src → lib}/Store/make-ordered-dictionary.js +0 -0
- /package/{src → lib}/Types/Auth.js +0 -0
- /package/{src → lib}/Types/Call.js +0 -0
- /package/{src → lib}/Types/Chat.js +0 -0
- /package/{src → lib}/Types/Contact.js +0 -0
- /package/{src → lib}/Types/Events.js +0 -0
- /package/{src → lib}/Types/GroupMetadata.js +0 -0
- /package/{src → lib}/Types/Label.js +0 -0
- /package/{src → lib}/Types/LabelAssociation.js +0 -0
- /package/{src → lib}/Types/Message.js +0 -0
- /package/{src → lib}/Types/Newsletter.js +0 -0
- /package/{src → lib}/Types/Product.js +0 -0
- /package/{src → lib}/Types/Signal.js +0 -0
- /package/{src → lib}/Types/Socket.js +0 -0
- /package/{src → lib}/Types/State.js +0 -0
- /package/{src/WABinary/types.js → lib/Types/USync.js} +0 -0
- /package/{src → lib}/Types/index.js +0 -0
- /package/{src → lib}/Utils/index.js +0 -0
- /package/{src → lib}/Utils/logger.js +0 -0
- /package/{src → lib}/Utils/lt-hash.js +0 -0
- /package/{src → lib}/Utils/noise-handler.js +0 -0
- /package/{src → lib}/WABinary/constants.js +0 -0
- /package/{src → lib}/WABinary/decode.js +0 -0
- /package/{src → lib}/WABinary/generic-utils.js +0 -0
- /package/{src → lib}/WABinary/index.js +0 -0
- /package/{src → lib}/WABinary/jid-utils.js +0 -0
- /package/{src → lib}/WAM/BinaryInfo.js +0 -0
- /package/{src → lib}/WAM/constants.js +0 -0
- /package/{src → lib}/WAM/encode.js +0 -0
- /package/{src → lib}/WAM/index.js +0 -0
|
@@ -1,319 +0,0 @@
|
|
|
1
|
-
import { proto } from '../../WAProto'
|
|
2
|
-
import { Chat, WAMessageKey, WAMessageStatus, WAMessageStubType, WAMessageUpdate } from '../Types'
|
|
3
|
-
import { delay, generateMessageID, makeEventBuffer, toNumber, unixTimestampSeconds } from '../Utils'
|
|
4
|
-
import logger from '../Utils/logger'
|
|
5
|
-
import { randomJid } from './utils'
|
|
6
|
-
|
|
7
|
-
describe('Event Buffer Tests', () => {
|
|
8
|
-
|
|
9
|
-
let ev: ReturnType<typeof makeEventBuffer>
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
const _logger = logger.child({ })
|
|
12
|
-
_logger.level = 'trace'
|
|
13
|
-
ev = makeEventBuffer(_logger)
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
it('should buffer a chat upsert & update event', async() => {
|
|
17
|
-
const chatId = randomJid()
|
|
18
|
-
|
|
19
|
-
const chats: Chat[] = []
|
|
20
|
-
|
|
21
|
-
ev.on('chats.upsert', c => chats.push(...c))
|
|
22
|
-
ev.on('chats.update', () => fail('should not emit update event'))
|
|
23
|
-
|
|
24
|
-
ev.buffer()
|
|
25
|
-
await Promise.all([
|
|
26
|
-
(async() => {
|
|
27
|
-
ev.buffer()
|
|
28
|
-
await delay(100)
|
|
29
|
-
ev.emit('chats.upsert', [{ id: chatId, conversationTimestamp: 123, unreadCount: 1 }])
|
|
30
|
-
const flushed = ev.flush()
|
|
31
|
-
expect(flushed).toBeFalsy()
|
|
32
|
-
})(),
|
|
33
|
-
(async() => {
|
|
34
|
-
ev.buffer()
|
|
35
|
-
await delay(200)
|
|
36
|
-
ev.emit('chats.update', [{ id: chatId, conversationTimestamp: 124, unreadCount: 1 }])
|
|
37
|
-
const flushed = ev.flush()
|
|
38
|
-
expect(flushed).toBeFalsy()
|
|
39
|
-
})()
|
|
40
|
-
])
|
|
41
|
-
|
|
42
|
-
const flushed = ev.flush()
|
|
43
|
-
expect(flushed).toBeTruthy()
|
|
44
|
-
|
|
45
|
-
expect(chats).toHaveLength(1)
|
|
46
|
-
expect(chats[0].conversationTimestamp).toEqual(124)
|
|
47
|
-
expect(chats[0].unreadCount).toEqual(2)
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
it('should overwrite a chats.delete event', async() => {
|
|
51
|
-
const chatId = randomJid()
|
|
52
|
-
const chats: Partial<Chat>[] = []
|
|
53
|
-
|
|
54
|
-
ev.on('chats.update', c => chats.push(...c))
|
|
55
|
-
ev.on('chats.delete', () => fail('not should have emitted'))
|
|
56
|
-
|
|
57
|
-
ev.buffer()
|
|
58
|
-
|
|
59
|
-
ev.emit('chats.update', [{ id: chatId, conversationTimestamp: 123, unreadCount: 1 }])
|
|
60
|
-
ev.emit('chats.delete', [chatId])
|
|
61
|
-
ev.emit('chats.update', [{ id: chatId, conversationTimestamp: 124, unreadCount: 1 }])
|
|
62
|
-
|
|
63
|
-
ev.flush()
|
|
64
|
-
|
|
65
|
-
expect(chats).toHaveLength(1)
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
it('should overwrite a chats.update event', async() => {
|
|
69
|
-
const chatId = randomJid()
|
|
70
|
-
const chatsDeleted: string[] = []
|
|
71
|
-
|
|
72
|
-
ev.on('chats.delete', c => chatsDeleted.push(...c))
|
|
73
|
-
ev.on('chats.update', () => fail('not should have emitted'))
|
|
74
|
-
|
|
75
|
-
ev.buffer()
|
|
76
|
-
|
|
77
|
-
ev.emit('chats.update', [{ id: chatId, conversationTimestamp: 123, unreadCount: 1 }])
|
|
78
|
-
ev.emit('chats.delete', [chatId])
|
|
79
|
-
|
|
80
|
-
ev.flush()
|
|
81
|
-
|
|
82
|
-
expect(chatsDeleted).toHaveLength(1)
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
it('should release a conditional update at the right time', async() => {
|
|
86
|
-
const chatId = randomJid()
|
|
87
|
-
const chatId2 = randomJid()
|
|
88
|
-
const chatsUpserted: Chat[] = []
|
|
89
|
-
const chatsSynced: Chat[] = []
|
|
90
|
-
|
|
91
|
-
ev.on('chats.upsert', c => chatsUpserted.push(...c))
|
|
92
|
-
ev.on('messaging-history.set', c => chatsSynced.push(...c.chats))
|
|
93
|
-
ev.on('chats.update', () => fail('not should have emitted'))
|
|
94
|
-
|
|
95
|
-
ev.buffer()
|
|
96
|
-
ev.emit('chats.update', [{
|
|
97
|
-
id: chatId,
|
|
98
|
-
archived: true,
|
|
99
|
-
conditional(buff) {
|
|
100
|
-
if(buff.chatUpserts[chatId]) {
|
|
101
|
-
return true
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}])
|
|
105
|
-
ev.emit('chats.update', [{
|
|
106
|
-
id: chatId2,
|
|
107
|
-
archived: true,
|
|
108
|
-
conditional(buff) {
|
|
109
|
-
if(buff.historySets.chats[chatId2]) {
|
|
110
|
-
return true
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}])
|
|
114
|
-
|
|
115
|
-
ev.flush()
|
|
116
|
-
|
|
117
|
-
ev.buffer()
|
|
118
|
-
ev.emit('chats.upsert', [{
|
|
119
|
-
id: chatId,
|
|
120
|
-
conversationTimestamp: 123,
|
|
121
|
-
unreadCount: 1,
|
|
122
|
-
muteEndTime: 123
|
|
123
|
-
}])
|
|
124
|
-
ev.emit('messaging-history.set', {
|
|
125
|
-
chats: [{
|
|
126
|
-
id: chatId2,
|
|
127
|
-
conversationTimestamp: 123,
|
|
128
|
-
unreadCount: 1,
|
|
129
|
-
muteEndTime: 123
|
|
130
|
-
}],
|
|
131
|
-
contacts: [],
|
|
132
|
-
messages: [],
|
|
133
|
-
isLatest: false
|
|
134
|
-
})
|
|
135
|
-
ev.flush()
|
|
136
|
-
|
|
137
|
-
expect(chatsUpserted).toHaveLength(1)
|
|
138
|
-
expect(chatsUpserted[0].id).toEqual(chatId)
|
|
139
|
-
expect(chatsUpserted[0].archived).toEqual(true)
|
|
140
|
-
expect(chatsUpserted[0].muteEndTime).toEqual(123)
|
|
141
|
-
|
|
142
|
-
expect(chatsSynced).toHaveLength(1)
|
|
143
|
-
expect(chatsSynced[0].id).toEqual(chatId2)
|
|
144
|
-
expect(chatsSynced[0].archived).toEqual(true)
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
it('should discard a conditional update', async() => {
|
|
148
|
-
const chatId = randomJid()
|
|
149
|
-
const chatsUpserted: Chat[] = []
|
|
150
|
-
|
|
151
|
-
ev.on('chats.upsert', c => chatsUpserted.push(...c))
|
|
152
|
-
ev.on('chats.update', () => fail('not should have emitted'))
|
|
153
|
-
|
|
154
|
-
ev.buffer()
|
|
155
|
-
ev.emit('chats.update', [{
|
|
156
|
-
id: chatId,
|
|
157
|
-
archived: true,
|
|
158
|
-
conditional(buff) {
|
|
159
|
-
if(buff.chatUpserts[chatId]) {
|
|
160
|
-
return false
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}])
|
|
164
|
-
ev.emit('chats.upsert', [{
|
|
165
|
-
id: chatId,
|
|
166
|
-
conversationTimestamp: 123,
|
|
167
|
-
unreadCount: 1,
|
|
168
|
-
muteEndTime: 123
|
|
169
|
-
}])
|
|
170
|
-
|
|
171
|
-
ev.flush()
|
|
172
|
-
|
|
173
|
-
expect(chatsUpserted).toHaveLength(1)
|
|
174
|
-
expect(chatsUpserted[0].archived).toBeUndefined()
|
|
175
|
-
})
|
|
176
|
-
|
|
177
|
-
it('should overwrite a chats.update event with a history event', async() => {
|
|
178
|
-
const chatId = randomJid()
|
|
179
|
-
let chatRecv: Chat | undefined
|
|
180
|
-
|
|
181
|
-
ev.on('messaging-history.set', ({ chats }) => {
|
|
182
|
-
chatRecv = chats[0]
|
|
183
|
-
})
|
|
184
|
-
ev.on('chats.update', () => fail('not should have emitted'))
|
|
185
|
-
|
|
186
|
-
ev.buffer()
|
|
187
|
-
|
|
188
|
-
ev.emit('messaging-history.set', {
|
|
189
|
-
chats: [{ id: chatId, conversationTimestamp: 123, unreadCount: 1 }],
|
|
190
|
-
messages: [],
|
|
191
|
-
contacts: [],
|
|
192
|
-
isLatest: true
|
|
193
|
-
})
|
|
194
|
-
ev.emit('chats.update', [{ id: chatId, archived: true }])
|
|
195
|
-
|
|
196
|
-
ev.flush()
|
|
197
|
-
|
|
198
|
-
expect(chatRecv).toBeDefined()
|
|
199
|
-
expect(chatRecv?.archived).toBeTruthy()
|
|
200
|
-
})
|
|
201
|
-
|
|
202
|
-
it('should buffer message upsert events', async() => {
|
|
203
|
-
const messageTimestamp = unixTimestampSeconds()
|
|
204
|
-
const msg: proto.IWebMessageInfo = {
|
|
205
|
-
key: {
|
|
206
|
-
remoteJid: randomJid(),
|
|
207
|
-
id: generateMessageID(),
|
|
208
|
-
fromMe: false
|
|
209
|
-
},
|
|
210
|
-
messageStubType: WAMessageStubType.CIPHERTEXT,
|
|
211
|
-
messageTimestamp
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
const msgs: proto.IWebMessageInfo[] = []
|
|
215
|
-
|
|
216
|
-
ev.on('messages.upsert', c => {
|
|
217
|
-
msgs.push(...c.messages)
|
|
218
|
-
expect(c.type).toEqual('notify')
|
|
219
|
-
})
|
|
220
|
-
|
|
221
|
-
ev.buffer()
|
|
222
|
-
ev.emit('messages.upsert', { messages: [proto.WebMessageInfo.fromObject(msg)], type: 'notify' })
|
|
223
|
-
|
|
224
|
-
msg.messageTimestamp = unixTimestampSeconds() + 1
|
|
225
|
-
msg.messageStubType = undefined
|
|
226
|
-
msg.message = { conversation: 'Test' }
|
|
227
|
-
ev.emit('messages.upsert', { messages: [proto.WebMessageInfo.fromObject(msg)], type: 'notify' })
|
|
228
|
-
ev.emit('messages.update', [{ key: msg.key, update: { status: WAMessageStatus.READ } }])
|
|
229
|
-
|
|
230
|
-
ev.flush()
|
|
231
|
-
|
|
232
|
-
expect(msgs).toHaveLength(1)
|
|
233
|
-
expect(msgs[0].message).toBeTruthy()
|
|
234
|
-
expect(toNumber(msgs[0].messageTimestamp!)).toEqual(messageTimestamp)
|
|
235
|
-
expect(msgs[0].status).toEqual(WAMessageStatus.READ)
|
|
236
|
-
})
|
|
237
|
-
|
|
238
|
-
it('should buffer a message receipt update', async() => {
|
|
239
|
-
const msg: proto.IWebMessageInfo = {
|
|
240
|
-
key: {
|
|
241
|
-
remoteJid: randomJid(),
|
|
242
|
-
id: generateMessageID(),
|
|
243
|
-
fromMe: false
|
|
244
|
-
},
|
|
245
|
-
messageStubType: WAMessageStubType.CIPHERTEXT,
|
|
246
|
-
messageTimestamp: unixTimestampSeconds()
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
const msgs: proto.IWebMessageInfo[] = []
|
|
250
|
-
|
|
251
|
-
ev.on('messages.upsert', c => msgs.push(...c.messages))
|
|
252
|
-
ev.on('message-receipt.update', () => fail('should not emit'))
|
|
253
|
-
|
|
254
|
-
ev.buffer()
|
|
255
|
-
ev.emit('messages.upsert', { messages: [proto.WebMessageInfo.fromObject(msg)], type: 'notify' })
|
|
256
|
-
ev.emit('message-receipt.update', [
|
|
257
|
-
{
|
|
258
|
-
key: msg.key,
|
|
259
|
-
receipt: {
|
|
260
|
-
userJid: randomJid(),
|
|
261
|
-
readTimestamp: unixTimestampSeconds()
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
])
|
|
265
|
-
|
|
266
|
-
ev.flush()
|
|
267
|
-
|
|
268
|
-
expect(msgs).toHaveLength(1)
|
|
269
|
-
expect(msgs[0].userReceipt).toHaveLength(1)
|
|
270
|
-
})
|
|
271
|
-
|
|
272
|
-
it('should buffer multiple status updates', async() => {
|
|
273
|
-
const key: WAMessageKey = {
|
|
274
|
-
remoteJid: randomJid(),
|
|
275
|
-
id: generateMessageID(),
|
|
276
|
-
fromMe: false
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
const msgs: WAMessageUpdate[] = []
|
|
280
|
-
|
|
281
|
-
ev.on('messages.update', c => msgs.push(...c))
|
|
282
|
-
|
|
283
|
-
ev.buffer()
|
|
284
|
-
ev.emit('messages.update', [{ key, update: { status: WAMessageStatus.DELIVERY_ACK } }])
|
|
285
|
-
ev.emit('messages.update', [{ key, update: { status: WAMessageStatus.READ } }])
|
|
286
|
-
|
|
287
|
-
ev.flush()
|
|
288
|
-
|
|
289
|
-
expect(msgs).toHaveLength(1)
|
|
290
|
-
expect(msgs[0].update.status).toEqual(WAMessageStatus.READ)
|
|
291
|
-
})
|
|
292
|
-
|
|
293
|
-
it('should remove chat unread counter', async() => {
|
|
294
|
-
const msg: proto.IWebMessageInfo = {
|
|
295
|
-
key: {
|
|
296
|
-
remoteJid: '12345@s.whatsapp.net',
|
|
297
|
-
id: generateMessageID(),
|
|
298
|
-
fromMe: false
|
|
299
|
-
},
|
|
300
|
-
message: {
|
|
301
|
-
conversation: 'abcd'
|
|
302
|
-
},
|
|
303
|
-
messageTimestamp: unixTimestampSeconds()
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
const chats: Partial<Chat>[] = []
|
|
307
|
-
|
|
308
|
-
ev.on('chats.update', c => chats.push(...c))
|
|
309
|
-
|
|
310
|
-
ev.buffer()
|
|
311
|
-
ev.emit('messages.upsert', { messages: [proto.WebMessageInfo.fromObject(msg)], type: 'notify' })
|
|
312
|
-
ev.emit('chats.update', [{ id: msg.key.remoteJid!, unreadCount: 1, conversationTimestamp: msg.messageTimestamp }])
|
|
313
|
-
ev.emit('messages.update', [{ key: msg.key, update: { status: WAMessageStatus.READ } }])
|
|
314
|
-
|
|
315
|
-
ev.flush()
|
|
316
|
-
|
|
317
|
-
expect(chats[0].unreadCount).toBeUndefined()
|
|
318
|
-
})
|
|
319
|
-
})
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
const Utils_1 = require("../Utils");
|
|
16
|
-
const logger_1 = __importDefault(require("../Utils/logger"));
|
|
17
|
-
const utils_1 = require("./utils");
|
|
18
|
-
logger_1.default.level = 'trace';
|
|
19
|
-
describe('Key Store w Transaction Tests', () => {
|
|
20
|
-
const rawStore = (0, utils_1.makeMockSignalKeyStore)();
|
|
21
|
-
const store = (0, Utils_1.addTransactionCapability)(rawStore, logger_1.default, {
|
|
22
|
-
maxCommitRetries: 1,
|
|
23
|
-
delayBetweenTriesMs: 10
|
|
24
|
-
});
|
|
25
|
-
it('should use transaction cache when mutated', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
26
|
-
const key = '123';
|
|
27
|
-
const value = new Uint8Array(1);
|
|
28
|
-
const ogGet = rawStore.get;
|
|
29
|
-
yield store.transaction(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
30
|
-
yield store.set({ 'session': { [key]: value } });
|
|
31
|
-
rawStore.get = () => {
|
|
32
|
-
throw new Error('should not have been called');
|
|
33
|
-
};
|
|
34
|
-
const { [key]: stored } = yield store.get('session', [key]);
|
|
35
|
-
expect(stored).toEqual(new Uint8Array(1));
|
|
36
|
-
}));
|
|
37
|
-
rawStore.get = ogGet;
|
|
38
|
-
}));
|
|
39
|
-
it('should not commit a failed transaction', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
40
|
-
const key = 'abcd';
|
|
41
|
-
yield expect(store.transaction(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
42
|
-
yield store.set({ 'session': { [key]: new Uint8Array(1) } });
|
|
43
|
-
throw new Error('fail');
|
|
44
|
-
}))).rejects.toThrowError('fail');
|
|
45
|
-
const { [key]: stored } = yield store.get('session', [key]);
|
|
46
|
-
expect(stored).toBeUndefined();
|
|
47
|
-
}));
|
|
48
|
-
it('should handle overlapping transactions', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
49
|
-
// promise to let transaction 2
|
|
50
|
-
// know that transaction 1 has started
|
|
51
|
-
let promiseResolve;
|
|
52
|
-
const promise = new Promise(resolve => {
|
|
53
|
-
promiseResolve = resolve;
|
|
54
|
-
});
|
|
55
|
-
store.transaction(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
56
|
-
yield store.set({
|
|
57
|
-
'session': {
|
|
58
|
-
'1': new Uint8Array(1)
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
// wait for the other transaction to start
|
|
62
|
-
yield (0, Utils_1.delay)(5);
|
|
63
|
-
// reolve the promise to let the other transaction continue
|
|
64
|
-
promiseResolve();
|
|
65
|
-
}));
|
|
66
|
-
yield store.transaction(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
67
|
-
yield promise;
|
|
68
|
-
yield (0, Utils_1.delay)(5);
|
|
69
|
-
expect(store.isInTransaction()).toBe(true);
|
|
70
|
-
}));
|
|
71
|
-
expect(store.isInTransaction()).toBe(false);
|
|
72
|
-
// ensure that the transaction were committed
|
|
73
|
-
const { ['1']: stored } = yield store.get('session', ['1']);
|
|
74
|
-
expect(stored).toEqual(new Uint8Array(1));
|
|
75
|
-
}));
|
|
76
|
-
});
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { addTransactionCapability, delay } from '../Utils'
|
|
2
|
-
import logger from '../Utils/logger'
|
|
3
|
-
import { makeMockSignalKeyStore } from './utils'
|
|
4
|
-
|
|
5
|
-
logger.level = 'trace'
|
|
6
|
-
|
|
7
|
-
describe('Key Store w Transaction Tests', () => {
|
|
8
|
-
|
|
9
|
-
const rawStore = makeMockSignalKeyStore()
|
|
10
|
-
const store = addTransactionCapability(
|
|
11
|
-
rawStore,
|
|
12
|
-
logger,
|
|
13
|
-
{
|
|
14
|
-
maxCommitRetries: 1,
|
|
15
|
-
delayBetweenTriesMs: 10
|
|
16
|
-
}
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
it('should use transaction cache when mutated', async() => {
|
|
20
|
-
const key = '123'
|
|
21
|
-
const value = new Uint8Array(1)
|
|
22
|
-
const ogGet = rawStore.get
|
|
23
|
-
await store.transaction(
|
|
24
|
-
async() => {
|
|
25
|
-
await store.set({ 'session': { [key]: value } })
|
|
26
|
-
|
|
27
|
-
rawStore.get = () => {
|
|
28
|
-
throw new Error('should not have been called')
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const { [key]: stored } = await store.get('session', [key])
|
|
32
|
-
expect(stored).toEqual(new Uint8Array(1))
|
|
33
|
-
}
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
rawStore.get = ogGet
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
it('should not commit a failed transaction', async() => {
|
|
40
|
-
const key = 'abcd'
|
|
41
|
-
await expect(
|
|
42
|
-
store.transaction(
|
|
43
|
-
async() => {
|
|
44
|
-
await store.set({ 'session': { [key]: new Uint8Array(1) } })
|
|
45
|
-
throw new Error('fail')
|
|
46
|
-
}
|
|
47
|
-
)
|
|
48
|
-
).rejects.toThrowError(
|
|
49
|
-
'fail'
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
const { [key]: stored } = await store.get('session', [key])
|
|
53
|
-
expect(stored).toBeUndefined()
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
it('should handle overlapping transactions', async() => {
|
|
57
|
-
// promise to let transaction 2
|
|
58
|
-
// know that transaction 1 has started
|
|
59
|
-
let promiseResolve: () => void
|
|
60
|
-
const promise = new Promise<void>(resolve => {
|
|
61
|
-
promiseResolve = resolve
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
store.transaction(
|
|
65
|
-
async() => {
|
|
66
|
-
await store.set({
|
|
67
|
-
'session': {
|
|
68
|
-
'1': new Uint8Array(1)
|
|
69
|
-
}
|
|
70
|
-
})
|
|
71
|
-
// wait for the other transaction to start
|
|
72
|
-
await delay(5)
|
|
73
|
-
// reolve the promise to let the other transaction continue
|
|
74
|
-
promiseResolve()
|
|
75
|
-
}
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
await store.transaction(
|
|
79
|
-
async() => {
|
|
80
|
-
await promise
|
|
81
|
-
await delay(5)
|
|
82
|
-
|
|
83
|
-
expect(store.isInTransaction()).toBe(true)
|
|
84
|
-
}
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
expect(store.isInTransaction()).toBe(false)
|
|
88
|
-
// ensure that the transaction were committed
|
|
89
|
-
const { ['1']: stored } = await store.get('session', ['1'])
|
|
90
|
-
expect(stored).toEqual(new Uint8Array(1))
|
|
91
|
-
})
|
|
92
|
-
})
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
const libsignal_1 = require("../Signal/libsignal");
|
|
13
|
-
const Utils_1 = require("../Utils");
|
|
14
|
-
describe('Signal Tests', () => {
|
|
15
|
-
it('should correctly encrypt/decrypt 1 message', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
16
|
-
const user1 = makeUser();
|
|
17
|
-
const user2 = makeUser();
|
|
18
|
-
const msg = Buffer.from('hello there!');
|
|
19
|
-
yield prepareForSendingMessage(user1, user2);
|
|
20
|
-
const result = yield user1.repository.encryptMessage({ jid: user2.jid, data: msg });
|
|
21
|
-
const dec = yield user2.repository.decryptMessage(Object.assign({ jid: user1.jid }, result));
|
|
22
|
-
expect(dec).toEqual(msg);
|
|
23
|
-
}));
|
|
24
|
-
it('should correctly override a session', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
25
|
-
const user1 = makeUser();
|
|
26
|
-
const user2 = makeUser();
|
|
27
|
-
const msg = Buffer.from('hello there!');
|
|
28
|
-
for (let preKeyId = 2; preKeyId <= 3; preKeyId++) {
|
|
29
|
-
yield prepareForSendingMessage(user1, user2, preKeyId);
|
|
30
|
-
const result = yield user1.repository.encryptMessage({ jid: user2.jid, data: msg });
|
|
31
|
-
const dec = yield user2.repository.decryptMessage(Object.assign({ jid: user1.jid }, result));
|
|
32
|
-
expect(dec).toEqual(msg);
|
|
33
|
-
}
|
|
34
|
-
}));
|
|
35
|
-
it('should correctly encrypt/decrypt multiple messages', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
36
|
-
const user1 = makeUser();
|
|
37
|
-
const user2 = makeUser();
|
|
38
|
-
const msg = Buffer.from('hello there!');
|
|
39
|
-
yield prepareForSendingMessage(user1, user2);
|
|
40
|
-
for (let i = 0; i < 10; i++) {
|
|
41
|
-
const result = yield user1.repository.encryptMessage({ jid: user2.jid, data: msg });
|
|
42
|
-
const dec = yield user2.repository.decryptMessage(Object.assign({ jid: user1.jid }, result));
|
|
43
|
-
expect(dec).toEqual(msg);
|
|
44
|
-
}
|
|
45
|
-
}));
|
|
46
|
-
it('should encrypt/decrypt messages from group', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
47
|
-
const groupId = '123456@g.us';
|
|
48
|
-
const participants = [...Array(5)].map(makeUser);
|
|
49
|
-
const msg = Buffer.from('hello there!');
|
|
50
|
-
const sender = participants[0];
|
|
51
|
-
const enc = yield sender.repository.encryptGroupMessage({
|
|
52
|
-
group: groupId,
|
|
53
|
-
meId: sender.jid,
|
|
54
|
-
data: msg
|
|
55
|
-
});
|
|
56
|
-
for (const participant of participants) {
|
|
57
|
-
if (participant === sender) {
|
|
58
|
-
continue;
|
|
59
|
-
}
|
|
60
|
-
yield participant.repository.processSenderKeyDistributionMessage({
|
|
61
|
-
item: {
|
|
62
|
-
groupId,
|
|
63
|
-
axolotlSenderKeyDistributionMessage: enc.senderKeyDistributionMessage
|
|
64
|
-
},
|
|
65
|
-
authorJid: sender.jid
|
|
66
|
-
});
|
|
67
|
-
const dec = yield participant.repository.decryptGroupMessage({
|
|
68
|
-
group: groupId,
|
|
69
|
-
authorJid: sender.jid,
|
|
70
|
-
msg: enc.ciphertext
|
|
71
|
-
});
|
|
72
|
-
expect(dec).toEqual(msg);
|
|
73
|
-
}
|
|
74
|
-
}));
|
|
75
|
-
});
|
|
76
|
-
function makeUser() {
|
|
77
|
-
const store = makeTestAuthState();
|
|
78
|
-
const jid = `${Math.random().toString().replace('.', '')}@s.whatsapp.net`;
|
|
79
|
-
const repository = (0, libsignal_1.makeLibSignalRepository)(store);
|
|
80
|
-
return { store, jid, repository };
|
|
81
|
-
}
|
|
82
|
-
function prepareForSendingMessage(sender_1, receiver_1) {
|
|
83
|
-
return __awaiter(this, arguments, void 0, function* (sender, receiver, preKeyId = 2) {
|
|
84
|
-
const preKey = Utils_1.Curve.generateKeyPair();
|
|
85
|
-
yield sender.repository.injectE2ESession({
|
|
86
|
-
jid: receiver.jid,
|
|
87
|
-
session: {
|
|
88
|
-
registrationId: receiver.store.creds.registrationId,
|
|
89
|
-
identityKey: (0, Utils_1.generateSignalPubKey)(receiver.store.creds.signedIdentityKey.public),
|
|
90
|
-
signedPreKey: {
|
|
91
|
-
keyId: receiver.store.creds.signedPreKey.keyId,
|
|
92
|
-
publicKey: (0, Utils_1.generateSignalPubKey)(receiver.store.creds.signedPreKey.keyPair.public),
|
|
93
|
-
signature: receiver.store.creds.signedPreKey.signature,
|
|
94
|
-
},
|
|
95
|
-
preKey: {
|
|
96
|
-
keyId: preKeyId,
|
|
97
|
-
publicKey: (0, Utils_1.generateSignalPubKey)(preKey.public),
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
yield receiver.store.keys.set({
|
|
102
|
-
'pre-key': {
|
|
103
|
-
[preKeyId]: preKey
|
|
104
|
-
}
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
function makeTestAuthState() {
|
|
109
|
-
const identityKey = Utils_1.Curve.generateKeyPair();
|
|
110
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
111
|
-
const store = {};
|
|
112
|
-
return {
|
|
113
|
-
creds: {
|
|
114
|
-
signedIdentityKey: identityKey,
|
|
115
|
-
registrationId: (0, Utils_1.generateRegistrationId)(),
|
|
116
|
-
signedPreKey: (0, Utils_1.signedKeyPair)(identityKey, 1),
|
|
117
|
-
},
|
|
118
|
-
keys: {
|
|
119
|
-
get(type, ids) {
|
|
120
|
-
const data = {};
|
|
121
|
-
for (const id of ids) {
|
|
122
|
-
const item = store[getUniqueId(type, id)];
|
|
123
|
-
if (typeof item !== 'undefined') {
|
|
124
|
-
data[id] = item;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
return data;
|
|
128
|
-
},
|
|
129
|
-
set(data) {
|
|
130
|
-
for (const type in data) {
|
|
131
|
-
for (const id in data[type]) {
|
|
132
|
-
store[getUniqueId(type, id)] = data[type][id];
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
},
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
function getUniqueId(type, id) {
|
|
139
|
-
return `${type}.${id}`;
|
|
140
|
-
}
|
|
141
|
-
}
|