Skip to content

Commit

Permalink
add batch, fix favicon, redesign some section
Browse files Browse the repository at this point in the history
  • Loading branch information
Fauzanmhr committed Oct 24, 2024
1 parent 065c8ca commit c8835d2
Show file tree
Hide file tree
Showing 6 changed files with 226 additions and 63 deletions.
18 changes: 16 additions & 2 deletions controllers/animeController.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { fetchOngoingAnime, fetchAnimeDetails } from '../services/animeService.js';
import { fetchOngoingAnime, fetchAnimeDetails, fetchBatchDetails } from '../services/animeService.js';

export const getOngoingAnime = async (req, res) => {
const page = req.query.page || 1;
Expand All @@ -15,6 +15,20 @@ export const getAnimeDetails = async (req, res) => {
}
};


export const GetBatchDetails = async (req, res) => {
const slug = req.params.slug;
if (!slug) return res.redirect('/');

const batch = await fetchBatchDetails(slug);
if (batch) {
res.json(batch); // Return the entire batch details
} else {
res.status(500).send('Error fetching batch details');
}
};


export const searchAnime = (req, res) => {
const { q: query, page = 1, limit = 20 } = req.query;
if (!query) return res.json({ results: [] });
Expand Down Expand Up @@ -66,4 +80,4 @@ export const renderAllAnimePage = (req, res) => {
};

res.render('all-anime', { animes: paginatedAnimes, pagination });
};
};
3 changes: 2 additions & 1 deletion routes/animeRoutes.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import express from 'express';
import { getOngoingAnime, getAnimeDetails, searchAnime, getAllAnimeAjax, renderAllAnimePage } from '../controllers/animeController.js';
import { getOngoingAnime, getAnimeDetails, searchAnime, getAllAnimeAjax, renderAllAnimePage, GetBatchDetails} from '../controllers/animeController.js';

const router = express.Router();

router.get('/', getOngoingAnime);
router.get('/anime/:slug', getAnimeDetails);
router.get('/batch/:slug', GetBatchDetails);
router.get('/search-ajax', searchAnime);
router.get('/all-anime-ajax', getAllAnimeAjax);
router.get('/all-anime', renderAllAnimePage);
Expand Down
25 changes: 23 additions & 2 deletions services/animeService.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import ky from 'ky';

// Function to fetch all anime data
export const fetchAllAnimeData = async () => {
try {
const response = await ky.get(`${process.env.API_URL}/otakudesu/anime`).json();
Expand All @@ -10,6 +11,7 @@ export const fetchAllAnimeData = async () => {
}
};

// Function to fetch ongoing anime
export const fetchOngoingAnime = async (page) => {
try {
return await ky.get(`${process.env.API_URL}/otakudesu/ongoing?page=${page}`).json();
Expand All @@ -19,12 +21,31 @@ export const fetchOngoingAnime = async (page) => {
}
};

// Function to fetch details of a specific anime by slug
export const fetchAnimeDetails = async (slug) => {
try {
const response = await ky.get(`${process.env.API_URL}/otakudesu/anime/${slug}`).json();
return response.data;
const anime = response.data;

// Ensure that batchId (or batch data) is included if batch data exists
if (anime.batch) {
anime.batchId = anime.batch.batchId;
}

return anime;
} catch (error) {
console.error('Error fetching anime details:', error);
return null;
}
};
};

// Function to fetch batch details by slug
export const fetchBatchDetails = async (slug) => {
try {
const response = await ky.get(`${process.env.API_URL}/otakudesu/batch/${slug}`).json();
return response.data;
} catch (error) {
console.error('Error fetching batch details:', error);
return null;
}
};
146 changes: 123 additions & 23 deletions views/detail.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -46,36 +46,136 @@
</div>
</div>

<!-- Episodes Section -->
<div class="mt-4">
<h2>Watch Now</h2>
<form action="/episode" method="get" class="mb-4">
<table class="table table-striped">
<thead>
<tr>
<th>Episode</th>
<!-- <th>Release Date</th> -->
<th>Action</th>
</tr>
</thead>
<tbody>
<!-- Redesigned Batch Information Section -->
<div class="my-4">
<h5 class="fw-bold">Download Batch</h5>
<div class="d-flex justify-content-between align-items-center border p-3 rounded bg-light">
<!-- Batch Title or Message -->
<% if (anime.batch) { %>
<span><%= anime.batch.title %></span>
<!-- Download Button with Icon -->
<button id="generateLinkBtn" class="btn btn-dark btn-sm" data-batch-id="<%= anime.batch.batchId %>">
<i class="bi bi-download me-1"></i>Generate Link
</button>
<% } else { %>
<!-- No Batch Available Message -->
<span class="text-muted">No batch available at the moment.</span>
<% } %>
</div>
<div id="downloadOptions" class="mt-3" style="display: none;">
<div class="table-responsive">
<table class="table table-bordered align-middle">
<thead class="table-dark">
<tr>
<th scope="col">Quality</th>
<th scope="col">Size</th>
<th scope="col">Download Links</th>
</tr>
</thead>
<tbody id="downloadLinksTableBody">
<!-- Download links will be populated here -->
</tbody>
</table>
</div>
</div>
</div>

<!-- Compact Episodes Section -->
<div class="my-4">
<h5 class="fw-bold">Watch Episodes</h5>
<div class="border p-3 rounded bg-light">
<% if (anime.episodeList.length > 0) { %>
<!-- Loop through each episode -->
<% anime.episodeList.forEach(episode => { %>
<tr>
<td><%= anime.title %> Episode <%= episode.title %></td>
<!-- <td><%= episode.aired %></td> -->
<td>
<a href="/episode/<%= episode.episodeId %>" class="btn btn-dark btn-sm">View</a>
</td>
</tr>
<div class="d-flex justify-content-between align-items-center mb-2">
<!-- Episode Title -->
<span>Episode <%= episode.title %>: <%= anime.title %></span>
<!-- View Button with Icon -->
<a href="/episode/<%= episode.episodeId %>" class="btn btn-dark btn-sm">
<i class="bi bi-play-fill me-1"></i>Watch
</a>
</div>
<% }) %>
</tbody>
</table>
</form>
<% } else { %>
<!-- No Episodes Available Message -->
<p class="text-muted mb-0">No episodes available.</p>
<% } %>
</div>
</div>

</div>

<%- include('partials/footer') %>
<!-- Bootstrap JS -->
<script src="/js/bootstrap.bundle.min.js"></script>
<script>
document.getElementById('generateLinkBtn').addEventListener('click', function() {
const batchId = this.getAttribute('data-batch-id');
fetch(`/batch/${batchId}`)
.then(response => response.json())
.then(data => {
if (data.downloadUrl && data.downloadUrl.formats) {
const formats = data.downloadUrl.formats;
const tableBody = document.getElementById('downloadLinksTableBody');
// Clear previous rows
tableBody.innerHTML = '';
// Populate the table with formats and qualities
formats.forEach(format => {
format.qualities.forEach(quality => {
const row = document.createElement('tr');
// Quality Badge
const qualityCell = document.createElement('td');
const qualityBadge = document.createElement('span');
qualityBadge.className = 'badge bg-dark fs-6';
qualityBadge.textContent = quality.title;
qualityCell.appendChild(qualityBadge);
row.appendChild(qualityCell);
// Size Badge
const sizeCell = document.createElement('td');
sizeCell.textContent = quality.size;
row.appendChild(sizeCell);
// Download Links as Buttons
const linksCell = document.createElement('td');
const linksDiv = document.createElement('div');
linksDiv.className = 'd-flex flex-wrap gap-2';
quality.urls.forEach(url => {
const linkButton = document.createElement('a');
linkButton.href = url.url;
linkButton.target = '_blank';
linkButton.className = 'btn btn-sm btn-outline-dark';
const icon = document.createElement('i');
icon.className = 'bi bi-download me-1';
linkButton.appendChild(icon);
linkButton.appendChild(document.createTextNode(url.title));
linksDiv.appendChild(linkButton);
});
linksCell.appendChild(linksDiv);
row.appendChild(linksCell);
tableBody.appendChild(row);
});
});
// Show the download options
document.getElementById('downloadOptions').style.display = 'block';
} else {
alert('Download options not available.');
}
})
.catch(error => {
console.error('Error fetching download options:', error);
alert('Error fetching download options.');
});
});
</script>
</body>
</html>
87 changes: 57 additions & 30 deletions views/episode.ejs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
<%- include('partials/header', { title: episode.title + ' - ZANNIME' }) %>
<div class="container">
<h1 class="mt-4"><%= episode.title %></h1>

<div class="container my-5">
<!-- Episode Title -->
<h1 class="display-5 mb-4"><%= episode.title %></h1>

<!-- Streaming Player Section -->
<div class="row">
<div class="col-md-12">
<div id="iframe-container" class="ratio ratio-16x9 mb-4 position-relative">
<!-- Loading Spinner -->
<!-- Original Loading Spinner -->
<div id="loading-spinner" class="d-flex justify-content-center align-items-center position-absolute top-0 bottom-0 start-0 end-0 bg-light">
<div class="spinner-border text-black" role="status">
<span class="visually-hidden">Loading...</span>
Expand All @@ -13,57 +17,80 @@
<!-- Streaming Iframe -->
<iframe id="streaming-iframe" class="d-none" src="<%= episode.defaultStreamingUrl %>" title="Streaming Player" allowfullscreen></iframe>
</div>

<!-- Streaming Sources Dropdown -->
<div class="mb-4">
<label for="streaming-source" class="form-label">Choose Streaming Source:</label>
<select id="streaming-source" class="form-select">
<option value="default">Default Source</option>
<% episode.server.qualities.forEach(quality => { %>
<% quality.serverList.forEach(server => { %>
<option value="<%= server.serverId %>"><%= server.title %> <%= quality.title %></option>
<option value="<%= server.serverId %>"><%= server.title %> - <%= quality.title %></option>
<% }) %>
<% }) %>
</select>
</div>

<!-- Episode Navigation -->
<div class="d-flex justify-content-between mb-4">
<% if (episode.prevEpisode) { %>
<a href="/episode/<%= episode.prevEpisode.episodeId %>" class="btn btn-dark">Previous Episode</a>
<a href="/episode/<%= episode.prevEpisode.episodeId %>" class="btn btn-dark">
<i class="bi bi-arrow-left me-1"></i>Previous Episode
</a>
<% } else { %>
<span class="btn btn-secondary disabled">Previous Episode</span>
<% } %>

<% if (episode.nextEpisode) { %>
<a href="/episode/<%= episode.nextEpisode.episodeId %>" class="btn btn-dark">Next Episode</a>
<a href="/episode/<%= episode.nextEpisode.episodeId %>" class="btn btn-dark">
Next Episode<i class="bi bi-arrow-right ms-1"></i>
</a>
<% } else { %>
<span class="btn btn-secondary disabled">Next Episode</span>
<% } %>
</div>
<h2 class="mt-4">Download Links</h2>
<table class="table table-striped">
<thead>
<tr>
<th>Quality</th>
<th>Size</th>
<th>Links</th>
</tr>
</thead>
<tbody>
<% episode.downloadUrl.qualities.forEach(quality => { %>

<!-- Redesigned Download Links Section -->
<h3 class="mb-3">Download Links</h3>
<div class="table-responsive">
<table class="table table-bordered align-middle">
<thead class="table-dark">
<tr>
<td><%= quality.title %></td>
<td><%= quality.size %></td>
<td>
<ul>
<% quality.urls.forEach(url => { %>
<li><a href="<%= url.url %>" target="_blank" style="color: black;"><%= url.title %></a></li>
<% }) %>
</ul>
</td>
<th scope="col">Quality</th>
<th scope="col">Size</th>
<th scope="col">Download Links</th>
</tr>
<% }) %>
</tbody>
</table>
</thead>
<tbody>
<% episode.downloadUrl.qualities.forEach(quality => { %>
<tr>
<!-- Quality Badge -->
<td class="fw-bold">
<span class="badge bg-dark fs-6"><%= quality.title %></span>
</td>
<!-- Size Badge -->
<td><%= quality.size %></td>
<!-- Download Links as Buttons -->
<td>
<div class="d-flex flex-wrap gap-2">
<% quality.urls.forEach(url => { %>
<a href="<%= url.url %>" target="_blank" class="btn btn-sm btn-outline-dark">
<i class="bi bi-download me-1"></i><%= url.title %>
</a>
<% }) %>
</div>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</div>
</div>
</div>

<%- include('partials/footer') %>

<!-- Bootstrap JS -->
<script src="/js/bootstrap.bundle.min.js"></script>
<script>
Expand Down Expand Up @@ -99,4 +126,4 @@
});
</script>
</body>
</html>
</html>
Loading

0 comments on commit c8835d2

Please sign in to comment.