// credit: gist.vyr.my.id import axios from 'axios' import { load } from 'cheerio' const BASE = 'https://tv46.juragan.film' const UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0 Safari/537.36' const _fetch = async (url) => { const { data } = await axios.get(url, { headers: { 'User-Agent': UA } }) return load(data) } const _parseCard = ($, el) => { const $el = $(el) const link = $el.find('.content-thumbnail > a').attr('href') || $el.find('h2 a').attr('href') const title = $el.find('h2.entry-title a').text().trim() const img = $el.find('.content-thumbnail img').attr('src') const rating = $el.find('.gmr-rating-item').text().replace(/[^\d.]/g, '').trim() || null const duration = $el.find('.gmr-duration-item').text().replace(/\s+/g, ' ').trim() || null const type = $el.find('.gmr-posttype-item').text().trim() || null const episode = $el.find('.gmr-episode-item').text().trim() || null const genres = [] $el.find('.gmr-movie-on a').each((_, a) => genres.push($(a).text().trim())) return { title, url: link, poster: img, rating, duration, type, episode, genres } } export const getHome = async (page = 1) => { const url = page > 1 ? `${BASE}/page/${page}/` : `${BASE}/` const $ = await _fetch(url) const list = [] $('article.item').each((_, el) => list.push(_parseCard($, el))) return { page, results: list } } export const search = async (query, page = 1) => { const url = `${BASE}/page/${page}/?s=${encodeURIComponent(query)}` const $ = await _fetch(url) const list = [] $('article.item').each((_, el) => list.push(_parseCard($, el))) return { query, page, results: list } } export const watch = async (url) => { const $ = await _fetch(url) const title = $('h1.entry-title, .entry-title').first().text().trim() const poster = $('.gmr-movie-data-top img, .content-thumbnail img').first().attr('src') const desc = $('.gmr-moviedata em p').first().text().trim() || null const iframe = $('iframe[id^="jf-frame"]').attr('src') || null const rating = $('span[itemprop="ratingValue"]').text().trim() || null const votes = $('span[itemprop="ratingCount"]').text().trim() || null const genres = [] $('.gmr-movie-genre a[href*="/kategori-film/"]').each((_, a) => genres.push($(a).text().trim())) const quality = $('.gmr-movie-quality a').text().trim() || null const year = $('.gmr-movie-innermeta a[href*="/tahun/"]').first().text().trim() || null const duration = $('.gmr-movie-runtime').text().replace('Duration:', '').trim() || null const meta = {} $('.content-moviedata .gmr-moviedata').each((_, el) => { const t = $(el).text() const [k, ...v] = t.split(':') if (v.length) meta[k.trim().toLowerCase()] = v.join(':').trim() }) const episodes = [] $('.jf-eps-wrap a.post-page-numbers, .jf-eps-wrap span.post-page-numbers').each((_, el) => { const $el = $(el) episodes.push({ episode: Number($el.text().trim()), url: $el.attr('href') || url, current: $el.is('span') }) }) const subtitle = $('.jf-info-box').text().replace(/\s+/g, ' ').trim() || null return { title, url, poster, desc: desc || meta.sinopsis || null, iframe, rating, votes, quality, year, duration, genres, meta, episodes, subtitle } }