fix
This commit is contained in:
@@ -273,9 +273,22 @@ export async function getAnimeInfoExtension(ext: Extension | null, id: string):
|
||||
const match = await ext.getMetadata(id);
|
||||
|
||||
if (match) {
|
||||
const normalized: any = {
|
||||
title: match.title ?? "Unknown",
|
||||
summary: match.summary ?? "No summary available",
|
||||
episodes: Number(match.episodes) || 0,
|
||||
characters: Array.isArray(match.characters) ? match.characters : [],
|
||||
season: match.season ?? null,
|
||||
status: match.status ?? "Unknown",
|
||||
studio: match.studio ?? "Unknown",
|
||||
score: Number(match.score) || 0,
|
||||
year: match.year ?? null,
|
||||
genres: Array.isArray(match.genres) ? match.genres : [],
|
||||
image: match.image ?? ""
|
||||
};
|
||||
|
||||
await cacheExtension(extName, id, match.title, match);
|
||||
return match;
|
||||
await cacheExtension(extName, id, normalized.title, normalized);
|
||||
return normalized;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`Extension getMetadata failed:`, e);
|
||||
|
||||
@@ -262,7 +262,7 @@ export async function searchBooksAniList(query: string): Promise<Book[]> {
|
||||
return [];
|
||||
}
|
||||
|
||||
export async function getBookInfoExtension(ext: Extension | null, id: string): Promise<Book[]> {
|
||||
export async function getBookInfoExtension(ext: Extension | null, id: string): Promise<any[]> {
|
||||
if (!ext) return [];
|
||||
|
||||
const extName = ext.constructor.name;
|
||||
@@ -271,18 +271,29 @@ export async function getBookInfoExtension(ext: Extension | null, id: string): P
|
||||
if (cached) {
|
||||
try {
|
||||
return JSON.parse(cached.metadata);
|
||||
} catch {
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
if (ext.type === 'book-board' && ext.getMetadata) {
|
||||
try {
|
||||
|
||||
const info = await ext.getMetadata(id);
|
||||
|
||||
if (info) {
|
||||
await cacheExtension(extName, id, info.title, info);
|
||||
return info;
|
||||
const normalized = {
|
||||
id: info.id ?? id,
|
||||
title: info.title ?? "",
|
||||
format: info.format ?? "",
|
||||
score: typeof info.score === "number" ? info.score : null,
|
||||
genres: Array.isArray(info.genres) ? info.genres : [],
|
||||
status: info.status ?? "",
|
||||
published: info.published ?? "",
|
||||
summary: info.summary ?? "",
|
||||
chapters: Number.isFinite(info.chapters) ? info.chapters : 1,
|
||||
image: typeof info.image === "string" ? info.image : ""
|
||||
};
|
||||
|
||||
await cacheExtension(extName, id, normalized.title, normalized);
|
||||
return [normalized];
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`Extension getInfo failed:`, e);
|
||||
|
||||
@@ -1,25 +1,6 @@
|
||||
import {FastifyReply, FastifyRequest} from 'fastify';
|
||||
import * as galleryService from './gallery.service';
|
||||
|
||||
export async function search(req: any, reply: FastifyReply) {
|
||||
try {
|
||||
const query = req.query.q || '';
|
||||
const page = parseInt(req.query.page as string) || 1;
|
||||
const perPage = parseInt(req.query.perPage as string) || 48;
|
||||
|
||||
return await galleryService.searchGallery(query, page, perPage);
|
||||
} catch (err) {
|
||||
const error = err as Error;
|
||||
console.error("Gallery Search Error:", error.message);
|
||||
return {
|
||||
results: [],
|
||||
total: 0,
|
||||
page: 1,
|
||||
hasNextPage: false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function searchInExtension(req: any, reply: FastifyReply) {
|
||||
try {
|
||||
const provider = req.query.provider;
|
||||
|
||||
@@ -2,7 +2,6 @@ import { FastifyInstance } from 'fastify';
|
||||
import * as controller from './gallery.controller';
|
||||
|
||||
async function galleryRoutes(fastify: FastifyInstance) {
|
||||
fastify.get('/gallery/search', controller.search);
|
||||
fastify.get('/gallery/fetch/:id', controller.getInfo);
|
||||
fastify.get('/gallery/search/provider', controller.searchInExtension);
|
||||
fastify.get('/gallery/favorites', controller.getFavorites);
|
||||
|
||||
@@ -2,30 +2,7 @@ import { getAllExtensions, getExtension } from '../../shared/extensions';
|
||||
import { GallerySearchResult, GalleryInfo, Favorite, FavoriteResult } from '../types';
|
||||
import { getDatabase } from '../../shared/database';
|
||||
|
||||
export async function searchGallery(query: string, page: number = 1, perPage: number = 48): Promise<GallerySearchResult> {
|
||||
const extensions = getAllExtensions();
|
||||
|
||||
for (const [name, ext] of extensions) {
|
||||
if (ext.type === 'image-board' && ext.search) {
|
||||
const result = await searchInExtension(name, query, page, perPage);
|
||||
if (result.results.length > 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
total: 0,
|
||||
next: 0,
|
||||
previous: 0,
|
||||
pages: 0,
|
||||
page,
|
||||
hasNextPage: false,
|
||||
results: []
|
||||
};
|
||||
}
|
||||
|
||||
export async function getGalleryInfo(id: string, providerName?: string): Promise<GalleryInfo> {
|
||||
export async function getGalleryInfo(id: string, providerName?: string): Promise<any> {
|
||||
const extensions = getAllExtensions();
|
||||
|
||||
if (providerName) {
|
||||
@@ -35,8 +12,12 @@ export async function getGalleryInfo(id: string, providerName?: string): Promise
|
||||
console.log(`[Gallery] Getting info from ${providerName} for: ${id}`);
|
||||
const info = await ext.getInfo(id);
|
||||
return {
|
||||
...info,
|
||||
provider: providerName
|
||||
id: info.id ?? id,
|
||||
provider: providerName,
|
||||
image: info.image,
|
||||
tags: info.tags,
|
||||
title: info.title,
|
||||
headers: info.headers
|
||||
};
|
||||
} catch (e) {
|
||||
const error = e as Error;
|
||||
@@ -65,25 +46,26 @@ export async function getGalleryInfo(id: string, providerName?: string): Promise
|
||||
throw new Error("Gallery item not found in any extension");
|
||||
}
|
||||
|
||||
export async function searchInExtension(providerName: string, query: string, page: number = 1, perPage: number = 48): Promise<GallerySearchResult> {
|
||||
export async function searchInExtension(providerName: string, query: string, page: number = 1, perPage: number = 48): Promise<any> {
|
||||
const ext = getExtension(providerName);
|
||||
|
||||
if (!ext || ext.type !== 'image-board' || !ext.search) {
|
||||
throw new Error(`La extensión "${providerName}" no existe o no soporta búsqueda.`);
|
||||
}
|
||||
|
||||
try {
|
||||
console.log(`[Gallery] Searching ONLY in ${providerName} for: ${query}`);
|
||||
const results = await ext.search(query, page, perPage);
|
||||
|
||||
const enrichedResults = (results?.results ?? []).map((r: any) => ({
|
||||
...r,
|
||||
const normalizedResults = (results?.results ?? []).map((r: any) => ({
|
||||
id: r.id,
|
||||
image: r.image,
|
||||
tags: r.tags,
|
||||
title: r.title,
|
||||
headers: r.headers,
|
||||
provider: providerName
|
||||
}));
|
||||
|
||||
return {
|
||||
...results,
|
||||
results: enrichedResults
|
||||
page: results.page ?? page,
|
||||
hasNextPage: !!results.hasNextPage,
|
||||
results: normalizedResults
|
||||
};
|
||||
|
||||
} catch (e) {
|
||||
|
||||
@@ -51,9 +51,10 @@ async function loadBookMetadata() {
|
||||
return;
|
||||
}
|
||||
|
||||
bookData = data;
|
||||
const raw = Array.isArray(data) ? data[0] : data;
|
||||
bookData = raw;
|
||||
|
||||
const metadata = MediaMetadataUtils.formatBookData(data, !!extensionName);
|
||||
const metadata = MediaMetadataUtils.formatBookData(raw, !!extensionName);
|
||||
|
||||
updatePageTitle(metadata.title);
|
||||
updateMetadata(metadata);
|
||||
|
||||
@@ -332,11 +332,6 @@ async function loadExtensions() {
|
||||
|
||||
providerSelector.innerHTML = '';
|
||||
|
||||
const global = document.createElement('option');
|
||||
global.value = '';
|
||||
global.textContent = 'Global Search';
|
||||
providerSelector.appendChild(global);
|
||||
|
||||
const favoritesOption = document.createElement('option');
|
||||
favoritesOption.value = 'favorites';
|
||||
favoritesOption.textContent = 'Favorites';
|
||||
|
||||
@@ -106,7 +106,7 @@ function copyLink() {
|
||||
|
||||
async function loadSimilarImages(item) {
|
||||
if (!item.tags || item.tags.length === 0) {
|
||||
document.getElementById('similar-section').innerHTML = '<p style="text-align:center;color:var(--text-secondary);padding:3rem 0;">No tags available to search for similar images.</p>';
|
||||
document.getElementById('similar-section').innerHTML = '<p style="text-align:center;color:var(--color-text-secondary);padding:3rem 0;">No tags available to search for similar images.</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -123,13 +123,13 @@ async function loadSimilarImages(item) {
|
||||
.slice(0, 15);
|
||||
|
||||
if (results.length === 0) {
|
||||
container.innerHTML = '<p style="text-align:center;color:var(--text-secondary);padding:3rem 0;">No similar images found.</p>';
|
||||
container.innerHTML = '<p style="text-align:center;color:var(--color-text-secondary);padding:3rem 0;">No similar images found.</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = `
|
||||
<h3 style="text-align:center;margin:2rem 0 1.5rem;font-size:1.7rem;">
|
||||
More images tagged with "<span style="color:var(--accent);">${firstTag}</span>"
|
||||
More images tagged with "<span style="color:var(--color-primary);">${firstTag}</span>"
|
||||
</h3>
|
||||
<div class="similar-grid">
|
||||
${results.map(img => {
|
||||
@@ -147,7 +147,7 @@ async function loadSimilarImages(item) {
|
||||
`;
|
||||
|
||||
} catch (err) {
|
||||
container.innerHTML = '<p style="text-align:center;color:var(--text-secondary);opacity:0.6;padding:3rem 0;">Could not load similar images.</p>';
|
||||
container.innerHTML = '<p style="text-align:center;color:var(--color-text-secondary);opacity:0.6;padding:3rem 0;">Could not load similar images.</p>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ function renderItem(item) {
|
||||
? item.tags.map(tag => `
|
||||
<a class="tag-item">${tag}</a>
|
||||
`).join('')
|
||||
: '<span style="opacity:0.6;color:var(--text-secondary);">No tags</span>'
|
||||
: '<span style="opacity:0.6;color:var(--color-text-secondary);">No tags</span>'
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -216,9 +216,9 @@ function renderError(msg) {
|
||||
itemMainContentContainer.innerHTML = `
|
||||
<div style="text-align:center;padding:8rem 1rem;">
|
||||
<i class="fa-solid fa-heart-crack" style="font-size:5rem;color:#ff6b6b;opacity:0.7;"></i>
|
||||
<h2 style="margin:2rem 0;color:var(--text-primary);">Image Not Available</h2>
|
||||
<p style="color:var(--text-secondary);max-width:600px;margin:0 auto 2rem;">${msg}</p>
|
||||
<a href="/gallery" style="padding:1rem 2.5rem;background:var(--accent);color:white;border-radius:99px;text-decoration:none;font-weight:600;">
|
||||
<h2 style="margin:2rem 0;color:var(--color-text-primary);">Image Not Available</h2>
|
||||
<p style="color:var(--color-text-secondary);max-width:600px;margin:0 auto 2rem;">${msg}</p>
|
||||
<a href="/gallery" style="padding:1rem 2.5rem;background:var(--color-primary);color:white;border-radius:99px;text-decoration:none;font-weight:600;">
|
||||
Back to Gallery
|
||||
</a>
|
||||
</div>
|
||||
@@ -268,13 +268,14 @@ async function loadFromProvider(provider, id) {
|
||||
if (!res.ok) throw new Error();
|
||||
|
||||
const data = await res.json();
|
||||
if (!data.fullImage) throw new Error();
|
||||
|
||||
if (!data.image) throw new Error();
|
||||
|
||||
const item = {
|
||||
id,
|
||||
title: data.title || data.publishedBy || 'Beautiful Art',
|
||||
fullImage: data.fullImage,
|
||||
originalImage: data.fullImage,
|
||||
title: data.title || 'Beautiful Art',
|
||||
fullImage: data.image,
|
||||
originalImage: data.image,
|
||||
tags: data.tags || [],
|
||||
provider,
|
||||
headers: data.headers
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
const cheerio = require("cheerio");
|
||||
const { queryAll, run } = require('./database');
|
||||
const { scrape } = require("./headless");
|
||||
|
||||
@@ -77,6 +78,7 @@ async function loadExtension(fileName) {
|
||||
|
||||
const name = instance.constructor.name;
|
||||
instance.scrape = scrape;
|
||||
instance.cheerio = cheerio;
|
||||
extensions.set(name, instance);
|
||||
|
||||
console.log(`📦 Installed & loaded: ${name}`);
|
||||
|
||||
@@ -21,7 +21,6 @@ async function initHeadless() {
|
||||
"--mute-audio",
|
||||
"--no-first-run",
|
||||
"--no-zygote",
|
||||
"--single-process"
|
||||
]
|
||||
});
|
||||
context = await browser.newContext({
|
||||
|
||||
Reference in New Issue
Block a user