Files
NebulaBrowser/plugins/return-youtube-dislike/main.js
T
andrew 71462d83de Replace Nebot plugin with Return YouTube Dislike
Removed the Nebot chat plugin and its files, and added the Return YouTube Dislike plugin with main process logic, renderer preload, and manifest. Updated plugin manager and main process to support internal plugin pages and improved plugin event handling. Minor updates to renderer and documentation.
2025-09-11 20:42:43 +12:00

86 lines
3.0 KiB
JavaScript

// Return YouTube Dislike - main process side
// Provides an IPC endpoint to fetch dislike data, bypassing page CSP.
// Also injects the renderer script into YouTube pages in webviews.
const fs = require('fs');
const path = require('path');
module.exports.activate = function(ctx) {
const CACHE_TTL_MS = 3 * 60 * 1000; // 3 minutes
const cache = new Map(); // key: videoId -> { t, data }
async function fetchVotes(videoId) {
const url = `https://returnyoutubedislikeapi.com/votes?videoId=${encodeURIComponent(videoId)}`;
let resp;
try {
resp = await fetch(url, { method: 'GET', headers: { 'Accept': 'application/json' } });
} catch (e) {
ctx.warn('[RYD] fetch failed', e);
return null;
}
if (!resp.ok) return null;
try { return await resp.json(); } catch { return null; }
}
ctx.registerIPC('return-youtube-dislike:get', async (_e, { videoId }) => {
if (!videoId || typeof videoId !== 'string') return { ok: false, error: 'bad_args' };
const now = Date.now();
const ent = cache.get(videoId);
if (ent && (now - ent.t) < CACHE_TTL_MS) {
return { ok: true, data: ent.data, cached: true };
}
const data = await fetchVotes(videoId);
if (!data) return { ok: false, error: 'fetch_failed' };
cache.set(videoId, { t: now, data });
return { ok: true, data };
});
// Load the renderer script
const rendererScriptPath = path.join(ctx.paths.pluginDir, 'renderer-preload.js');
let rendererScript = '';
try {
rendererScript = fs.readFileSync(rendererScriptPath, 'utf8');
} catch (e) {
ctx.error('[RYD] Failed to load renderer script:', e);
return;
}
// Listen for web contents creation to inject into YouTube pages
ctx.on('web-contents-created', (contents) => {
// Only inject into webviews (guest pages), not the main window
if (!contents.hostWebContents) return;
// Handle IPC messages from the injected script
contents.on('ipc-message', async (event, message) => {
if (message && message.data && message.data.channel === 'return-youtube-dislike:get') {
const { videoId, id } = message.data.args[0];
try {
const data = await fetchVotes(videoId);
if (data) {
event.reply('return-youtube-dislike:get', { ok: true, data, id });
} else {
event.reply('return-youtube-dislike:get', { ok: false, error: 'fetch_failed', id });
}
} catch (e) {
event.reply('return-youtube-dislike:get', { ok: false, error: e.message, id });
}
}
});
contents.on('dom-ready', () => {
const url = contents.getURL();
if (!url || !/^(?:.*\.)?youtube\.com$/.test(new URL(url).hostname)) return;
// Inject the script into the guest page
try {
contents.executeJavaScript(rendererScript);
ctx.log('[RYD] Injected script into YouTube page');
} catch (e) {
ctx.warn('[RYD] Failed to inject script:', e);
}
});
});
ctx.log('Return YouTube Dislike plugin activated');
};