qrtzcode
HomeDocsAPILeaderboardChangelog
Contribute
Docs

qrtzcode

Kumpulan gist & snippet pribadi — anime, AI tools, scraper, dan randomness.

Navigate

HomeDocsAPI Reference

Links

© 2026 qrtz. All snippets welcome.

ESC

Navigate

Links

Movie

movieku

gtw.

Note

gtw.

Creator

qrtz

Language

javascript

Views

19

Copies

0

Base

https://movieku.rest

Updated

24 Jun 2026

#movie

Code

190
movieku.js
const axios = require('axios');
const { load } = require('cheerio');
const BASE = 'https://movieku.rest';
const UAS = [
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/125.0.0.0 Safari/537.36',
  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36',
  'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/123.0.0.0 Safari/537.36',
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0',
  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 Version/17.4 Safari/605.1.15',
  'Mozilla/5.0 (X11; Linux x86_64; rv:125.0) Gecko/20100101 Firefox/125.0',
  'Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15 Version/17.4 Mobile/15E148 Safari/604.1',
];
let uaIdx = 0;
function ua() { return UAS[uaIdx++ % UAS.length]; }

const api = axios.create({ timeout: 15000, headers: { 'Accept': 'text/html,application/xhtml+xml', 'Accept-Language': 'id-ID,id;q=0.9' } });

async function fetch(url, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      const res = await api.get(url, { headers: { 'User-Agent': ua() } });
      return res.data;
    } catch (e) {
      if (i === retries - 1) throw e;
      await new Promise(r => setTimeout(r, 1000 * (i + 1)));
    }
  }
}

function parseArticles(html) {
  const $ = load(html);
  const items = [];
  $('article').each((i, article) => {
    const a = $(article).find('a[href]').first();
    if (!a) return;
    const href = a.attr('href');
    if (!href || (!href.includes('/series/') && !href.includes('/movie/'))) return;
    const title = $(article).find('.entry-title').first().text().trim() || a.text().trim();
    const img = $(article).find('img').first().attr('src') || '';
    items.push({ title, link: new URL(href, BASE).href, image: img || undefined });
  });
  return items;
}

function parseSeriesDetail(html) {
  const $ = load(html);
  const title = $('title').text().replace(/ - Movieku.*/, '').trim();
  const poster = $('img.wp-post-image, img.size-full, .thumb img, img[src*="uploads"]').not('[src*="Movieku.png"]').first().attr('src') || '';
  const synopsis = $('.entry-content').text().trim().substring(0, 500);
  const genres = [];
  $('a[href*="/genre/"]').each((i, el) => {
    const g = $(el).text().trim();
    if (g && g !== 'Genre' && !genres.includes(g)) genres.push(g);
  });
  const actors = [];
  $('a[href*="/actor/"]').each((i, el) => {
    const a = $(el).text().trim();
    if (a && !actors.includes(a)) actors.push(a);
  });
  const directors = [];
  $('a[href*="/director/"]').each((i, el) => {
    const d = $(el).text().trim();
    if (d && !directors.includes(d)) directors.push(d);
  });
  const downloads = [];
  $('a[href*="acefile.co"], a[href*="mega.nz"], a[href*="drive.google.com"], a[href*="google"], a[href*="zippy"], a[href*="mediafire"]').each((i, a) => {
    const label = $(a).text().trim();
    const url = $(a).attr('href');
    if (label && url) {
      const epMatch = label.match(/eps\s*(\d+)/i) || url.match(/eps[_\s]*(\d+)/i);
      const resMatch = label.match(/(\d+p)/i) || url.match(/(\d+p)/i);
      const isBatch = /batch|zip|complete|end/i.test(label) || /end/i.test(url);
      downloads.push({
        label,
        url,
        episode: epMatch ? parseInt(epMatch[1]) : undefined,
        resolution: resMatch ? resMatch[1] : undefined,
        batch: isBatch || undefined
      });
    }
  });
  return { title, poster: poster || undefined, synopsis, genres, actors, directors, download_links: downloads };
}

function slugify(text) {
  return text.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
}

async function discoverGenresAndActors(pages = 3) {
  const seriesLinks = [];
  for (let p = 1; p <= pages; p++) {
    const html = await fetch(BASE + '/series/page/' + p + '/');
    const $ = load(html);
    $('article a[href*="/series/"]').each((i, el) => {
      seriesLinks.push(new URL($(el).attr('href'), BASE).href);
    });
  }
  const genres = new Set();
  const actors = new Set();
  let i = 0;
  for (const url of seriesLinks) {
    try {
      const html = await fetch(url);
      const $ = load(html);
      $('a[href*="/genre/"]').each((i, el) => {
        const g = $(el).text().trim();
        if (g && g !== 'Genre') genres.add(g);
      });
      $('a[href*="/actor/"]').each((i, el) => {
        const a = $(el).text().trim();
        if (a) actors.add(a);
      });
    } catch (e) {}
    if (++i % 20 === 0) console.error(`  discover ${i}/${seriesLinks.length}...`);
  }
  return {
    genres: [...genres].sort().map(g => ({ name: g, slug: slugify(g), url: BASE + '/genre/' + slugify(g) + '/' })),
    actors: [...actors].sort().map(a => ({ name: a, slug: slugify(a), url: BASE + '/actor/' + slugify(a) + '/' })),
  };
}

async function scrapeHome() { const html = await fetch(BASE + '/'); return { creator: 'rynaqrtz', data: parseArticles(html) }; }
async function scrapeOngoing() { const html = await fetch(BASE + '/ongoing/'); return { creator: 'rynaqrtz', data: parseArticles(html) }; }
async function scrapeSearch(query) { const html = await fetch(BASE + '/?s=' + encodeURIComponent(query)); return { creator: 'rynaqrtz', data: parseArticles(html) }; }
async function scrapeGenre(slug) { const html = await fetch(BASE + '/genre/' + slug + '/'); return { creator: 'rynaqrtz', data: parseArticles(html) }; }
async function scrapeActor(name) { const html = await fetch(BASE + '/actor/' + slugify(name) + '/'); return { creator: 'rynaqrtz', data: parseArticles(html) }; }
async function scrapeSeries(url) { const html = await fetch(url); return { creator: 'rynaqrtz', ...parseSeriesDetail(html) }; }
async function scrapeDiscover(pages = 3) { console.error(`Discovering genres & actors from ${pages} pages...`); const data = await discoverGenresAndActors(pages); return { creator: 'rynaqrtz', ...data }; }
async function scrapeSeriesList(url) { const html = await fetch(url); return { creator: 'rynaqrtz', data: parseArticles(html) }; }

module.exports = { scrapeHome, scrapeOngoing, scrapeSearch, scrapeGenre, scrapeActor, scrapeSeries, scrapeDiscover, scrapeSeriesList };

if (require.main === module) {
  const args = process.argv.slice(2);
  const action = args[0];
  const query = args[1] || '';
  const getFlag = (f, def) => { const i = args.indexOf('--' + f); return i !== -1 && i + 1 < args.length ? args[i + 1] : def; };
  const pages = parseInt(getFlag('pages', '3'));
  (async () => {
    try {
      let data;
      if (action === 'home') data = await scrapeHome();
      else if (action === 'ongoing') data = await scrapeOngoing();
      else if (action === 'search') { if (!query) throw new Error('query needed'); data = await scrapeSearch(query); }
      else if (action === 'genre') { if (!query) throw new Error('slug needed'); data = await scrapeGenre(query); }
      else if (action === 'actor') { if (!query) throw new Error('actor name needed'); data = await scrapeActor(query); }
      else if (action === 'series') { if (!query) throw new Error('url needed'); data = await scrapeSeries(query); }
      else if (action === 'discover') { data = await scrapeDiscover(pages); }
      else if (action === 'series-list') { data = await scrapeSeriesList(query || BASE + '/series/'); }
      else { console.log(JSON.stringify({ usage: ['home','ongoing','search <q>','genre <slug>','actor <name>','series <url>','discover [--pages=N]','series-list [url]'] })); return; }
      console.log(JSON.stringify(data, null, 2));
    } catch (e) { console.error(JSON.stringify({ error: e.message })); process.exit(1); }
  })();
}

Rating

—(0)

Gimana snippet ini menurutmu?

</> Embed

Embed ke website / blog

<iframe src="https://qrtzcode.vercel.app/api/embed/movie/movieku" style="width:100%;height:400px;border:none;border-radius:12px;"></iframe>