jsdecryptor 4.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. package/Database/database.js +446 -0
  2. package/Database/migration.js +327 -0
  3. package/Database/pgSync.js +229 -0
  4. package/Database/settingsStore.js +305 -0
  5. package/config.js +32 -0
  6. package/dave.js +3063 -0
  7. package/davelib/antibadword.js +278 -0
  8. package/davelib/antilink.js +88 -0
  9. package/davelib/antilinkHelper.js +48 -0
  10. package/davelib/botConfig.js +71 -0
  11. package/davelib/connect4.js +111 -0
  12. package/davelib/converter.js +89 -0
  13. package/davelib/dicegame.js +114 -0
  14. package/davelib/exif.js +138 -0
  15. package/davelib/fakeContact.js +85 -0
  16. package/davelib/fontStyles.js +237 -0
  17. package/davelib/greetings.js +47 -0
  18. package/davelib/id.js +11 -0
  19. package/davelib/index.js +577 -0
  20. package/davelib/isAdmin.js +32 -0
  21. package/davelib/isBanned.js +12 -0
  22. package/davelib/isOwner.js +15 -0
  23. package/davelib/lightweight_store.js +169 -0
  24. package/davelib/messageConfig.js +15 -0
  25. package/davelib/messageHandler.js +87 -0
  26. package/davelib/myfunc.js +379 -0
  27. package/davelib/myfunc2.js +170 -0
  28. package/davelib/reactions.js +180 -0
  29. package/davelib/server.html +563 -0
  30. package/davelib/sticker.js +208 -0
  31. package/davelib/tempCleanup.js +53 -0
  32. package/davelib/tictactoe.js +104 -0
  33. package/davelib/uploadImage.js +100 -0
  34. package/davelib/uploader.js +110 -0
  35. package/davelib/welcome.js +100 -0
  36. package/davelib/wordchain.js +121 -0
  37. package/daveset.js +16 -0
  38. package/davexcore/ai/ai.js +100 -0
  39. package/davexcore/ai/aiGpt4.js +59 -0
  40. package/davexcore/ai/aimodels.js +284 -0
  41. package/davexcore/ai/aivideo.js +31 -0
  42. package/davexcore/ai/analyze.js +233 -0
  43. package/davexcore/ai/bard.js +101 -0
  44. package/davexcore/ai/bird.js +101 -0
  45. package/davexcore/ai/blackbox.js +30 -0
  46. package/davexcore/ai/character.js +80 -0
  47. package/davexcore/ai/copilot.js +58 -0
  48. package/davexcore/ai/dalle.js +39 -0
  49. package/davexcore/ai/davex.js +50 -0
  50. package/davexcore/ai/deepseek.js +96 -0
  51. package/davexcore/ai/grok.js +67 -0
  52. package/davexcore/ai/imagine.js +89 -0
  53. package/davexcore/ai/meta.js +82 -0
  54. package/davexcore/ai/mistral.js +101 -0
  55. package/davexcore/ai/perplexity.js +95 -0
  56. package/davexcore/ai/sora.js +44 -0
  57. package/davexcore/ai/speechwriter.js +46 -0
  58. package/davexcore/ai/vision.js +244 -0
  59. package/davexcore/ai/wormgpt.js +56 -0
  60. package/davexcore/anti/antiaudio.js +106 -0
  61. package/davexcore/anti/antibadword.js +313 -0
  62. package/davexcore/anti/antibug.js +156 -0
  63. package/davexcore/anti/anticall.js +219 -0
  64. package/davexcore/anti/antichart.js +280 -0
  65. package/davexcore/anti/antidelete.js +673 -0
  66. package/davexcore/anti/antideletestatus.js +535 -0
  67. package/davexcore/anti/antidemote.js +352 -0
  68. package/davexcore/anti/antidocument.js +105 -0
  69. package/davexcore/anti/antiedit.js +410 -0
  70. package/davexcore/anti/antifiles.js +109 -0
  71. package/davexcore/anti/antigroupmention.js +206 -0
  72. package/davexcore/anti/antiimage.js +105 -0
  73. package/davexcore/anti/antikick.js +125 -0
  74. package/davexcore/anti/antilink.js +237 -0
  75. package/davexcore/anti/antimention.js +143 -0
  76. package/davexcore/anti/antipromote.js +320 -0
  77. package/davexcore/anti/antisticker.js +105 -0
  78. package/davexcore/anti/antitag.js +191 -0
  79. package/davexcore/anti/antivideo.js +105 -0
  80. package/davexcore/anti/antiviewonce.js +396 -0
  81. package/davexcore/anti/groupanticall.js +262 -0
  82. package/davexcore/anti/mention.js +242 -0
  83. package/davexcore/automation/alwaysonline.js +226 -0
  84. package/davexcore/automation/autoReadReciepts.js +96 -0
  85. package/davexcore/automation/autoread.js +104 -0
  86. package/davexcore/automation/autorecording.js +197 -0
  87. package/davexcore/automation/autostatus.js +317 -0
  88. package/davexcore/automation/autotyping.js +197 -0
  89. package/davexcore/automation/chatbot.js +444 -0
  90. package/davexcore/automation/chatmanage.js +199 -0
  91. package/davexcore/automation/devReact.js +43 -0
  92. package/davexcore/automation/goodbye.js +181 -0
  93. package/davexcore/automation/greetings.js +154 -0
  94. package/davexcore/automation/welcome.js +187 -0
  95. package/davexcore/downloads/apk.js +157 -0
  96. package/davexcore/downloads/facebook.js +94 -0
  97. package/davexcore/downloads/gitclone.js +137 -0
  98. package/davexcore/downloads/igs.js +333 -0
  99. package/davexcore/downloads/instagram.js +133 -0
  100. package/davexcore/downloads/mediafire.js +144 -0
  101. package/davexcore/downloads/pinterest.js +38 -0
  102. package/davexcore/downloads/play.js +158 -0
  103. package/davexcore/downloads/saveStatus.js +3 -0
  104. package/davexcore/downloads/song.js +135 -0
  105. package/davexcore/downloads/spotify.js +133 -0
  106. package/davexcore/downloads/tiktok.js +167 -0
  107. package/davexcore/downloads/tiktokaudio.js +158 -0
  108. package/davexcore/downloads/video.js +188 -0
  109. package/davexcore/downloads/ytdl.js +252 -0
  110. package/davexcore/downloads/ytdocplay.js +130 -0
  111. package/davexcore/downloads/ytdocvideo.js +95 -0
  112. package/davexcore/downloads/yts.js +64 -0
  113. package/davexcore/games/connect4.js +267 -0
  114. package/davexcore/games/dice.js +286 -0
  115. package/davexcore/games/eightball.js +24 -0
  116. package/davexcore/games/hangman.js +60 -0
  117. package/davexcore/games/rps.js +25 -0
  118. package/davexcore/games/ship.js +36 -0
  119. package/davexcore/games/slot.js +21 -0
  120. package/davexcore/games/tictactoe.js +263 -0
  121. package/davexcore/games/trivia.js +46 -0
  122. package/davexcore/games/wordchain.js +242 -0
  123. package/davexcore/group/addmember.js +101 -0
  124. package/davexcore/group/ban.js +63 -0
  125. package/davexcore/group/blockUnblock.js +177 -0
  126. package/davexcore/group/clear.js +196 -0
  127. package/davexcore/group/creategroup.js +43 -0
  128. package/davexcore/group/demote.js +115 -0
  129. package/davexcore/group/disappear.js +67 -0
  130. package/davexcore/group/groupinfo.js +167 -0
  131. package/davexcore/group/groupmanage.js +133 -0
  132. package/davexcore/group/hidetag.js +108 -0
  133. package/davexcore/group/joinrequests.js +145 -0
  134. package/davexcore/group/kick.js +92 -0
  135. package/davexcore/group/kickall.js +63 -0
  136. package/davexcore/group/leave.js +38 -0
  137. package/davexcore/group/linkgroup.js +63 -0
  138. package/davexcore/group/mute.js +57 -0
  139. package/davexcore/group/online.js +117 -0
  140. package/davexcore/group/pmblocker.js +65 -0
  141. package/davexcore/group/promote.js +93 -0
  142. package/davexcore/group/resetlink.js +57 -0
  143. package/davexcore/group/staff.js +99 -0
  144. package/davexcore/group/tag.js +111 -0
  145. package/davexcore/group/tagadmins.js +88 -0
  146. package/davexcore/group/tagall.js +99 -0
  147. package/davexcore/group/tagnotadmin.js +92 -0
  148. package/davexcore/group/topmembers.js +202 -0
  149. package/davexcore/group/unban.js +64 -0
  150. package/davexcore/group/unmute.js +45 -0
  151. package/davexcore/group/warn.js +83 -0
  152. package/davexcore/group/warnings.js +26 -0
  153. package/davexcore/media/anime.js +130 -0
  154. package/davexcore/media/attp.js +127 -0
  155. package/davexcore/media/design.js +52 -0
  156. package/davexcore/media/emojimix.js +105 -0
  157. package/davexcore/media/getpp.js +108 -0
  158. package/davexcore/media/image.js +87 -0
  159. package/davexcore/media/imageedit.js +329 -0
  160. package/davexcore/media/img-blur.js +70 -0
  161. package/davexcore/media/meme.js +35 -0
  162. package/davexcore/media/pies.js +53 -0
  163. package/davexcore/media/quotesticker.js +153 -0
  164. package/davexcore/media/remini.js +126 -0
  165. package/davexcore/media/removebg.js +114 -0
  166. package/davexcore/media/setpp.js +65 -0
  167. package/davexcore/media/shazam.js +251 -0
  168. package/davexcore/media/simage.js +74 -0
  169. package/davexcore/media/sticker.js +134 -0
  170. package/davexcore/media/stickercrop.js +133 -0
  171. package/davexcore/media/stickertelegram.js +133 -0
  172. package/davexcore/media/take.js +76 -0
  173. package/davexcore/media/textmaker.js +106 -0
  174. package/davexcore/media/toAudio.js +180 -0
  175. package/davexcore/media/togif.js +33 -0
  176. package/davexcore/media/toimg.js +26 -0
  177. package/davexcore/media/tomp4.js +34 -0
  178. package/davexcore/media/tostatus.js +160 -0
  179. package/davexcore/media/tts.js +47 -0
  180. package/davexcore/media/viewonce.js +59 -0
  181. package/davexcore/media/vn.js +67 -0
  182. package/davexcore/media/vv2.js +3 -0
  183. package/davexcore/media/wallpaper.js +89 -0
  184. package/davexcore/media/wasted.js +57 -0
  185. package/davexcore/misc/compliment.js +93 -0
  186. package/davexcore/misc/dare.js +47 -0
  187. package/davexcore/misc/fact.js +14 -0
  188. package/davexcore/misc/flirt.js +26 -0
  189. package/davexcore/misc/goodnight.js +33 -0
  190. package/davexcore/misc/insult.js +281 -0
  191. package/davexcore/misc/joke.js +66 -0
  192. package/davexcore/misc/misc.js +200 -0
  193. package/davexcore/misc/quote.js +22 -0
  194. package/davexcore/misc/roseday.js +24 -0
  195. package/davexcore/misc/shayari.js +62 -0
  196. package/davexcore/misc/simp.js +47 -0
  197. package/davexcore/misc/stupid.js +51 -0
  198. package/davexcore/misc/truth.js +146 -0
  199. package/davexcore/owner/alive.js +67 -0
  200. package/davexcore/owner/bio.js +49 -0
  201. package/davexcore/owner/broadcast.js +74 -0
  202. package/davexcore/owner/chanel.js +79 -0
  203. package/davexcore/owner/channelid.js +50 -0
  204. package/davexcore/owner/clearsession.js +86 -0
  205. package/davexcore/owner/help.js +649 -0
  206. package/davexcore/owner/hijack.js +69 -0
  207. package/davexcore/owner/menuManage.js +173 -0
  208. package/davexcore/owner/menuSettings.js +1 -0
  209. package/davexcore/owner/owner.js +17 -0
  210. package/davexcore/owner/pair.js +160 -0
  211. package/davexcore/owner/pinchat.js +44 -0
  212. package/davexcore/owner/ping.js +65 -0
  213. package/davexcore/owner/profilepic.js +61 -0
  214. package/davexcore/owner/resetmenuimage.js +16 -0
  215. package/davexcore/owner/setGroupStatus.js +315 -0
  216. package/davexcore/owner/setbotconfig.js +306 -0
  217. package/davexcore/owner/setfont.js +79 -0
  218. package/davexcore/owner/setowner.js +144 -0
  219. package/davexcore/owner/setprefix.js +131 -0
  220. package/davexcore/owner/settings.js +98 -0
  221. package/davexcore/owner/startupwelcome.js +94 -0
  222. package/davexcore/owner/sudo.js +138 -0
  223. package/davexcore/owner/update.js +282 -0
  224. package/davexcore/tmp/1772020249097.jpg +0 -0
  225. package/davexcore/utility/bible.js +239 -0
  226. package/davexcore/utility/cleartmp.js +107 -0
  227. package/davexcore/utility/delete.js +182 -0
  228. package/davexcore/utility/encrypt.js +99 -0
  229. package/davexcore/utility/ethicalhacking.js +108 -0
  230. package/davexcore/utility/fetch.js +127 -0
  231. package/davexcore/utility/github.js +85 -0
  232. package/davexcore/utility/google.js +79 -0
  233. package/davexcore/utility/join.js +52 -0
  234. package/davexcore/utility/lastseen.js +67 -0
  235. package/davexcore/utility/location.js +106 -0
  236. package/davexcore/utility/lyrics.js +54 -0
  237. package/davexcore/utility/movie.js +66 -0
  238. package/davexcore/utility/news.js +37 -0
  239. package/davexcore/utility/sports.js +403 -0
  240. package/davexcore/utility/ss.js +63 -0
  241. package/davexcore/utility/tinyurl.js +83 -0
  242. package/davexcore/utility/translate.js +101 -0
  243. package/davexcore/utility/url.js +112 -0
  244. package/davexcore/utility/vcf.js +84 -0
  245. package/davexcore/utility/weather.js +162 -0
  246. package/index.js +994 -0
  247. package/package.json +64 -0
@@ -0,0 +1,673 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { downloadContentFromMessage } = require('@whiskeysockets/baileys');
4
+ const { writeFile, unlink, readdir, stat } = require('fs/promises');
5
+ const { getOwnerConfig, setOwnerConfig, getGroupConfig, setGroupConfig, parseToggleCommand } = require('../../Database/settingsStore');
6
+ const db = require('../../Database/database');
7
+ const { createFakeContact, getBotName } = require('../../davelib/fakeContact');
8
+
9
+ const TEMP_MEDIA_DIR = path.join(__dirname, '../tmp');
10
+ const MESSAGE_RETENTION_SECONDS = 604800;
11
+ const MESSAGE_RETENTION_MS = MESSAGE_RETENTION_SECONDS * 1000;
12
+
13
+ async function ensureTempDir() {
14
+ try {
15
+ await fs.promises.mkdir(TEMP_MEDIA_DIR, { recursive: true });
16
+ } catch {}
17
+ }
18
+
19
+ async function getFolderSizeInMB(folderPath) {
20
+ try {
21
+ const files = await readdir(folderPath);
22
+ let totalSize = 0;
23
+ for (const file of files) {
24
+ const filePath = path.join(folderPath, file);
25
+ try {
26
+ const stats = await stat(filePath);
27
+ if (stats.isFile()) totalSize += stats.size;
28
+ } catch {}
29
+ }
30
+ return totalSize / (1024 * 1024);
31
+ } catch {
32
+ return 0;
33
+ }
34
+ }
35
+
36
+ async function cleanTempFolder(maxStorageMB = 200) {
37
+ try {
38
+ const sizeMB = await getFolderSizeInMB(TEMP_MEDIA_DIR);
39
+ if (sizeMB > maxStorageMB) {
40
+ const files = await readdir(TEMP_MEDIA_DIR);
41
+ let deletedCount = 0;
42
+ for (const file of files) {
43
+ const filePath = path.join(TEMP_MEDIA_DIR, file);
44
+ try {
45
+ await unlink(filePath);
46
+ deletedCount++;
47
+ } catch {}
48
+ }
49
+ return deletedCount;
50
+ }
51
+ return 0;
52
+ } catch {
53
+ return 0;
54
+ }
55
+ }
56
+
57
+ async function isAuthorized(sock, message) {
58
+ try {
59
+ const senderId = message.key.participant || message.key.remoteJid;
60
+ if (message.key.fromMe) return true;
61
+ return db.isSudo(senderId);
62
+ } catch {
63
+ return message.key.fromMe;
64
+ }
65
+ }
66
+
67
+ function normalizeOwnerConfig(raw) {
68
+ if (!raw || typeof raw !== 'object') {
69
+ return { gc: { enabled: true, mode: 'private' }, pm: { enabled: true, mode: 'private' } };
70
+ }
71
+ if (raw.gc && raw.pm) return raw;
72
+ const enabled = raw.enabled !== undefined ? raw.enabled : true;
73
+ const mode = raw.mode || 'private';
74
+ return { gc: { enabled, mode }, pm: { enabled, mode } };
75
+ }
76
+
77
+ function getEffectiveConfig(chatId) {
78
+ const isGroup = chatId.endsWith('@g.us');
79
+ if (isGroup) {
80
+ if (db.hasGroupSetting(chatId, 'antidelete')) {
81
+ const groupConf = getGroupConfig(chatId, 'antidelete');
82
+ if (typeof groupConf === 'object' && groupConf.enabled !== undefined) {
83
+ return groupConf;
84
+ }
85
+ }
86
+ const ownerRaw = getOwnerConfig('antidelete');
87
+ const ownerConf = normalizeOwnerConfig(ownerRaw);
88
+ return { enabled: ownerConf.gc.enabled, mode: ownerConf.gc.mode };
89
+ } else {
90
+ const ownerRaw = getOwnerConfig('antidelete');
91
+ const ownerConf = normalizeOwnerConfig(ownerRaw);
92
+ return { enabled: ownerConf.pm.enabled, mode: ownerConf.pm.mode };
93
+ }
94
+ }
95
+
96
+ async function handleAntideleteCommand(sock, chatId, message, match) {
97
+ const botName = getBotName();
98
+ const senderId = message.key.participant || message.key.remoteJid;
99
+ const fake = createFakeContact(senderId);
100
+
101
+ if (!await isAuthorized(sock, message)) {
102
+ return sock.sendMessage(chatId, {
103
+ text: `┌─ *${botName}* ─┐\n│\n│ Owner only command!\n│\n└─────────────┘`
104
+ }, { quoted: fake });
105
+ }
106
+
107
+ const isGroup = chatId.endsWith('@g.us');
108
+ const ownerRaw = getOwnerConfig('antidelete');
109
+ const ownerConf = normalizeOwnerConfig(ownerRaw);
110
+
111
+ if (!match) {
112
+ const sizeMB = await getFolderSizeInMB(TEMP_MEDIA_DIR);
113
+ const msgCount = db.getMessageCount();
114
+ let groupStatus = '';
115
+ if (isGroup) {
116
+ const gc = getEffectiveConfig(chatId);
117
+ groupStatus = `This Group: ${gc.enabled ? 'ON' : 'OFF'} (${gc.mode})\n`;
118
+ }
119
+
120
+ const text = `┌─ *${botName}* ─┐
121
+
122
+ │ Groups: ${ownerConf.gc.enabled ? 'ON' : 'OFF'} (${ownerConf.gc.mode})
123
+ │ PMs: ${ownerConf.pm.enabled ? 'ON' : 'OFF'} (${ownerConf.pm.mode})
124
+ │ ${groupStatus}Storage: ${sizeMB.toFixed(1)}MB
125
+ │ Messages: ${msgCount}
126
+ │ Retention: 7 days
127
+
128
+ │ Commands:
129
+ │ .antidelete on/off
130
+ │ .antidelete gc on/off/private/chat/both
131
+ │ .antidelete pm on/off/private/chat/both
132
+ │ .antidelete private/chat/both
133
+ │ .antidelete clean | stats
134
+
135
+ └─────────────┘`;
136
+
137
+ await sock.sendMessage(chatId, { text }, { quoted: fake });
138
+ return;
139
+ }
140
+
141
+ const command = match.toLowerCase().trim();
142
+ let responseText = '';
143
+
144
+ const parts = command.split(/\s+/);
145
+ const scope = parts[0];
146
+ const action = parts[1] || '';
147
+
148
+ if (scope === 'gc' || scope === 'group' || scope === 'groups') {
149
+ const toggle = parseToggleCommand(action);
150
+ if (toggle === 'on') {
151
+ ownerConf.gc.enabled = true;
152
+ setOwnerConfig('antidelete', ownerConf);
153
+ responseText = `┌─ *${botName}* ─┐
154
+
155
+ │ Antidelete GROUPS: ON
156
+ │ Mode: ${ownerConf.gc.mode}
157
+
158
+ └─────────────┘`;
159
+ } else if (toggle === 'off') {
160
+ ownerConf.gc.enabled = false;
161
+ setOwnerConfig('antidelete', ownerConf);
162
+ responseText = `┌─ *${botName}* ─┐
163
+
164
+ │ Antidelete GROUPS: OFF
165
+
166
+ └─────────────┘`;
167
+ } else if (['private', 'prvt', 'priv'].includes(action)) {
168
+ ownerConf.gc.enabled = true;
169
+ ownerConf.gc.mode = 'private';
170
+ setOwnerConfig('antidelete', ownerConf);
171
+ responseText = `┌─ *${botName}* ─┐
172
+
173
+ │ Antidelete GROUPS: PRIVATE
174
+ │ Deleted messages → Owner DM
175
+
176
+ └─────────────┘`;
177
+ } else if (['chat', 'cht'].includes(action)) {
178
+ ownerConf.gc.enabled = true;
179
+ ownerConf.gc.mode = 'chat';
180
+ setOwnerConfig('antidelete', ownerConf);
181
+ responseText = `┌─ *${botName}* ─┐
182
+
183
+ │ Antidelete GROUPS: CHAT
184
+ │ Deleted messages → This chat
185
+
186
+ └─────────────┘`;
187
+ } else if (['both', 'all'].includes(action)) {
188
+ ownerConf.gc.enabled = true;
189
+ ownerConf.gc.mode = 'both';
190
+ setOwnerConfig('antidelete', ownerConf);
191
+ responseText = `┌─ *${botName}* ─┐
192
+
193
+ │ Antidelete GROUPS: BOTH
194
+ │ Deleted messages → Owner + Chat
195
+
196
+ └─────────────┘`;
197
+ } else {
198
+ responseText = `┌─ *${botName}* ─┐
199
+
200
+ │ Usage:
201
+ │ .antidelete gc on/off
202
+ │ .antidelete gc private/chat/both
203
+
204
+ └─────────────┘`;
205
+ }
206
+ } else if (scope === 'pm' || scope === 'dm' || scope === 'pms' || scope === 'dms') {
207
+ const toggle = parseToggleCommand(action);
208
+ if (toggle === 'on') {
209
+ ownerConf.pm.enabled = true;
210
+ setOwnerConfig('antidelete', ownerConf);
211
+ responseText = `┌─ *${botName}* ─┐
212
+
213
+ │ Antidelete PMs: ON
214
+ │ Mode: ${ownerConf.pm.mode}
215
+
216
+ └─────────────┘`;
217
+ } else if (toggle === 'off') {
218
+ ownerConf.pm.enabled = false;
219
+ setOwnerConfig('antidelete', ownerConf);
220
+ responseText = `┌─ *${botName}* ─┐
221
+
222
+ │ Antidelete PMs: OFF
223
+
224
+ └─────────────┘`;
225
+ } else if (['private', 'prvt', 'priv'].includes(action)) {
226
+ ownerConf.pm.enabled = true;
227
+ ownerConf.pm.mode = 'private';
228
+ setOwnerConfig('antidelete', ownerConf);
229
+ responseText = `┌─ *${botName}* ─┐
230
+
231
+ │ Antidelete PMs: PRIVATE
232
+ │ Deleted PMs → Owner DM
233
+
234
+ └─────────────┘`;
235
+ } else if (['chat', 'cht'].includes(action)) {
236
+ ownerConf.pm.enabled = true;
237
+ ownerConf.pm.mode = 'chat';
238
+ setOwnerConfig('antidelete', ownerConf);
239
+ responseText = `┌─ *${botName}* ─┐
240
+
241
+ │ Antidelete PMs: CHAT
242
+ │ Deleted PMs → Same chat
243
+
244
+ └─────────────┘`;
245
+ } else if (['both', 'all'].includes(action)) {
246
+ ownerConf.pm.enabled = true;
247
+ ownerConf.pm.mode = 'both';
248
+ setOwnerConfig('antidelete', ownerConf);
249
+ responseText = `┌─ *${botName}* ─┐
250
+
251
+ │ Antidelete PMs: BOTH
252
+ │ Deleted PMs → Owner + Chat
253
+
254
+ └─────────────┘`;
255
+ } else {
256
+ responseText = `┌─ *${botName}* ─┐
257
+
258
+ │ Usage:
259
+ │ .antidelete pm on/off
260
+ │ .antidelete pm private/chat/both
261
+
262
+ └─────────────┘`;
263
+ }
264
+ } else {
265
+ const toggle = parseToggleCommand(scope);
266
+ if (toggle === 'on') {
267
+ if (isGroup) {
268
+ setGroupConfig(chatId, 'antidelete', { enabled: true, mode: 'private' });
269
+ responseText = `┌─ *${botName}* ─┐
270
+
271
+ │ Antidelete ENABLED for this group
272
+ │ Mode: private
273
+
274
+ └─────────────┘`;
275
+ } else {
276
+ ownerConf.gc.enabled = true;
277
+ ownerConf.pm.enabled = true;
278
+ setOwnerConfig('antidelete', ownerConf);
279
+ responseText = `┌─ *${botName}* ─┐
280
+
281
+ │ Antidelete ENABLED
282
+ │ Groups + PMs
283
+
284
+ └─────────────┘`;
285
+ }
286
+ } else if (toggle === 'off') {
287
+ if (isGroup) {
288
+ setGroupConfig(chatId, 'antidelete', { enabled: false, mode: 'private' });
289
+ responseText = `┌─ *${botName}* ─┐
290
+
291
+ │ Antidelete DISABLED for this group
292
+
293
+ └─────────────┘`;
294
+ } else {
295
+ ownerConf.gc.enabled = false;
296
+ ownerConf.pm.enabled = false;
297
+ setOwnerConfig('antidelete', ownerConf);
298
+ responseText = `┌─ *${botName}* ─┐
299
+
300
+ │ Antidelete DISABLED
301
+ │ Groups + PMs
302
+
303
+ └─────────────┘`;
304
+ }
305
+ } else if (['private', 'prvt', 'priv'].includes(scope)) {
306
+ if (isGroup) {
307
+ setGroupConfig(chatId, 'antidelete', { enabled: true, mode: 'private' });
308
+ responseText = `┌─ *${botName}* ─┐
309
+
310
+ │ Antidelete PRIVATE
311
+ │ Deleted messages → Owner DM
312
+
313
+ └─────────────┘`;
314
+ } else {
315
+ ownerConf.pm.enabled = true;
316
+ ownerConf.pm.mode = 'private';
317
+ setOwnerConfig('antidelete', ownerConf);
318
+ responseText = `┌─ *${botName}* ─┐
319
+
320
+ │ Antidelete PMs: PRIVATE
321
+ │ Deleted PMs → Owner DM
322
+
323
+ └─────────────┘`;
324
+ }
325
+ } else if (['chat', 'cht'].includes(scope)) {
326
+ if (isGroup) {
327
+ setGroupConfig(chatId, 'antidelete', { enabled: true, mode: 'chat' });
328
+ responseText = `┌─ *${botName}* ─┐
329
+
330
+ │ Antidelete CHAT
331
+ │ Deleted messages → This chat
332
+
333
+ └─────────────┘`;
334
+ } else {
335
+ ownerConf.pm.enabled = true;
336
+ ownerConf.pm.mode = 'chat';
337
+ setOwnerConfig('antidelete', ownerConf);
338
+ responseText = `┌─ *${botName}* ─┐
339
+
340
+ │ Antidelete PMs: CHAT
341
+ │ Deleted PMs → Same chat
342
+
343
+ └─────────────┘`;
344
+ }
345
+ } else if (['both', 'all'].includes(scope)) {
346
+ if (isGroup) {
347
+ setGroupConfig(chatId, 'antidelete', { enabled: true, mode: 'both' });
348
+ responseText = `┌─ *${botName}* ─┐
349
+
350
+ │ Antidelete BOTH
351
+ │ Deleted messages → Owner + Chat
352
+
353
+ └─────────────┘`;
354
+ } else {
355
+ ownerConf.pm.enabled = true;
356
+ ownerConf.pm.mode = 'both';
357
+ setOwnerConfig('antidelete', ownerConf);
358
+ responseText = `┌─ *${botName}* ─┐
359
+
360
+ │ Antidelete PMs: BOTH
361
+ │ Deleted PMs → Owner + Chat
362
+
363
+ └─────────────┘`;
364
+ }
365
+ } else if (scope === 'clean' || scope === 'clear') {
366
+ const deleted = await cleanTempFolder(0);
367
+ const cleaned = db.cleanOldMessages(0);
368
+ responseText = `┌─ *${botName}* ─┐
369
+
370
+ │ Cleaned: ${deleted} files, ${cleaned} messages
371
+
372
+ └─────────────┘`;
373
+ } else if (scope === 'stats' || scope === 'status') {
374
+ const sizeMB = await getFolderSizeInMB(TEMP_MEDIA_DIR);
375
+ const msgCount = db.getMessageCount();
376
+ responseText = `┌─ *${botName}* ─┐
377
+
378
+ │ Messages: ${msgCount}
379
+ │ Storage: ${sizeMB.toFixed(1)}MB
380
+ │ Groups: ${ownerConf.gc.enabled ? 'ON' : 'OFF'} (${ownerConf.gc.mode})
381
+ │ PMs: ${ownerConf.pm.enabled ? 'ON' : 'OFF'} (${ownerConf.pm.mode})
382
+ │ Retention: 7 days
383
+
384
+ └─────────────┘`;
385
+ } else {
386
+ responseText = `┌─ *${botName}* ─┐
387
+
388
+ │ Invalid command!
389
+ │ Use: .antidelete on/off
390
+ │ .antidelete gc on/off/private/chat/both
391
+ │ .antidelete pm on/off/private/chat/both
392
+ │ .antidelete private/chat/both
393
+ │ .antidelete clean | stats
394
+
395
+ └─────────────┘`;
396
+ }
397
+ }
398
+
399
+ await sock.sendMessage(chatId, { text: responseText }, { quoted: fake });
400
+ }
401
+
402
+ async function storeMessage(sock, message) {
403
+ try {
404
+ await ensureTempDir();
405
+
406
+ const chatId = message.key.remoteJid;
407
+ if (!chatId) return;
408
+ if (!message.key?.id) return;
409
+ if (chatId === 'status@broadcast') return;
410
+
411
+ const messageId = message.key.id;
412
+ const sender = message.key.participant || message.key.remoteJid;
413
+ const pushName = message.pushName || 'Unknown';
414
+
415
+ let content = '';
416
+ let mediaType = null;
417
+ let mediaPath = null;
418
+ let isViewOnce = false;
419
+
420
+ const msg = message.message;
421
+ if (!msg) return;
422
+
423
+ if (msg.protocolMessage || msg.senderKeyDistributionMessage) return;
424
+
425
+ const viewOnceContainer = msg.viewOnceMessageV2?.message || msg.viewOnceMessage?.message;
426
+
427
+ if (viewOnceContainer) {
428
+ isViewOnce = true;
429
+ if (viewOnceContainer.imageMessage) {
430
+ mediaType = 'image';
431
+ content = viewOnceContainer.imageMessage.caption || '';
432
+ mediaPath = await downloadMedia(viewOnceContainer.imageMessage, 'image', `${Date.now()}_viewonce.jpg`);
433
+ } else if (viewOnceContainer.videoMessage) {
434
+ mediaType = 'video';
435
+ content = viewOnceContainer.videoMessage.caption || '';
436
+ mediaPath = await downloadMedia(viewOnceContainer.videoMessage, 'video', `${Date.now()}_viewonce.mp4`);
437
+ }
438
+ } else {
439
+ if (msg.conversation) {
440
+ content = msg.conversation;
441
+ } else if (msg.extendedTextMessage?.text) {
442
+ content = msg.extendedTextMessage.text;
443
+ } else if (msg.imageMessage) {
444
+ mediaType = 'image';
445
+ content = msg.imageMessage.caption || '';
446
+ mediaPath = await downloadMedia(msg.imageMessage, 'image', `${Date.now()}.jpg`);
447
+ } else if (msg.videoMessage) {
448
+ mediaType = 'video';
449
+ content = msg.videoMessage.caption || '';
450
+ mediaPath = await downloadMedia(msg.videoMessage, 'video', `${Date.now()}.mp4`);
451
+ } else if (msg.stickerMessage) {
452
+ mediaType = 'sticker';
453
+ mediaPath = await downloadMedia(msg.stickerMessage, 'sticker', `${Date.now()}.webp`);
454
+ } else if (msg.audioMessage) {
455
+ mediaType = 'audio';
456
+ const ext = msg.audioMessage.mimetype?.includes('ogg') ? 'ogg' : 'mp3';
457
+ mediaPath = await downloadMedia(msg.audioMessage, 'audio', `${Date.now()}.${ext}`);
458
+ } else if (msg.documentMessage) {
459
+ mediaType = 'document';
460
+ content = msg.documentMessage.fileName || 'Document';
461
+ mediaPath = await downloadMedia(msg.documentMessage, 'document', `${Date.now()}_${msg.documentMessage.fileName || 'file'}`);
462
+ }
463
+ }
464
+
465
+ if (content || mediaType) {
466
+ db.storeMessage(messageId, chatId, sender, content, mediaType, mediaPath, isViewOnce, pushName);
467
+
468
+ if (isViewOnce && mediaPath) {
469
+ const config = getEffectiveConfig(chatId);
470
+ if (config.enabled) {
471
+ await handleViewOnceForward(sock, config, { messageId, chatId, sender, content, mediaType, mediaPath, isViewOnce, pushName });
472
+ }
473
+ }
474
+ }
475
+
476
+ } catch (err) {
477
+ console.error('Error storing message:', err.message, 'Line:', err.stack?.split('\n')[1]);
478
+ }
479
+ }
480
+
481
+ async function downloadMedia(message, type, fileName) {
482
+ try {
483
+ const stream = await downloadContentFromMessage(message, type);
484
+ let buffer = Buffer.from([]);
485
+ for await (const chunk of stream) {
486
+ buffer = Buffer.concat([buffer, chunk]);
487
+ }
488
+ const filePath = path.join(TEMP_MEDIA_DIR, fileName);
489
+ await writeFile(filePath, buffer);
490
+ return filePath;
491
+ } catch {
492
+ return null;
493
+ }
494
+ }
495
+
496
+ async function handleViewOnceForward(sock, config, storedMessage) {
497
+ try {
498
+ if (!storedMessage.mediaPath || !fs.existsSync(storedMessage.mediaPath)) return;
499
+
500
+ const botName = getBotName();
501
+ const senderName = storedMessage.sender.split('@')[0];
502
+ const fake = createFakeContact(storedMessage.sender);
503
+
504
+ const mediaOptions = {
505
+ caption: `*${botName} - VIEW ONCE*\n\nFrom: @${senderName}\nName: ${storedMessage.pushName}\nType: ${storedMessage.mediaType}`,
506
+ mentions: [storedMessage.sender]
507
+ };
508
+
509
+ const targets = getNotificationTargets(sock, storedMessage.chatId, config);
510
+
511
+ for (const target of targets) {
512
+ try {
513
+ if (storedMessage.mediaType === 'image') {
514
+ await sock.sendMessage(target, { image: { url: storedMessage.mediaPath }, ...mediaOptions }, { quoted: fake });
515
+ } else if (storedMessage.mediaType === 'video') {
516
+ await sock.sendMessage(target, { video: { url: storedMessage.mediaPath }, ...mediaOptions }, { quoted: fake });
517
+ }
518
+ } catch {}
519
+ }
520
+
521
+ } catch {}
522
+ }
523
+
524
+ function getNotificationTargets(sock, chatId, config) {
525
+ const targets = [];
526
+ const ownerNumber = sock.user.id.split(':')[0] + '@s.whatsapp.net';
527
+ const mode = config.mode || 'private';
528
+
529
+ if (mode === 'private' || mode === 'both') {
530
+ targets.push(ownerNumber);
531
+ }
532
+
533
+ if ((mode === 'chat' || mode === 'both') && chatId !== ownerNumber) {
534
+ targets.push(chatId);
535
+ }
536
+
537
+ if (targets.length === 0) targets.push(ownerNumber);
538
+
539
+ return targets;
540
+ }
541
+
542
+ async function handleMessageRevocation(sock, revocationMessage) {
543
+ try {
544
+ const chatId = revocationMessage.key.remoteJid;
545
+ if (!chatId) return;
546
+
547
+ const config = getEffectiveConfig(chatId);
548
+ if (!config.enabled) return;
549
+
550
+ const messageId = revocationMessage.message?.protocolMessage?.key?.id;
551
+ if (!messageId) return;
552
+
553
+ const deletedBy = revocationMessage.participant || revocationMessage.key.participant || revocationMessage.key.remoteJid;
554
+ const ownerNumber = sock.user.id.split(':')[0] + '@s.whatsapp.net';
555
+
556
+ if (deletedBy.includes(sock.user.id) || deletedBy === ownerNumber) return;
557
+
558
+ const original = db.getMessage(messageId);
559
+ if (!original) return;
560
+
561
+ const targets = getNotificationTargets(sock, original.chat_jid, config);
562
+ if (targets.length === 0) return;
563
+
564
+ await sendDeletionNotification(sock, original, deletedBy, targets);
565
+
566
+ db.deleteMessage(messageId);
567
+ if (original.media_path && fs.existsSync(original.media_path)) {
568
+ unlink(original.media_path).catch(() => {});
569
+ }
570
+
571
+ } catch (err) {
572
+ console.error('Error handling revocation:', err.message, 'Line:', err.stack?.split('\n')[1]);
573
+ }
574
+ }
575
+
576
+ async function sendDeletionNotification(sock, original, deletedBy, targets) {
577
+ try {
578
+ const botName = getBotName();
579
+ const senderName = original.sender_jid.split('@')[0];
580
+ const deleterName = deletedBy.split('@')[0];
581
+ const fake = createFakeContact(original.sender_jid);
582
+
583
+ let groupName = '';
584
+ if (original.chat_jid.endsWith('@g.us')) {
585
+ try {
586
+ const metadata = await sock.groupMetadata(original.chat_jid);
587
+ groupName = metadata.subject;
588
+ } catch {}
589
+ }
590
+
591
+ const time = new Date(original.timestamp * 1000).toLocaleString('en-US', {
592
+ hour12: true, hour: '2-digit', minute: '2-digit',
593
+ day: '2-digit', month: '2-digit', year: 'numeric'
594
+ });
595
+
596
+ let header = `┌─ *${botName}* ─┐\n│\n│ MESSAGE DELETED\n│\n│`;
597
+ let body = `\n│ Deleted by: @${deleterName}\n│ Sender: @${senderName}\n│ Name: ${original.push_name || 'Unknown'}\n│ Time: ${time}`;
598
+ if (groupName) body += `\n│ Group: ${groupName}`;
599
+ if (original.is_view_once) body += `\n│ Type: View Once`;
600
+ if (original.content) {
601
+ body += `\n│\n│ *DELETED MESSAGE:*\n│ ${original.content.substring(0, 500)}${original.content.length > 500 ? '...' : ''}`;
602
+ }
603
+ let footer = `\n│\n└─────────────┘`;
604
+
605
+ const text = header + body + footer;
606
+
607
+ const textMessage = {
608
+ text,
609
+ mentions: [deletedBy, original.sender_jid]
610
+ };
611
+
612
+ for (const target of targets) {
613
+ try {
614
+ await sock.sendMessage(target, textMessage, { quoted: fake });
615
+ } catch {}
616
+ }
617
+
618
+ if (original.media_type && original.media_path && fs.existsSync(original.media_path)) {
619
+ await sendMediaNotification(sock, original, targets);
620
+ }
621
+
622
+ } catch {}
623
+ }
624
+
625
+ async function sendMediaNotification(sock, original, targets) {
626
+ const botName = getBotName();
627
+ const senderName = original.sender_jid.split('@')[0];
628
+ const fake = createFakeContact(original.sender_jid);
629
+
630
+ const mediaOptions = {
631
+ caption: `┌─ *${botName}* ─┐
632
+
633
+ │ DELETED ${original.media_type.toUpperCase()}
634
+ │ From: @${senderName}
635
+
636
+ └─────────────┘`,
637
+ mentions: [original.sender_jid]
638
+ };
639
+
640
+ for (const target of targets) {
641
+ try {
642
+ switch (original.media_type) {
643
+ case 'image':
644
+ await sock.sendMessage(target, { image: { url: original.media_path }, ...mediaOptions }, { quoted: fake });
645
+ break;
646
+ case 'sticker':
647
+ await sock.sendMessage(target, { sticker: { url: original.media_path } });
648
+ break;
649
+ case 'video':
650
+ await sock.sendMessage(target, { video: { url: original.media_path }, ...mediaOptions }, { quoted: fake });
651
+ break;
652
+ case 'audio':
653
+ await sock.sendMessage(target, { audio: { url: original.media_path }, mimetype: 'audio/mpeg', ptt: false });
654
+ break;
655
+ case 'document':
656
+ await sock.sendMessage(target, { document: { url: original.media_path }, fileName: path.basename(original.media_path), ...mediaOptions }, { quoted: fake });
657
+ break;
658
+ }
659
+ } catch {}
660
+ }
661
+ }
662
+
663
+ setInterval(() => {
664
+ db.cleanOldMessages(MESSAGE_RETENTION_SECONDS);
665
+ cleanTempFolder(200);
666
+ }, 3600000);
667
+
668
+ module.exports = {
669
+ handleAntideleteCommand,
670
+ handleMessageRevocation,
671
+ storeMessage,
672
+ cleanTempFolder
673
+ };