-
-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
543 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import fs from 'fs' | ||
import path from 'path' | ||
import archiver from 'archiver' | ||
|
||
export default (handler) => { | ||
handler.reg({ | ||
cmd: ['backup', 'b'], | ||
tags: 'owner', | ||
desc: 'Backup files, send to owner', | ||
isOwner: true, | ||
run: async (m, { sock, db }) => { | ||
const excludePatterns = ['.npm', 'node_modules', 'temp', 'package-lock.json'] | ||
const rootDir = process.cwd() | ||
const tempDir = path.join(rootDir, 'temp') | ||
let backupNumber = 1 | ||
|
||
try { | ||
const ownerNumber = db?.setting?.owner | ||
if (!ownerNumber) { | ||
return m.reply('❌ Nomor owner tidak ditemukan di pengaturan.') | ||
} | ||
if (!fs.existsSync(tempDir)) { | ||
fs.mkdirSync(tempDir, { recursive: true }) | ||
} | ||
|
||
const existingBackups = fs.readdirSync(tempDir) | ||
.filter(file => /^backup-\d+\.zip$/.test(file)) | ||
.map(file => parseInt(file.match(/^backup-(\d+)\.zip$/)[1], 10)) | ||
.sort((a, b) => b - a) | ||
if (existingBackups.length > 0) { | ||
backupNumber = existingBackups[0] + 1 | ||
} | ||
const backupFilename = `backup-${backupNumber}.zip` | ||
const output = fs.createWriteStream(path.join(tempDir, backupFilename)) | ||
const archive = archiver('zip', { zlib: { level: 9 } }) | ||
output.on('close', async () => { | ||
console.log(`✅ File backup selesai: ${backupFilename}`) | ||
const fileSizeInBytes = archive.pointer() | ||
const fileSizeInKB = (fileSizeInBytes / 1024).toFixed(2) // KB | ||
const fileSizeInMB = (fileSizeInKB / 1024).toFixed(2) // MB | ||
|
||
let fileSize | ||
if (fileSizeInMB >= 1) { | ||
fileSize = `${fileSizeInMB} MB` | ||
} else if (fileSizeInKB >= 1) { | ||
fileSize = `${fileSizeInKB} KB` | ||
} | ||
try { | ||
await sock.sendMessage(ownerNumber + '@s.whatsapp.net', { | ||
document: { url: path.join(tempDir, backupFilename) }, | ||
mimetype: 'application/zip', | ||
fileName: backupFilename, | ||
caption: `🔒 Backup berhasil!\nNama file: ${backupFilename}\nUkuran: ${fileSize}.`, | ||
}) | ||
|
||
m.reply(`✅ Backup selesai dan telah dikirim ke owner.`) | ||
|
||
} catch (err) { | ||
m.reply(`❌ Gagal mengirim file backup ke owner: ${err.message}`) | ||
} | ||
}) | ||
|
||
archive.on('error', (err) => { | ||
throw err | ||
}) | ||
|
||
archive.pipe(output) | ||
|
||
const addToArchive = (src) => { | ||
const items = fs.readdirSync(src) | ||
|
||
for (const item of items) { | ||
const sourcePath = path.join(src, item) | ||
if (excludePatterns.some(pattern => item.includes(pattern))) { | ||
console.log(`⏩ Melewati: ${item}`) | ||
continue | ||
} | ||
const stats = fs.statSync(sourcePath) | ||
if (stats.isDirectory()) { | ||
archive.directory(sourcePath, item) | ||
console.log(`📁 Menambahkan folder: ${item}`) | ||
} else if (stats.isFile()) { | ||
archive.file(sourcePath, { name: item }) | ||
console.log(`✅ Menambahkan file: ${item}`) | ||
} | ||
} | ||
} | ||
|
||
addToArchive(rootDir) | ||
archive.finalize() | ||
} catch (error) { | ||
m.reply(`❌ Terjadi kesalahan: ${error.message}`) | ||
} | ||
}, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
export default (handler) => { | ||
handler.reg({ | ||
cmd: ['delpremium', 'delprem', 'removepremium'], | ||
tags: 'owner', | ||
desc: 'delete premium user.', | ||
isOwner: true, | ||
run: async (m, { db, sock }) => { | ||
const input = m.text ? m.text : m.quoted ? m.quoted.sender : m.mentions.length > 0 ? m.mentions[0] : false | ||
if (!input) { | ||
return m.reply( | ||
'Silakan tag atau reply target untuk dihapus status premiumnya.\nContoh: .delpremium @user', | ||
true | ||
) | ||
} | ||
|
||
// Mengecek apakah nomor terdaftar di WhatsApp | ||
const p = await sock.onWhatsApp(input.trim()) | ||
if (p.length === 0) return m.reply('⚠️ Nomor tidak terdaftar di WhatsApp.', true) | ||
|
||
// Mendapatkan JID dan mencari pengguna di database | ||
const jid = sock.decodeJid(p[0].jid) | ||
const user = db.users[jid] | ||
|
||
// Jika pengguna tidak ditemukan | ||
if (!user) { | ||
return m.reply('⚠️ Pengguna tersebut tidak ditemukan dalam database.', true) | ||
} | ||
|
||
// Hapus status premium dan atur ulang limit | ||
user.premium = false | ||
user.exp_prem = -1 | ||
user.limit = 10 | ||
|
||
// Kirim pesan konfirmasi | ||
const removeMessage = { | ||
text: `❌ Pengguna @${jid.split('@')[0]} telah dihapus status premiumnya.\nLimit pengguna sekarang diatur menjadi 10.`, | ||
mentions: [jid], | ||
} | ||
|
||
m.reply(removeMessage) | ||
|
||
// Simpan perubahan ke database | ||
if (db && db.write) { | ||
await db.write() | ||
} | ||
}, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
export default (handler) => { | ||
handler.reg({ | ||
cmd: ['join'], | ||
tags: 'owner', | ||
desc: 'Join a group using an invite link', | ||
isOwner: true, | ||
run: async (m, { sock }) => { | ||
try { | ||
const text = m.text && m.text.trim() | ||
if (!text) { | ||
m.reply('❌ Harap berikan tautan undangan grup yang valid.\n\n*Penggunaan:*\n.join https://chat.whatsapp.com/XXXXXX') | ||
return | ||
} | ||
|
||
const inviteCode = text.split("https://chat.whatsapp.com/")[1] | ||
if (!inviteCode) { | ||
m.reply('❌ Tautan undangan grup tidak valid. Harap berikan tautan yang benar.') | ||
return | ||
} | ||
|
||
const groupId = await sock.groupAcceptInvite(inviteCode).catch((err) => { | ||
if (err.message.includes('already in group')) { | ||
throw new Error('Bot sudah menjadi anggota grup ini.') | ||
} | ||
throw err | ||
}) | ||
|
||
const groupMeta = await sock.groupMetadata(groupId) | ||
const groupName = groupMeta.subject || 'grup tersebut' | ||
const groupAdmins = groupMeta.participants | ||
.filter((p) => ['admin', 'superadmin'].includes(p.admin)) | ||
.map((p) => p.id) | ||
|
||
if (groupAdmins.length === 0) { | ||
m.reply(`✅ Bot berhasil bergabung ke grup *${groupName}*.\nNamun, tidak ada admin untuk memberi bot akses sebagai admin.`) | ||
return | ||
} | ||
|
||
const adminMessage = `✅ Bot telah bergabung ke grup *${groupName}*.\n\nAdmin, silakan berikan akses admin kepada bot jika diperlukan.` | ||
|
||
for (const admin of groupAdmins) { | ||
try { | ||
await sock.sendMessage(admin, { text: adminMessage }) | ||
} catch (err) { | ||
m.reply(`❌ Gagal mengirim pesan ke admin: @${admin.split('@')[0]} (${err.message})`) | ||
} | ||
} | ||
|
||
m.reply(`🔄 Permintaan telah dikirim ke admin grup untuk memberikan akses admin kepada bot di grup *${groupName}*.`) | ||
} catch (error) { | ||
if (error.message === 'Bot sudah menjadi anggota grup ini.') { | ||
m.reply('⚠️ Bot sudah berada di grup ini.') | ||
} else { | ||
m.reply(`❌ Terjadi kesalahan: ${error.message}`) | ||
} | ||
} | ||
}, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
export default (handler) => { | ||
handler.reg({ | ||
cmd: ['leave'], | ||
tags: 'owner', | ||
desc: 'leave the group', | ||
isOwner: true, | ||
isGroup: true, | ||
run: async (m, { sock, db }) => { | ||
try { | ||
const groupId = m.from | ||
const groupMeta = await sock.groupMetadata(groupId) | ||
const groupName = groupMeta.subject | ||
const ownerNumber = db?.setting?.owner | ||
if (!ownerNumber) { | ||
return m.reply('❌ Nomor owner tidak ditemukan di pengaturan.') | ||
} | ||
|
||
await sock.sendMessage(groupId, { | ||
text: `⚠️ Bot akan keluar dari grup *${groupName}* dalam beberapa detik.` | ||
}) | ||
|
||
await sock.sendMessage(ownerNumber + '@s.whatsapp.net', { | ||
text: `⚠️ Bot akan keluar dari grup *${groupName}*\n(${groupId}).` | ||
}) | ||
|
||
await sock.groupLeave(groupId) | ||
m.reply(`✅ Bot telah keluar dari grup *${groupName}*.`) | ||
} catch (error) { | ||
m.reply(`❌ Terjadi kesalahan: ${error.message}`) | ||
} | ||
}, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import moment from 'moment-timezone' | ||
|
||
export default (handler) => { | ||
handler.reg({ | ||
cmd: ['listgrup', 'listgc', 'listgroup'], | ||
tags: 'owner', | ||
desc: 'List groups connected with bot', | ||
isOwner: true, | ||
run: async (m, { sock }) => { | ||
try { | ||
// Mengambil daftar semua grup yang bot ikuti | ||
const groups = await sock.groupFetchAllParticipating() | ||
const groupList = Object.values(groups) | ||
|
||
if (groupList.length === 0) { | ||
return m.reply('⚠️ Bot tidak terhubung dengan grup mana pun.') | ||
} | ||
|
||
// Menyusun informasi grup | ||
let teks = `𖦏 *LIST GROUP CHAT*\n\nTotal Grup: ${groupList.length} Grup\n\n` | ||
let mentions = [] // Menyimpan semua mention | ||
|
||
for (let i = 0; i < groupList.length; i++) { | ||
const group = groupList[i] | ||
const metadata = await sock.groupMetadata(group.id).catch(() => null) | ||
|
||
if (metadata) { | ||
teks += `𖥔 Nama: ${metadata.subject}\n` | ||
if (metadata.owner !== undefined) { | ||
const ownerJid = metadata.owner | ||
const ownerTag = '@' + ownerJid.split('@')[0] | ||
teks += `𖥔 Owner: ${ownerTag}\n` | ||
mentions.push(ownerJid) // Menambahkan owner ke daftar mention | ||
} else { | ||
teks += `𖥔 Owner: Tidak diketahui\n` | ||
} | ||
teks += `𖥔 ID: ${metadata.id}\n` | ||
teks += `𖥔 Dibuat: ${moment(metadata.creation * 1000) | ||
.tz('Asia/Jakarta') | ||
.format('DD/MM/YYYY HH:mm:ss')}\n` | ||
teks += `𖥔 Member: ${metadata.participants.length}\n` | ||
teks += `────────────────────────\n\n` | ||
} else { | ||
teks += `${i + 1}. *${group.subject}*\n(ID: ${group.id})\n\n` | ||
} | ||
} | ||
|
||
// Mengirim balasan dengan mention | ||
m.reply(teks, null, { mentions }) | ||
} catch (error) { | ||
m.reply(`❌ Terjadi kesalahan: ${error.message}`) | ||
} | ||
}, | ||
}) | ||
} |
Oops, something went wrong.