Files
AniKotoAPI/src/extractors/status.extractor.js
T
Shinei Nouzen a8f1917ce7 feat: v2.2.0 — Modularize codebase, unify mirror fallback, harden security
Major Changes:
- Add shared parseListItem.helper.js for unified list parsing (DRY)
- Migrate all 22 extractors to use fetchWithMirror() for consistent mirror fallback
- Remove unused cors dependency (custom CORS middleware handles it)
- Fix middleware ordering: timeout now registered before routes
- Fix CORS to allow POST for /api/mirrors/reset endpoint
- Remove redundant cache check in homeInfo extractor

New Features:
- Request ID tracking (X-Request-Id header) for debugging
- Graceful shutdown handling (SIGTERM/SIGINT) with 10s timeout
- CSP and HSTS security headers
- Rate limiter cleanup interval (every 5 min) to prevent memory leak
- Request body size limits (10kb) via express.json()

Security:
- Content-Security-Policy header for XSS protection
- Strict-Transport-Security for HTTPS enforcement
- X-Permitted-Cross-Domain-Policies: none
- Body size limits to prevent large payload attacks

Code Quality:
- All files follow strict documentation style (box headers, section separators,
  feature markers, JSDoc params/returns, inline notes, module footers)
- Eliminated ~200 lines of duplicated code across 8+ extractors
- Updated CHANGELOG.md with comprehensive change history
2026-07-28 19:28:21 +05:30

69 lines
3.0 KiB
JavaScript

/*
* ======= • ======= • ======= • ======= • =======• =======
* AniKotoAPI — status.extractor.js
* Repository: https://github.com/Shineii86/AniKotoAPI
*
* @description
* Extracts anime filtered by status (ongoing, completed, etc.).
* Supports pagination for browsing large result sets.
*
* @exports
* extractStatus
*
* @author Shinei Nouzen
* @license MIT
* ======= • ======= • ======= • ======= • =======• =======
*/
import { URLS } from "../configs/dataUrl.js";
import { extractPages } from "../helper/extractPages.helper.js";
import { countPages } from "../helper/countPages.helper.js";
import { parseListItems } from "../helper/parseListItem.helper.js";
// ══════════════════════════════════════════════════════════════
// STATUS FILTER EXTRACTION
// ══════════════════════════════════════════════════════════════
// ---- FEATURE: Extract anime filtered by status with pagination ----
/**
* Fetches and parses anime filtered by status (ongoing, completed, etc.).
* Returns paginated results with total page count.
*
* @param {string} status - Status to filter by (e.g., "ongoing", "completed")
* @param {number} page - Page number to fetch (default: 1)
* @returns {Promise<Object>} Object containing totalPages, status, and data array
* @returns {number} return.totalPages - Total number of pages available
* @returns {string} return.status - The status filter used
* @returns {Array<Object>} return.data - Array of anime objects
* @returns {string} return.data[].slug - URL slug for the anime
* @returns {string} return.data[].poster - Poster image URL
* @returns {string} return.data[].title - English title
* @returns {string} return.data[].japaneseTitle - Japanese title
* @returns {number} return.data[].sub - Subbed episode count
* @returns {number} return.data[].dub - Dubbed episode count
* @returns {number} return.data[].total - Total episode count
* @returns {string} return.data[].type - Anime type (TV, Movie, etc.)
* @returns {string} return.data[].rating - Anime rating
*
* @example
* const ongoing = await extractStatus("ongoing", 1);
* console.log(ongoing.status); // "ongoing"
* console.log(ongoing.data[0].title); // First ongoing anime
*/
const extractStatus = async (status, page = 1) => {
try {
const url = URLS.status(status);
const $ = await extractPages(url, page);
const totalPages = countPages($);
const results = parseListItems($);
return { totalPages, status, data: results };
} catch (error) {
throw error;
}
};
export { extractStatus };
// ══════════════════════════════════════════════════════════════ END: status.extractor.js