Files
WaifuBoard/main.js
itsskaiya 5f3020ca6e Organized all the code
Updated the update notification to check periodically every 5 minutes
Added in headless browser support for extensions (check the extensions repo to see an example)
Added in DiscordRPC support
2025-11-19 16:28:33 -05:00

111 lines
3.2 KiB
JavaScript

const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
const fs = require('fs');
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');
try {
if (!fs.existsSync(waifuBoardsPath)) {
fs.mkdirSync(waifuBoardsPath);
}
if (!fs.existsSync(pluginsPath)) {
fs.mkdirSync(pluginsPath, { recursive: true });
}
} catch (error) {
console.error('Failed to create directories:', error);
}
const loadedScrapers = {};
function loadScrapers() {
console.log('Loading scrapers...');
console.log(`Checking for plugins in: ${pluginsPath}`);
const files = fs.readdirSync(pluginsPath);
files
.filter((file) => file.endsWith('.js'))
.forEach((file) => {
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);
}
});
}
loadScrapers();
const db = initDatabase(dbPath);
function createWindow() {
const mainWindow = new BrowserWindow({
width: 1000,
height: 800,
webPreferences: {
preload: path.join(__dirname, '/src/preload.js'),
contextIsolation: true,
nodeIntegration: false,
},
});
mainWindow.loadFile('views/index.html');
mainWindow.setMenu(null);
// mainWindow.webContents.openDevTools();
}
app.whenReady().then(() => {
createWindow();
initDiscordRPC();
app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') {
db.close((err) => {
if (err) console.error('Error closing database:', err.message);
});
app.quit();
}
});
const apiHandlers = require('./src/ipc/api-handlers')(loadedScrapers);
const dbHandlers = require('./src/ipc/db-handlers')(db);
ipcMain.handle('api:getSources', apiHandlers.getSources);
ipcMain.handle('api:search', apiHandlers.search);
ipcMain.handle('db:getFavorites', dbHandlers.getFavorites);
ipcMain.handle('db:addFavorite', dbHandlers.addFavorite);
ipcMain.handle('db:removeFavorite', dbHandlers.removeFavorite);