(sock, message, args, context)
| 8 | description: 'Search APKs and download by reply', |
| 9 | usage: '.apkdl <apk_name>', |
| 10 | async handler(sock, message, args, context) { |
| 11 | const chatId = context.chatId || message.key.remoteJid; |
| 12 | const query = args.join(' ').trim(); |
| 13 | try { |
| 14 | if (!query) { |
| 15 | return await sock.sendMessage(chatId, { text: '*Please provide an APK name.*\nExample: .apkdl Telegram' }, { quoted: message }); |
| 16 | } |
| 17 | await sock.sendMessage(chatId, { text: '🔎 Searching for APKs...' }, { quoted: message }); |
| 18 | const res = await QasimAny.apksearch(query); |
| 19 | if (!res?.data || !Array.isArray(res.data) || res.data.length === 0) { |
| 20 | return await sock.sendMessage(chatId, { text: '❌ No APKs found.' }, { quoted: message }); |
| 21 | } |
| 22 | const results = res.data; |
| 23 | const first = results[0]; |
| 24 | let caption = `📱 *APK Search Results for:* *${query}*\n\n`; |
| 25 | caption += `↩️ *Reply with a number to download*\n\n`; |
| 26 | results.forEach((item, i) => { |
| 27 | caption += |
| 28 | `*${i + 1}.* ${item.judul}\n` + |
| 29 | `👨💻 Developer: ${item.dev}\n` + |
| 30 | `⭐ Rating: ${item.rating}\n` + |
| 31 | `🔗 ${item.link}\n\n`; |
| 32 | }); |
| 33 | const sentMsg = await sock.sendMessage(chatId, { image: { url: first.thumb }, caption }, { quoted: message }); |
| 34 | const timeout = setTimeout(async () => { |
| 35 | sock.ev.off('messages.upsert', listener); |
| 36 | await sock.sendMessage(chatId, { text: '⏱ APK selection expired. Please search again.' }, { quoted: sentMsg }); |
| 37 | }, 5 * 60 * 1000); |
| 38 | const listener = async ({ messages }) => { |
| 39 | const m = messages[0]; |
| 40 | if (!m?.message || m.key.remoteJid !== chatId) |
| 41 | return; |
| 42 | const ctx = m.message?.extendedTextMessage?.contextInfo; |
| 43 | if (!ctx?.stanzaId || ctx.stanzaId !== sentMsg.key.id) |
| 44 | return; |
| 45 | const replyText = m.message.conversation || |
| 46 | m.message.extendedTextMessage?.text || |
| 47 | ''; |
| 48 | const choice = parseInt(replyText.trim(), 10); |
| 49 | if (isNaN(choice) || choice < 1 || choice > results.length) { |
| 50 | return await sock.sendMessage(chatId, { text: `❌ Invalid choice. Pick 1-${results.length}.` }, { quoted: m }); |
| 51 | } |
| 52 | clearTimeout(timeout); |
| 53 | sock.ev.off('messages.upsert', listener); |
| 54 | const selected = results[choice - 1]; |
| 55 | await sock.sendMessage(chatId, { text: `⬇️ Downloading *${selected.judul}*...\n⏱ Please wait...` }, { quoted: m }); |
| 56 | const apiUrl = `https://discardapi.dpdns.org/api/apk/dl/android1?apikey=guru&url=${ |
| 57 | encodeURIComponent(selected.link)}`; |
| 58 | const dlRes = await axios.get(apiUrl); |
| 59 | const apk = dlRes.data?.result; |
| 60 | if (!apk?.url) { |
| 61 | return await sock.sendMessage(chatId, { text: '❌ Failed to get APK download link.' }, { quoted: m }); |
| 62 | } |
| 63 | const safeName = apk.name.replace(/[^\w.-]/g, '_'); |
| 64 | const apkCaption = `📦 *APK Downloaded*\n\n` + |
| 65 | `📛 Name: ${apk.name}\n` + |
| 66 | `⭐ Rating: ${apk.rating}\n` + |
| 67 | `📦 Size: ${apk.size}\n` + |
nothing calls this directly
no outgoing calls
no test coverage detected