From 20b8a7267827e3a07c1eef668c3b9c22fda43765 Mon Sep 17 00:00:00 2001 From: Factiven Date: Tue, 26 Sep 2023 23:35:35 +0700 Subject: Update v4.1.2 --- README.md | 4 +- components/admin/dashboard/index.js | 134 +++++++++++++ components/admin/layout.js | 75 ++++++++ components/admin/meta/AppendMeta.js | 252 +++++++++++++++++++++++++ components/anime/episode.js | 30 +-- components/anime/mobile/reused/description.js | 2 +- components/anime/viewMode/thumbnailDetail.js | 4 +- components/anime/viewMode/thumbnailOnly.js | 2 +- components/anime/viewSelector.js | 4 + components/home/schedule.js | 2 +- components/searchPalette.js | 2 +- components/shared/NavBar.js | 2 +- components/watch/player/artplayer.js | 43 ++++- components/watch/player/playerComponent.js | 5 +- components/watch/secondary/episodeLists.js | 7 +- lib/context/isOpenState.js | 17 ++ lib/context/watchPageProvider.js | 41 ++++ lib/hooks/isOpenState.js | 17 -- lib/hooks/watchPageProvider.js | 41 ---- package-lock.json | 45 ++--- package.json | 7 +- pages/_app.js | 4 +- pages/admin/index.js | 261 +++++--------------------- pages/api/v2/admin/meta/index.js | 6 - pages/en/anime/[...id].js | 4 +- pages/en/anime/watch/[...info].js | 38 +++- release.md | 7 +- utils/getRedisWithPrefix.js | 71 +++++++ 28 files changed, 774 insertions(+), 353 deletions(-) create mode 100644 components/admin/dashboard/index.js create mode 100644 components/admin/layout.js create mode 100644 components/admin/meta/AppendMeta.js create mode 100644 lib/context/isOpenState.js create mode 100644 lib/context/watchPageProvider.js delete mode 100644 lib/hooks/isOpenState.js delete mode 100644 lib/hooks/watchPageProvider.js create mode 100644 utils/getRedisWithPrefix.js diff --git a/README.md b/README.md index 17dda87..6d3abd6 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ ## Introduction -

Moopa is an anime streaming website made possible by Consumet API build with NextJs and Tailwind with a sleek and modern design that offers Anilist integration to help you keep track of your favorite anime series. Moopa is entirely free and does not feature any ads, making it a great option for you who want an uninterrupted viewing experience.

+

Moopa is an anime streaming website made possible by the Consumet API, built with Next.js and Tailwind, featuring a sleek and modern design. It offers Anilist integration to help you keep track of your favorite anime series. Moopa is entirely free and does not display any ads, making it a great option for those who want an uninterrupted viewing experience.

## Features @@ -80,7 +80,7 @@ If you encounter any issues or bug on the site please head to [issues](https://g ## For Local Development -> If you host this site for personal use, please refrain from cloning it or adding ads. This project is non-profit and ads may violate its terms, leading to legal action or site takedown. Uphold these guidelines to maintain its integrity and mission. +> If you want to self-host this app, please note that it is only allowed for personal use. Commercial use is not permitted, and including ads on your self-hosted site may result in actions such as site takedown. 1. Clone this repository using : diff --git a/components/admin/dashboard/index.js b/components/admin/dashboard/index.js new file mode 100644 index 0000000..64a1d6f --- /dev/null +++ b/components/admin/dashboard/index.js @@ -0,0 +1,134 @@ +import React, { useState } from "react"; + +export default function AdminDashboard({ + animeCount, + infoCount, + metaCount, + report, +}) { + const [message, setMessage] = useState(""); + const [selectedTime, setSelectedTime] = useState(""); + const [unixTimestamp, setUnixTimestamp] = useState(null); + + const handleSubmit = (e) => { + e.preventDefault(); + + if (selectedTime) { + const unixTime = Math.floor(new Date(selectedTime).getTime() / 1000); + setUnixTimestamp(unixTime); + } + }; + return ( +
+
+

Stats

+
+
+

{animeCount}

+

Anime

+
+
+

{infoCount}

+

detail info

+
+
+

{metaCount}

+

Metadata

+
+
+
+
+
+

Broadcast

+
+
+
+ + setMessage(e.target.value)} + required + className="w-full px-3 py-2 border rounded-md focus:outline-none text-black" + /> +
+
+ + setSelectedTime(e.target.value)} + required + className="w-full px-3 py-2 border rounded-md focus:outline-none text-black" + /> +
+ +
+ {unixTimestamp && ( +

+ Unix Timestamp: {unixTimestamp} +

+ )} +
+
+
+

Recent Reports

+
+
+ {report?.map((i, index) => ( +
+ {i.desc}{" "} + {i.severity === "Low" && ( + + {/* */} + + + )} + {i.severity === "Medium" && ( + + {/* */} + + + )} + {i.severity === "High" && ( + + {/* */} + + + )} + {i.severity === "Critical" && ( + + + + + )} +
+ ))} +
+
+
+
+
a
+
+ ); +} diff --git a/components/admin/layout.js b/components/admin/layout.js new file mode 100644 index 0000000..3209dcf --- /dev/null +++ b/components/admin/layout.js @@ -0,0 +1,75 @@ +import { + CloudArrowUpIcon, + Cog6ToothIcon, + HomeIcon, + UserIcon, +} from "@heroicons/react/24/outline"; +import Link from "next/link"; +import { useRouter } from "next/router"; +import React from "react"; + +const Navigation = [ + { + name: "Dashboard", + page: 1, + icon: , + current: false, + }, + { + name: "Metadata", + page: 2, + icon: , + current: false, + }, + { + name: "Users", + page: 3, + icon: , + current: false, + }, + { + name: "Settings", + page: 4, + icon: , + current: false, + }, +]; + +export default function AdminLayout({ children, page, setPage }) { + return ( +
+
+
+

moopa

+

+ Admin
+ Dashboard +

+
+
+ {Navigation.map((item, index) => ( + + ))} +
+
+
{children}
+
+ ); +} diff --git a/components/admin/meta/AppendMeta.js b/components/admin/meta/AppendMeta.js new file mode 100644 index 0000000..1707ed2 --- /dev/null +++ b/components/admin/meta/AppendMeta.js @@ -0,0 +1,252 @@ +import Loading from "@/components/shared/loading"; +import Image from "next/image"; +import { useState } from "react"; +import { toast } from "react-toastify"; + +// Define a function to convert the data +function convertData(episodes) { + const convertedData = episodes.map((episode) => ({ + episode: episode.episode, + title: episode?.title, + description: episode?.description || null, + img: episode?.img?.hd || episode?.img?.mobile || null, // Use hd if available, otherwise use mobile + })); + + return convertedData; +} + +export default function AppendMeta({ api }) { + const [id, setId] = useState(); + const [resultData, setResultData] = useState(null); + + const [query, setQuery] = useState(""); + const [tmdbId, setTmdbId] = useState(); + const [hasilQuery, setHasilQuery] = useState([]); + const [season, setSeason] = useState(); + + const [override, setOverride] = useState(); + + const [loading, setLoading] = useState(false); + + const handleSearch = async () => { + try { + setLoading(true); + setResultData(null); + const res = await fetch(`${api}/meta/tmdb/${query}`); + const json = await res.json(); + const data = json.results.filter((i) => i.type === "TV Series"); + setHasilQuery(data); + setLoading(false); + } catch (err) { + console.log(err); + } + }; + + const handleDetail = async () => { + try { + setLoading(true); + const res = await fetch(`${api}/meta/tmdb/info/${tmdbId}?type=TV%20Series +`); + const json = await res.json(); + const data = json.seasons; + setHasilQuery(data); + setLoading(false); + } catch (err) { + console.log(err); + } + }; + + const handleStore = async () => { + try { + setLoading(true); + if (!resultData && !id) { + console.log("No data to store"); + setLoading(false); + return; + } + const data = await fetch("/api/v2/admin/meta", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + id: id, + data: resultData, + }), + }); + if (data.status === 200) { + const json = await data.json(); + toast.success(json.message); + setLoading(false); + } + } catch (err) { + console.log(err); + } + }; + + const handleOverride = async () => { + setResultData(JSON.parse(override)); + }; + + return ( + <> +
+

Append Data Page

+
+
+ + setQuery(e.target.value)} + /> + +
+
+ + setTmdbId(e.target.value)} + /> + +
+ +
+ +