Logo OmniDevvKANA Web
Kembali ke katalog plugin

download

tiktok

Unduh video atau slide TikTok tanpa watermark

Download a TikTok video or slideshow without watermark

plugins/download/tiktok.js

Lokasi file di repo kana-md

3

Perintah termasuk alias

3.6 KB

Ukuran file sumber

4/11/2026

Update terakhir, commit 095e221

Daftar perintah

Ketuk tombol salin untuk menyalin perintah, lalu tempel di chat WhatsApp bot KANA.

.tiktok.tt.ttdl

Cara pakai

.tiktok <link tiktok>

Contoh

.tiktok https://www.tiktok.com/@user/video/123456789

Kode sumber plugin

Unduh .js

Cara pasang: simpan file ini ke folder plugins/download/ di bot KANA kamu, lalu restart bot. Pemilik source code lain bisa mengambil update plugin terbaru dari halaman ini kapan saja.

import { tiktokDownload } from '../../src/scrapers/tiktok/tiktok.js'
import { downloadBuffer } from '../../src/scrapers/runner.js'
import { sendVideo, sendImage, MAX_VIDEO_BYTES, MAX_IMAGE_BYTES } from '../../src/ui/media.js'
import { sendButtons } from '../../src/ui/buttons.js'

export const config = {
  name: 'tiktok',
  alias: ['tt', 'ttdl'],
  category: 'download',
  description: { id: 'Unduh video atau slide TikTok tanpa watermark', en: 'Download a TikTok video or slideshow without watermark' },
  usage: '.tiktok <link tiktok>',
  example: '.tiktok https://www.tiktok.com/@user/video/123456789',
  cooldown: 10,
  limit: 5,
}

export const i18n = {
  id: {
    tiktok: {
      needUrl: 'Kirim link TikTok-nya dulu yaa, contoh: .tiktok https://www.tiktok.com/@user/video/...~',
      working: 'Sebentar, KANA ambilin kontennya dulu... {mood}',
      failed: 'Mouu, gagal ambil kontennya: {message}. Coba lagi nanti ya~',
      tooBig: 'Aduh, videonya kegedean buat dikirim lewat WhatsApp (di atas 64 MB)~',
      caption: '{title}',
      btnRetry: 'Unduh ulang',
      btnMenu: 'Menu unduhan',
      btnAio: 'Coba .aio',
      followUp: 'Lanjutan: .tiktok {url} • .menu download',
    },
  },
  en: {
    tiktok: {
      needUrl: 'Send the TikTok link first, example: .tiktok https://www.tiktok.com/@user/video/...~',
      working: 'One sec, KANA is fetching the content... {mood}',
      failed: 'Mouu, failed to fetch the content: {message}. Try again later~',
      tooBig: 'Oops, the video is too big to send over WhatsApp (over 64 MB)~',
      caption: '{title}',
      btnRetry: 'Download again',
      btnMenu: 'Download menu',
      btnAio: 'Try .aio',
      followUp: 'Next: .tiktok {url} • .menu download',
    },
  },
}

// Tombol susulan sesudah media terkirim: unduh ulang URL yang sama + menu
// unduhan. URL tidak tersedia: menu unduhan + .aio saja.
export function buildTiktokButtons(url, t) {
  return url
    ? [
        { text: t('tiktok.btnRetry'), id: `.tiktok ${url}` },
        { text: t('tiktok.btnMenu'), id: '.menu download' },
      ]
    : [
        { text: t('tiktok.btnMenu'), id: '.menu download' },
        { text: t('tiktok.btnAio'), id: '.aio' },
      ]
}

export const test = { input: '.tiktok https://www.tiktok.com/@pojoksatu.id/video/7647074044960984340', expect: /video|TikTok/i }

export async function handler(ctx) {
  const url = ctx.args[0]
  if (!url) return ctx.reply(ctx.t('tiktok.needUrl'))
  await ctx.reply(ctx.t('tiktok.working', { mood: ctx.say('mikir') }))
  const result = await tiktokDownload(url)
  if (!result.status) return ctx.reply(ctx.t('tiktok.failed', { message: result.message }))
  const data = result.result
  const caption = ctx.t('tiktok.caption', { title: data.title || 'TikTok' })
  try {
    if (data.images?.length) {
      for (const [index, imageUrl] of data.images.slice(0, 4).entries()) {
        const media = await downloadBuffer(imageUrl, { maxBytes: MAX_IMAGE_BYTES })
        await sendImage(ctx, media.buffer, { caption: index === 0 ? caption : undefined })
      }
    } else {
      const media = await downloadBuffer(data.video, { maxBytes: MAX_VIDEO_BYTES })
      await sendVideo(ctx, media.buffer, { caption })
    }
  } catch (err) {
    if (err.code === 'TOO_BIG') return ctx.reply(ctx.t('tiktok.tooBig'))
    return ctx.reply(ctx.t('tiktok.failed', { message: err.message }))
  }
  const body = [caption, ctx.t('tiktok.followUp', { url })].join('\n')
  return sendButtons(ctx.sock, ctx.chat, {
    title: 'KANA',
    body,
    footer: ctx.t('menu.footer'),
    replies: buildTiktokButtons(url, ctx.t),
    textFallback: body,
  })
}