mirror of
https://github.com/iptv-org/epg.git
synced 2025-05-09 08:30:06 -04:00
commit
7783d752cc
7 changed files with 1818 additions and 0 deletions
1327
sites/tivie.id/__data__/content.html
Normal file
1327
sites/tivie.id/__data__/content.html
Normal file
File diff suppressed because it is too large
Load diff
102
sites/tivie.id/__data__/program01.html
Normal file
102
sites/tivie.id/__data__/program01.html
Normal file
|
@ -0,0 +1,102 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="id">
|
||||
<body class="font-sans text-black text-opacity-80 antialiased bg-slate-50">
|
||||
<div class="min-h-screen max-w-lg mx-auto bg-white relative flex flex-col">
|
||||
<header class="sticky top-0 z-30 bg-white bg-opacity-90 backdrop-blur border-b border-gray-100" id="appbar">
|
||||
<div class="flex h-14 px-4">
|
||||
<div class="shrink-0 flex items-center">
|
||||
<a href="https://tivie.id">
|
||||
<svg viewBox="0 0 30.808 13.383" xmlns="http://www.w3.org/2000/svg"
|
||||
class="block h-8 w-auto fill-teal-700" stroke-width="0.25">
|
||||
<path
|
||||
d="M7.229,4.682h-2.47L3.14,10.702H0.852l1.619-6.021H0l0.502-1.875H7.73L7.229,4.682z M6.547,10.702h2.289l2.121-7.896H8.668
|
||||
L6.547,10.702z M9.448,0L8.84,2.258h2.265L11.713,0H9.448z M18.054,2.807l-3.75,6.749L13.84,2.807h-2.265l0.683,10.577h2.265
|
||||
l5.796-10.577H18.054z M20.953,2.807l-2.121,7.896h2.289l2.121-7.896H20.953z M30.319,4.609l0.488-1.803h-6.642l-2.121,7.896h6.702
|
||||
l0.479-1.803h-4.465l0.39-1.412h4.1l0.407-1.527h-4.102l0.361-1.352H30.319z M23.995,0H21.73l-0.608,2.258h2.265L23.995,0z" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
<nav
|
||||
class="flex-grow gap-0.5 flex items-center justify-end uppercase relative left-2 text-sm font-medium leading-none">
|
||||
<a class="inline-flex items-center p-2 focus:outline-none transition duration-150 ease-in-out relative before:content-[''] before:block before:h-px before:absolute before:inset-x-1.5 before:bottom-0 before:bg-teal-800 hover:text-teal-800 before:opacity-50 hover:before:opacity-80 before:transition before:duration-150 before:ease-in-out before:scale-x-0 hover:before:scale-x-100"
|
||||
href="https://tivie.id">
|
||||
Beranda
|
||||
</a>
|
||||
<a class="inline-flex items-center p-2 focus:outline-none transition duration-150 ease-in-out relative before:content-[''] before:block before:h-px before:absolute before:inset-x-1.5 before:bottom-0 before:bg-teal-800 hover:text-teal-800 before:opacity-50 hover:before:opacity-80 before:transition before:duration-150 before:ease-in-out before:scale-x-0 hover:before:scale-x-100"
|
||||
href="https://tivie.id/channel">
|
||||
Channel
|
||||
</a>
|
||||
<a class="inline-flex items-center p-2 focus:outline-none transition duration-150 ease-in-out relative before:content-[''] before:block before:h-px before:absolute before:inset-x-1.5 before:bottom-0 before:bg-teal-800 text-teal-800 before:opacity-80"
|
||||
href="https://tivie.id/program">
|
||||
Program
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
<main id="main-content" class="flex-grow w-full">
|
||||
<div class="">
|
||||
<div class="aspect-video bg-gray-100">
|
||||
<img src="https://i0.wp.com/is3.cloudhost.id/tivie/poster/2023/09/65116c78791c2-1695640694.jpg?resize=480,270"
|
||||
alt="" class="w-full h-full object-fit">
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<div class="">
|
||||
<a href="https://tivie.id/programs/film"
|
||||
class="text-sm uppercase font-bold tracking-wide text-teal-800 hover:text-teal-900">Film</a>
|
||||
</div>
|
||||
<h2 class="font-bold text-2xl leading-tight mb-0.5">White House Down</h2>
|
||||
<h2 class="font-medium text-lg leading-tight mb-3">2013</h2>
|
||||
<div class="">
|
||||
<p>Saat melakukan tur di Gedung Putih bersama putrinya yang masih kecil, seorang perwira polisi
|
||||
beraksi untuk melindungi anaknya dan presiden dari sekelompok penjajah paramiliter
|
||||
bersenjata lengkap.</p>
|
||||
</div>
|
||||
<div class="pt-2">
|
||||
<script async
|
||||
src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-7024487184083415"
|
||||
crossorigin="anonymous"></script>
|
||||
<ins class="adsbygoogle" style="display:block; text-align:center;" data-ad-layout="in-article"
|
||||
data-ad-format="fluid" data-ad-client="ca-pub-7024487184083415"
|
||||
data-ad-slot="3702712377"></ins>
|
||||
<script>
|
||||
(adsbygoogle = window.adsbygoogle || []).push({});
|
||||
</script>
|
||||
</div>
|
||||
<div class="mt-4 max-w-fit">
|
||||
<h4 class="font-bold tracking-tight leading-tight mb-1 uppercase">Terakhir Tayang</h4>
|
||||
<ul class="divide-y">
|
||||
<li>
|
||||
<div x-data="{url: 'https://tivie.id/channel/axn/kemarin'}"
|
||||
class="py-1.5 flex items-start gap-3">
|
||||
<a href="https://tivie.id/channel/axn/kemarin"
|
||||
class="shrink-0 w-10 -my-0.5 aspect-logo overflow-hidden" title="AXN">
|
||||
<img src="https://tivie.id-www.my.id/channel-hwfGtC5uHWwHLfxwmufCZSdtiex9LEm9KkiGG279-sm.png"
|
||||
alt="AXN" class="w-full h-full object-contain">
|
||||
<span class="sr-only">Jadwal Acara AXN Kemarin</span>
|
||||
</a>
|
||||
<div class="shrink-0 w-36 flex justify-between cursor-pointer"
|
||||
@click="window.location.href = url">
|
||||
<span class="shrink-0 w-16 font-medium">Kemarin</span>
|
||||
<div
|
||||
class="w-13 font-medium flex justify-center items-center text-center shrink-0 leading-tight opacity-90">
|
||||
<span before=":"
|
||||
class="shrink-0 w-1 h-4 leading-4 flex flex-col items-center overflow-hidden before:content-[attr(before)] before:w-full before:scale-90">21:40</span>
|
||||
<span before="2" after="1"
|
||||
class="order-first flex w-1/2 flex justify-end -space-x-px before:content-[attr(before)] before:block before:shrink-0 before:w-2.5 before:scale-90 after:content-[attr(after)] after:block after:shrink-0 after:w-2.5 after:scale-90"></span>
|
||||
<span before="4" after="0"
|
||||
class="flex w-1/2 flex justify-start -space-x-px before:content-[attr(before)] before:block before:shrink-0 before:w-2.5 before:scale-90 after:content-[attr(after)] after:block after:shrink-0 after:w-2.5 after:scale-90"></span>
|
||||
<span class="text-xs tracking-wider opacity-75 pt-px px-1">WIB</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="">
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
106
sites/tivie.id/__data__/program02.html
Normal file
106
sites/tivie.id/__data__/program02.html
Normal file
|
@ -0,0 +1,106 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="id">
|
||||
<body class="font-sans text-black text-opacity-80 antialiased bg-slate-50">
|
||||
<div class="min-h-screen max-w-lg mx-auto bg-white relative flex flex-col">
|
||||
<header class="sticky top-0 z-30 bg-white bg-opacity-90 backdrop-blur border-b border-gray-100" id="appbar">
|
||||
<div class="flex h-14 px-4">
|
||||
<div class="shrink-0 flex items-center">
|
||||
<a href="https://tivie.id">
|
||||
<svg viewBox="0 0 30.808 13.383" xmlns="http://www.w3.org/2000/svg"
|
||||
class="block h-8 w-auto fill-teal-700" stroke-width="0.25">
|
||||
<path
|
||||
d="M7.229,4.682h-2.47L3.14,10.702H0.852l1.619-6.021H0l0.502-1.875H7.73L7.229,4.682z M6.547,10.702h2.289l2.121-7.896H8.668
|
||||
L6.547,10.702z M9.448,0L8.84,2.258h2.265L11.713,0H9.448z M18.054,2.807l-3.75,6.749L13.84,2.807h-2.265l0.683,10.577h2.265
|
||||
l5.796-10.577H18.054z M20.953,2.807l-2.121,7.896h2.289l2.121-7.896H20.953z M30.319,4.609l0.488-1.803h-6.642l-2.121,7.896h6.702
|
||||
l0.479-1.803h-4.465l0.39-1.412h4.1l0.407-1.527h-4.102l0.361-1.352H30.319z M23.995,0H21.73l-0.608,2.258h2.265L23.995,0z" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
<nav
|
||||
class="flex-grow gap-0.5 flex items-center justify-end uppercase relative left-2 text-sm font-medium leading-none">
|
||||
<a class="inline-flex items-center p-2 focus:outline-none transition duration-150 ease-in-out relative before:content-[''] before:block before:h-px before:absolute before:inset-x-1.5 before:bottom-0 before:bg-teal-800 hover:text-teal-800 before:opacity-50 hover:before:opacity-80 before:transition before:duration-150 before:ease-in-out before:scale-x-0 hover:before:scale-x-100"
|
||||
href="https://tivie.id">
|
||||
Beranda
|
||||
</a>
|
||||
<a class="inline-flex items-center p-2 focus:outline-none transition duration-150 ease-in-out relative before:content-[''] before:block before:h-px before:absolute before:inset-x-1.5 before:bottom-0 before:bg-teal-800 hover:text-teal-800 before:opacity-50 hover:before:opacity-80 before:transition before:duration-150 before:ease-in-out before:scale-x-0 hover:before:scale-x-100"
|
||||
href="https://tivie.id/channel">
|
||||
Channel
|
||||
</a>
|
||||
<a class="inline-flex items-center p-2 focus:outline-none transition duration-150 ease-in-out relative before:content-[''] before:block before:h-px before:absolute before:inset-x-1.5 before:bottom-0 before:bg-teal-800 text-teal-800 before:opacity-80"
|
||||
href="https://tivie.id/program">
|
||||
Program
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
<main id="main-content" class="flex-grow w-full">
|
||||
<div class="">
|
||||
<div class="aspect-video bg-gray-100">
|
||||
<img src="https://i0.wp.com/is3.cloudhost.id/tivie/poster/2024/07/668b7ced47b25-1720417517.jpg?resize=480,270"
|
||||
alt="" class="w-full h-full object-fit">
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<div class="">
|
||||
<a href="https://tivie.id/programs/serial"
|
||||
class="text-sm uppercase font-bold tracking-wide text-teal-800 hover:text-teal-900">Serial</a>
|
||||
</div>
|
||||
<h2 class="font-bold text-2xl leading-tight mb-0.5">Hudson & Rex S6</h2>
|
||||
<h2 class="font-medium text-lg leading-tight mb-3">Episode 14</h2>
|
||||
<div class="">
|
||||
<p>Saat guru musik Jesse terbunuh di studio rekamannya, Charlie dan Rex menghubungkan kejahatan
|
||||
tersebut dengan pembunuhan yang tampaknya tak ada hubungannya.</p>
|
||||
</div>
|
||||
<div class="pt-2">
|
||||
<script async
|
||||
src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-7024487184083415"
|
||||
crossorigin="anonymous"></script>
|
||||
<ins class="adsbygoogle" style="display:block; text-align:center;" data-ad-layout="in-article"
|
||||
data-ad-format="fluid" data-ad-client="ca-pub-7024487184083415"
|
||||
data-ad-slot="3702712377"></ins>
|
||||
<script>
|
||||
(adsbygoogle = window.adsbygoogle || []).push({});
|
||||
</script>
|
||||
</div>
|
||||
<div class="mt-4 max-w-fit">
|
||||
<h4 class="font-bold tracking-tight leading-tight mb-1 uppercase">Terakhir Tayang</h4>
|
||||
<ul class="divide-y">
|
||||
<li>
|
||||
<div x-data="{url: 'https://tivie.id/channel/axn'}"
|
||||
class="py-1.5 flex items-start gap-3">
|
||||
<a href="https://tivie.id/channel/axn"
|
||||
class="shrink-0 w-10 -my-0.5 aspect-logo overflow-hidden" title="AXN">
|
||||
<img src="https://tivie.id-www.my.id/channel-hwfGtC5uHWwHLfxwmufCZSdtiex9LEm9KkiGG279-sm.png"
|
||||
alt="AXN" class="w-full h-full object-contain">
|
||||
<span class="sr-only">Jadwal Acara AXN Hari Ini</span>
|
||||
</a>
|
||||
<div class="shrink-0 w-36 flex justify-between cursor-pointer"
|
||||
@click="window.location.href = url">
|
||||
<span class="shrink-0 w-16 font-medium">Hari Ini</span>
|
||||
<div
|
||||
class="w-13 font-medium flex justify-center items-center text-center shrink-0 leading-tight opacity-90">
|
||||
<span before=":"
|
||||
class="shrink-0 w-1 h-4 leading-4 flex flex-col items-center overflow-hidden before:content-[attr(before)] before:w-full before:scale-90">11:00</span>
|
||||
<span before="1" after="1"
|
||||
class="order-first flex w-1/2 flex justify-end -space-x-px before:content-[attr(before)] before:block before:shrink-0 before:w-2.5 before:scale-90 after:content-[attr(after)] after:block after:shrink-0 after:w-2.5 after:scale-90"></span>
|
||||
<span before="0" after="0"
|
||||
class="flex w-1/2 flex justify-start -space-x-px before:content-[attr(before)] before:block before:shrink-0 before:w-2.5 before:scale-90 after:content-[attr(after)] after:block after:shrink-0 after:w-2.5 after:scale-90"></span>
|
||||
<span class="text-xs tracking-wider opacity-75 pt-px px-1">WIB</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="">
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pb-4 px-4 text-center">
|
||||
<a href="https://tivie.id/program/hudson-rex-s6-nwzDnwvBnAb6"
|
||||
class="inline-block rounded-sm uppercase py-2 px-4 text-sm text-center tracking-wide text-white bg-teal-600 font-medium">Episode
|
||||
Lainnya</a>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
21
sites/tivie.id/readme.md
Normal file
21
sites/tivie.id/readme.md
Normal file
|
@ -0,0 +1,21 @@
|
|||
# tivie.id
|
||||
|
||||
https://tivie.id
|
||||
|
||||
### Download the guide
|
||||
|
||||
```sh
|
||||
npm run grab --- --site=tivie.id
|
||||
```
|
||||
|
||||
### Update channel list
|
||||
|
||||
```sh
|
||||
npm run channels:parse --- --config=./sites/tivie.id/tivie.id.config.js --output=./sites/tivie.id/tivie.id.channels.xml
|
||||
```
|
||||
|
||||
### Test
|
||||
|
||||
```sh
|
||||
npm test --- tivie.id
|
||||
```
|
53
sites/tivie.id/tivie.id.channels.xml
Normal file
53
sites/tivie.id/tivie.id.channels.xml
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<channels>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="ANTV.id" site_id="antv">ANTV</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="AXN.id" site_id="axn">AXN</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="beINSports1.id" site_id="beinsports1">beIN Sports 1</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="beINSports2.id" site_id="beinsports2">beIN Sports 2</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="beINSports3.id" site_id="beinsports3">beIN Sports 3</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="BTV.id" site_id="btv">BTV</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="CinemaxAsia.sg" site_id="cinemax">Cinemax</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="CNNIndonesia.id" site_id="cnnindonesia">CNN</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="Galaxy.id" site_id="galaxy">Galaxy</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="GalaxyPremium.id" site_id="galaxypremium">Galaxy Premium</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="GarudaTV.id" site_id="garudatv">Garuda TV</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="GTV.id" site_id="gtv">GTV</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="HBOAsia.sg" site_id="hbo">HBO</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="HBOFamilyAsia.sg" site_id="hbofamily">HBO Family</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="HBOHitsAsia.sg" site_id="hbohits">HBO Hits</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="HBOSignatureAsia.sg" site_id="hbosignature">HBO Signature</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="HITS.sg" site_id="hits">HITS</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="HITSMovies.sg" site_id="hitsmovies">HITS Movies</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="HITSNowHD.sg" site_id="hitsnow">HITS Now</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="Indosiar.id" site_id="indosiar">Indosiar</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="iNews.id" site_id="inews">iNews</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="KompasTV.id" site_id="kompastv">Kompas TV</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="LifetimeAsia.us" site_id="lifetime">Lifetime</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="MentariTV.id" site_id="mentaritv">Mentari TV</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="MetroTV.id" site_id="metrotv">Metro TV</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="MNCTV.id" site_id="mnctv">MNC TV</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="Moji.id" site_id="moji">Moji</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="MyCinema.id" site_id="mycinema">My Cinema</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="MyCinemaAsia.id" site_id="mycinemaasia">My Cinema Asia</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="MyFamily.id" site_id="myfamily">My Family Channel</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="MyKidz.id" site_id="mykidz">My Kidz</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="NET.id" site_id="net">NET.</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="NusantaraTV.id" site_id="nusantaratv">Nusantara TV</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="RajawaliTV.id" site_id="rtv">RTV</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="RCTI.id" site_id="rcti">RCTI</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="ROCKEntertainment.sg" site_id="rockentertainment">Rock Entertainment</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="ROCKExtreme.sg" site_id="rockaction">Rock Action</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="SCTV.id" site_id="sctv">SCTV</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="SEAToday.id" site_id="seatoday">SEA Today</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="SindoNewsTV.id" site_id="sindonews">Sindonews TV</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="SPOTV2.id" site_id="spotv2">SpoTV 2</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="SPOTV.id" site_id="spotv">SpoTV</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="Trans7.id" site_id="trans7">Trans7</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="TransTV.id" site_id="transtv">Trans TV</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="tvNAsia.hk" site_id="tvn">tvN</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="tvNMoviesAsia.hk" site_id="tvnmovies">tvN Movies</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="tvOne.id" site_id="tvone">TvOne</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="TVRINasional.id" site_id="tvri">TVRI</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="VTV.id" site_id="vtv">VTV</channel>
|
||||
<channel site="tivie.id" lang="id" xmltv_id="ZeeBioskop.id" site_id="zeebioskop">Zee Bioskop</channel>
|
||||
</channels>
|
132
sites/tivie.id/tivie.id.config.js
Normal file
132
sites/tivie.id/tivie.id.config.js
Normal file
|
@ -0,0 +1,132 @@
|
|||
const axios = require('axios')
|
||||
const cheerio = require('cheerio')
|
||||
const dayjs = require('dayjs')
|
||||
const utc = require('dayjs/plugin/utc')
|
||||
const timezone = require('dayjs/plugin/timezone')
|
||||
const customParseFormat = require('dayjs/plugin/customParseFormat')
|
||||
const doFetch = require('@ntlab/sfetch')
|
||||
const debug = require('debug')('site:tivie.id')
|
||||
|
||||
dayjs.extend(utc)
|
||||
dayjs.extend(timezone)
|
||||
dayjs.extend(customParseFormat)
|
||||
|
||||
doFetch
|
||||
.setDebugger(debug)
|
||||
|
||||
const tz = 'Asia/Jakarta'
|
||||
|
||||
module.exports = {
|
||||
site: 'tivie.id',
|
||||
days: 2,
|
||||
url({ channel, date }) {
|
||||
return `https://tivie.id/channel/${
|
||||
channel.site_id
|
||||
}/${
|
||||
date.format('YYYYMMDD')
|
||||
}`
|
||||
},
|
||||
async parser({ content, date }) {
|
||||
const programs = []
|
||||
if (content) {
|
||||
const $ = cheerio.load(content)
|
||||
const items = $('ul[x-data] > li[id*="event-"] > div.w-full').toArray()
|
||||
.map(item => {
|
||||
const $item = $(item)
|
||||
const time = $item.find('div:nth-child(1) span:nth-child(1)')
|
||||
const info = $item.find('div:nth-child(2) h5')
|
||||
const detail = info.find('a')
|
||||
const p = {
|
||||
start: dayjs.tz(`${date.format('YYYY-MM-DD')} ${time.html()}`, 'YYYY-MM-DD HH:mm', tz)
|
||||
}
|
||||
if (detail.length) {
|
||||
const subtitle = detail.find('div')
|
||||
p.title = parseText(subtitle.length ? subtitle : detail)
|
||||
p.url = detail.attr('href')
|
||||
} else {
|
||||
p.title = parseText(info)
|
||||
}
|
||||
if (p.title) {
|
||||
const [, , season, episode] = p.title.match(/( S(\d+))?, Ep\. (\d+)/) || [null, null, null, null]
|
||||
if (season) {
|
||||
p.season = parseInt(season)
|
||||
}
|
||||
if (episode) {
|
||||
p.episode = parseInt(episode)
|
||||
}
|
||||
}
|
||||
return p
|
||||
})
|
||||
// fetch detailed guide if necessary
|
||||
const queues = items
|
||||
.filter(i => i.url)
|
||||
.map(i => {
|
||||
const url = i.url
|
||||
delete i.url
|
||||
return {i, url}
|
||||
})
|
||||
if (queues.length) {
|
||||
await doFetch(queues, (queue, res) => {
|
||||
const $ = cheerio.load(res)
|
||||
const img = $('#main-content > div > div:nth-child(1) img')
|
||||
const info = $('#main-content > div > div:nth-child(2)')
|
||||
const title = parseText(info.find('h2:nth-child(2)'))
|
||||
if (!queue.i.title.startsWith(title)) {
|
||||
queue.i.subTitle = parseText(info.find('h2:nth-child(2)'))
|
||||
}
|
||||
queue.i.description = parseText(info.find('div[class=""]:nth-child(4)'))
|
||||
queue.i.date = parseText(info.find('h2:nth-child(3)'))
|
||||
queue.i.image = img.length ? img.attr('src') : null
|
||||
})
|
||||
}
|
||||
// fill start-stop
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (i < items.length - 1) {
|
||||
items[i].stop = items[i + 1].start
|
||||
} else {
|
||||
items[i].stop = dayjs.tz(`${date.add(1, 'd').format('YYYY-MM-DD')} 00:00`, 'YYYY-MM-DD HH:mm', tz)
|
||||
}
|
||||
}
|
||||
// add programs
|
||||
programs.push(...items)
|
||||
}
|
||||
|
||||
return programs
|
||||
},
|
||||
async channels({ lang = 'id' }) {
|
||||
const result = await axios
|
||||
.get('https://tivie.id/channel')
|
||||
.then(response => response.data)
|
||||
.catch(console.error)
|
||||
|
||||
const $ = cheerio.load(result)
|
||||
const items = $('ul[x-data] li[x-data] div header h2 a').toArray()
|
||||
const channels = items.map(item => {
|
||||
const $item = $(item)
|
||||
const url = $item.attr('href')
|
||||
return {
|
||||
lang,
|
||||
site_id: url.substr(url.lastIndexOf('/') + 1),
|
||||
name: $item.find('strong').text()
|
||||
}
|
||||
})
|
||||
|
||||
return channels
|
||||
}
|
||||
}
|
||||
|
||||
function parseText($item) {
|
||||
let text = $item.text()
|
||||
.replace(/\t/g, '')
|
||||
.replace(/\n/g, ' ')
|
||||
.trim()
|
||||
while (true) {
|
||||
if (text.match(/ /)) {
|
||||
text = text.replace(/ /g, ' ')
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
return text
|
||||
}
|
77
sites/tivie.id/tivie.id.test.js
Normal file
77
sites/tivie.id/tivie.id.test.js
Normal file
|
@ -0,0 +1,77 @@
|
|||
const { parser, url } = require('./tivie.id.config')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const axios = require('axios')
|
||||
const dayjs = require('dayjs')
|
||||
const utc = require('dayjs/plugin/utc')
|
||||
const customParseFormat = require('dayjs/plugin/customParseFormat')
|
||||
|
||||
dayjs.extend(customParseFormat)
|
||||
dayjs.extend(utc)
|
||||
|
||||
jest.mock('axios')
|
||||
|
||||
const date = dayjs.utc('2024-12-31').startOf('d')
|
||||
const channel = {
|
||||
site_id: 'axn',
|
||||
xmltv_id: 'AXN.id',
|
||||
lang: 'id'
|
||||
}
|
||||
|
||||
axios.get.mockImplementation(url => {
|
||||
const urls = {
|
||||
'https://tivie.id/film/white-house-down-nwzDnwz9nAv6':
|
||||
'program01.html',
|
||||
'https://tivie.id/program/hudson-rex-s6-e14-nwzDnwvBmQr9':
|
||||
'program02.html',
|
||||
}
|
||||
let data = ''
|
||||
if (urls[url] !== undefined) {
|
||||
data = fs.readFileSync(path.join(__dirname, '__data__', urls[url])).toString()
|
||||
}
|
||||
return Promise.resolve({ data })
|
||||
})
|
||||
|
||||
it('can generate valid url', () => {
|
||||
expect(url({ channel, date })).toBe('https://tivie.id/channel/axn/20241231')
|
||||
})
|
||||
|
||||
it('can parse response', async () => {
|
||||
const content = fs.readFileSync(path.join(__dirname, '__data__', 'content.html'))
|
||||
const results = (
|
||||
await parser({ date, content, channel })
|
||||
).map(p => {
|
||||
p.start = p.start.toJSON()
|
||||
p.stop = p.stop.toJSON()
|
||||
return p
|
||||
})
|
||||
|
||||
expect(results.length).toBe(27)
|
||||
expect(results[0]).toMatchObject({
|
||||
start: '2024-12-30T17:00:00.000Z',
|
||||
stop: '2024-12-30T17:05:00.000Z',
|
||||
title: 'White House Down',
|
||||
description:
|
||||
'Saat melakukan tur di Gedung Putih bersama putrinya yang masih kecil, seorang perwira polisi beraksi untuk melindungi anaknya dan presiden dari sekelompok penjajah paramiliter bersenjata lengkap.',
|
||||
image: 'https://i0.wp.com/is3.cloudhost.id/tivie/poster/2023/09/65116c78791c2-1695640694.jpg?resize=480,270',
|
||||
})
|
||||
expect(results[2]).toMatchObject({
|
||||
start: '2024-12-30T18:00:00.000Z',
|
||||
stop: '2024-12-30T18:55:00.000Z',
|
||||
title: 'Hudson & Rex S6, Ep. 14',
|
||||
description:
|
||||
'Saat guru musik Jesse terbunuh di studio rekamannya, Charlie dan Rex menghubungkan kejahatan tersebut dengan pembunuhan yang tampaknya tak ada hubungannya.',
|
||||
image: 'https://i0.wp.com/is3.cloudhost.id/tivie/poster/2024/07/668b7ced47b25-1720417517.jpg?resize=480,270',
|
||||
season: 6,
|
||||
episode: 14,
|
||||
})
|
||||
})
|
||||
|
||||
it('can handle empty guide', async () => {
|
||||
const results = await parser({
|
||||
date,
|
||||
channel,
|
||||
content: '',
|
||||
})
|
||||
expect(results).toMatchObject([])
|
||||
})
|
Loading…
Add table
Add a link
Reference in a new issue