@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,88 @@
1
+ import { proto } from '../../WAProto'
2
+ import { ILogger } from './logger'
3
+
4
+ export interface RecentMessageKey {
5
+ to: string
6
+ id: string
7
+ }
8
+
9
+ export interface RecentMessage {
10
+ message: proto.IMessage
11
+ timestamp: number
12
+ }
13
+
14
+ export interface SessionRecreateHistory {
15
+ [jid: string]: number
16
+ }
17
+
18
+ export interface RetryCounter {
19
+ [messageId: string]: number
20
+ }
21
+
22
+ export interface PendingPhoneRequest {
23
+ [messageId: string]: NodeJS.Timeout
24
+ }
25
+
26
+ export interface RetryStatistics {
27
+ totalRetries: number
28
+ successfulRetries: number
29
+ failedRetries: number
30
+ mediaRetries: number
31
+ sessionRecreations: number
32
+ phoneRequests: number
33
+ }
34
+
35
+ export declare class MessageRetryManager {
36
+ private logger
37
+ private recentMessagesMap
38
+ private sessionRecreateHistory
39
+ private retryCounters
40
+ private pendingPhoneRequests
41
+ private readonly maxMsgRetryCount
42
+ private statistics
43
+ constructor(logger: ILogger, maxMsgRetryCount: number)
44
+ /**
45
+ * Add a recent message to the cache for retry handling
46
+ */
47
+ addRecentMessage(to: string, id: string, message: proto.IMessage): void
48
+ /**
49
+ * Get a recent message from the cache
50
+ */
51
+ getRecentMessage(to: string, id: string): RecentMessage | undefined
52
+ /**
53
+ * Check if a session should be recreated based on retry count and history
54
+ */
55
+ shouldRecreateSession(jid: string, retryCount: number, hasSession: boolean): {
56
+ reason: string
57
+ recreate: boolean
58
+ }
59
+ /**
60
+ * Increment retry counter for a message
61
+ */
62
+ incrementRetryCount(messageId: string): number
63
+ /**
64
+ * Get retry count for a message
65
+ */
66
+ getRetryCount(messageId: string): number
67
+ /**
68
+ * Check if message has exceeded maximum retry attempts
69
+ */
70
+ hasExceededMaxRetries(messageId: string): boolean
71
+ /**
72
+ * Mark retry as successful
73
+ */
74
+ markRetrySuccess(messageId: string): void
75
+ /**
76
+ * Mark retry as failed
77
+ */
78
+ markRetryFailed(messageId: string): void
79
+ /**
80
+ * Schedule a phone request with delay
81
+ */
82
+ schedulePhoneRequest(messageId: string, callback: () => void, delay?: number): void
83
+ /**
84
+ * Cancel pending phone request
85
+ */
86
+ cancelPendingPhoneRequest(messageId: string): void
87
+ private keyToString
88
+ }
@@ -0,0 +1,160 @@
1
+ 'use strict'
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true })
4
+
5
+ const LRUCache_1 = require('lru-cache')
6
+
7
+ /** Number of sent messages to cache in memory for handling retry receipts */
8
+ const RECENT_MESSAGES_SIZE = 512
9
+
10
+ /** Timeout for session recreation - 1 hour */
11
+ const RECREATE_SESSION_TIMEOUT = 60 * 60 * 1000 // 1 hour in milliseconds
12
+
13
+ const PHONE_REQUEST_DELAY = 3000
14
+
15
+ class MessageRetryManager {
16
+ constructor(logger, maxMsgRetryCount) {
17
+ this.logger = logger
18
+ this.recentMessagesMap = new LRUCache_1.LRUCache({
19
+ max: RECENT_MESSAGES_SIZE
20
+ })
21
+ this.sessionRecreateHistory = new LRUCache_1.LRUCache({
22
+ ttl: RECREATE_SESSION_TIMEOUT * 2,
23
+ ttlAutopurge: true
24
+ })
25
+ this.retryCounters = new LRUCache_1.LRUCache({
26
+ ttl: 15 * 60 * 1000,
27
+ ttlAutopurge: true,
28
+ updateAgeOnGet: true
29
+ }) // 15 minutes TTL
30
+ this.pendingPhoneRequests = {}
31
+ this.maxMsgRetryCount = 5
32
+ this.statistics = {
33
+ totalRetries: 0,
34
+ successfulRetries: 0,
35
+ failedRetries: 0,
36
+ mediaRetries: 0,
37
+ sessionRecreations: 0,
38
+ phoneRequests: 0
39
+ }
40
+ this.maxMsgRetryCount = maxMsgRetryCount
41
+ }
42
+ /**
43
+ * Add a recent message to the cache for retry handling
44
+ */
45
+ addRecentMessage(to, id, message) {
46
+ const key = { to, id }
47
+ const keyStr = this.keyToString(key)
48
+ // Add new message
49
+ this.recentMessagesMap.set(keyStr, {
50
+ message,
51
+ timestamp: Date.now()
52
+ })
53
+ this.logger.debug(`Added message to retry cache: ${to}/${id}`)
54
+ }
55
+ /**
56
+ * Get a recent message from the cache
57
+ */
58
+ getRecentMessage(to, id) {
59
+ const key = { to, id }
60
+ const keyStr = this.keyToString(key)
61
+ return this.recentMessagesMap.get(keyStr)
62
+ }
63
+ /**
64
+ * Check if a session should be recreated based on retry count and history
65
+ */
66
+ shouldRecreateSession(jid, retryCount, hasSession) {
67
+ // If we don't have a session, always recreate
68
+ if (!hasSession) {
69
+ this.sessionRecreateHistory.set(jid, Date.now())
70
+ this.statistics.sessionRecreations++
71
+ return {
72
+ reason: "we don't have a Signal session with them",
73
+ recreate: true
74
+ }
75
+ }
76
+ // Only consider recreation if retry count > 1
77
+ if (retryCount < 2) {
78
+ return { reason: '', recreate: false }
79
+ }
80
+ const now = Date.now()
81
+ const prevTime = this.sessionRecreateHistory.get(jid)
82
+ // If no previous recreation or it's been more than an hour
83
+ if (!prevTime || now - prevTime > RECREATE_SESSION_TIMEOUT) {
84
+ this.sessionRecreateHistory.set(jid, now)
85
+ this.statistics.sessionRecreations++
86
+ return {
87
+ reason: 'retry count > 1 and over an hour since last recreation',
88
+ recreate: true
89
+ }
90
+ }
91
+ return { reason: '', recreate: false }
92
+ }
93
+ /**
94
+ * Increment retry counter for a message
95
+ */
96
+ incrementRetryCount(messageId) {
97
+ this.retryCounters.set(messageId, (this.retryCounters.get(messageId) || 0) + 1)
98
+ this.statistics.totalRetries++
99
+ return this.retryCounters.get(messageId)
100
+ }
101
+ /**
102
+ * Get retry count for a message
103
+ */
104
+ getRetryCount(messageId) {
105
+ return this.retryCounters.get(messageId) || 0
106
+ }
107
+ /**
108
+ * Check if message has exceeded maximum retry attempts
109
+ */
110
+ hasExceededMaxRetries(messageId) {
111
+ return this.getRetryCount(messageId) >= this.maxMsgRetryCount
112
+ }
113
+ /**
114
+ * Mark retry as successful
115
+ */
116
+ markRetrySuccess(messageId) {
117
+ this.statistics.successfulRetries++
118
+ // Clean up retry counter for successful message
119
+ this.retryCounters.delete(messageId)
120
+ this.cancelPendingPhoneRequest(messageId)
121
+ }
122
+ /**
123
+ * Mark retry as failed
124
+ */
125
+ markRetryFailed(messageId) {
126
+ this.statistics.failedRetries++
127
+ this.retryCounters.delete(messageId)
128
+ }
129
+ /**
130
+ * Schedule a phone request with delay
131
+ */
132
+ schedulePhoneRequest(messageId, callback, delay = PHONE_REQUEST_DELAY) {
133
+ // Cancel any existing request for this message
134
+ this.cancelPendingPhoneRequest(messageId)
135
+ this.pendingPhoneRequests[messageId] = setTimeout(() => {
136
+ delete this.pendingPhoneRequests[messageId]
137
+ this.statistics.phoneRequests++
138
+ callback()
139
+ }, delay)
140
+ this.logger.debug(`Scheduled phone request for message ${messageId} with ${delay}ms delay`)
141
+ }
142
+ /**
143
+ * Cancel pending phone request
144
+ */
145
+ cancelPendingPhoneRequest(messageId) {
146
+ const timeout = this.pendingPhoneRequests[messageId]
147
+ if (timeout) {
148
+ clearTimeout(timeout)
149
+ delete this.pendingPhoneRequests[messageId]
150
+ this.logger.debug(`Cancelled pending phone request for message ${messageId}`)
151
+ }
152
+ }
153
+ keyToString(key) {
154
+ return `${key.to}:${key.id}`
155
+ }
156
+ }
157
+
158
+ module.exports = {
159
+ MessageRetryManager
160
+ }
@@ -0,0 +1,52 @@
1
+ import type { WAMessage } from '../Types'
2
+
3
+ export interface SearchOptions {
4
+ caseSensitive?: boolean
5
+ jid?: string
6
+ fromDate?: Date
7
+ toDate?: Date
8
+ limit?: number
9
+ messageTypes?: ('text' | 'image' | 'video' | 'document' | 'audio' | 'sticker' | 'location' | 'contact')[]
10
+ includeCaption?: boolean
11
+ fromSender?: string
12
+ fromMe?: boolean
13
+ }
14
+
15
+ export interface SearchResult {
16
+ message: WAMessage
17
+ matchedText: string
18
+ matchPosition: number
19
+ relevanceScore: number
20
+ }
21
+
22
+ export declare const extractMessageText: (message: WAMessage) => string
23
+
24
+ export declare const searchMessages: (
25
+ messages: WAMessage[],
26
+ query: string,
27
+ options?: SearchOptions
28
+ ) => SearchResult[]
29
+
30
+ export declare const searchMessagesRegex: (
31
+ messages: WAMessage[],
32
+ pattern: RegExp,
33
+ options?: Omit<SearchOptions, 'caseSensitive'>
34
+ ) => SearchResult[]
35
+
36
+ export declare class MessageSearchManager {
37
+ private messages
38
+ private messageIndex
39
+ constructor()
40
+ addMessages(messages: WAMessage[]): void
41
+ removeMessages(messageIds: string[]): void
42
+ clear(): void
43
+ get count(): number
44
+ search(query: string, options?: SearchOptions): SearchResult[]
45
+ searchRegex(pattern: RegExp, options?: Omit<SearchOptions, 'caseSensitive'>): SearchResult[]
46
+ getByJid(jid: string): WAMessage[]
47
+ getBySender(sender: string): WAMessage[]
48
+ getByType(type: 'text' | 'image' | 'video' | 'document' | 'audio' | 'sticker' | 'location' | 'contact'): WAMessage[]
49
+ getById(id: string): WAMessage | undefined
50
+ }
51
+
52
+ export declare const createMessageSearch: () => MessageSearchManager
@@ -0,0 +1,226 @@
1
+ 'use strict'
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true })
4
+ exports.createMessageSearch =
5
+ exports.MessageSearchManager =
6
+ exports.searchMessagesRegex =
7
+ exports.searchMessages =
8
+ exports.extractMessageText =
9
+ void 0
10
+
11
+ /**
12
+ * Message Search Utilities
13
+ * Ported from Baileys-Joss
14
+ */
15
+
16
+ const extractMessageText = (message) => {
17
+ const content = message.message
18
+ if (!content) return ''
19
+
20
+ if (content.conversation) return content.conversation
21
+ if (content.extendedTextMessage?.text) return content.extendedTextMessage.text
22
+
23
+ if (content.imageMessage?.caption) return content.imageMessage.caption
24
+ if (content.videoMessage?.caption) return content.videoMessage.caption
25
+ if (content.documentMessage?.caption) return content.documentMessage.caption
26
+
27
+ if (content.documentMessage?.fileName) return content.documentMessage.fileName
28
+
29
+ if (content.locationMessage?.name) return content.locationMessage.name
30
+ if (content.locationMessage?.address) return content.locationMessage.address
31
+
32
+ if (content.contactMessage?.displayName) return content.contactMessage.displayName
33
+
34
+ if (content.pollCreationMessage?.name) return content.pollCreationMessage.name
35
+
36
+ return ''
37
+ }
38
+ exports.extractMessageText = extractMessageText
39
+
40
+ const getMessageType = (message) => {
41
+ const content = message.message
42
+ if (!content) return 'other'
43
+
44
+ if (content.conversation || content.extendedTextMessage) return 'text'
45
+ if (content.imageMessage) return 'image'
46
+ if (content.videoMessage) return 'video'
47
+ if (content.documentMessage) return 'document'
48
+ if (content.audioMessage) return 'audio'
49
+ if (content.stickerMessage) return 'sticker'
50
+ if (content.locationMessage || content.liveLocationMessage) return 'location'
51
+ if (content.contactMessage || content.contactsArrayMessage) return 'contact'
52
+
53
+ return 'other'
54
+ }
55
+
56
+ const calculateRelevance = (query, text, position) => {
57
+ let score = 100
58
+
59
+ if (text.toLowerCase() === query.toLowerCase()) {
60
+ score += 50
61
+ }
62
+
63
+ score -= Math.min(position / 10, 20)
64
+
65
+ const lowerText = text.toLowerCase()
66
+ const lowerQuery = query.toLowerCase()
67
+ if (
68
+ position === 0 ||
69
+ lowerText[position - 1] === ' ' ||
70
+ lowerText[position + lowerQuery.length] === ' ' ||
71
+ position + lowerQuery.length === text.length
72
+ ) {
73
+ score += 20
74
+ }
75
+
76
+ return Math.max(score, 0)
77
+ }
78
+
79
+ const searchMessages = (messages, query, options = {}) => {
80
+ const results = []
81
+ const searchQuery = options.caseSensitive ? query : query.toLowerCase()
82
+
83
+ for (const message of messages) {
84
+ if (options.jid && message.key.remoteJid !== options.jid) continue
85
+
86
+ const ts = message.messageTimestamp
87
+ const messageTime = ts
88
+ ? new Date(typeof ts === 'number' ? ts * 1000 : Number(ts) * 1000)
89
+ : null
90
+
91
+ if (options.fromDate && messageTime && messageTime < options.fromDate) continue
92
+ if (options.toDate && messageTime && messageTime > options.toDate) continue
93
+
94
+ if (options.fromSender && message.key.participant !== options.fromSender) continue
95
+ if (options.fromMe !== undefined && message.key.fromMe !== options.fromMe) continue
96
+
97
+ if (options.messageTypes && options.messageTypes.length > 0) {
98
+ const type = getMessageType(message)
99
+ if (!options.messageTypes.includes(type)) continue
100
+ }
101
+
102
+ const text = (0, exports.extractMessageText)(message)
103
+ if (!text) continue
104
+
105
+ const searchText = options.caseSensitive ? text : text.toLowerCase()
106
+ const position = searchText.indexOf(searchQuery)
107
+
108
+ if (position !== -1) {
109
+ results.push({
110
+ message,
111
+ matchedText: text.substring(
112
+ Math.max(0, position - 20),
113
+ Math.min(text.length, position + query.length + 20)
114
+ ),
115
+ matchPosition: position,
116
+ relevanceScore: calculateRelevance(query, text, position)
117
+ })
118
+ }
119
+
120
+ if (options.limit && results.length >= options.limit) break
121
+ }
122
+
123
+ results.sort((a, b) => b.relevanceScore - a.relevanceScore)
124
+
125
+ return results
126
+ }
127
+ exports.searchMessages = searchMessages
128
+
129
+ const searchMessagesRegex = (messages, pattern, options = {}) => {
130
+ const results = []
131
+
132
+ for (const message of messages) {
133
+ if (options.jid && message.key.remoteJid !== options.jid) continue
134
+ if (options.fromSender && message.key.participant !== options.fromSender) continue
135
+ if (options.fromMe !== undefined && message.key.fromMe !== options.fromMe) continue
136
+
137
+ if (options.messageTypes && options.messageTypes.length > 0) {
138
+ const type = getMessageType(message)
139
+ if (!options.messageTypes.includes(type)) continue
140
+ }
141
+
142
+ const text = (0, exports.extractMessageText)(message)
143
+ if (!text) continue
144
+
145
+ const match = text.match(pattern)
146
+ if (match) {
147
+ results.push({
148
+ message,
149
+ matchedText: match[0],
150
+ matchPosition: match.index || 0,
151
+ relevanceScore: 100
152
+ })
153
+ }
154
+
155
+ if (options.limit && results.length >= options.limit) break
156
+ }
157
+
158
+ return results
159
+ }
160
+ exports.searchMessagesRegex = searchMessagesRegex
161
+
162
+ class MessageSearchManager {
163
+ constructor() {
164
+ this.messages = []
165
+ this.messageIndex = new Map()
166
+ }
167
+
168
+ addMessages(messages) {
169
+ for (const msg of messages) {
170
+ const id = msg.key.id
171
+ if (id && !this.messageIndex.has(id)) {
172
+ this.messages.push(msg)
173
+ this.messageIndex.set(id, msg)
174
+ }
175
+ }
176
+ }
177
+
178
+ removeMessages(messageIds) {
179
+ const idSet = new Set(messageIds)
180
+ this.messages = this.messages.filter((m) => !idSet.has(m.key.id || ''))
181
+ for (const id of messageIds) {
182
+ this.messageIndex.delete(id)
183
+ }
184
+ }
185
+
186
+ clear() {
187
+ this.messages = []
188
+ this.messageIndex.clear()
189
+ }
190
+
191
+ get count() {
192
+ return this.messages.length
193
+ }
194
+
195
+ search(query, options) {
196
+ return (0, exports.searchMessages)(this.messages, query, options)
197
+ }
198
+
199
+ searchRegex(pattern, options) {
200
+ return (0, exports.searchMessagesRegex)(this.messages, pattern, options)
201
+ }
202
+
203
+ getByJid(jid) {
204
+ return this.messages.filter((m) => m.key.remoteJid === jid)
205
+ }
206
+
207
+ getBySender(sender) {
208
+ return this.messages.filter(
209
+ (m) => m.key.participant === sender || m.key.remoteJid === sender
210
+ )
211
+ }
212
+
213
+ getByType(type) {
214
+ return this.messages.filter((m) => getMessageType(m) === type)
215
+ }
216
+
217
+ getById(id) {
218
+ return this.messageIndex.get(id)
219
+ }
220
+ }
221
+ exports.MessageSearchManager = MessageSearchManager
222
+
223
+ const createMessageSearch = () => {
224
+ return new MessageSearchManager()
225
+ }
226
+ exports.createMessageSearch = createMessageSearch