aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorFactiven <[email protected]>2023-07-16 22:35:39 +0700
committerFactiven <[email protected]>2023-07-16 22:35:39 +0700
commit1eee181e219dfd993d396ac3169e7aad3dd285eb (patch)
tree23fe54e9c3f8810f3ac9ab6b29070b4f0d4b9d20 /lib
parentremoved console.log (diff)
downloadmoopa-1eee181e219dfd993d396ac3169e7aad3dd285eb.tar.xz
moopa-1eee181e219dfd993d396ac3169e7aad3dd285eb.zip
Update v3.6.4
- Added Manga page with a working tracker for AniList user - Added schedule component to home page - Added disqus comment section so you can fight on each other (not recommended) - Added /id and /en route for english and indonesian subs (id route still work in progress)
Diffstat (limited to 'lib')
-rw-r--r--lib/anilist/AniList.js (renamed from lib/AniList.js)0
-rw-r--r--lib/anilist/aniAdvanceSearch.js68
-rw-r--r--lib/anilist/getUpcomingAnime.js80
-rw-r--r--lib/anilist/useAnilist.js126
-rw-r--r--lib/apolloClient.js20
-rw-r--r--lib/useAnilist.js221
-rw-r--r--lib/useCountdownSeconds.js37
7 files changed, 311 insertions, 241 deletions
diff --git a/lib/AniList.js b/lib/anilist/AniList.js
index f602dad..f602dad 100644
--- a/lib/AniList.js
+++ b/lib/anilist/AniList.js
diff --git a/lib/anilist/aniAdvanceSearch.js b/lib/anilist/aniAdvanceSearch.js
new file mode 100644
index 0000000..bb22ead
--- /dev/null
+++ b/lib/anilist/aniAdvanceSearch.js
@@ -0,0 +1,68 @@
+const advance = `
+ query ($search: String, $type: MediaType, $status: MediaStatus, $season: MediaSeason, $seasonYear: Int, $genres: [String], $tags: [String], $sort: [MediaSort], $page: Int, $perPage: Int) {
+ Page (page: $page, perPage: $perPage) {
+ pageInfo {
+ total
+ currentPage
+ lastPage
+ hasNextPage
+ }
+ media (search: $search, type: $type, status: $status, season: $season, seasonYear: $seasonYear, genre_in: $genres, tag_in: $tags, sort: $sort, isAdult: false) {
+ id
+ title {
+ userPreferred
+ }
+ type
+ episodes
+ status
+ format
+ season
+ seasonYear
+ coverImage {
+ extraLarge
+ color
+ }
+ averageScore
+ isAdult
+ }
+ }
+ }
+`;
+
+export async function aniAdvanceSearch(options = {}) {
+ const {
+ search = null,
+ type = "ANIME",
+ seasonYear = NaN,
+ season = undefined,
+ genres = null,
+ page = 1,
+ perPage = null,
+ sort = "POPULARITY_DESC",
+ } = options;
+ // console.log(page);
+ const response = await fetch("https://graphql.anilist.co/", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ query: advance,
+ variables: {
+ search: search,
+ type: type,
+ seasonYear: seasonYear,
+ season: season,
+ genres: genres,
+ perPage: perPage,
+ sort: sort,
+ page: page,
+ },
+ }),
+ });
+
+ const datas = await response.json();
+ // console.log(datas);
+ const data = datas.data.Page;
+ return data;
+}
diff --git a/lib/anilist/getUpcomingAnime.js b/lib/anilist/getUpcomingAnime.js
new file mode 100644
index 0000000..fc848fd
--- /dev/null
+++ b/lib/anilist/getUpcomingAnime.js
@@ -0,0 +1,80 @@
+const getUpcomingAnime = async () => {
+ // Determine the current season and year
+ const currentDate = new Date();
+ const currentMonth = currentDate.getMonth();
+ let currentSeason, currentYear;
+
+ if (currentMonth < 3) {
+ currentSeason = "WINTER";
+ currentYear = currentDate.getFullYear();
+ } else if (currentMonth < 6) {
+ currentSeason = "SPRING";
+ currentYear = currentDate.getFullYear();
+ } else if (currentMonth < 9) {
+ currentSeason = "SUMMER";
+ currentYear = currentDate.getFullYear();
+ } else {
+ currentSeason = "FALL";
+ currentYear = currentDate.getFullYear();
+ }
+
+ const query = `
+ query ($season: MediaSeason, $seasonYear: Int) {
+ Page(page: 1, perPage: 20) {
+ media(season: $season, seasonYear: $seasonYear, sort: POPULARITY_DESC, type: ANIME) {
+ id
+ coverImage{
+ large
+ }
+ bannerImage
+ title {
+ english
+ romaji
+ native
+ }
+ nextAiringEpisode {
+ episode
+ airingAt
+ timeUntilAiring
+ }
+ }
+ }
+ }
+ `;
+
+ const variables = {
+ season: currentSeason,
+ seasonYear: currentYear,
+ };
+
+ let response = await fetch("https://graphql.anilist.co", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Accept: "application/json",
+ },
+ body: JSON.stringify({
+ query,
+ variables: variables ? variables : undefined,
+ }),
+ });
+
+ let json = await response.json();
+
+ let currentSeasonAnime = json.data.Page.media;
+ let nextAiringAnime = currentSeasonAnime.filter(
+ (anime) =>
+ anime.nextAiringEpisode !== null && anime.nextAiringEpisode.episode === 1
+ );
+
+ if (nextAiringAnime.length >= 1) {
+ nextAiringAnime.sort(
+ (a, b) => a.nextAiringEpisode.airingAt - b.nextAiringEpisode.airingAt
+ );
+ return nextAiringAnime; // return all upcoming anime, not just the first two
+ }
+
+ return null;
+};
+
+export default getUpcomingAnime;
diff --git a/lib/anilist/useAnilist.js b/lib/anilist/useAnilist.js
new file mode 100644
index 0000000..4ec55a9
--- /dev/null
+++ b/lib/anilist/useAnilist.js
@@ -0,0 +1,126 @@
+import { useState, useEffect } from "react";
+import { toast } from "react-toastify";
+
+function useMedia(username, accessToken, status) {
+ const [media, setMedia] = useState([]);
+
+ const fetchGraphQL = async (query, variables) => {
+ const response = await fetch("https://graphql.anilist.co/", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({ query, variables }),
+ });
+ return response.json();
+ };
+
+ useEffect(() => {
+ if (!username || !accessToken) return;
+ const queryMedia = `
+ query ($username: String, $status: MediaListStatus) {
+ MediaListCollection(userName: $username, type: ANIME, status: $status) {
+ lists {
+ status
+ name
+ entries {
+ id
+ mediaId
+ status
+ progress
+ score
+ media {
+ id
+ status
+ nextAiringEpisode {
+ timeUntilAiring
+ episode
+ }
+ title {
+ english
+ romaji
+ }
+ episodes
+ coverImage {
+ large
+ }
+ }
+ }
+ }
+ }
+ }
+ `;
+ fetchGraphQL(queryMedia, { username, status: status?.stats }).then((data) =>
+ setMedia(data.data.MediaListCollection.lists)
+ );
+ }, [username, accessToken, status?.stats]);
+
+ return media;
+}
+
+export function useAniList(session, stats) {
+ const accessToken = session?.user?.token;
+ const username = session?.user?.name;
+ const status = stats || null;
+ const media = useMedia(username, accessToken, status);
+
+ const fetchGraphQL = async (query, variables) => {
+ const response = await fetch("https://graphql.anilist.co/", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: accessToken ? `Bearer ${accessToken}` : undefined,
+ },
+ body: JSON.stringify({ query, variables }),
+ });
+ return response.json();
+ };
+
+ const markComplete = (mediaId) => {
+ if (!accessToken) return;
+ const completeQuery = `
+ mutation($mediaId: Int ) {
+ SaveMediaListEntry(mediaId: $mediaId, status: COMPLETED) {
+ id
+ mediaId
+ status
+ }
+ }
+ `;
+ fetchGraphQL(completeQuery, { mediaId }).then((data) =>
+ console.log({ Complete: data })
+ );
+ };
+
+ const markProgress = (mediaId, progress, stats, volumeProgress) => {
+ if (!accessToken) return;
+ const progressWatched = `
+ mutation($mediaId: Int, $progress: Int, $status: MediaListStatus, $progressVolumes: Int) {
+ SaveMediaListEntry(mediaId: $mediaId, progress: $progress, status: $status, progressVolumes: $progressVolumes) {
+ id
+ mediaId
+ progress
+ status
+ }
+ }
+ `;
+ fetchGraphQL(progressWatched, {
+ mediaId,
+ progress,
+ status: stats,
+ progressVolumes: volumeProgress,
+ }).then(() => {
+ console.log(`Progress Updated: ${progress}`);
+ toast.success(`Progress Updated: ${progress}`, {
+ position: "bottom-right",
+ autoClose: 5000,
+ hideProgressBar: false,
+ closeOnClick: true,
+ draggable: true,
+ theme: "dark",
+ });
+ });
+ };
+
+ return { media, markComplete, markProgress };
+}
diff --git a/lib/apolloClient.js b/lib/apolloClient.js
deleted file mode 100644
index 8a25156..0000000
--- a/lib/apolloClient.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import { ApolloClient, DefaultOptions, InMemoryCache } from "@apollo/client";
-
-const defaultOptions = {
- watchQuery: {
- fetchPolicy: "no-cache",
- errorPolicy: "ignore",
- },
- query: {
- fetchPolicy: "no-cache",
- errorPolicy: "all",
- },
-};
-
-const client = new ApolloClient({
- uri: "https://graphql.anilist.co",
- cache: new InMemoryCache(),
- defaultOptions: defaultOptions,
-});
-
-export { client };
diff --git a/lib/useAnilist.js b/lib/useAnilist.js
deleted file mode 100644
index fc25902..0000000
--- a/lib/useAnilist.js
+++ /dev/null
@@ -1,221 +0,0 @@
-import { useState, useEffect } from "react";
-
-export function useAniList(session, stats) {
- const [media, setMedia] = useState([]);
- // const [aniAdvanceSearch, setAniAdvanceSearch] = useState([]);
-
- // Queries
-
- const queryMedia = `
- query ($username: String, $status: MediaListStatus) {
- MediaListCollection(userName: $username, type: ANIME, status: $status) {
- lists {
- status
- name
- entries {
- id
- mediaId
- status
- progress
- score
- media {
- id
- nextAiringEpisode {
- timeUntilAiring
- episode
- }
- title {
- english
- romaji
- }
- episodes
- coverImage {
- large
- }
- }
- }
- }
- }
- }
- `;
-
- const advance = `
- query ($search: String, $type: MediaType, $status: MediaStatus, $season: MediaSeason, $seasonYear: Int, $genres: [String], $tags: [String], $sort: [MediaSort], $page: Int, $perPage: Int) {
- Page (page: $page, perPage: $perPage) {
- pageInfo {
- total
- currentPage
- lastPage
- hasNextPage
- }
- media (search: $search, type: $type, status: $status, season: $season, seasonYear: $seasonYear, genre_in: $genres, tag_in: $tags, sort: $sort, isAdult: false) {
- id
- title {
- userPreferred
- }
- type
- episodes
- status
- format
- season
- seasonYear
- coverImage {
- extraLarge
- color
- }
- averageScore
- isAdult
- }
- }
- }
- `;
-
- // Mutations
-
- const completeQuery = `
- mutation($mediaId: Int ) {
- SaveMediaListEntry(mediaId: $mediaId, status: COMPLETED) {
- id
- mediaId
- status
- }
- }
- `;
-
- const progressWatched = `
- mutation($mediaId: Int, $progress: Int, $status: MediaListStatus) {
- SaveMediaListEntry(mediaId: $mediaId, progress: $progress, status: $status) {
- id
- mediaId
- progress
- status
- }
- }
- `;
-
- const username = session?.user?.name;
- const accessToken = session?.user?.token;
- let statuss = stats || null;
- // console.log(session);
-
- useEffect(() => {
- async function fetchData() {
- if (!username || !accessToken) return;
-
- const response = await fetch("https://graphql.anilist.co/", {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- query: queryMedia,
- variables: {
- username: username,
- status: statuss?.stats,
- },
- }),
- });
-
- const data = await response.json();
- setMedia(data.data.MediaListCollection.lists);
- }
-
- fetchData();
- }, [queryMedia, username, accessToken, statuss?.stats]);
-
- async function markComplete(mediaId) {
- if (!accessToken) return;
- const response = await fetch("https://graphql.anilist.co/", {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${accessToken}`,
- },
- body: JSON.stringify({
- query: completeQuery,
- variables: {
- mediaId: mediaId,
- },
- }),
- });
- if (response.ok) {
- const data = await response.json();
- console.log({ Complete: data });
- } else if (response.status === 401) {
- console.log("Unauthorized");
- } else if (response.status === 400) {
- console.log("validation error");
- }
- }
-
- async function markProgress(mediaId, progress, stats) {
- if (!accessToken) return;
- const response = await fetch("https://graphql.anilist.co/", {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${accessToken}`,
- },
- body: JSON.stringify({
- query: progressWatched,
- variables: {
- mediaId: mediaId,
- progress: progress,
- status: stats,
- },
- }),
- });
- if (response.ok) {
- console.log(`Progress Updated: ${progress}`);
- } else if (response.status === 401) {
- console.log("Unauthorized");
- } else if (response.status === 400) {
- console.log("validation error");
- }
- }
-
- async function aniAdvanceSearch(options = {}) {
- const {
- search = null,
- type = "ANIME",
- seasonYear = NaN,
- season = undefined,
- genres = null,
- page = 1,
- perPage = null,
- sort = "POPULARITY_DESC",
- } = options;
- // console.log(page);
- const response = await fetch("https://graphql.anilist.co/", {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- query: advance,
- variables: {
- search: search,
- type: type,
- seasonYear: seasonYear,
- season: season,
- genres: genres,
- perPage: perPage,
- sort: sort,
- page: page,
- },
- }),
- });
-
- const datas = await response.json();
- // console.log(datas);
- const data = datas.data.Page;
- return data;
- }
-
- return {
- media,
- markComplete,
- aniAdvanceSearch,
- markProgress,
- };
-}
diff --git a/lib/useCountdownSeconds.js b/lib/useCountdownSeconds.js
new file mode 100644
index 0000000..df3cb63
--- /dev/null
+++ b/lib/useCountdownSeconds.js
@@ -0,0 +1,37 @@
+import { useEffect, useState } from "react";
+
+const useCountdown = (targetDate, update) => {
+ const countDownDate = new Date(targetDate).getTime();
+
+ const [countDown, setCountDown] = useState(
+ countDownDate - new Date().getTime()
+ );
+
+ useEffect(() => {
+ const interval = setInterval(() => {
+ const newCountDown = countDownDate - new Date().getTime();
+ setCountDown(newCountDown);
+ if (newCountDown <= 0 && newCountDown > -1000) {
+ update();
+ }
+ }, 1000);
+
+ return () => clearInterval(interval);
+ }, [countDownDate, update]);
+
+ return getReturnValues(countDown);
+};
+
+const getReturnValues = (countDown) => {
+ // calculate time left
+ const days = Math.floor(countDown / (1000 * 60 * 60 * 24));
+ const hours = Math.floor(
+ (countDown % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
+ );
+ const minutes = Math.floor((countDown % (1000 * 60 * 60)) / (1000 * 60));
+ const seconds = Math.floor((countDown % (1000 * 60)) / 1000);
+
+ return [days, hours, minutes, seconds];
+};
+
+export { useCountdown };