Kembali ke katalog plugin
maker
tomp3
Ubah video atau audio yang dikutip jadi MP3
Turn a quoted video or audio into MP3
plugins/maker/tomp3.js
Lokasi file di repo kana-md
1
Perintah termasuk alias
2.7 KB
Ukuran file sumber
4/11/2026
Update terakhir, commit 7d56ace
Daftar perintah
Ketuk tombol salin untuk menyalin perintah, lalu tempel di chat WhatsApp bot KANA.
.tomp3Cara pakai
.tomp3 (kutip video/audio)
Contoh
.tomp3
Kode sumber plugin
Cara pasang: simpan file ini ke folder plugins/maker/ di bot KANA kamu, lalu restart bot. Pemilik source code lain bisa mengambil update plugin terbaru dari halaman ini kapan saja.
import { execFile } from 'node:child_process'
import { promisify } from 'node:util'
import { readFile, writeFile } from 'node:fs/promises'
import { join } from 'node:path'
import { withTempDir } from '../../src/scrapers/runner.js'
import { sendAudio, MAX_VIDEO_BYTES } from '../../src/ui/media.js'
import { fetchSourceMedia, mediaKindOf } from './sticker.js'
const execFileP = promisify(execFile)
export const config = {
name: 'tomp3',
alias: [],
category: 'maker',
description: { id: 'Ubah video atau audio yang dikutip jadi MP3', en: 'Turn a quoted video or audio into MP3' },
usage: '.tomp3 (kutip video/audio)',
example: '.tomp3',
cooldown: 5,
limit: 3,
}
export const i18n = {
id: {
tomp3: {
needMedia: 'Kutip video atau audionya dulu yaa, terus ketik .tomp3~',
tooBig: 'Mouu, medianya kegedean (di atas 64 MB)~',
failed: 'Mouu, gagal ubah ke MP3: {message}~',
},
},
en: {
tomp3: {
needMedia: 'Quote a video or audio first, then type .tomp3~',
tooBig: 'Mouu, the media is too big (over 64 MB)~',
failed: 'Mouu, failed to convert to MP3: {message}~',
},
},
}
// audioMessage tidak ditangkap fetchSourceMedia umum, jadi cek sendiri di sini.
async function fetchAudioSource(ctx) {
const quotedKind = ctx.quoted?.message ? mediaKindOf(ctx.quoted.message) : null
const quotedAudio = ctx.quoted?.message?.audioMessage
if (quotedAudio || quotedKind) {
const buffer = await ctx.downloadQuoted()
return { kind: quotedAudio ? 'audio' : quotedKind.kind, buffer }
}
if (ctx.raw?.message?.audioMessage) return { kind: 'audio', buffer: await ctx.downloadMedia() }
return fetchSourceMedia(ctx)
}
export async function toMp3(buffer) {
return withTempDir(async (dir) => {
const input = join(dir, 'in.bin')
const out = join(dir, 'out.mp3')
await writeFile(input, buffer)
try {
await execFileP('ffmpeg', ['-y', '-i', input, '-vn', '-c:a', 'libmp3lame', '-q:a', '4', out], { timeout: 60000 })
} catch (err) {
throw new Error(`ffmpeg tomp3 gagal: ${(err.stderr || err.message).slice(-200)}`)
}
return readFile(out)
})
}
export const test = { input: '.tomp3', expect: /kutip/i }
export async function handler(ctx) {
let src
try {
src = await fetchAudioSource(ctx)
} catch (err) {
return ctx.reply(ctx.t('tomp3.failed', { message: err.message }))
}
if (!src || !['video', 'audio', 'document'].includes(src.kind)) return ctx.reply(ctx.t('tomp3.needMedia'))
if (src.buffer.length > MAX_VIDEO_BYTES) return ctx.reply(ctx.t('tomp3.tooBig'))
try {
const mp3 = await toMp3(src.buffer)
await sendAudio(ctx, mp3, { mimetype: 'audio/mpeg', title: 'tomp3' })
} catch (err) {
return ctx.reply(ctx.t('tomp3.failed', { message: err.message }))
}
}
