From 6ddc45b9892604b485c7158d1e736aaeb95cd003 Mon Sep 17 00:00:00 2001 From: itsskaiya Date: Thu, 20 Nov 2025 09:30:19 -0500 Subject: [PATCH] Extensions are now lazy loaded to prevent long wait times to use the app. --- main.js | 59 +++++++++++---------------- package.json | 2 +- src/ipc/api-handlers.js | 85 +++++++++++++++++++++++++++++++-------- src/updateNotification.js | 2 +- 4 files changed, 93 insertions(+), 55 deletions(-) diff --git a/main.js b/main.js index b23f377..b9c7172 100644 --- a/main.js +++ b/main.js @@ -7,9 +7,6 @@ const initDatabase = require('./src/database/db-init'); const { initDiscordRPC } = require('./src/discord-rpc'); const headlessBrowser = require('./src/utils/headless-browser'); -const fetchPath = require.resolve('node-fetch'); -const cheerioPath = require.resolve('cheerio'); - const waifuBoardsPath = path.join(app.getPath('home'), 'WaifuBoards'); const pluginsPath = path.join(waifuBoardsPath, 'extensions'); const dbPath = path.join(waifuBoardsPath, 'favorites.db'); @@ -25,44 +22,34 @@ try { console.error('Failed to create directories:', error); } -const loadedScrapers = {}; +const availableScrapers = {}; function loadScrapers() { - console.log('Loading scrapers...'); - console.log(`Checking for plugins in: ${pluginsPath}`); + console.log('Scanning for plugins...'); + + let files = []; + try { + files = fs.readdirSync(pluginsPath).filter((file) => file.endsWith('.js')); + } catch (e) { + console.error("Failed to read plugins directory", e); + return; + } - const files = fs.readdirSync(pluginsPath); - files - .filter((file) => file.endsWith('.js')) - .forEach((file) => { + files.forEach((file) => { + const name = file.replace('.js', ''); const filePath = path.join(pluginsPath, file); - try { - const scraperModule = require(filePath); - const className = Object.keys(scraperModule)[0]; - const ScraperClass = scraperModule[className]; - - if ( - typeof ScraperClass === 'function' && - ScraperClass.prototype.fetchSearchResult - ) { - const instance = new ScraperClass(fetchPath, cheerioPath, headlessBrowser); - - loadedScrapers[className] = { - instance: instance, - baseUrl: instance.baseUrl, - }; - console.log( - `Successfully loaded scraper: ${className} from ${instance.baseUrl}` - ); - } else { - console.warn(`File ${file} does not export a valid scraper class.`); - } - } catch (error) { - console.error(`Failed to load scraper from ${file}:`, error); - } - }); + + availableScrapers[name] = { + name: name, + path: filePath, + instance: null + }; + }); + + console.log(`Found ${files.length} plugins. (Lazy Loaded)`); } + loadScrapers(); const db = initDatabase(dbPath); @@ -100,7 +87,7 @@ app.on('window-all-closed', function () { } }); -const apiHandlers = require('./src/ipc/api-handlers')(loadedScrapers); +const apiHandlers = require('./src/ipc/api-handlers')(availableScrapers, headlessBrowser); const dbHandlers = require('./src/ipc/db-handlers')(db); ipcMain.handle('api:getSources', apiHandlers.getSources); diff --git a/package.json b/package.json index 7c78df4..387eb1f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "waifu-board", - "version": "v1.3.0", + "version": "v1.3.1", "description": "An image board app to store and browse your favorite waifus!", "main": "main.js", "scripts": { diff --git a/src/ipc/api-handlers.js b/src/ipc/api-handlers.js index 28f93f9..b5d91af 100644 --- a/src/ipc/api-handlers.js +++ b/src/ipc/api-handlers.js @@ -1,29 +1,80 @@ -module.exports = function (loadedScrapers) { +const fs = require('fs'); +const fetchPath = require.resolve('node-fetch'); +const cheerioPath = require.resolve('cheerio'); + +function peekBaseUrl(filePath) { + try { + const content = fs.readFileSync(filePath, 'utf-8'); + const match = content.match(/baseUrl\s*=\s*["']([^"']+)["']/); + return match ? match[1] : null; + } catch (e) { + return null; + } +} + +module.exports = function (availableScrapers, headlessBrowser) { + + Object.keys(availableScrapers).forEach(name => { + const scraper = availableScrapers[name]; + if (!scraper.url) { + const url = peekBaseUrl(scraper.path); + if (url) { + scraper.url = url; + } + } + }); + return { getSources: () => { - return Object.keys(loadedScrapers).map((name) => { + return Object.keys(availableScrapers).map((name) => { + const scraper = availableScrapers[name]; return { name: name, - url: loadedScrapers[name].baseUrl, + url: scraper.url || name }; }); }, search: async (event, source, query, page) => { - try { - if (loadedScrapers[source] && loadedScrapers[source].instance) { - const results = await loadedScrapers[source].instance.fetchSearchResult( - query, - page - ); - return { success: true, data: results }; - } else { - throw new Error(`Unknown source or source failed to load: ${source}`); - } - } catch (error) { - console.error(`Error searching ${source}:`, error); - return { success: false, error: error.message }; + const scraperData = availableScrapers[source]; + + if (!scraperData) { + return { success: false, error: `Source ${source} not found.` }; } - }, + + if (!scraperData.instance) { + console.log(`[LazyLoad] Initializing scraper: ${source}...`); + try { + const scraperModule = require(scraperData.path); + + const className = Object.keys(scraperModule)[0]; + const ScraperClass = scraperModule[className]; + + if (!ScraperClass || typeof ScraperClass !== 'function') { + throw new Error(`File ${scraperData.path} does not export a valid class.`); + } + + const instance = new ScraperClass(fetchPath, cheerioPath, headlessBrowser); + + scraperData.instance = instance; + + if (instance.baseUrl) { + scraperData.url = instance.baseUrl; + } + + } catch (err) { + console.error(`Failed to lazy load ${source}:`, err); + return { success: false, error: `Failed to load extension: ${err.message}` }; + } + } + + try { + const results = await scraperData.instance.fetchSearchResult(query, page); + return { success: true, data: results }; + } catch (err) { + console.error(`Error during search in ${source}:`, err); + return { success: false, error: err.message }; + } + } }; }; \ No newline at end of file diff --git a/src/updateNotification.js b/src/updateNotification.js index 801830d..78d2562 100644 --- a/src/updateNotification.js +++ b/src/updateNotification.js @@ -1,6 +1,6 @@ const GITHUB_OWNER = 'ItsSkaiya'; const GITHUB_REPO = 'WaifuBoard'; -const CURRENT_VERSION = 'v1.3.0'; +const CURRENT_VERSION = 'v1.3.1'; const UPDATE_CHECK_INTERVAL = 5 * 60 * 1000; let currentVersionDisplay;