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,327 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const db = require('./database');
4
+ const { setGroupConfig, setOwnerConfig, clearAllCache } = require('./settingsStore');
5
+
6
+ const DATA_DIR = path.join(__dirname, '../data');
7
+ const MIGRATION_STATUS_FILE = path.join(__dirname, '.migration_status.json');
8
+
9
+ function getMigrationStatus() {
10
+ try {
11
+ if (fs.existsSync(MIGRATION_STATUS_FILE)) {
12
+ return JSON.parse(fs.readFileSync(MIGRATION_STATUS_FILE, 'utf8'));
13
+ }
14
+ } catch {}
15
+ return {};
16
+ }
17
+
18
+ function saveMigrationStatus(status) {
19
+ try {
20
+ fs.writeFileSync(MIGRATION_STATUS_FILE, JSON.stringify(status, null, 2));
21
+ } catch {}
22
+ }
23
+
24
+ function isFileMigrated(filename) {
25
+ const status = getMigrationStatus();
26
+ return status[filename] === true;
27
+ }
28
+
29
+ function markFileMigrated(filename) {
30
+ const status = getMigrationStatus();
31
+ status[filename] = true;
32
+ saveMigrationStatus(status);
33
+ }
34
+
35
+ function migrateFromJson() {
36
+ console.log('[ DAVE-X ] Checking for pending JSON migrations...');
37
+ let hasPendingMigrations = false;
38
+ let migrated = 0;
39
+
40
+ try {
41
+ const userGroupPath = path.join(DATA_DIR, 'userGroupData.json');
42
+ if (fs.existsSync(userGroupPath) && !isFileMigrated('userGroupData.json')) {
43
+ hasPendingMigrations = true;
44
+ const data = JSON.parse(fs.readFileSync(userGroupPath, 'utf8'));
45
+
46
+ const features = [
47
+ 'antibadword', 'antilink', 'antitag', 'antimention', 'antigroupmention',
48
+ 'antidemote', 'antisticker', 'antiimage', 'antiaudio', 'antidocument',
49
+ 'antifiles', 'antipromote', 'antivideo', 'antibug', 'antichart',
50
+ 'welcome', 'goodbye', 'chatbot'
51
+ ];
52
+
53
+ for (const feature of features) {
54
+ if (data[feature]) {
55
+ for (const [groupId, config] of Object.entries(data[feature])) {
56
+ setGroupConfig(groupId, feature, config);
57
+ migrated++;
58
+ }
59
+ }
60
+ }
61
+
62
+ if (data.warnings) {
63
+ for (const [groupId, users] of Object.entries(data.warnings)) {
64
+ for (const [userId, count] of Object.entries(users)) {
65
+ const database = db.getDb();
66
+ const stmt = database.prepare(`
67
+ INSERT OR REPLACE INTO warnings (group_jid, user_jid, count, updated_at)
68
+ VALUES (?, ?, ?, strftime('%s', 'now'))
69
+ `);
70
+ stmt.run(groupId, userId, count);
71
+ migrated++;
72
+ }
73
+ }
74
+ }
75
+
76
+ if (Array.isArray(data.sudo)) {
77
+ for (const userId of data.sudo) {
78
+ db.addSudoUser(userId);
79
+ migrated++;
80
+ }
81
+ }
82
+
83
+ markFileMigrated('userGroupData.json');
84
+ console.log(`[ DAVE-X ] Migrated ${migrated} settings from userGroupData.json`);
85
+ }
86
+
87
+ const antideleteConfig = path.join(DATA_DIR, 'antidelete.json');
88
+ if (fs.existsSync(antideleteConfig) && !isFileMigrated('antidelete.json')) {
89
+ hasPendingMigrations = true;
90
+ try {
91
+ const config = JSON.parse(fs.readFileSync(antideleteConfig, 'utf8'));
92
+ setOwnerConfig('antidelete', config);
93
+ markFileMigrated('antidelete.json');
94
+ console.log('[ DAVE-X ] Migrated antidelete config');
95
+ } catch {}
96
+ }
97
+
98
+ const anticallConfig = path.join(DATA_DIR, 'anticall.json');
99
+ if (fs.existsSync(anticallConfig) && !isFileMigrated('anticall.json')) {
100
+ try {
101
+ const config = JSON.parse(fs.readFileSync(anticallConfig, 'utf8'));
102
+ setOwnerConfig('anticall', { enabled: config.enabled || false, mode: 'block', message: 'Calls not allowed!' });
103
+ markFileMigrated('anticall.json');
104
+ console.log('[ DAVE-X ] Migrated anticall config');
105
+ } catch {}
106
+ }
107
+
108
+ const antieditConfig = path.join(DATA_DIR, 'antiedit.json');
109
+ if (fs.existsSync(antieditConfig) && !isFileMigrated('antiedit.json')) {
110
+ try {
111
+ const config = JSON.parse(fs.readFileSync(antieditConfig, 'utf8'));
112
+ setOwnerConfig('antiedit', config);
113
+ markFileMigrated('antiedit.json');
114
+ console.log('[ DAVE-X ] Migrated antiedit config');
115
+ } catch {}
116
+ }
117
+
118
+ const autoreadConfig = path.join(DATA_DIR, 'autoread.json');
119
+ if (fs.existsSync(autoreadConfig) && !isFileMigrated('autoread.json')) {
120
+ try {
121
+ const config = JSON.parse(fs.readFileSync(autoreadConfig, 'utf8'));
122
+ setOwnerConfig('autoread', config.enabled || false);
123
+ markFileMigrated('autoread.json');
124
+ console.log('[ DAVE-X ] Migrated autoread config');
125
+ } catch {}
126
+ }
127
+
128
+ const autotypingConfig = path.join(DATA_DIR, 'autotyping.json');
129
+ if (fs.existsSync(autotypingConfig) && !isFileMigrated('autotyping.json')) {
130
+ try {
131
+ const config = JSON.parse(fs.readFileSync(autotypingConfig, 'utf8'));
132
+ setOwnerConfig('autotyping', config.enabled || false);
133
+ markFileMigrated('autotyping.json');
134
+ console.log('[ DAVE-X ] Migrated autotyping config');
135
+ } catch {}
136
+ }
137
+
138
+ const autorecordingConfig = path.join(DATA_DIR, 'autorecording.json');
139
+ if (fs.existsSync(autorecordingConfig) && !isFileMigrated('autorecording.json')) {
140
+ try {
141
+ const config = JSON.parse(fs.readFileSync(autorecordingConfig, 'utf8'));
142
+ setOwnerConfig('autorecording', config.enabled || false);
143
+ markFileMigrated('autorecording.json');
144
+ console.log('[ DAVE-X ] Migrated autorecording config');
145
+ } catch {}
146
+ }
147
+
148
+ const ownerConfig = path.join(DATA_DIR, 'owner.json');
149
+ if (fs.existsSync(ownerConfig) && !isFileMigrated('owner.json')) {
150
+ try {
151
+ const config = JSON.parse(fs.readFileSync(ownerConfig, 'utf8'));
152
+ if (Array.isArray(config)) {
153
+ for (const owner of config) {
154
+ if (typeof owner === 'string') {
155
+ db.addSudoUser(owner.includes('@') ? owner : owner + '@s.whatsapp.net');
156
+ }
157
+ }
158
+ }
159
+ markFileMigrated('owner.json');
160
+ console.log('[ DAVE-X ] Migrated owner config');
161
+ } catch {}
162
+ }
163
+
164
+ const bannedConfig = path.join(DATA_DIR, 'banned.json');
165
+ if (fs.existsSync(bannedConfig) && !isFileMigrated('banned.json')) {
166
+ try {
167
+ const config = JSON.parse(fs.readFileSync(bannedConfig, 'utf8'));
168
+ if (Array.isArray(config)) {
169
+ for (const user of config) {
170
+ if (typeof user === 'string') {
171
+ db.addBannedUser(user);
172
+ }
173
+ }
174
+ } else if (typeof config === 'object') {
175
+ for (const [userId, reason] of Object.entries(config)) {
176
+ db.addBannedUser(userId, reason || '');
177
+ }
178
+ }
179
+ markFileMigrated('banned.json');
180
+ console.log('[ DAVE-X ] Migrated banned users');
181
+ } catch {}
182
+ }
183
+
184
+ const premiumConfig = path.join(DATA_DIR, 'premium.json');
185
+ if (fs.existsSync(premiumConfig) && !isFileMigrated('premium.json')) {
186
+ try {
187
+ const config = JSON.parse(fs.readFileSync(premiumConfig, 'utf8'));
188
+ if (Array.isArray(config)) {
189
+ for (const user of config) {
190
+ if (typeof user === 'string') {
191
+ const database = db.getDb();
192
+ const stmt = database.prepare(`
193
+ INSERT OR IGNORE INTO premium_users (user_jid, added_at)
194
+ VALUES (?, strftime('%s', 'now'))
195
+ `);
196
+ stmt.run(user);
197
+ }
198
+ }
199
+ }
200
+ markFileMigrated('premium.json');
201
+ console.log('[ DAVE-X ] Migrated premium users');
202
+ } catch {}
203
+ }
204
+
205
+ const warningsConfig = path.join(DATA_DIR, 'warnings.json');
206
+ if (fs.existsSync(warningsConfig) && !isFileMigrated('warnings.json')) {
207
+ try {
208
+ const config = JSON.parse(fs.readFileSync(warningsConfig, 'utf8'));
209
+ if (typeof config === 'object' && config !== null) {
210
+ for (const [groupId, users] of Object.entries(config)) {
211
+ if (typeof users === 'object' && users !== null) {
212
+ for (const [userId, count] of Object.entries(users)) {
213
+ const database = db.getDb();
214
+ const stmt = database.prepare(`
215
+ INSERT OR REPLACE INTO warnings (group_jid, user_jid, count, updated_at)
216
+ VALUES (?, ?, ?, strftime('%s', 'now'))
217
+ `);
218
+ stmt.run(groupId, userId, typeof count === 'number' ? count : 0);
219
+ }
220
+ }
221
+ }
222
+ }
223
+ markFileMigrated('warnings.json');
224
+ console.log('[ DAVE-X ] Migrated warnings');
225
+ } catch {}
226
+ }
227
+
228
+ const pmblockerConfig = path.join(DATA_DIR, 'pmblocker.json');
229
+ if (fs.existsSync(pmblockerConfig) && !isFileMigrated('pmblocker.json')) {
230
+ try {
231
+ const config = JSON.parse(fs.readFileSync(pmblockerConfig, 'utf8'));
232
+ setOwnerConfig('pmblocker', { enabled: config.enabled || false, message: config.message || '' });
233
+ markFileMigrated('pmblocker.json');
234
+ console.log('[ DAVE-X ] Migrated pmblocker config');
235
+ } catch {}
236
+ }
237
+
238
+ const autoStatusConfig = path.join(DATA_DIR, 'autoStatus.json');
239
+ if (fs.existsSync(autoStatusConfig) && !isFileMigrated('autoStatus.json')) {
240
+ try {
241
+ const config = JSON.parse(fs.readFileSync(autoStatusConfig, 'utf8'));
242
+ setOwnerConfig('autostatus', config);
243
+ setOwnerConfig('autoviewstatus', config.enabled || config.autoView || false);
244
+ markFileMigrated('autoStatus.json');
245
+ console.log('[ DAVE-X ] Migrated autoStatus config');
246
+ } catch {}
247
+ }
248
+
249
+ const prefixConfig = path.join(DATA_DIR, 'prefix.json');
250
+ if (fs.existsSync(prefixConfig) && !isFileMigrated('prefix.json')) {
251
+ try {
252
+ const config = JSON.parse(fs.readFileSync(prefixConfig, 'utf8'));
253
+ setOwnerConfig('prefix', config.prefix || '.');
254
+ markFileMigrated('prefix.json');
255
+ console.log('[ DAVE-X ] Migrated prefix config');
256
+ } catch {}
257
+ }
258
+
259
+ const botconfigPath = path.join(DATA_DIR, 'botconfig.json');
260
+ if (fs.existsSync(botconfigPath) && !isFileMigrated('botconfig.json')) {
261
+ try {
262
+ const config = JSON.parse(fs.readFileSync(botconfigPath, 'utf8'));
263
+ setOwnerConfig('botconfig', config);
264
+ markFileMigrated('botconfig.json');
265
+ console.log('[ DAVE-X ] Migrated botconfig');
266
+ } catch {}
267
+ }
268
+
269
+ const menuSettingsPath = path.join(DATA_DIR, 'menuSettings.json');
270
+ if (fs.existsSync(menuSettingsPath) && !isFileMigrated('menuSettings.json')) {
271
+ try {
272
+ const config = JSON.parse(fs.readFileSync(menuSettingsPath, 'utf8'));
273
+ setOwnerConfig('menuSettings', config);
274
+ markFileMigrated('menuSettings.json');
275
+ console.log('[ DAVE-X ] Migrated menuSettings');
276
+ } catch {}
277
+ }
278
+
279
+ const statusAntideleteConfig = path.join(DATA_DIR, 'status_antidelete.json');
280
+ if (fs.existsSync(statusAntideleteConfig) && !isFileMigrated('status_antidelete.json')) {
281
+ try {
282
+ const config = JSON.parse(fs.readFileSync(statusAntideleteConfig, 'utf8'));
283
+ setOwnerConfig('status_antidelete', config);
284
+ markFileMigrated('status_antidelete.json');
285
+ console.log('[ DAVE-X ] Migrated status_antidelete config');
286
+ } catch {}
287
+ }
288
+
289
+ if (hasPendingMigrations) {
290
+ clearAllCache();
291
+ console.log('[ DAVE-X ] Migration completed successfully!');
292
+ } else {
293
+ console.log('[ DAVE-X ] No pending migrations.');
294
+ }
295
+
296
+ } catch (error) {
297
+ console.error('[ DAVE-X ] Migration error:', error.message);
298
+ console.error('[ DAVE-X ] Migration incomplete - will retry on next startup');
299
+ }
300
+ }
301
+
302
+ function cleanupLegacyFiles() {
303
+ const filesToKeep = ['botConfig.js', 'fakeContact.js', 'greetings.js', 'messageHandler.js'];
304
+
305
+ try {
306
+ if (!fs.existsSync(DATA_DIR)) return;
307
+
308
+ const files = fs.readdirSync(DATA_DIR);
309
+ let cleaned = 0;
310
+
311
+ for (const file of files) {
312
+ if (file.endsWith('.json') && !filesToKeep.includes(file)) {
313
+ console.log(`[ DAVE-X ] Note: Legacy file ${file} can be removed after verifying migration`);
314
+ cleaned++;
315
+ }
316
+ }
317
+
318
+ if (cleaned > 0) {
319
+ console.log(`[ DAVE-X ] ${cleaned} legacy JSON files identified for cleanup`);
320
+ }
321
+ } catch {}
322
+ }
323
+
324
+ module.exports = {
325
+ migrateFromJson,
326
+ cleanupLegacyFiles
327
+ };
@@ -0,0 +1,229 @@
1
+ const { Pool } = require('pg');
2
+
3
+ let pool = null;
4
+ let pgAvailable = false;
5
+
6
+ const PG_TABLES_SQL = `
7
+ CREATE TABLE IF NOT EXISTS owner_settings (
8
+ setting_key TEXT PRIMARY KEY,
9
+ setting_value TEXT NOT NULL,
10
+ updated_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW()))
11
+ );
12
+ CREATE TABLE IF NOT EXISTS group_settings (
13
+ group_jid TEXT NOT NULL,
14
+ setting_key TEXT NOT NULL,
15
+ setting_value TEXT NOT NULL,
16
+ updated_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW())),
17
+ PRIMARY KEY (group_jid, setting_key)
18
+ );
19
+ CREATE TABLE IF NOT EXISTS warnings (
20
+ group_jid TEXT NOT NULL,
21
+ user_jid TEXT NOT NULL,
22
+ count INTEGER DEFAULT 0,
23
+ updated_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW())),
24
+ PRIMARY KEY (group_jid, user_jid)
25
+ );
26
+ CREATE TABLE IF NOT EXISTS banned_users (
27
+ user_jid TEXT PRIMARY KEY,
28
+ reason TEXT,
29
+ banned_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW()))
30
+ );
31
+ CREATE TABLE IF NOT EXISTS sudo_users (
32
+ user_jid TEXT PRIMARY KEY,
33
+ added_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW()))
34
+ );
35
+ CREATE TABLE IF NOT EXISTS premium_users (
36
+ user_jid TEXT PRIMARY KEY,
37
+ expires_at BIGINT,
38
+ added_at BIGINT DEFAULT (EXTRACT(EPOCH FROM NOW()))
39
+ );
40
+ CREATE TABLE IF NOT EXISTS message_counts (
41
+ group_jid TEXT NOT NULL,
42
+ user_jid TEXT NOT NULL,
43
+ count INTEGER DEFAULT 0,
44
+ PRIMARY KEY (group_jid, user_jid)
45
+ );
46
+ `;
47
+
48
+ function getPgUrl() {
49
+ return process.env.DATABASE_URL || process.env.HEROKU_DATABASE_URL || null;
50
+ }
51
+
52
+ async function initPg() {
53
+ const url = getPgUrl();
54
+ if (!url) return false;
55
+
56
+ try {
57
+ pool = new Pool({
58
+ connectionString: url,
59
+ ssl: { rejectUnauthorized: false },
60
+ max: 3,
61
+ idleTimeoutMillis: 30000,
62
+ connectionTimeoutMillis: 10000
63
+ });
64
+
65
+ await pool.query('SELECT 1');
66
+ await pool.query(PG_TABLES_SQL);
67
+ pgAvailable = true;
68
+ console.log('[ DAVE-X ][PG] PostgreSQL connected');
69
+ return true;
70
+ } catch (err) {
71
+ console.error('[ DAVE-X ][PG] PostgreSQL init failed:', err.message);
72
+ pgAvailable = false;
73
+ return false;
74
+ }
75
+ }
76
+
77
+ async function loadFromPg(sqliteDb) {
78
+ if (!pgAvailable || !pool) return 0;
79
+
80
+ let loaded = 0;
81
+ try {
82
+ const ownerRows = await pool.query('SELECT setting_key, setting_value FROM owner_settings');
83
+ for (const row of ownerRows.rows) {
84
+ sqliteDb.prepare('INSERT OR REPLACE INTO owner_settings (setting_key, setting_value, updated_at) VALUES (?, ?, strftime(\'%s\', \'now\'))').run(row.setting_key, row.setting_value);
85
+ loaded++;
86
+ }
87
+
88
+ const groupRows = await pool.query('SELECT group_jid, setting_key, setting_value FROM group_settings');
89
+ for (const row of groupRows.rows) {
90
+ sqliteDb.prepare('INSERT OR REPLACE INTO group_settings (group_jid, setting_key, setting_value, updated_at) VALUES (?, ?, ?, strftime(\'%s\', \'now\'))').run(row.group_jid, row.setting_key, row.setting_value);
91
+ loaded++;
92
+ }
93
+
94
+ const warnRows = await pool.query('SELECT group_jid, user_jid, count FROM warnings');
95
+ for (const row of warnRows.rows) {
96
+ sqliteDb.prepare('INSERT OR REPLACE INTO warnings (group_jid, user_jid, count, updated_at) VALUES (?, ?, ?, strftime(\'%s\', \'now\'))').run(row.group_jid, row.user_jid, row.count);
97
+ loaded++;
98
+ }
99
+
100
+ const banRows = await pool.query('SELECT user_jid, reason FROM banned_users');
101
+ for (const row of banRows.rows) {
102
+ sqliteDb.prepare('INSERT OR REPLACE INTO banned_users (user_jid, reason, banned_at) VALUES (?, ?, strftime(\'%s\', \'now\'))').run(row.user_jid, row.reason);
103
+ loaded++;
104
+ }
105
+
106
+ const sudoRows = await pool.query('SELECT user_jid FROM sudo_users');
107
+ for (const row of sudoRows.rows) {
108
+ sqliteDb.prepare('INSERT OR IGNORE INTO sudo_users (user_jid, added_at) VALUES (?, strftime(\'%s\', \'now\'))').run(row.user_jid);
109
+ loaded++;
110
+ }
111
+
112
+ const premRows = await pool.query('SELECT user_jid, expires_at FROM premium_users');
113
+ for (const row of premRows.rows) {
114
+ sqliteDb.prepare('INSERT OR REPLACE INTO premium_users (user_jid, expires_at, added_at) VALUES (?, ?, strftime(\'%s\', \'now\'))').run(row.user_jid, row.expires_at);
115
+ loaded++;
116
+ }
117
+
118
+ const countRows = await pool.query('SELECT group_jid, user_jid, count FROM message_counts');
119
+ for (const row of countRows.rows) {
120
+ sqliteDb.prepare('INSERT OR REPLACE INTO message_counts (group_jid, user_jid, count) VALUES (?, ?, ?)').run(row.group_jid, row.user_jid, row.count);
121
+ loaded++;
122
+ }
123
+
124
+ if (loaded > 0) {
125
+ console.log(`[ DAVE-X ][PG] Loaded ${loaded} records from PostgreSQL`);
126
+ }
127
+ } catch (err) {
128
+ console.error('[ DAVE-X ][PG] Load from PG failed:', err.message);
129
+ }
130
+ return loaded;
131
+ }
132
+
133
+ function pgWrite(query, params = []) {
134
+ if (!pgAvailable || !pool) return;
135
+ pool.query(query, params).catch(err => {
136
+ console.error('[ DAVE-X ][PG] Write error:', err.message);
137
+ });
138
+ }
139
+
140
+ function pgSetOwnerSetting(key, value) {
141
+ pgWrite(
142
+ 'INSERT INTO owner_settings (setting_key, setting_value, updated_at) VALUES ($1, $2, EXTRACT(EPOCH FROM NOW())) ON CONFLICT (setting_key) DO UPDATE SET setting_value = $2, updated_at = EXTRACT(EPOCH FROM NOW())',
143
+ [key, JSON.stringify(value)]
144
+ );
145
+ }
146
+
147
+ function pgSetGroupSetting(groupJid, key, value) {
148
+ pgWrite(
149
+ 'INSERT INTO group_settings (group_jid, setting_key, setting_value, updated_at) VALUES ($1, $2, $3, EXTRACT(EPOCH FROM NOW())) ON CONFLICT (group_jid, setting_key) DO UPDATE SET setting_value = $3, updated_at = EXTRACT(EPOCH FROM NOW())',
150
+ [groupJid, key, JSON.stringify(value)]
151
+ );
152
+ }
153
+
154
+ function pgDeleteGroupSetting(groupJid, key) {
155
+ pgWrite('DELETE FROM group_settings WHERE group_jid = $1 AND setting_key = $2', [groupJid, key]);
156
+ }
157
+
158
+ function pgSetWarning(groupJid, userJid, count) {
159
+ if (count <= 0) {
160
+ pgWrite('DELETE FROM warnings WHERE group_jid = $1 AND user_jid = $2', [groupJid, userJid]);
161
+ } else {
162
+ pgWrite(
163
+ 'INSERT INTO warnings (group_jid, user_jid, count, updated_at) VALUES ($1, $2, $3, EXTRACT(EPOCH FROM NOW())) ON CONFLICT (group_jid, user_jid) DO UPDATE SET count = $3, updated_at = EXTRACT(EPOCH FROM NOW())',
164
+ [groupJid, userJid, count]
165
+ );
166
+ }
167
+ }
168
+
169
+ function pgResetWarning(groupJid, userJid) {
170
+ pgWrite('DELETE FROM warnings WHERE group_jid = $1 AND user_jid = $2', [groupJid, userJid]);
171
+ }
172
+
173
+ function pgAddBannedUser(userJid, reason) {
174
+ pgWrite(
175
+ 'INSERT INTO banned_users (user_jid, reason, banned_at) VALUES ($1, $2, EXTRACT(EPOCH FROM NOW())) ON CONFLICT (user_jid) DO UPDATE SET reason = $2, banned_at = EXTRACT(EPOCH FROM NOW())',
176
+ [userJid, reason]
177
+ );
178
+ }
179
+
180
+ function pgRemoveBannedUser(userJid) {
181
+ pgWrite('DELETE FROM banned_users WHERE user_jid = $1', [userJid]);
182
+ }
183
+
184
+ function pgAddSudoUser(userJid) {
185
+ pgWrite(
186
+ 'INSERT INTO sudo_users (user_jid, added_at) VALUES ($1, EXTRACT(EPOCH FROM NOW())) ON CONFLICT (user_jid) DO NOTHING',
187
+ [userJid]
188
+ );
189
+ }
190
+
191
+ function pgRemoveSudoUser(userJid) {
192
+ pgWrite('DELETE FROM sudo_users WHERE user_jid = $1', [userJid]);
193
+ }
194
+
195
+ function pgIncrementMsgCount(groupJid, userJid) {
196
+ pgWrite(
197
+ 'INSERT INTO message_counts (group_jid, user_jid, count) VALUES ($1, $2, 1) ON CONFLICT (group_jid, user_jid) DO UPDATE SET count = message_counts.count + 1',
198
+ [groupJid, userJid]
199
+ );
200
+ }
201
+
202
+ function pgResetGroupMsgCounts(groupJid) {
203
+ pgWrite('DELETE FROM message_counts WHERE group_jid = $1', [groupJid]);
204
+ }
205
+
206
+ async function closePg() {
207
+ if (pool) {
208
+ try { await pool.end(); } catch {}
209
+ pool = null;
210
+ pgAvailable = false;
211
+ }
212
+ }
213
+
214
+ module.exports = {
215
+ initPg,
216
+ loadFromPg,
217
+ closePg,
218
+ pgSetOwnerSetting,
219
+ pgSetGroupSetting,
220
+ pgDeleteGroupSetting,
221
+ pgSetWarning,
222
+ pgResetWarning,
223
+ pgAddBannedUser,
224
+ pgRemoveBannedUser,
225
+ pgAddSudoUser,
226
+ pgRemoveSudoUser,
227
+ pgIncrementMsgCount,
228
+ pgResetGroupMsgCounts
229
+ };