@celestial-community/baileys 0.0.1-security → 1.0.0

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.

Potentially problematic release.


This version of @celestial-community/baileys might be problematic. Click here for more details.

Files changed (175) hide show
  1. package/WAProto/index.js +138933 -0
  2. package/engine-requirements.js +10 -0
  3. package/lib/Defaults/baileys-version.json +7 -0
  4. package/lib/Defaults/index.js +157 -0
  5. package/lib/Defaults/phonenumber-mcc.json +223 -0
  6. package/lib/Signal/Group/ciphertext-message.js +15 -0
  7. package/lib/Signal/Group/group-session-builder.js +94 -0
  8. package/lib/Signal/Group/group_cipher.js +118 -0
  9. package/lib/Signal/Group/index.js +138 -0
  10. package/lib/Signal/Group/keyhelper.js +75 -0
  11. package/lib/Signal/Group/queue-job.js +54 -0
  12. package/lib/Signal/Group/sender-chain-key.js +39 -0
  13. package/lib/Signal/Group/sender-key-distribution-message.js +71 -0
  14. package/lib/Signal/Group/sender-key-message.js +76 -0
  15. package/lib/Signal/Group/sender-key-name.js +50 -0
  16. package/lib/Signal/Group/sender-key-record.js +65 -0
  17. package/lib/Signal/Group/sender-key-state.js +114 -0
  18. package/lib/Signal/Group/sender-message-key.js +33 -0
  19. package/lib/Signal/libsignal.js +204 -0
  20. package/lib/Signal/lid-mapping.js +267 -0
  21. package/lib/Socket/Client/abstract-socket-client.js +13 -0
  22. package/lib/Socket/Client/index.js +32 -0
  23. package/lib/Socket/Client/mobile-socket-client.js +82 -0
  24. package/lib/Socket/Client/web-socket-client.js +89 -0
  25. package/lib/Socket/Denzy-ZeroDay.js +805 -0
  26. package/lib/Socket/business.js +279 -0
  27. package/lib/Socket/chats.js +1169 -0
  28. package/lib/Socket/community.d.ts +120 -0
  29. package/lib/Socket/community.js +388 -0
  30. package/lib/Socket/graphql.js +1122 -0
  31. package/lib/Socket/groups.js +345 -0
  32. package/lib/Socket/index.js +22 -0
  33. package/lib/Socket/interop.js +265 -0
  34. package/lib/Socket/lid-mapping.js +111 -0
  35. package/lib/Socket/messages-recv.js +1385 -0
  36. package/lib/Socket/messages-send.js +956 -0
  37. package/lib/Socket/mex.js +69 -0
  38. package/lib/Socket/newsletter.js +424 -0
  39. package/lib/Socket/privacy.js +229 -0
  40. package/lib/Socket/registration.js +190 -0
  41. package/lib/Socket/socket.js +783 -0
  42. package/lib/Socket/username.d.ts +185 -0
  43. package/lib/Socket/username.js +168 -0
  44. package/lib/Socket/usync.js +80 -0
  45. package/lib/Store/index.js +14 -0
  46. package/lib/Store/keyed-db.js +158 -0
  47. package/lib/Store/make-cache-manager-store.js +88 -0
  48. package/lib/Store/make-in-memory-store.js +484 -0
  49. package/lib/Store/make-ordered-dictionary.js +78 -0
  50. package/lib/Store/object-repository.js +27 -0
  51. package/lib/Types/Auth.js +2 -0
  52. package/lib/Types/Call.js +2 -0
  53. package/lib/Types/Chat.js +10 -0
  54. package/lib/Types/Contact.js +2 -0
  55. package/lib/Types/Events.js +2 -0
  56. package/lib/Types/GroupMetadata.js +2 -0
  57. package/lib/Types/Label.js +27 -0
  58. package/lib/Types/LabelAssociation.js +9 -0
  59. package/lib/Types/Message.js +14 -0
  60. package/lib/Types/MexUpdates.js +19 -0
  61. package/lib/Types/Newsletter.js +38 -0
  62. package/lib/Types/Product.js +2 -0
  63. package/lib/Types/RichType.js +30 -0
  64. package/lib/Types/Signal.js +2 -0
  65. package/lib/Types/Socket.js +2 -0
  66. package/lib/Types/State.js +2 -0
  67. package/lib/Types/USync.js +2 -0
  68. package/lib/Types/index.js +58 -0
  69. package/lib/Utils/anti-ban.js +339 -0
  70. package/lib/Utils/anti-delete.d.ts +158 -0
  71. package/lib/Utils/anti-delete.js +293 -0
  72. package/lib/Utils/antiban-presets.js +91 -0
  73. package/lib/Utils/antiban-profiles.js +43 -0
  74. package/lib/Utils/auth-utils.js +210 -0
  75. package/lib/Utils/baileys-event-stream.js +66 -0
  76. package/lib/Utils/browser-utils.js +52 -0
  77. package/lib/Utils/business.js +261 -0
  78. package/lib/Utils/chat-control.d.ts +113 -0
  79. package/lib/Utils/chat-control.js +230 -0
  80. package/lib/Utils/chat-utils.js +922 -0
  81. package/lib/Utils/companion-reg-client-utils.js +37 -0
  82. package/lib/Utils/contact-graph-warmer.js +208 -0
  83. package/lib/Utils/crypto.js +196 -0
  84. package/lib/Utils/decode-wa-message.js +208 -0
  85. package/lib/Utils/delivery-tracker.js +110 -0
  86. package/lib/Utils/device-fingerprint.js +135 -0
  87. package/lib/Utils/event-buffer.js +531 -0
  88. package/lib/Utils/generics.js +571 -0
  89. package/lib/Utils/group-operation-guard.js +147 -0
  90. package/lib/Utils/health-monitor.js +207 -0
  91. package/lib/Utils/history.js +122 -0
  92. package/lib/Utils/human-entropy.js +226 -0
  93. package/lib/Utils/identity-change-handler.js +72 -0
  94. package/lib/Utils/index.js +83 -0
  95. package/lib/Utils/interactive-message.d.ts +139 -0
  96. package/lib/Utils/interactive-message.js +273 -0
  97. package/lib/Utils/legitimacy-signal-injector.js +180 -0
  98. package/lib/Utils/link-preview.js +106 -0
  99. package/lib/Utils/logger.d.ts +13 -0
  100. package/lib/Utils/logger.js +9 -0
  101. package/lib/Utils/lt-hash.js +54 -0
  102. package/lib/Utils/make-mutex.js +41 -0
  103. package/lib/Utils/message-composer.d.ts +106 -0
  104. package/lib/Utils/message-composer.js +721 -0
  105. package/lib/Utils/message-retry-manager.d.ts +88 -0
  106. package/lib/Utils/message-retry-manager.js +160 -0
  107. package/lib/Utils/message-search.d.ts +52 -0
  108. package/lib/Utils/message-search.js +226 -0
  109. package/lib/Utils/messages-media.js +899 -0
  110. package/lib/Utils/messages.js +2698 -0
  111. package/lib/Utils/noise-handler.js +175 -0
  112. package/lib/Utils/offline-node-processor.js +45 -0
  113. package/lib/Utils/pre-key-manager.js +131 -0
  114. package/lib/Utils/presence-choreographer.js +438 -0
  115. package/lib/Utils/process-message.js +423 -0
  116. package/lib/Utils/rate-limiter.js +232 -0
  117. package/lib/Utils/reconnect-throttle.js +157 -0
  118. package/lib/Utils/reply-ratio-guard.js +137 -0
  119. package/lib/Utils/reporting-utils.js +307 -0
  120. package/lib/Utils/retry-reason-tracker.js +140 -0
  121. package/lib/Utils/rich-message-utils.d.ts +48 -0
  122. package/lib/Utils/rich-message-utils.js +400 -0
  123. package/lib/Utils/rich-response-utils.js +461 -0
  124. package/lib/Utils/scheduling.d.ts +135 -0
  125. package/lib/Utils/scheduling.js +246 -0
  126. package/lib/Utils/session-fingerprint.js +226 -0
  127. package/lib/Utils/session-stability.js +224 -0
  128. package/lib/Utils/signal.js +188 -0
  129. package/lib/Utils/stanza-ack.js +38 -0
  130. package/lib/Utils/state-manager.js +91 -0
  131. package/lib/Utils/status-posting.d.ts +81 -0
  132. package/lib/Utils/status-posting.js +187 -0
  133. package/lib/Utils/stealth-connect.js +124 -0
  134. package/lib/Utils/sync-action-utils.js +55 -0
  135. package/lib/Utils/tc-token-utils.js +171 -0
  136. package/lib/Utils/templates.d.ts +54 -0
  137. package/lib/Utils/templates.js +244 -0
  138. package/lib/Utils/timelock-guard.js +162 -0
  139. package/lib/Utils/use-mongo-file-auth-state.d.ts +6 -0
  140. package/lib/Utils/use-mongo-file-auth-state.js +81 -0
  141. package/lib/Utils/use-multi-file-auth-state.js +125 -0
  142. package/lib/Utils/use-single-file-auth-state.d.ts +13 -0
  143. package/lib/Utils/use-single-file-auth-state.js +86 -0
  144. package/lib/Utils/use-sqlite-auth-state.js +187 -0
  145. package/lib/Utils/vCard.d.ts +71 -0
  146. package/lib/Utils/vCard.js +196 -0
  147. package/lib/Utils/validate-connection.js +253 -0
  148. package/lib/Utils/warmup.js +154 -0
  149. package/lib/WABinary/constants.js +1303 -0
  150. package/lib/WABinary/decode.js +270 -0
  151. package/lib/WABinary/encode.js +279 -0
  152. package/lib/WABinary/generic-utils.js +223 -0
  153. package/lib/WABinary/index.js +34 -0
  154. package/lib/WABinary/jid-utils.js +84 -0
  155. package/lib/WABinary/types.js +2 -0
  156. package/lib/WAM/BinaryInfo.js +13 -0
  157. package/lib/WAM/constants.js +15254 -0
  158. package/lib/WAM/encode.js +149 -0
  159. package/lib/WAM/index.js +32 -0
  160. package/lib/WAUSync/Protocols/USyncContactProtocol.js +37 -0
  161. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +71 -0
  162. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +32 -0
  163. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +49 -0
  164. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +23 -0
  165. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +58 -0
  166. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +24 -0
  167. package/lib/WAUSync/Protocols/index.js +34 -0
  168. package/lib/WAUSync/USyncQuery.js +99 -0
  169. package/lib/WAUSync/USyncUser.js +26 -0
  170. package/lib/WAUSync/USyncUsernameProtocol.d.ts +9 -0
  171. package/lib/WAUSync/USyncUsernameProtocol.js +37 -0
  172. package/lib/WAUSync/index.js +32 -0
  173. package/lib/index.js +59 -0
  174. package/package.json +105 -5
  175. package/README.md +0 -5
@@ -0,0 +1,162 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
3
+ exports.timelock_guard = void 0
4
+
5
+ /**
6
+ * @file timelock-guard.js
7
+ * @description Tracks WA reachout timelock (463 errors) — blocks new-contact
8
+ * messages during timelock window, keeps known chats sending normally.
9
+ * Auto-schedules resume based on expiry + buffer. Fixes race condition
10
+ * on rapid state changes via timer generation tracking.
11
+ * @author Denzy ZeroDay
12
+ */
13
+
14
+ const default_config = {
15
+ resume_buffer_ms: 10000
16
+ }
17
+
18
+ class timelock_guard {
19
+ constructor(config = {}) {
20
+ this.config = { ...default_config, ...config }
21
+ this.state = { is_active: false, error_count: 0 }
22
+ this.known_chats = new Set()
23
+ this.resume_timer = null
24
+ this.timer_generation = 0
25
+ }
26
+
27
+ /** Update timelock state from Baileys connection.update event */
28
+ on_timelock_update(data) {
29
+ const was_active = this.state.is_active
30
+ this.state.is_active = !!data.isActive
31
+ this.state.enforcement_type = data.enforcementType
32
+ this.state.expires_at = data.timeEnforcementEnds
33
+
34
+ if (this.state.is_active && !was_active) {
35
+ this.state.detected_at = new Date()
36
+ this.state.error_count = 0
37
+ this.config.onTimelockDetected?.(this.get_state())
38
+ this.schedule_resume()
39
+ } else if (this.state.is_active && was_active) {
40
+ this.schedule_resume()
41
+ }
42
+
43
+ if (!this.state.is_active && was_active) {
44
+ this.clear_resume_timer()
45
+ this.config.onTimelockLifted?.(this.get_state())
46
+ }
47
+ }
48
+
49
+ /** Record a 463 error from a failed send */
50
+ record_463_error() {
51
+ this.state.error_count++
52
+ if (!this.state.is_active) {
53
+ this.state.is_active = true
54
+ this.state.detected_at = new Date()
55
+ this.state.expires_at = new Date(Date.now() + 60000)
56
+ this.config.onTimelockDetected?.(this.get_state())
57
+ this.schedule_resume()
58
+ }
59
+ }
60
+
61
+ /** Register a JID as a known/existing chat (has tctoken / prior history) */
62
+ register_known_chat(jid) {
63
+ this.known_chats.add(jid)
64
+ }
65
+
66
+ /** Register multiple known chats at once (e.g. from chat list on connect) */
67
+ register_known_chats(jids) {
68
+ for (const jid of jids) this.known_chats.add(jid)
69
+ }
70
+
71
+ /** Check if a message to this recipient should be allowed */
72
+ can_send(jid) {
73
+ if (!this.state.is_active) return { allowed: true }
74
+
75
+ if (this.state.expires_at) {
76
+ const expiry_with_buffer =
77
+ this.state.expires_at.getTime() + this.config.resume_buffer_ms
78
+ if (Date.now() >= expiry_with_buffer) {
79
+ this.lift()
80
+ return { allowed: true }
81
+ }
82
+ }
83
+
84
+ if (jid.endsWith('@g.us') || jid.endsWith('@newsletter')) return { allowed: true }
85
+ if (this.known_chats.has(jid)) return { allowed: true }
86
+
87
+ const expires_in = this.state.expires_at
88
+ ? Math.max(0, this.state.expires_at.getTime() - Date.now())
89
+ : 60000
90
+
91
+ return {
92
+ allowed: false,
93
+ reason: `Reachout timelocked (${this.state.enforcement_type || 'unknown'}). New contacts blocked. Expires in ${Math.ceil(expires_in / 1000)}s.`
94
+ }
95
+ }
96
+
97
+ /** Get current timelock state */
98
+ get_state() {
99
+ return { ...this.state }
100
+ }
101
+
102
+ /** Check if currently timelocked */
103
+ is_timelocked() {
104
+ if (!this.state.is_active) return false
105
+ if (this.state.expires_at) {
106
+ const expiry_with_buffer =
107
+ this.state.expires_at.getTime() + this.config.resume_buffer_ms
108
+ if (Date.now() >= expiry_with_buffer) {
109
+ this.lift()
110
+ return false
111
+ }
112
+ }
113
+ return true
114
+ }
115
+
116
+ /** Get the set of known chat JIDs */
117
+ get_known_chats() {
118
+ return new Set(this.known_chats)
119
+ }
120
+
121
+ /** Manually lift the timelock */
122
+ lift() {
123
+ if (this.state.is_active) {
124
+ this.state.is_active = false
125
+ this.clear_resume_timer()
126
+ this.config.onTimelockLifted?.(this.get_state())
127
+ }
128
+ }
129
+
130
+ /** Reset all state */
131
+ reset() {
132
+ this.state = { is_active: false, error_count: 0 }
133
+ this.known_chats.clear()
134
+ this.clear_resume_timer()
135
+ }
136
+
137
+ schedule_resume() {
138
+ this.clear_resume_timer()
139
+ if (this.state.expires_at) {
140
+ const delay =
141
+ this.state.expires_at.getTime() - Date.now() + this.config.resume_buffer_ms
142
+ if (delay > 0) {
143
+ this.timer_generation++
144
+ const current_generation = this.timer_generation
145
+ this.resume_timer = setTimeout(() => {
146
+ if (current_generation === this.timer_generation) this.lift()
147
+ }, delay)
148
+ }
149
+ }
150
+ }
151
+
152
+ clear_resume_timer() {
153
+ if (this.resume_timer) {
154
+ clearTimeout(this.resume_timer)
155
+ this.resume_timer = null
156
+ this.timer_generation++
157
+ }
158
+ }
159
+ }
160
+
161
+ exports.timelock_guard = timelock_guard
162
+ module.exports = { timelock_guard }
@@ -0,0 +1,6 @@
1
+ import { AuthenticationState } from '../Types'
2
+
3
+ export declare const useMongoFileAuthState: (collection: string) => Promise<{
4
+ state: AuthenticationState
5
+ saveCreds: () => Promise<void>
6
+ }>
@@ -0,0 +1,81 @@
1
+ 'use strict'
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true })
4
+
5
+ const WAProto_1 = require('../../WAProto')
6
+ const auth_utils_1 = require('./auth-utils')
7
+ const generics_1 = require('./generics')
8
+
9
+ /*
10
+ code from amiruldev readjusted by @irull2nd, don't delete WM!
11
+ */
12
+ const useMongoFileAuthState = async (collection) => {
13
+ const writeData = (data, id) => {
14
+ const informationToStore = JSON.parse(JSON.stringify(data, generics_1.BufferJSON.replacer))
15
+ const update = {
16
+ $set: {
17
+ ...informationToStore
18
+ }
19
+ }
20
+
21
+ return collection.updateOne({ _id: id }, update, { upsert: true })
22
+ }
23
+
24
+ const readData = async (id) => {
25
+ try {
26
+ const data = JSON.stringify(await collection.findOne({ _id: id }))
27
+ return JSON.parse(data, generics_1.BufferJSON.reviver)
28
+ } catch (err) {
29
+ console.log(err)
30
+ }
31
+ }
32
+
33
+ const removeData = async (id) => {
34
+ try {
35
+ await collection.deleteOne({ _id: id })
36
+ } catch (err) {
37
+ console.log('error', err)
38
+ }
39
+ }
40
+
41
+ const creds = (await readData('creds')) || auth_utils_1.initAuthCreds()
42
+
43
+ return {
44
+ state: {
45
+ creds,
46
+ keys: {
47
+ get: async (type, ids) => {
48
+ const data = {}
49
+ await Promise.all(
50
+ ids.map(async (id) => {
51
+ let value = await readData(`${type}-${id}`)
52
+ if (type === 'app-state-sync-key') {
53
+ value = WAProto_1.proto.Message.AppStateSyncKeyData.fromObject(data)
54
+ }
55
+ data[id] = value
56
+ })
57
+ )
58
+ return data
59
+ },
60
+ set: async (data) => {
61
+ const tasks = []
62
+ for (const category of Object.keys(data)) {
63
+ for (const id of Object.keys(data[category])) {
64
+ const value = data[category][id]
65
+ const key = `${category}-${id}`
66
+ tasks.push(value ? writeData(value, key) : removeData(key))
67
+ }
68
+ }
69
+ await Promise.all(tasks)
70
+ }
71
+ }
72
+ },
73
+ saveCreds: () => {
74
+ return writeData(creds, 'creds')
75
+ }
76
+ }
77
+ }
78
+
79
+ module.exports = {
80
+ useMongoFileAuthState
81
+ }
@@ -0,0 +1,125 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
3
+ exports.useMultiFileAuthState = void 0
4
+ const async_mutex_1 = require('async-mutex')
5
+ const promises_1 = require('fs/promises')
6
+ const path_1 = require('path')
7
+ const WAProto_1 = require('../../WAProto')
8
+ const auth_utils_1 = require('./auth-utils')
9
+ const generics_1 = require('./generics')
10
+ const fileLocks = new Map()
11
+ const getFileLock = (path) => {
12
+ let mutex = fileLocks.get(path)
13
+ if (!mutex) {
14
+ mutex = new async_mutex_1.Mutex()
15
+ fileLocks.set(path, mutex)
16
+ }
17
+ return mutex
18
+ }
19
+ /**
20
+ * stores the full authentication state in a single folder.
21
+ * Far more efficient than singlefileauthstate
22
+ *
23
+ * Again, I wouldn't endorse this for any production level use other than perhaps a bot.
24
+ * Would recommend writing an auth state for use with a proper SQL or No-SQL DB
25
+ * */
26
+ const useMultiFileAuthState = async (folder) => {
27
+ const writeData = async (data, file) => {
28
+ const filePath = (0, path_1.join)(folder, fixFileName(file))
29
+ const mutex = getFileLock(filePath)
30
+ return mutex.acquire().then(async (release) => {
31
+ try {
32
+ await (0, promises_1.writeFile)(
33
+ filePath,
34
+ JSON.stringify(data, generics_1.BufferJSON.replacer)
35
+ )
36
+ } finally {
37
+ release()
38
+ }
39
+ })
40
+ }
41
+ const readData = async (file) => {
42
+ try {
43
+ const filePath = (0, path_1.join)(folder, fixFileName(file))
44
+ const mutex = getFileLock(filePath)
45
+ return await mutex.acquire().then(async (release) => {
46
+ try {
47
+ const data = await (0, promises_1.readFile)(filePath, { encoding: 'utf-8' })
48
+ return JSON.parse(data, generics_1.BufferJSON.reviver)
49
+ } finally {
50
+ release()
51
+ }
52
+ })
53
+ } catch (error) {
54
+ return null
55
+ }
56
+ }
57
+ const removeData = async (file) => {
58
+ try {
59
+ const filePath = (0, path_1.join)(folder, fixFileName(file))
60
+ const mutex = getFileLock(filePath)
61
+ return mutex.acquire().then(async (release) => {
62
+ try {
63
+ await (0, promises_1.unlink)(filePath)
64
+ } catch (_a) {
65
+ } finally {
66
+ release()
67
+ }
68
+ })
69
+ } catch (_a) {}
70
+ }
71
+ const folderInfo = await (0, promises_1.stat)(folder).catch(() => {})
72
+ if (folderInfo) {
73
+ if (!folderInfo.isDirectory()) {
74
+ throw new Error(
75
+ `found something that is not a directory at ${folder}, either delete it or specify a different location`
76
+ )
77
+ }
78
+ } else {
79
+ await (0, promises_1.mkdir)(folder, { recursive: true })
80
+ }
81
+ const fixFileName = (file) => {
82
+ var _a
83
+ return (_a = file === null || file === void 0 ? void 0 : file.replace(/\//g, '__')) ===
84
+ null || _a === void 0
85
+ ? void 0
86
+ : _a.replace(/:/g, '-')
87
+ }
88
+ const creds = (await readData('creds.json')) || (0, auth_utils_1.initAuthCreds)()
89
+ return {
90
+ state: {
91
+ creds,
92
+ keys: {
93
+ get: async (type, ids) => {
94
+ const data = {}
95
+ await Promise.all(
96
+ ids.map(async (id) => {
97
+ let value = await readData(`${type}-${id}.json`)
98
+ if (type === 'app-state-sync-key' && value) {
99
+ value =
100
+ WAProto_1.proto.Message.AppStateSyncKeyData.fromObject(value)
101
+ }
102
+ data[id] = value
103
+ })
104
+ )
105
+ return data
106
+ },
107
+ set: async (data) => {
108
+ const tasks = []
109
+ for (const category in data) {
110
+ for (const id in data[category]) {
111
+ const value = data[category][id]
112
+ const file = `${category}-${id}.json`
113
+ tasks.push(value ? writeData(value, file) : removeData(file))
114
+ }
115
+ }
116
+ await Promise.all(tasks)
117
+ }
118
+ }
119
+ },
120
+ saveCreds: async () => {
121
+ return writeData(creds, 'creds.json')
122
+ }
123
+ }
124
+ }
125
+ exports.useMultiFileAuthState = useMultiFileAuthState
@@ -0,0 +1,13 @@
1
+ import { ILogger } from './logger'
2
+ import type { AuthenticationState } from '../Types'
3
+
4
+ /**
5
+ * @deprecated use multi file auth state instead please
6
+ * stores the full authentication state in a single JSON file
7
+ *
8
+ * DO NOT USE IN A PROD ENVIRONMENT, only meant to serve as an example
9
+ * */
10
+ export declare const useSingleFileAuthState: (filename: string, logger?: ILogger) => {
11
+ state: AuthenticationState
12
+ saveState: () => void
13
+ }
@@ -0,0 +1,86 @@
1
+ 'use strict'
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true })
4
+
5
+ const WAProto_1 = require('../../WAProto')
6
+ const auth_utils_1 = require('./auth-utils')
7
+ const generics_1 = require('./generics')
8
+
9
+ // useless key map only there to maintain backwards compatibility
10
+ // do not use in your own systems please
11
+ const KEY_MAP = {
12
+ 'pre-key': 'preKeys',
13
+ session: 'sessions',
14
+ 'sender-key': 'senderKeys',
15
+ 'app-state-sync-key': 'appStateSyncKeys',
16
+ 'app-state-sync-version': 'appStateVersions',
17
+ 'sender-key-memory': 'senderKeyMemory',
18
+ 'lid-mapping': 'lidMappings'
19
+ }
20
+
21
+ /**
22
+ * @deprecated use multi file auth state instead please
23
+ * stores the full authentication state in a single JSON file
24
+ *
25
+ * DO NOT USE IN A PROD ENVIRONMENT, only meant to serve as an example
26
+ * */
27
+ const useSingleFileAuthState = (filename, logger) => {
28
+ // require fs here so that in case "fs" is not available -- the app does not crash
29
+ const { readFileSync, writeFileSync, existsSync } = require('fs')
30
+ let creds
31
+ let keys = {}
32
+ // save the authentication state to a file
33
+ const saveState = () => {
34
+ logger && logger.trace('saving auth state')
35
+ writeFileSync(
36
+ filename,
37
+ // BufferJSON replacer utility saves buffers nicely
38
+ JSON.stringify({ creds, keys }, generics_1.BufferJSON.replacer, 2)
39
+ )
40
+ }
41
+ if (existsSync(filename)) {
42
+ const result = JSON.parse(
43
+ readFileSync(filename, { encoding: 'utf-8' }),
44
+ generics_1.BufferJSON.reviver
45
+ )
46
+ creds = result.creds
47
+ keys = result.keys
48
+ } else {
49
+ creds = auth_utils_1.initAuthCreds()
50
+ keys = {}
51
+ }
52
+ return {
53
+ state: {
54
+ creds,
55
+ keys: {
56
+ get: (type, ids) => {
57
+ const key = KEY_MAP[type]
58
+ return ids.reduce((dict, id) => {
59
+ let value = keys[key]?.[id]
60
+ if (value) {
61
+ if (type === 'app-state-sync-key') {
62
+ value =
63
+ WAProto_1.proto.Message.AppStateSyncKeyData.fromObject(value)
64
+ }
65
+ dict[id] = value
66
+ }
67
+ return dict
68
+ }, {})
69
+ },
70
+ set: (data) => {
71
+ for (const _key in data) {
72
+ const key = KEY_MAP[_key]
73
+ keys[key] = keys[key] || {}
74
+ Object.assign(keys[key], data[_key])
75
+ }
76
+ saveState()
77
+ }
78
+ }
79
+ },
80
+ saveState
81
+ }
82
+ }
83
+
84
+ module.exports = {
85
+ useSingleFileAuthState
86
+ }
@@ -0,0 +1,187 @@
1
+ "use strict"
2
+ Object.defineProperty(exports, "__esModule", { value: true })
3
+ exports.use_sqlite_auth_state = void 0
4
+
5
+ /**
6
+ * @file use-sqlite-auth-state.js
7
+ * @description Auth state persisted in a local SQLite database (using
8
+ * Node's built-in `node:sqlite` — no external DB driver needed).
9
+ * Much faster and more robust than one-file-per-key JSON storage for
10
+ * bots with heavy session key churn. Requires Node.js 22.5+.
11
+ * Can auto-migrate an existing folder-based (useMultiFileAuthState)
12
+ * session into the new SQLite db on first run.
13
+ * @author Denzy ZeroDay
14
+ */
15
+
16
+ const { mkdir, readdir, readFile } = require('fs/promises')
17
+ const { dirname, join } = require('path')
18
+ const { proto } = require('../../WAProto')
19
+ const { initAuthCreds } = require('./auth-utils')
20
+
21
+ /**
22
+ * @param {string} path_or_folder - full .db/.sqlite path, or a folder (fileName is appended)
23
+ * @param {object} options
24
+ * @param {string} options.fileName - db file name when path_or_folder is a folder (default 'auth.db')
25
+ * @param {string} options.migrateFromFolder - optional legacy useMultiFileAuthState folder to import from on first run
26
+ * @param {object} options.logger - optional logger with .warn/.info
27
+ * @returns {Promise<{ state, saveCreds, db, close }>}
28
+ */
29
+ const use_sqlite_auth_state = async (path_or_folder, options = {}) => {
30
+ const { fileName = 'auth.db', migrateFromFolder: migrate_from_folder, logger } = options
31
+ const db_path = /\.(db|sqlite|sqlite3)$/i.test(path_or_folder) ? path_or_folder : join(path_or_folder, fileName)
32
+
33
+ const buf_replacer = (_, value) => {
34
+ if (Buffer.isBuffer(value) || value instanceof Uint8Array || value?.type === 'Buffer') {
35
+ return { type: 'Buffer', data: Buffer.from(value?.data || value).toString('base64') }
36
+ }
37
+ return value
38
+ }
39
+
40
+ const buf_reviver = (_, value) => {
41
+ if (value && typeof value === 'object' && value.type === 'Buffer' && typeof value.data === 'string') {
42
+ return Buffer.from(value.data, 'base64')
43
+ }
44
+ return value
45
+ }
46
+
47
+ const encode = (value) => {
48
+ if (Buffer.isBuffer(value) || value instanceof Uint8Array) {
49
+ return Buffer.concat([Buffer.from([1]), Buffer.from(value)])
50
+ }
51
+ return Buffer.concat([Buffer.from([0]), Buffer.from(JSON.stringify(value, buf_replacer), 'utf8')])
52
+ }
53
+
54
+ const decode = (blob) => {
55
+ if (!blob || blob.length === 0) return null
56
+ if (blob[0] === 1) return Buffer.from(blob.subarray(1))
57
+ return JSON.parse(Buffer.from(blob.subarray(1)).toString('utf8'), buf_reviver)
58
+ }
59
+
60
+ const fix_name = (s) => s?.replace(/\//g, '__')?.replace(/:/g, '-')
61
+ const key_of = (category, id) => fix_name(`${category}-${id}`)
62
+
63
+ let DatabaseSync
64
+ try {
65
+ ;({ DatabaseSync } = await import('node:sqlite'))
66
+ } catch (err) {
67
+ throw new Error("use_sqlite_auth_state needs the built-in 'node:sqlite' module (Node 22.5+). Upgrade Node, or use useMultiFileAuthState instead.")
68
+ }
69
+
70
+ await mkdir(dirname(db_path), { recursive: true }).catch(() => {})
71
+
72
+ const db = new DatabaseSync(db_path)
73
+ db.exec('PRAGMA journal_mode = TRUNCATE')
74
+ db.exec('PRAGMA synchronous = NORMAL')
75
+ db.exec('PRAGMA busy_timeout = 5000')
76
+ db.exec('CREATE TABLE IF NOT EXISTS auth_state (k TEXT PRIMARY KEY, v BLOB NOT NULL) WITHOUT ROWID')
77
+
78
+ const q_get = db.prepare('SELECT v FROM auth_state WHERE k = ?')
79
+ const q_upsert = db.prepare('INSERT INTO auth_state(k,v) VALUES(?,?) ON CONFLICT(k) DO UPDATE SET v=excluded.v')
80
+ const q_delete = db.prepare('DELETE FROM auth_state WHERE k = ?')
81
+
82
+ const run_tx = (fn) => {
83
+ db.exec('BEGIN')
84
+ try {
85
+ const r = fn()
86
+ db.exec('COMMIT')
87
+ return r
88
+ } catch (err) {
89
+ db.exec('ROLLBACK')
90
+ throw err
91
+ }
92
+ }
93
+
94
+ const read_raw = (k) => {
95
+ const row = q_get.get(k)
96
+ if (!row) return null
97
+ try {
98
+ return decode(row.v)
99
+ } catch (err) {
100
+ logger?.warn?.({ k, err: err?.message }, 'sqlite-auth: failed to decode row, treating as missing')
101
+ return null
102
+ }
103
+ }
104
+
105
+ const run_migration = async (folder) => {
106
+ let files
107
+ try {
108
+ files = await readdir(folder)
109
+ } catch {
110
+ return 0
111
+ }
112
+ const rows = []
113
+ for (const file of files) {
114
+ if (!file.endsWith('.json')) continue
115
+ let value
116
+ try {
117
+ value = JSON.parse(await readFile(join(folder, file), 'utf8'), buf_reviver)
118
+ } catch {
119
+ continue
120
+ }
121
+ if (value === null || value === undefined) continue
122
+ rows.push([file.slice(0, -'.json'.length), encode(value)])
123
+ }
124
+ run_tx(() => {
125
+ for (const [k, v] of rows) q_upsert.run(k, v)
126
+ })
127
+ return rows.length
128
+ }
129
+
130
+ const has_creds = () => !!q_get.get('creds')
131
+
132
+ if (migrate_from_folder && !has_creds()) {
133
+ const n = await run_migration(migrate_from_folder)
134
+ if (n > 0) logger?.info?.({ count: n, from: migrate_from_folder }, 'sqlite-auth: migrated legacy auth state')
135
+ }
136
+
137
+ let creds = read_raw('creds')
138
+ if (!creds) {
139
+ creds = initAuthCreds()
140
+ q_upsert.run('creds', encode(creds))
141
+ }
142
+
143
+ const keys = {
144
+ get: async (type, ids) => {
145
+ const data = {}
146
+ for (const id of ids) {
147
+ let value = read_raw(key_of(type, id))
148
+ if (type === 'app-state-sync-key' && value) {
149
+ value = proto.Message.AppStateSyncKeyData.fromObject(value)
150
+ }
151
+ if (value !== null && value !== undefined) {
152
+ data[id] = value
153
+ }
154
+ }
155
+ return data
156
+ },
157
+ set: async (data) => {
158
+ const ops = []
159
+ for (const category in data) {
160
+ for (const id in data[category]) {
161
+ ops.push([key_of(category, id), data[category][id]])
162
+ }
163
+ }
164
+ run_tx(() => {
165
+ for (const [k, value] of ops) {
166
+ if (value === null || value === undefined) q_delete.run(k)
167
+ else q_upsert.run(k, encode(value))
168
+ }
169
+ })
170
+ },
171
+ clear: async () => {
172
+ db.prepare("DELETE FROM auth_state WHERE k <> 'creds'").run()
173
+ }
174
+ }
175
+
176
+ return {
177
+ state: { creds, keys },
178
+ saveCreds: async () => {
179
+ q_upsert.run('creds', encode(creds))
180
+ },
181
+ db,
182
+ close: () => db.close()
183
+ }
184
+ }
185
+
186
+ exports.use_sqlite_auth_state = use_sqlite_auth_state
187
+ module.exports = { use_sqlite_auth_state }