manga / hfService.js
haaaaus's picture
Upload 17 files
0acf70a verified
const https = require('https');
const HF_API_URL = "https://huggingface.co/api/datasets/datalocalapi/truyen/tree/main?recursive=true";
const HF_ASSET_BASE = "https://huggingface.co/datasets/datalocalapi/truyen/resolve/main";
// Auto-refresh interval (15 minutes = 900000ms)
const REFRESH_INTERVAL_MS = 15 * 60 * 1000;
// Cache for HF data
let hfStoriesCache = {};
let isLoaded = false;
let lastFetchTime = null;
let refreshIntervalId = null;
/**
* Fetch data from Hugging Face
*/
async function fetchHFData() {
try {
console.log('Fetching data from Hugging Face...');
const response = await fetch(HF_API_URL);
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
const tree = await response.json();
const processed = {};
// Process tree structure
for (const item of tree) {
if (item.type !== 'file') continue;
const parts = item.path.split('/');
if (parts.length < 2) continue;
const storyName = parts[0];
if (!processed[storyName]) {
processed[storyName] = {
id: storyName,
chapters: {},
cover: null
};
}
// Check for cover image
if (parts.length === 2 && /^thum\.(jpg|jpeg|png|webp|gif)$/i.test(parts[1])) {
processed[storyName].cover = item.path; // Store relative path only
continue;
}
// Check for chapter images
if (parts.length >= 3) {
const chapterName = parts[1];
const fileName = parts[2];
if (/\.(png|jpg|jpeg|webp|gif)$/i.test(fileName)) {
if (!processed[storyName].chapters[chapterName]) {
processed[storyName].chapters[chapterName] = [];
}
processed[storyName].chapters[chapterName].push({
name: fileName,
path: item.path // Store relative path
});
}
}
}
hfStoriesCache = processed;
isLoaded = true;
lastFetchTime = new Date();
console.log(`[${lastFetchTime.toLocaleTimeString()}] Loaded ${Object.keys(processed).length} stories from Hugging Face`);
} catch (error) {
console.error('Failed to fetch HF data:', error);
}
}
/**
* Force refresh Hugging Face data
*/
async function forceRefreshHFData() {
console.log('Force refreshing Hugging Face data...');
await fetchHFData();
return {
success: isLoaded,
storyCount: Object.keys(hfStoriesCache).length,
lastFetchTime: lastFetchTime
};
}
/**
* Start auto-refresh interval
*/
function startAutoRefresh() {
if (refreshIntervalId) {
clearInterval(refreshIntervalId);
}
refreshIntervalId = setInterval(async () => {
console.log('Auto-refreshing Hugging Face data...');
await fetchHFData();
}, REFRESH_INTERVAL_MS);
console.log(`Auto-refresh enabled: every ${REFRESH_INTERVAL_MS / 60000} minutes`);
}
/**
* Stop auto-refresh interval
*/
function stopAutoRefresh() {
if (refreshIntervalId) {
clearInterval(refreshIntervalId);
refreshIntervalId = null;
console.log('Auto-refresh disabled');
}
}
/**
* Get the cached stories
*/
function getHFStories() {
return hfStoriesCache;
}
/**
* Get cache status
*/
function getHFCacheStatus() {
return {
isLoaded,
storyCount: Object.keys(hfStoriesCache).length,
lastFetchTime,
autoRefreshEnabled: refreshIntervalId !== null,
refreshIntervalMinutes: REFRESH_INTERVAL_MS / 60000
};
}
/**
* Get the HF Asset Base URL
*/
function getHFAssetBase() {
return HF_ASSET_BASE;
}
module.exports = {
fetchHFData,
forceRefreshHFData,
startAutoRefresh,
stopAutoRefresh,
getHFStories,
getHFCacheStatus,
getHFAssetBase
};