From 1eb531338f5ae3696fa9d68a4171a73f0107c2f8 Mon Sep 17 00:00:00 2001 From: Factiven Date: Fri, 4 Aug 2023 14:49:35 +0700 Subject: Update v3.8.5 - Merged Beta to Main (#32) * initial commit * Update_v.3.6.7-beta-v1.2 * Update_v.3.6.7-beta-v1.3 * Update_v.3.6.7-beta-v1.3 > update API * Fixed mediaList won't update * added .env disqus shortname * Update_v3.6.7-beta-v1.4 >Implementing database * Create main.yml * Update v3.6.7-beta-v1.5 small patch * title home page * Update content.js * Delete db-test.js * Update content.js * Update home page card * Update v3.7.0 * Update v3.7.1-beta > migrating backend to main code > fixed schedule component * Update v3.8.0 > Added dub options > Moved schedule backend * Update v.3.8.1 > Fixed episodes on watch page isn't dubbed * Update v3.8.1-patch-1 * Update v3.8.1-patch-2 > Another patch for dub * Update v3.8.2 > Removed prisma configuration for database since it's not stable yet * Update v3.8.3 > Fixed different provider have same id * Update v.3.8.3 > Fixed player bug where the controls won't hide after updating anilist progress * Update v3.8.4-patch-2 * Update v3.8.5 > Update readme.md > Update .env.example --- pages/404.js | 69 +-- pages/api/anify/schedule.js | 53 ++ pages/api/consumet/episode/[id].js | 63 ++ pages/api/consumet/source/[...params].js | 36 ++ pages/en/anime/[...id].js | 1000 +++--------------------------- pages/en/anime/watch/[...info].js | 749 ++++++---------------- pages/en/index.js | 7 +- pages/en/test.js | 11 + 8 files changed, 423 insertions(+), 1565 deletions(-) create mode 100644 pages/api/anify/schedule.js create mode 100644 pages/api/consumet/episode/[id].js create mode 100644 pages/api/consumet/source/[...params].js create mode 100644 pages/en/test.js (limited to 'pages') diff --git a/pages/404.js b/pages/404.js index 746e8fa..c774372 100644 --- a/pages/404.js +++ b/pages/404.js @@ -32,74 +32,7 @@ export default function Custom404() {
- - - - - - - - - - - - - - - - - - - - - - - + 404

Oops! Page not found

diff --git a/pages/api/anify/schedule.js b/pages/api/anify/schedule.js new file mode 100644 index 0000000..99f10d6 --- /dev/null +++ b/pages/api/anify/schedule.js @@ -0,0 +1,53 @@ +import axios from "axios"; +import cacheData from "memory-cache"; +import cron from "cron"; + +const API_KEY = process.env.API_KEY; + +// Function to fetch new data +async function fetchData() { + try { + const { data } = await axios.get( + `https://api.anify.tv/schedule?apikey=${API_KEY}` + ); + return data; + } catch (error) { + console.error("Error fetching data:", error); + return null; + } +} + +// Function to refresh the cache with new data +async function refreshCache() { + const newData = await fetchData(); + if (newData) { + cacheData.put("schedule", newData, 1000 * 60 * 15); + console.log("Cache refreshed successfully."); + } +} + +// Schedule cache refresh every Monday at 00:00 AM (local time) +const job = new cron.CronJob("0 0 * * 1", () => { + refreshCache(); +}); +job.start(); + +export default async function handler(req, res) { + try { + const cached = cacheData.get("schedule"); + if (cached) { + return res.status(200).json(cached); + } else { + const data = await fetchData(); + + if (data) { + res.status(200).json(data); + cacheData.put("schedule", data, 1000 * 60 * 60 * 24 * 7); + } else { + res.status(404).json({ message: "Schedule not found" }); + } + } + } catch (error) { + res.status(500).json({ error }); + } +} diff --git a/pages/api/consumet/episode/[id].js b/pages/api/consumet/episode/[id].js new file mode 100644 index 0000000..60bb4fb --- /dev/null +++ b/pages/api/consumet/episode/[id].js @@ -0,0 +1,63 @@ +import axios from "axios"; +import cacheData from "memory-cache"; + +const API_URL = process.env.API_URI; + +export default async function handler(req, res) { + try { + const id = req.query.id; + const dub = req.query.dub || false; + + const providers = ["enime", "gogoanime"]; + const datas = []; + + const cached = cacheData.get(id + dub); + if (cached) { + return res.status(200).json(cached); + } else { + async function fetchData(provider) { + try { + const data = await fetch( + dub && provider === "gogoanime" + ? `${API_URL}/meta/anilist/info/${id}?dub=true` + : `${API_URL}/meta/anilist/info/${id}?provider=${provider}` + ).then((res) => { + if (!res.ok) { + switch (res.status) { + case 404: { + return null; + } + } + } + return res.json(); + }); + if (data.episodes.length > 0) { + datas.push({ + providerId: provider, + episodes: dub ? data.episodes : data.episodes.reverse(), + }); + } + } catch (error) { + console.error( + `Error fetching data for provider '${provider}':`, + error + ); + } + } + if (dub === false) { + await Promise.all(providers.map((provider) => fetchData(provider))); + } else { + await fetchData("gogoanime"); + } + + if (datas.length === 0) { + return res.status(404).json({ message: "Anime not found" }); + } else { + cacheData.put(id + dub, { data: datas }, 1000 * 60 * 60 * 15); // 15 minutes + res.status(200).json({ data: datas }); + } + } + } catch (error) { + res.status(500).json({ error }); + } +} diff --git a/pages/api/consumet/source/[...params].js b/pages/api/consumet/source/[...params].js new file mode 100644 index 0000000..e589d4a --- /dev/null +++ b/pages/api/consumet/source/[...params].js @@ -0,0 +1,36 @@ +import axios from "axios"; +import cacheData from "memory-cache"; + +const API_URL = process.env.API_URI; + +export default async function handler(req, res) { + const query = req.query.params; + try { + const provider = query[0]; + const id = query[1]; + + const cached = cacheData.get(id); + if (cached) { + return res.status(200).json(cached); + } else { + let datas; + + const { data } = await axios.get( + `${API_URL}/meta/anilist/watch/${id}?provider=${provider}` + ); + + if (data) { + datas = data; + cacheData.put(id, data, 1000 * 60 * 5); + } + + if (!datas) { + return res.status(404).json({ message: "Source not found" }); + } + + res.status(200).json(datas); + } + } catch (error) { + res.status(500).json({ error }); + } +} diff --git a/pages/en/anime/[...id].js b/pages/en/anime/[...id].js index 86396e3..0b83f24 100644 --- a/pages/en/anime/[...id].js +++ b/pages/en/anime/[...id].js @@ -1,22 +1,8 @@ -import Skeleton from "react-loading-skeleton"; - -import { - ChevronDownIcon, - ClockIcon, - HeartIcon, -} from "@heroicons/react/20/solid"; -import { - TvIcon, - ArrowTrendingUpIcon, - RectangleStackIcon, -} from "@heroicons/react/24/outline"; - import Head from "next/head"; import Image from "next/image"; import { useRouter } from "next/router"; import { useEffect, useState } from "react"; import Layout from "../../../components/layout"; -import Link from "next/link"; import Content from "../../../components/home/content"; import Modal from "../../../components/modal"; @@ -28,252 +14,75 @@ import { GET_MEDIA_USER } from "../../../queries"; import { GET_MEDIA_INFO } from "../../../queries"; import { ToastContainer } from "react-toastify"; -import { convertSecondsToTime } from "../../../utils/getTimes"; - -// import { aniInfo } from "../../components/devComp/data"; -// console.log(GET_MEDIA_USER); -export default function Info({ info, color, api }) { - // Episodes dropdown - const [firstEpisodeIndex, setFirstEpisodeIndex] = useState(0); - const [lastEpisodeIndex, setLastEpisodeIndex] = useState(); - const [selectedRange, setSelectedRange] = useState("All"); - function onEpisodeIndexChange(e) { - if (e.target.value === "All") { - setFirstEpisodeIndex(0); - setLastEpisodeIndex(); - setSelectedRange("All"); - return; - } - setFirstEpisodeIndex(e.target.value.split("-")[0] - 1); - setLastEpisodeIndex(e.target.value.split("-")[1]); - setSelectedRange(e.target.value); - } +import DetailTop from "../../../components/anime/mobile/topSection"; +import DesktopDetails from "../../../components/anime/infoDetails"; +import AnimeEpisode from "../../../components/anime/episode"; +export default function Info({ info, color }) { const { data: session } = useSession(); - const [episode, setEpisode] = useState(null); const [loading, setLoading] = useState(false); const [progress, setProgress] = useState(0); const [statuses, setStatuses] = useState(null); const [domainUrl, setDomainUrl] = useState(""); const [showAll, setShowAll] = useState(false); - const [visible, setVisible] = useState(false); const [open, setOpen] = useState(false); - const [time, setTime] = useState(0); const { id } = useRouter().query; - const [epiView, setEpiView] = useState("3"); - - const [artStorage, setArtStorage] = useState(null); - const rec = info?.recommendations?.nodes?.map( (data) => data.mediaRecommendation ); - const [provider, setProvider] = useState(); - const [prvValue, setPrvValue] = useState("gogoanime"); - - const [availableProviders, setAvailableProviders] = useState([]); - // const [err, setErr] = useState(''); - - function handleProvider(e) { - setEpisode( - Array.isArray(provider[e.target.value]) - ? provider[e.target.value]?.reverse() - : provider[e.target.value] - ); - setPrvValue(e.target.value); - localStorage.setItem("provider", e.target.value); - } - - //for episodes dropdown - useEffect(() => { - setFirstEpisodeIndex(0); - setLastEpisodeIndex(); - setSelectedRange("All"); - }, [info, prvValue]); - useEffect(() => { handleClose(); async function fetchData() { setLoading(true); if (id) { try { - const { protocol, host } = window.location; - const prv = localStorage.getItem("provider"); - const url = `${protocol}//${host}`; - - const view = localStorage.getItem("epiView"); - - if (prv) { - setPrvValue(prv); - } else { - setPrvValue("gogoanime"); - } - - setDomainUrl(url); + setDomainUrl(window.location.origin); - setArtStorage(JSON.parse(localStorage.getItem("artplayer_settings"))); - - setEpisode(null); setProgress(0); setStatuses(null); - let reloadCount = 0; - - try { - const fetchPromises = [ - fetch(`${api}/meta/anilist/info/${info.id}?provider=enime`), - fetch(`${api}/meta/anilist/info/${info.id}?provider=zoro`), - fetch(`${api}/meta/anilist/info/${info.id}?provider=gogoanime`), - ]; - - const results = await Promise.allSettled(fetchPromises); - const successfulResponses = []; - let errorCount = 0; - - results.forEach((result) => { - if (result.status === "fulfilled") { - successfulResponses.push(result.value); - } else { - errorCount++; - } - }); - - if (errorCount === fetchPromises.length) { - // All fetch requests failed, handle the error here - setEpisode([]); - } else { - // Process the successfulResponses here - const responsesData = await Promise.all( - successfulResponses.map((response) => response.json()) - ); - const [enime, zoro, gogoanime] = responsesData; - - const prov = { - enime: enime?.episodes || enime, - zoro: zoro?.episodes || zoro, - gogoanime: gogoanime?.episodes || gogoanime, - }; - - const aPrv = [ - { - name: "enime", - available: - enime?.episodes && enime?.episodes.length > 0 - ? true - : false, + if (session?.user?.name) { + const response = await fetch("https://graphql.anilist.co/", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + query: GET_MEDIA_USER, + variables: { + username: session?.user?.name, }, - { - name: "zoro", - available: - zoro?.episodes && zoro?.episodes.length > 0 ? true : false, - }, - { - name: "gogoanime", - available: - gogoanime?.episodes && gogoanime?.episodes.length > 0 - ? true - : false, - }, - ]; - - setAvailableProviders(aPrv); - - const infProv = { - enime: enime, - zoro: zoro, - gogoanime: gogoanime, - }; - - if (prv) { - setEpisode( - Array.isArray(prov[prv]) ? prov[prv]?.reverse() : prov[prv] - ); - } else { - setEpisode( - Array.isArray(prov["gogoanime"]) - ? prov["gogoanime"]?.reverse() - : prov["gogoanime"] - ); - } - - const data = infProv[prv] || infProv["gogoanime"]; - // const data = aniInfo; - if (!data || data?.episodes?.length === 0) { - setEpisode([]); - } else { - if (data.episodes?.some((i) => i.title === null)) { - setEpiView("3"); - } else if (view) { - setEpiView(view); - } else { - setEpiView("3"); - } - } - - if (session?.user?.name) { - const response = await fetch("https://graphql.anilist.co/", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - query: GET_MEDIA_USER, - variables: { - username: session?.user?.name, - }, - }), - }); - - const responseData = await response.json(); - - const prog = responseData?.data?.MediaListCollection; - - if (prog && prog.lists.length > 0) { - const gut = prog.lists - .flatMap((item) => item.entries) - .find((item) => item.mediaId === parseInt(id[0])); - - if (gut) { - setProgress(gut.progress); - const statusMapping = { - CURRENT: { name: "Watching", value: "CURRENT" }, - PLANNING: { name: "Plan to watch", value: "PLANNING" }, - COMPLETED: { name: "Completed", value: "COMPLETED" }, - DROPPED: { name: "Dropped", value: "DROPPED" }, - PAUSED: { name: "Paused", value: "PAUSED" }, - REPEATING: { name: "Rewatching", value: "REPEATING" }, - }; - setStatuses(statusMapping[gut.status]); - } - } - } + }), + }); - if (data.nextAiringEpisode) { - setTime( - convertSecondsToTime(data.nextAiringEpisode.timeUntilAiring) - ); + const responseData = await response.json(); + + const prog = responseData?.data?.MediaListCollection; + + if (prog && prog.lists.length > 0) { + const gut = prog.lists + .flatMap((item) => item.entries) + .find((item) => item.mediaId === parseInt(id[0])); + + if (gut) { + setProgress(gut.progress); + const statusMapping = { + CURRENT: { name: "Watching", value: "CURRENT" }, + PLANNING: { name: "Plan to watch", value: "PLANNING" }, + COMPLETED: { name: "Completed", value: "COMPLETED" }, + DROPPED: { name: "Dropped", value: "DROPPED" }, + PAUSED: { name: "Paused", value: "PAUSED" }, + REPEATING: { name: "Rewatching", value: "REPEATING" }, + }; + setStatuses(statusMapping[gut.status]); } - - setProvider(prov); - } - } catch (error) { - console.error(error); - if (reloadCount < 2) { - reloadCount++; - setTimeout(() => { - window.location.reload(); - }, 1000); - } else { - setEpisode([]); } } } catch (error) { console.error(error); - setTimeout(() => { - window.location.reload(); - }, 1000); } finally { setLoading(false); } @@ -292,8 +101,6 @@ export default function Info({ info, color, api }) { document.body.style.overflow = "auto"; } - const filterProviders = availableProviders?.filter((x) => x.available); - return ( <> @@ -343,7 +150,7 @@ export default function Info({ info, color, api }) {
{info ? ( - banner anime + <> + banner anime + banner anime + ) : (
)}
- {/* Mobile */} + {/* Mobile Anime Information */} -
-
-

- {info?.title?.romaji || info?.title?.english} -

-

-

- {info?.genres - ?.slice( - 0, - info?.genres?.length > 3 ? info?.genres?.length : 3 - ) - .map((item, index) => ( - - {item} - - ))} -
- {info && ( -
-
- -
- -
-
-
- )} -
-
-
- {info && info.status !== "NOT_YET_RELEASED" ? ( - <> -
- -

{info?.type}

-
-
- -

{info?.averageScore}%

-
-
- - {info?.episodes ? ( -

{info?.episodes} Episodes

- ) : ( -

TBA

- )} -
- - ) : ( -
{info && "Not Yet Released"}
- )} -
-
-
- - {/* PC */} -
-
- {info ? ( - <> -
- poster anime - - - ) : ( - - )} -
+ - {/* PC */} -
-
-

- {info ? ( - info?.title?.romaji || info?.title?.english - ) : ( - - )} -

- {info ? ( -
- {info?.episodes && ( -
- {info?.episodes} Episodes -
- )} - {info?.startDate?.year && ( -
- {info?.startDate?.year} -
- )} - {info?.averageScore && ( -
- {info?.averageScore}% -
- )} - {info?.type && ( -
- {info?.type} -
- )} - {info?.status && ( -
- {info?.status} -
- )} -
- Sub | EN -
-
- ) : ( - - )} -
- {info ? ( -

- ) : ( - - )} -

-
+ {/* PC Anime Information*/} + -
-
- {info?.relations?.edges?.length > 0 && ( -
- Relations -
- )} - {info?.relations?.edges?.length > 3 && ( -
setShowAll(!showAll)} - > - {showAll ? "show less" : "show more"} -
- )} -
-
- {info?.relations?.edges ? ( - info?.relations?.edges - .slice(0, showAll ? info?.relations?.edges.length : 3) - .map((r, index) => { - const rel = r.node; - return ( - -
-
- {rel.id} -
-
-
- {r.relationType} -
-
- {rel.title.userPreferred || rel.title.romaji} -
-
{rel.type}
-
-
- - ); - }) - ) : ( - <> - {[1, 2, 3].map((item) => ( -
- -
- ))} -
- -
- - )} -
-
-
-
-
-
- {info && ( -

- Episodes -

- )} - {info?.nextAiringEpisode && ( -
-
-

Next :

-
- {time} -
-
-
- -
-
- )} -
-
setVisible(!visible)} - > - - - -
-
-
-
- {filterProviders?.length > 0 && ( -
-

Provider

- - -
- )} - {episode?.length > 50 && ( -
-

Episodes

- - -
- )} -
-
-
0 - ? episode?.some((item) => item?.title === null) - ? "pointer-events-none" - : "cursor-pointer" - : "pointer-events-none" - } - onClick={() => { - setEpiView("1"); - localStorage.setItem("epiView", "1"); - }} - > - - 0 - ? episode?.some((item) => item?.title === null) - ? "fill-[#1c1c22]" - : epiView === "1" - ? "fill-action" - : "fill-[#3A3A44]" - : "fill-[#1c1c22]" - }`} - rx="3" - > - -
-
0 - ? episode?.some((item) => item?.title === null) - ? "pointer-events-none" - : "cursor-pointer" - : "pointer-events-none" - } - onClick={() => { - setEpiView("2"); - localStorage.setItem("epiView", "2"); - }} - > - 0 - ? episode?.some((item) => item?.title === null) - ? "fill-[#1c1c22]" - : epiView === "2" - ? "fill-action" - : "fill-[#3A3A44]" - : "fill-[#1c1c22]" - }`} - viewBox="0 0 33 20" - > - - - -
-
0 - ? `cursor-pointer` - : "pointer-events-none" - } - onClick={() => { - setEpiView("3"); - localStorage.setItem("epiView", "3"); - }} - > - 0 - ? epiView === "3" - ? "fill-action" - : "fill-[#3A3A44]" - : "fill-[#1c1c22]" - }`} - viewBox="0 0 33 20" - > - - - - -
-
-
-
- {!loading ? ( - Array.isArray(episode) ? ( - episode && ( -
- {episode?.length !== 0 && episode ? ( -
- {epiView === "1" - ? episode - .slice(firstEpisodeIndex, lastEpisodeIndex) - ?.map((epi, index) => { - const time = artStorage?.[epi?.id]?.time; - const duration = - artStorage?.[epi?.id]?.duration; - let prog = (time / duration) * 100; - if (prog > 90) prog = 100; - return ( - - - Episode {epi?.number} - - -
- epi image - - ); - }) - : ""} - {epiView === "2" && - episode - .slice(firstEpisodeIndex, lastEpisodeIndex) - .map((epi, index) => { - const time = artStorage?.[epi?.id]?.time; - const duration = - artStorage?.[epi?.id]?.duration; - let prog = (time / duration) * 100; - if (prog > 90) prog = 100; - return ( - -
-
- Anime Cover - - - Episode {epi?.number} - -
- - - -
-
-
+ {/* Episodes */} -
-

- {epi?.title} -

- {epi?.description && ( -

- {epi?.description} -

- )} -
- - ); - })} - {epiView === "3" && - episode - .slice(firstEpisodeIndex, lastEpisodeIndex) - .map((epi, index) => { - return ( -
- -

Episode {epi.number}

- {epi.title && ( -

- "{epi.title}" -

- )} - - {index !== episode?.length - 1 && ( - - )} -
- ); - })} -
- ) : ( -

No Episodes Available

- )} -
- ) - ) : ( -
-
-                      {episode?.message}
-                    
-
- ) - ) : ( -
-
-
-
-
-
-
-
- )} -
+
{info && rec?.length !== 0 && (
@@ -1114,17 +286,3 @@ function setTxtColor(hexColor) { const brightness = getBrightness(hexColor); return brightness < 150 ? "#fff" : "#000"; } - -const getLanguageClassName = (language) => { - switch (language) { - case "javascript": - return "language-javascript"; - case "html": - return "language-html"; - case "bash": - return "language-bash"; - // add more languages here as needed - default: - return ""; - } -}; diff --git a/pages/en/anime/watch/[...info].js b/pages/en/anime/watch/[...info].js index 17ec5f7..67e38c2 100644 --- a/pages/en/anime/watch/[...info].js +++ b/pages/en/anime/watch/[...info].js @@ -1,151 +1,82 @@ -import Image from "next/image"; -import Link from "next/link"; import Head from "next/head"; import { useEffect, useState } from "react"; -import dynamic from "next/dynamic"; import { getServerSession } from "next-auth/next"; import { authOptions } from "../../../api/auth/[...nextauth]"; -import Skeleton from "react-loading-skeleton"; - -import { ChevronDownIcon, ForwardIcon } from "@heroicons/react/24/solid"; -import { useRouter } from "next/router"; - -import { GET_MEDIA_USER } from "../../../../queries"; - import dotenv from "dotenv"; import Navigasi from "../../../../components/home/staticNav"; -import DisqusComments from "../../../../components/disqus"; - -const VideoPlayer = dynamic(() => - import("../../../../components/videoPlayer", { ssr: false }) -); +import PrimarySide from "../../../../components/anime/watch/primarySide"; +import SecondarySide from "../../../../components/anime/watch/secondarySide"; +import { GET_MEDIA_USER } from "../../../../queries"; -export default function Info({ sessions, id, aniId, provider, proxy, api }) { - const [epiData, setEpiData] = useState(null); - const [data, setAniData] = useState(null); - const [skip, setSkip] = useState({ op: null, ed: null }); - const [statusWatch, setStatusWatch] = useState("CURRENT"); +export default function Info({ + sessions, + aniId, + watchId, + provider, + epiNumber, + dub, + proxy, + disqus, +}) { + const [info, setInfo] = useState(null); + const [currentEpisode, setCurrentEpisode] = useState(null); const [loading, setLoading] = useState(false); - const [showComments, setShowComments] = useState(false); - const [playing, setPlaying] = useState(null); - const [playingEpisode, setPlayingEpisode] = useState(null); - const [playingTitle, setPlayingTitle] = useState(null); - - const [poster, setPoster] = useState(null); const [progress, setProgress] = useState(0); - - const [episodes, setEpisodes] = useState([]); + const [statuses, setStatuses] = useState("CURRENT"); const [artStorage, setArtStorage] = useState(null); - - const [url, setUrl] = useState(null); - - const router = useRouter(); - - // console.log({ playing }); + const [episodesList, setepisodesList] = useState(); + const [onList, setOnList] = useState(false); useEffect(() => { - const defaultState = { - epiData: null, - skip: { op: null, ed: null }, - statusWatch: "CURRENT", - playingEpisode: null, - loading: false, - showComments: false, - }; - - // Reset all state variables to their default values - Object.keys(defaultState).forEach((key) => { - const value = defaultState[key]; - if (Array.isArray(value)) { - value.length - ? eval( - `set${ - key.charAt(0).toUpperCase() + key.slice(1) - }(${JSON.stringify(value)})` - ) - : eval(`set${key.charAt(0).toUpperCase() + key.slice(1)}([])`); - } else { - eval( - `set${key.charAt(0).toUpperCase() + key.slice(1)}(${JSON.stringify( - value - )})` - ); - } - }); - - const url = window.location.href; - setUrl(url); - - const fetchData = async () => { - try { - if (provider) { - const res = await fetch( - `${api}/meta/anilist/watch/${id}?provider=${provider}` - ); - const epiData = await res.json(); - setEpiData(epiData); - } else { - const res = await fetch(`${api}/meta/anilist/watch/${id}`); - const epiData = await res.json(); - setEpiData(epiData); - } - } catch (error) { - setTimeout(() => { - window.location.reload(); - }, 3000); - } - - let aniData = null; - setArtStorage(JSON.parse(localStorage.getItem("artplayer_settings"))); - - if (provider) { - const res = await fetch( - `${api}/meta/anilist/info/${aniId}?provider=${provider}` - ); - aniData = await res.json(); - setEpisodes(aniData.episodes?.reverse()); - setAniData(aniData); - } else { - const res2 = await fetch(`${api}/meta/anilist/info/${aniId}`); - aniData = await res2.json(); - setEpisodes(aniData.episodes?.reverse()); - setAniData(aniData); - } - - let playingEpisode = aniData.episodes - .filter((item) => item.id == id) - .map((item) => item.number); - - setPlayingEpisode(playingEpisode); - - const playing = aniData.episodes.find((item) => item.id === id); - - setPoster(playing?.image); - setPlaying(playing); - - const title = aniData.episodes - .filter((item) => item.id == id) - .find((item) => item.title !== null); - setPlayingTitle( - title?.title || aniData.title?.romaji || aniData.title?.english - ); - - const res4 = await fetch( - `https://api.aniskip.com/v2/skip-times/${aniData.malId}/${parseInt( - playingEpisode - )}?types[]=ed&types[]=mixed-ed&types[]=mixed-op&types[]=op&types[]=recap&episodeLength=` - ); - const skip = await res4.json(); - - const op = skip.results?.find((item) => item.skipType === "op") || null; - const ed = skip.results?.find((item) => item.skipType === "ed") || null; - - setSkip({ op, ed }); + setLoading(true); + async function getInfo() { + const ress = await fetch(`https://graphql.anilist.co`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + query: `query ($id: Int) { + Media (id: $id) { + id + idMal + title { + romaji + english + native + } + status + genres + episodes + studios { + edges { + node { + id + name + } + } + } + description + coverImage { + extraLarge + color + } + synonyms + + } + } + `, + variables: { + id: aniId, + }, + }), + }); + const data = await ress.json(); - if (sessions) { + if (sessions?.user?.name) { const response = await fetch("https://graphql.anilist.co/", { method: "POST", headers: { @@ -154,450 +85,121 @@ export default function Info({ sessions, id, aniId, provider, proxy, api }) { body: JSON.stringify({ query: GET_MEDIA_USER, variables: { - username: sessions?.user.name, + username: sessions?.user?.name, }, }), }); - const dat = await response.json(); - - const prog = dat.data.MediaListCollection; + const responseData = await response.json(); + + const prog = responseData?.data?.MediaListCollection; + + if (prog && prog.lists.length > 0) { + const gut = prog.lists + .flatMap((item) => item.entries) + .find((item) => item.mediaId === parseInt(aniId)); + + if (gut) { + setProgress(gut.progress); + setOnList(true); + } + + if (gut?.status === "COMPLETED") { + setStatuses("REPEATING"); + } else if ( + gut?.status === "REPEATING" && + gut?.media?.episodes === parseInt(epiNumber) + ) { + setStatuses("COMPLETED"); + } else if (gut?.status === "REPEATING") { + setStatuses("REPEATING"); + } else if (gut?.media?.episodes === parseInt(epiNumber)) { + setStatuses("COMPLETED"); + } else if ( + gut?.media?.episodes !== null && + data?.data?.Media.episodes === parseInt(epiNumber) + ) { + setStatuses("COMPLETED"); + setLoading(false); + } + } + } - const gat = prog?.lists.map((item) => item.entries); - const git = gat?.map((item) => - item?.find((item) => item.media.id === parseInt(aniId)) - ); - const gut = git?.find((item) => item?.media.id === parseInt(aniId)); + setInfo(data.data.Media); - if (gut) { - setProgress(gut.progress); - } + const response = await fetch( + `/api/consumet/episode/${aniId}${dub ? `?dub=${dub}` : ""}` + ); + const episodes = await response.json(); - if (gut?.status === "COMPLETED") { - setStatusWatch("REPEATING"); - } else if ( - gut?.status === "REPEATING" && - gut?.media?.episodes === parseInt(playingEpisode) - ) { - setStatusWatch("COMPLETED"); - } else if (gut?.status === "REPEATING") { - setStatusWatch("REPEATING"); - } else if (gut?.media?.episodes === parseInt(playingEpisode)) { - setStatusWatch("COMPLETED"); - } else if ( - gut?.media?.episodes !== null && - aniData.totalEpisodes === parseInt(playingEpisode) - ) { - setStatusWatch("COMPLETED"); - setLoading(true); + if (episodes) { + const getProvider = episodes.data?.find( + (i) => i.providerId === provider + ); + if (getProvider) { + setepisodesList(getProvider.episodes); + const currentEpisode = getProvider.episodes?.find( + (i) => i.number === parseInt(epiNumber) + ); + const nextEpisode = getProvider.episodes?.find( + (i) => i.number === parseInt(epiNumber) + 1 + ); + const previousEpisode = getProvider.episodes?.find( + (i) => i.number === parseInt(epiNumber) - 1 + ); + setCurrentEpisode({ + prev: previousEpisode, + playing: currentEpisode, + next: nextEpisode, + }); + } else { + setLoading(false); } } - setLoading(true); - }; - fetchData(); - }, [id, aniId, provider, sessions]); - - useEffect(() => { - const mediaSession = navigator.mediaSession; - if (!mediaSession) return; - const artwork = poster - ? [{ src: poster, sizes: "512x512", type: "image/jpeg" }] - : undefined; + setArtStorage(JSON.parse(localStorage.getItem("artplayer_settings"))); + // setEpiData(episodes); + setLoading(false); + } + getInfo(); + }, [sessions?.user?.name, epiNumber, dub]); - mediaSession.metadata = new MediaMetadata({ - title: playingTitle, - artist: `Moopa ${ - playingTitle === data?.title?.romaji - ? "- Episode " + playingEpisode - : `- ${data?.title?.romaji || data?.title?.english}` - }`, - artwork, - }); - }, [poster, playingTitle, playingEpisode, data]); + // console.log(proxy); return ( <> - {playingTitle || "Loading..."} + {info?.title?.romaji || "Retrieving data..."} -
- -
-
- {loading ? ( - Array.isArray(epiData?.sources) ? ( -
- -
- ) : ( -
-

- Whoops! Something went wrong. Please reload the page or try - other sources. {`:(`} -

-
- ) - ) : ( -
- )} -
- {data && data?.episodes.length > 0 ? ( - data.episodes - .filter((items) => items.id == id) - .map((item, index) => ( -
-
-
- - {item.title || - data.title.romaji || - data.title.english} - -
-

- Episode {item.number} -

-
-
-
- - -
- -
-
- )) - ) : ( -
-
-
- -
-
-

- -

-
- )} -
- -
-
- {data ? ( - Anime Cover - ) : ( - - )} -
-
-
-

- Studios -

-
- {data ? data.studios : } -
-
-
- - - -
-
-
-
-

- Status -

-
{data ? data.status : }
-
-
-

- Titles -

-
- {data ? ( - <> -
- {data.title.romaji || ""} -
-
- {data.title.english || ""} -
-
- {data.title.native || ""} -
- - ) : ( - - )} -
-
-
-
-
- {data && - data.genres.map((item, index) => ( -
- {item} -
- ))} -
-
- {data && ( -

- )} -

- {!showComments && loading && ( -
- -
- )} - {showComments && ( -
- {data && url && playing && ( -
- -
- )} -
- )} -
-
-
-

- Up Next -

-
- {data && data?.episodes.length > 0 ? ( - data.episodes.some((item) => item.title && item.description) ? ( - episodes.map((item) => { - const time = artStorage?.[item.id]?.time; - const duration = artStorage?.[item.id]?.duration; - let prog = (time / duration) * 100; - if (prog > 90) prog = 100; - return ( - -
-
- Anime Cover - - - Episode {item.number} - - {item.id == id && ( -
- - - -
- )} -
-
-
-

- {item.title} -

-

- {item.description} -

-
- - ); - }) - ) : ( - data.episodes.map((item) => { - return ( - - Episode {item.number} - - ); - }) - ) - ) : ( - <> - {[1].map((item) => ( - - ))} - - )} -
-
+ +
+
+ +
@@ -607,31 +209,34 @@ export default function Info({ sessions, id, aniId, provider, proxy, api }) { export async function getServerSideProps(context) { dotenv.config(); - const API_URI = process.env.API_URI; - const session = await getServerSession(context.req, context.res, authOptions); - const proxy = process.env.PROXY_URI; - - const { info } = context.query; - if (!info) { + const query = context.query; + if (!query) { return { notFound: true, }; } - const id = info[0]; - const aniId = info[1]; - const provider = info[2] || null; + const proxy = process.env.PROXY_URI; + const disqus = process.env.DISQUS_SHORTNAME; + + const aniId = query.info[0]; + const provider = query.info[1]; + const watchId = query.id; + const epiNumber = query.num; + const dub = query.dub; return { props: { sessions: session, - id, - aniId, - provider, + aniId: aniId || null, + provider: provider || null, + watchId: watchId || null, + epiNumber: epiNumber || null, + dub: dub || null, proxy, - api: API_URI, + disqus, }, }; } diff --git a/pages/en/index.js b/pages/en/index.js index cbf96cd..35de96d 100644 --- a/pages/en/index.js +++ b/pages/en/index.js @@ -16,10 +16,11 @@ import SearchBar from "../../components/searchBar"; import Genres from "../../components/home/genres"; import Schedule from "../../components/home/schedule"; import getUpcomingAnime from "../../lib/anilist/getUpcomingAnime"; -import { useCountdown } from "../../lib/useCountdownSeconds"; +import { useCountdown } from "../../utils/useCountdownSeconds"; import Navigasi from "../../components/home/staticNav"; import MobileNav from "../../components/home/mobileNav"; +import axios from "axios"; // Filter schedules for each day // const filterByCountryOfOrigin = (schedule, country) => { @@ -58,8 +59,7 @@ export default function Home({ detail, populars, sessions, upComing }) { useEffect(() => { const getSchedule = async () => { - const res = await fetch(`https://ruka.moopa.live/api/schedules`); - const data = await res.json(); + const { data } = await axios.get(`/api/anify/schedule`); setSchedules(data); }; getSchedule(); @@ -132,7 +132,6 @@ export default function Home({ detail, populars, sessions, upComing }) { } userData(); }, [sessions, current, plan]); - return ( <> diff --git a/pages/en/test.js b/pages/en/test.js new file mode 100644 index 0000000..cf76827 --- /dev/null +++ b/pages/en/test.js @@ -0,0 +1,11 @@ +import VideoPlayer from "../../components/videoPlayer"; + +export default function Test() { + return ( +
+
+ +
+
+ ); +} -- cgit v1.2.3