Extensions are now lazy loaded to prevent

long wait times to use the app.
This commit is contained in:
2025-11-20 09:30:19 -05:00
parent 2a453c40a8
commit 6ddc45b989
4 changed files with 93 additions and 55 deletions

59
main.js
View File

@@ -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);

View File

@@ -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": {

View File

@@ -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 };
}
}
};
};

View File

@@ -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;