Removed useless things from all files Added an update notification if there is an update Updated the directory for the app icon
259 lines
6.9 KiB
JavaScript
259 lines
6.9 KiB
JavaScript
const { app, BrowserWindow, ipcMain } = require('electron');
|
|
const path = require('path');
|
|
const fs = require('fs');
|
|
const sqlite3 = require('sqlite3').verbose();
|
|
|
|
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);
|
|
|
|
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 = new sqlite3.Database(dbPath, (err) => {
|
|
if (err) {
|
|
console.error('Error opening database:', err.message);
|
|
} else {
|
|
console.log('Connected to the favorites database.');
|
|
runDatabaseMigrations();
|
|
}
|
|
});
|
|
|
|
function runDatabaseMigrations() {
|
|
db.serialize(() => {
|
|
|
|
db.run(
|
|
`
|
|
CREATE TABLE IF NOT EXISTS favorites (
|
|
id TEXT PRIMARY KEY,
|
|
title TEXT NOT NULL,
|
|
image_url TEXT NOT NULL,
|
|
thumbnail_url TEXT NOT NULL DEFAULT "",
|
|
tags TEXT NOT NULL DEFAULT ""
|
|
)
|
|
`,
|
|
(err) => {
|
|
if (err) console.error('Error creating table:', err.message);
|
|
}
|
|
);
|
|
|
|
console.log('Checking database schema for "thumbnail_url"...');
|
|
db.all('PRAGMA table_info(favorites)', (err, columns) => {
|
|
if (err) {
|
|
console.error('Failed to get table info:', err.message);
|
|
return;
|
|
}
|
|
const hasThumbnailColumn = columns.some(
|
|
(col) => col.name === 'thumbnail_url'
|
|
);
|
|
|
|
if (!hasThumbnailColumn) {
|
|
console.log(
|
|
'MIGRATION: Adding "thumbnail_url" column...'
|
|
);
|
|
db.run(
|
|
'ALTER TABLE favorites ADD COLUMN thumbnail_url TEXT NOT NULL DEFAULT ""',
|
|
(err) => {
|
|
if (err)
|
|
console.error('Migration error (thumbnail_url):', err.message);
|
|
else console.log('MIGRATION: "thumbnail_url" added successfully.');
|
|
}
|
|
);
|
|
} else {
|
|
console.log('"thumbnail_url" column is up-to-date.');
|
|
}
|
|
});
|
|
|
|
console.log('Checking database schema for "tags" column...');
|
|
db.all('PRAGMA table_info(favorites)', (err, columns) => {
|
|
if (err) {
|
|
console.error('Failed to get table info:', err.message);
|
|
return;
|
|
}
|
|
const hasTagsColumn = columns.some((col) => col.name === 'tags');
|
|
|
|
if (!hasTagsColumn) {
|
|
console.log('MIGRATION: Adding "tags" column...');
|
|
db.run(
|
|
'ALTER TABLE favorites ADD COLUMN tags TEXT NOT NULL DEFAULT ""',
|
|
(err) => {
|
|
if (err) console.error('Migration error (tags):', err.message);
|
|
else console.log('MIGRATION: "tags" column added successfully.');
|
|
}
|
|
);
|
|
} else {
|
|
console.log('"tags" column is up-to-date.');
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function createWindow() {
|
|
|
|
const mainWindow = new BrowserWindow({
|
|
width: 1000,
|
|
height: 800,
|
|
webPreferences: {
|
|
|
|
preload: path.join(__dirname, '/scripts/preload.js'),
|
|
|
|
contextIsolation: true,
|
|
|
|
nodeIntegration: false,
|
|
},
|
|
});
|
|
|
|
mainWindow.loadFile('views/index.html');
|
|
|
|
mainWindow.setMenu(null);
|
|
}
|
|
|
|
app.whenReady().then(() => {
|
|
createWindow();
|
|
|
|
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();
|
|
}
|
|
});
|
|
|
|
ipcMain.handle('api:getSources', () => {
|
|
return Object.keys(loadedScrapers).map((name) => {
|
|
return {
|
|
name: name,
|
|
url: loadedScrapers[name].baseUrl,
|
|
};
|
|
});
|
|
});
|
|
|
|
ipcMain.handle('api: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 };
|
|
}
|
|
});
|
|
ipcMain.handle('db:getFavorites', () => {
|
|
return new Promise((resolve, reject) => {
|
|
db.all('SELECT * FROM favorites', [], (err, rows) => {
|
|
if (err) {
|
|
console.error('Error getting favorites:', err.message);
|
|
resolve([]);
|
|
} else {
|
|
resolve(rows);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
ipcMain.handle('db:addFavorite', (event, fav) => {
|
|
return new Promise((resolve) => {
|
|
const stmt =
|
|
'INSERT INTO favorites (id, title, image_url, thumbnail_url, tags) VALUES (?, ?, ?, ?, ?)';
|
|
db.run(
|
|
stmt,
|
|
[fav.id, fav.title, fav.imageUrl, fav.thumbnailUrl, fav.tags],
|
|
function (err) {
|
|
|
|
if (err) {
|
|
if (err.code.includes('SQLITE_CONSTRAINT')) {
|
|
resolve({ success: false, error: 'Item is already a favorite.' });
|
|
} else {
|
|
console.error('Error adding favorite:', err.message);
|
|
resolve({ success: false, error: err.message });
|
|
}
|
|
} else {
|
|
resolve({ success: true, id: fav.id });
|
|
}
|
|
}
|
|
);
|
|
});
|
|
});
|
|
|
|
ipcMain.handle('db:removeFavorite', (event, id) => {
|
|
return new Promise((resolve) => {
|
|
const stmt = 'DELETE FROM favorites WHERE id = ?';
|
|
db.run(stmt, id, function (err) {
|
|
|
|
if (err) {
|
|
console.error('Error removing favorite:', err.message);
|
|
resolve({ success: false, error: err.message });
|
|
} else {
|
|
resolve({ success: this.changes > 0 });
|
|
}
|
|
});
|
|
});
|
|
}); |