Add aniliberty/aniliberty.js

This commit is contained in:
aka paul 2025-10-12 17:07:42 +00:00
parent 9eacd16f54
commit c86ada85ef

132
aniliberty/aniliberty.js Normal file
View file

@ -0,0 +1,132 @@
// AniLiberty module for Sora
// Author: emp0ry
// Version: 1.0.0
// Description:
// Streams anime directly from AniLiberty / AniLibria API v1
// Endpoints used:
// • /app/status
// • /app/search/releases?query=
// • /anime/releases/{id}
//
// Supports 1080p / 720p / 480p HLS playback
// ------------------------------------------------------------
// Detect working API domain
// ------------------------------------------------------------
async function checkApiStatus() {
const domains = [
"https://anilibria.top/api/v1/",
"https://aniliberty.top/api/v1/",
"https://anilibria.wtf/api/v1/"
];
for (const base of domains) {
try {
const res = await fetchv2(base + "app/status");
const data = await res.json();
if (data?.is_alive || data?.result === "ok") return base;
} catch (_) {}
}
return "https://anilibria.top/api/v1/";
}
// ------------------------------------------------------------
// Search anime releases
// ------------------------------------------------------------
async function searchResults(keyword) {
const base = await checkApiStatus();
const url = `${base}app/search/releases?query=${encodeURIComponent(keyword)}&include=id,name,poster,year,description`;
try {
const response = await fetchv2(url);
const data = await response.json();
if (!Array.isArray(data) || !data.length)
return [{
title: `No results from AniLiberty (${base})`,
image: "https://anilibria.top/favicon.ico",
href: "https://anilibria.top"
}];
return data.map(item => {
const title = item.name?.main || item.name?.english || "Unknown title";
const year = item.year ? ` (${item.year})` : "";
const img = item.poster?.optimized?.preview
? `https://anilibria.top${item.poster.optimized.preview}`
: `https://anilibria.top${item.poster?.preview || "/favicon.ico"}`;
return {
title: title + year,
image: img,
href: `${base}anime/releases/${item.id}`
};
});
} catch (err) {
console.log("AniLiberty search error:", err);
return [{
title: "AniLiberty: Error during search",
image: "https://anilibria.top/favicon.ico",
href: "https://anilibria.top"
}];
}
}
// ------------------------------------------------------------
// Extract anime details
// ------------------------------------------------------------
async function extractDetails(url) {
try {
const response = await fetchv2(url);
const data = await response.json();
return [{
description: data.description || "No description available.",
aliases: data.name?.english || "N/A",
airdate: data.year ? String(data.year) : "Unknown"
}];
} catch (err) {
console.log("AniLiberty details error:", err);
return [{
description: "Error loading details",
aliases: "N/A",
airdate: "N/A"
}];
}
}
// ------------------------------------------------------------
// Extract episode list (with HLS sources)
// ------------------------------------------------------------
async function extractEpisodes(url) {
try {
const response = await fetchv2(url);
const data = await response.json();
const eps = data.episodes || [];
if (!eps.length) return [];
return eps.map(ep => ({
number: ep.ordinal || ep.sort_order || 0,
image: ep.preview?.optimized?.preview
? `https://anilibria.top${ep.preview.optimized.preview}`
: "https://anilibria.top/favicon.ico",
href:
ep.hls_1080 ||
ep.hls_720 ||
ep.hls_480 ||
null
})).filter(e => e.href);
} catch (err) {
console.log("AniLiberty episodes error:", err);
return [];
}
}
// ------------------------------------------------------------
// Extract direct stream URL (HLS)
// ------------------------------------------------------------
async function extractStreamUrl(url) {
try {
// Direct HLS links are already provided; just return the same URL
return url;
} catch (err) {
console.log("AniLiberty stream error:", err);
return null;
}
}