| 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";
|
|
|
|
|
| const REFRESH_INTERVAL_MS = 15 * 60 * 1000;
|
|
|
|
|
| let hfStoriesCache = {};
|
| let isLoaded = false;
|
| let lastFetchTime = null;
|
| let refreshIntervalId = null;
|
|
|
| |
| |
|
|
| 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 = {};
|
|
|
|
|
| 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
|
| };
|
| }
|
|
|
|
|
| if (parts.length === 2 && /^thum\.(jpg|jpeg|png|webp|gif)$/i.test(parts[1])) {
|
| processed[storyName].cover = item.path;
|
| continue;
|
| }
|
|
|
|
|
| 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
|
| });
|
| }
|
| }
|
| }
|
|
|
| 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);
|
| }
|
| }
|
|
|
| |
| |
|
|
| async function forceRefreshHFData() {
|
| console.log('Force refreshing Hugging Face data...');
|
| await fetchHFData();
|
| return {
|
| success: isLoaded,
|
| storyCount: Object.keys(hfStoriesCache).length,
|
| lastFetchTime: lastFetchTime
|
| };
|
| }
|
|
|
| |
| |
|
|
| 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`);
|
| }
|
|
|
| |
| |
|
|
| function stopAutoRefresh() {
|
| if (refreshIntervalId) {
|
| clearInterval(refreshIntervalId);
|
| refreshIntervalId = null;
|
| console.log('Auto-refresh disabled');
|
| }
|
| }
|
|
|
| |
| |
|
|
| function getHFStories() {
|
| return hfStoriesCache;
|
| }
|
|
|
| |
| |
|
|
| function getHFCacheStatus() {
|
| return {
|
| isLoaded,
|
| storyCount: Object.keys(hfStoriesCache).length,
|
| lastFetchTime,
|
| autoRefreshEnabled: refreshIntervalId !== null,
|
| refreshIntervalMinutes: REFRESH_INTERVAL_MS / 60000
|
| };
|
| }
|
|
|
| |
| |
|
|
| function getHFAssetBase() {
|
| return HF_ASSET_BASE;
|
| }
|
|
|
| module.exports = {
|
| fetchHFData,
|
| forceRefreshHFData,
|
| startAutoRefresh,
|
| stopAutoRefresh,
|
| getHFStories,
|
| getHFCacheStatus,
|
| getHFAssetBase
|
| };
|
|
|