diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..bffb357 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "next/core-web-vitals" +} diff --git a/src/components/EpisodePlayer.js b/src/components/EpisodePlayer.js index 73e8e82..9ae03f2 100644 --- a/src/components/EpisodePlayer.js +++ b/src/components/EpisodePlayer.js @@ -1,22 +1,26 @@ -import React, { useMemo, useState } from 'react'; +import React, { useMemo, useState, useEffect } from 'react'; import dynamic from 'next/dynamic'; import CustomDropdown from '@/components/CustomDropdown'; const ReactPlayer = dynamic(() => import('react-player'), { ssr: false }); -const EpisodePlayer = ({ episode, selectedQuality, setSelectedQuality, setSelectedServer, selectedServer }) => { +const EpisodePlayer = ({ episode, selectedQuality, setSelectedQuality }) => { const [loading, setLoading] = useState(true); const sources = episode?.sources ?? []; const sourceUrl = useMemo(() => { const source = sources.find(source => source.quality === selectedQuality); - return source ? source.source : sources[0]?.source; + return source ? source.url : sources[0]?.url; }, [sources, selectedQuality]); const handleReady = () => { setLoading(false); }; + useEffect(() => { + setLoading(true); + }, [sourceUrl]); + return (

Episode {episode ? episode.episodeNumber : '1'}

@@ -34,29 +38,10 @@ const EpisodePlayer = ({ episode, selectedQuality, setSelectedQuality, setSelect height="100%" className="react-player" onReady={handleReady} - onStart={() => setLoading(true)} /> )}
-

Select Server:

-
-
-

If one server isn't working, Try the next

-
-
- - source.quality)} diff --git a/src/pages/anime/[name].js b/src/pages/anime/[name].js index 63cf82a..4974f45 100644 --- a/src/pages/anime/[name].js +++ b/src/pages/anime/[name].js @@ -1,6 +1,5 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import { useRouter } from 'next/router'; -import useSWR from 'swr'; import axios from 'axios'; import Image from 'next/image'; import Head from 'next/head'; @@ -9,107 +8,68 @@ import { useSession } from 'next-auth/react'; import Comments from '@/components/Comments'; import CommentForm from '@/components/CommentForm'; -const api = "/api"; // Use the relative path for Next.js API -const fetcher = url => axios.get(url).then(res => res.data); +const apiBaseUrl = "https://api-anime.sziwyz.easypanel.host/anime/gogoanime"; // Use the new API base URL const AnimePage = () => { const router = useRouter(); const { name, ep } = router.query; // Extract the 'ep' parameter from the query - const { data: animeData, error } = useSWR(name ? `${api}/anime/${name}` : null, fetcher); - const { data: session, status } = useSession(); // Fetch the session - const [currentPage, setCurrentPage] = useState(1); + const { data: session, status: sessionStatus } = useSession(); // Rename session status to sessionStatus + const [animeData, setAnimeData] = useState(null); + const [error, setError] = useState(null); const [selectedEpisode, setSelectedEpisode] = useState(null); const [episodeSources, setEpisodeSources] = useState({}); const [selectedQuality, setSelectedQuality] = useState('1080p'); - const [selectedServer, setSelectedServer] = useState('gogocdn'); useEffect(() => { - if (name) { - const episodeToPlay = ep ? parseInt(ep, 10) : 1; // Use 'ep' parameter or default to 1 - if (episodeToPlay === 0) { - playByAnimeName(name); // Play the anime by its name if episode is 0 - } else { - fetchEpisodeDetails(episodeToPlay); - } - } - }, [name, ep, selectedServer]); - - const fetchEpisodeDetails = async (episodeNumber) => { - const episodeId = `${name}-episode-${episodeNumber}`; - setSelectedEpisode({ episodeNumber, episodeId, sources: null }); - - if (!episodeSources[episodeId] || episodeSources[episodeId].server !== selectedServer) { // Check for server + const fetchAnimeData = async () => { try { - const response = await axios.get(`${api}/watch/${episodeId}?server=${selectedServer}`); // Include server in API request - const sources = response.data; - setEpisodeSources(prevState => ({ ...prevState, [episodeId]: { sources, server: selectedServer } })); // Store server with sources - const defaultQuality = sources.find(source => source.quality === '1080p') ? '1080p' : sources[0].quality; - setSelectedQuality(defaultQuality); - setSelectedEpisode(prevState => ({ ...prevState, sources })); - let AnimeName = episodeId.split('-episode-')[0]; - AnimeName = AnimeName.replace(/-/g, ' ').toUpperCase(); - addHistory(AnimeName, episodeId, episodeNumber); + const response = await axios.get(`${apiBaseUrl}/info/${name}`); + setAnimeData(response.data); } catch (error) { - console.error('Error fetching episode sources:', error); - } - } else { - setSelectedEpisode(prevState => ({ ...prevState, sources: episodeSources[episodeId].sources })); - if (!episodeSources[episodeId].sources.some(source => source.quality === selectedQuality)) { - setSelectedQuality(episodeSources[episodeId].sources[0].quality); + setError(error); } + }; + + if (name) { + fetchAnimeData(); } - }; + }, [name]); - const playByAnimeName = async (animeName) => { + const fetchEpisodeDetails = useCallback(async (episodeNumber) => { + const episodeId = episodeNumber === 0 ? name : `${name}-episode-${episodeNumber}`; try { - const response = await axios.get(`${api}/watch/${animeName}`); - const sources = response.data; - setEpisodeSources(prevState => ({ ...prevState, [animeName]: { sources, server: selectedServer } })); + const response = await axios.get(`${apiBaseUrl}/watch/${episodeId}`); + const sources = response.data.sources; + setEpisodeSources(prevState => ({ ...prevState, [episodeId]: { sources } })); const defaultQuality = sources.find(source => source.quality === '1080p') ? '1080p' : sources[0].quality; setSelectedQuality(defaultQuality); - setSelectedEpisode({ episodeNumber: 0, episodeId: animeName, sources }); - addHistory(animeName, animeName, 0); + setSelectedEpisode({ episodeNumber, episodeId, sources }); } catch (error) { - console.error('Error fetching anime sources:', error); + console.error('Error fetching episode sources:', error); } - }; + }, [name]); - const addHistory = async (name, animeId, episodeNumber) => { - try { - const response = await axios.post(`${api}/history/add`, { - name, - animeId, - episodeNumber - }, { - headers: { - 'Authorization': `Bearer ${localStorage.getItem('token')}` // Ensure the token is correctly set - } - }); - console.log('History added:', response.data.message); - } catch (error) { - console.error('Error adding history:', error.response?.data?.error || error.message); - } - }; - - const handleEpisodeSelect = episodeNumber => { - const episodeNum = parseInt(episodeNumber, 10); // Convert to number - if (episodeNum === 0) { - router.push({ - pathname: `/anime/${name}` - }, undefined, { shallow: true }); - playByAnimeName(name); - } else { + const playFirstEpisode = useCallback(() => { + if (animeData && animeData.episodes.length > 0) { + const firstEpisode = animeData.episodes[0]; + fetchEpisodeDetails(firstEpisode.number); router.push({ pathname: `/anime/${name}`, - query: { ep: episodeNum } + query: { ep: firstEpisode.number } }, undefined, { shallow: true }); - fetchEpisodeDetails(episodeNum); } - }; + }, [animeData, name, router, fetchEpisodeDetails]); - const handlePageChange = (direction) => { - setCurrentPage(prev => prev + direction); - }; + useEffect(() => { + if (name && !selectedEpisode) { + const episodeToPlay = ep ? parseInt(ep, 10) : 1; // Use 'ep' parameter or default to 1 + if (episodeToPlay === 0) { + playFirstEpisode(); // Play the first episode in the list if episode is 0 + } else { + fetchEpisodeDetails(episodeToPlay); + } + } + }, [name, ep, selectedEpisode, playFirstEpisode, fetchEpisodeDetails]); if (!animeData && !error) { return
Loading...
; @@ -118,30 +78,53 @@ const AnimePage = () => { return
Failed to load anime data
; } - const { animeInfo, episodes } = animeData; - const episodesPerPage = 13; - const totalPages = Math.ceil(episodes.length / episodesPerPage); - const currentEpisodes = episodes.slice((currentPage - 1) * episodesPerPage, currentPage * episodesPerPage); + const { title, description, status, genres, releaseDate, totalEpisodes, image, episodes } = animeData; + + const handleEpisodeSelect = (episodeNumber) => { + const episodeNum = parseInt(episodeNumber, 10); // Convert to number + fetchEpisodeDetails(episodeNum); + router.push({ + pathname: `/anime/${name}`, + query: { ep: episodeNum } + }, undefined, { shallow: true }); + }; - const episodeButtons = currentEpisodes.map(episode => ( -
  • + const episodeButtons = episodes.map(episode => ( +
  • )); + const addHistory = async (name, animeId, episodeNumber) => { + try { + const response = await axios.post(`${apiBaseUrl}/history/add`, { + name, + animeId, + episodeNumber + }, { + headers: { + 'Authorization': `Bearer ${localStorage.getItem('token')}` // Ensure the token is correctly set + } + }); + console.log('History added:', response.data.message); + } catch (error) { + console.error('Error adding history:', error.response?.data?.error || error.message); + } + }; + return ( <> - {animeInfo.title} - - - - + {title} + + + +
    @@ -154,9 +137,9 @@ const AnimePage = () => { className="w-full bg-gray-700 text-yellow-500 p-2 rounded" onChange={(e) => handleEpisodeSelect(parseInt(e.target.value, 10))} > - {currentEpisodes.map(episode => ( - ))} @@ -165,16 +148,6 @@ const AnimePage = () => { {episodeButtons}
    - {episodes.length > episodesPerPage && ( -
    - - -
    - )}
    @@ -182,14 +155,20 @@ const AnimePage = () => { episode={selectedEpisode} selectedQuality={selectedQuality} setSelectedQuality={setSelectedQuality} - setSelectedServer={setSelectedServer} - selectedServer={selectedServer} />

    - + - {status === 'authenticated' && } + {sessionStatus === 'authenticated' && }
    @@ -198,16 +177,16 @@ const AnimePage = () => { ); }; -const AnimeDetails = ({ animeInfo }) => ( +const AnimeDetails = ({ title, description, status, genres, releaseDate, totalEpisodes, image }) => (
    - +
    -

    {animeInfo.title}

    -

    Description: {animeInfo.description}

    -

    Status: {animeInfo.status}

    -

    Genres: {animeInfo.genres.join(', ')}

    -

    Released: {animeInfo.released}

    -

    Total Episodes: {animeInfo.totalEpisodes}

    +

    {title}

    +

    Description: {description}

    +

    Status: {status}

    +

    Genres: {genres.join(', ')}

    +

    Released: {releaseDate}

    +

    Total Episodes: {totalEpisodes}

    ); diff --git a/src/pages/auth/profile.js b/src/pages/auth/profile.js index a814c9b..eb035e8 100644 --- a/src/pages/auth/profile.js +++ b/src/pages/auth/profile.js @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react'; import { useSession, signOut } from 'next-auth/react'; import axios from 'axios'; import Link from 'next/link'; -import History from '@/components/History'; +import Image from 'next/image'; const Dashboard = () => { const { data: session, status } = useSession(); @@ -118,7 +118,7 @@ const Dashboard = () => { {activeTab === 'profile' && (
    - {session.user.name} + {session.user.name}

    Name: {session.user.name}

    Email: {session.user.email}

    ID: {session.user.id}

    @@ -168,7 +168,7 @@ const Dashboard = () => { comments.map((comment) => (
    - {comment.user.name} + {comment.user.name} {comment.user.name} | {comment.animeId}-episode-{comment.episodeNumber}

    {comment.text}

    diff --git a/src/pages/search.js b/src/pages/search.js index 1981bc9..9f98bb6 100644 --- a/src/pages/search.js +++ b/src/pages/search.js @@ -54,7 +54,7 @@ const SearchResults = () => {
    -

    Search Results for "{query}"

    +

    Search Results for "{query}"

    {results.length > 0 ? ( @@ -75,7 +75,7 @@ const SearchResults = () => { )) ) : ( -

    No results found for "{query}".

    +

    No results found for "{query}".

    )}