Watch Together Plugin + Electron Desktop App mit Ad-Blocker
Neuer Tab: Watch Together - gemeinsam Videos schauen (w2g.tv-Style) - Raum-System mit optionalem Passwort und Host-Kontrolle - Video-Queue mit Hinzufuegen/Entfernen/Umordnen - YouTube (IFrame API) + direkte Video-URLs (.mp4, .webm) - Synchronisierte Wiedergabe via WebSocket (/ws/watch-together) - Server-autoritative Playback-State mit Drift-Korrektur (2.5s Sync-Pulse) - Host-Transfer bei Disconnect, Room-Cleanup nach 30s Electron Desktop App (electron/): - Wrapper fuer Gaming Hub mit integriertem Ad-Blocker - uBlock-Style Request-Filtering via session.webRequest - 100+ Ad-Domains + YouTube-spezifische Filter - Download-Button im Web-Header (nur sichtbar wenn nicht in Electron) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
4943bbf4a1
commit
73f247ada3
16 changed files with 7386 additions and 4833 deletions
87
electron/ad-blocker.js
Normal file
87
electron/ad-blocker.js
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
function setupAdBlocker(session) {
|
||||
// Load filter domains
|
||||
const filtersPath = path.join(__dirname, 'filters.txt');
|
||||
let rawFilters;
|
||||
try {
|
||||
rawFilters = fs.readFileSync(filtersPath, 'utf-8');
|
||||
} catch (err) {
|
||||
console.error('[AdBlocker] Could not load filters.txt:', err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse: each line is either a domain, a URL path pattern, or a regex
|
||||
const blockedDomains = new Set();
|
||||
const blockedPatterns = [];
|
||||
|
||||
for (const line of rawFilters.split('\n')) {
|
||||
const trimmed = line.trim();
|
||||
if (!trimmed || trimmed.startsWith('#')) continue;
|
||||
|
||||
if (trimmed.startsWith('/') && trimmed.endsWith('/')) {
|
||||
// Regex pattern
|
||||
try {
|
||||
blockedPatterns.push(new RegExp(trimmed.slice(1, -1)));
|
||||
} catch {
|
||||
// invalid regex, skip
|
||||
}
|
||||
} else if (trimmed.includes('/')) {
|
||||
// URL path pattern (string match)
|
||||
blockedPatterns.push(trimmed);
|
||||
} else {
|
||||
// Domain
|
||||
blockedDomains.add(trimmed);
|
||||
}
|
||||
}
|
||||
|
||||
let blockedCount = 0;
|
||||
|
||||
session.webRequest.onBeforeRequest((details, callback) => {
|
||||
try {
|
||||
const url = new URL(details.url);
|
||||
const hostname = url.hostname;
|
||||
|
||||
// Check domain blocklist (including subdomains)
|
||||
for (const domain of blockedDomains) {
|
||||
if (hostname === domain || hostname.endsWith('.' + domain)) {
|
||||
blockedCount++;
|
||||
callback({ cancel: true });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check URL patterns
|
||||
const fullUrl = details.url;
|
||||
for (const pattern of blockedPatterns) {
|
||||
if (pattern instanceof RegExp) {
|
||||
if (pattern.test(fullUrl)) {
|
||||
blockedCount++;
|
||||
callback({ cancel: true });
|
||||
return;
|
||||
}
|
||||
} else if (fullUrl.includes(pattern)) {
|
||||
blockedCount++;
|
||||
callback({ cancel: true });
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// URL parsing error, allow request
|
||||
}
|
||||
|
||||
callback({});
|
||||
});
|
||||
|
||||
// Log stats periodically
|
||||
setInterval(() => {
|
||||
if (blockedCount > 0) {
|
||||
console.log(`[AdBlocker] ${blockedCount} requests blocked`);
|
||||
}
|
||||
}, 30000);
|
||||
|
||||
console.log(`[AdBlocker] Loaded ${blockedDomains.size} domains + ${blockedPatterns.length} patterns`);
|
||||
}
|
||||
|
||||
module.exports = { setupAdBlocker };
|
||||
Loading…
Add table
Add a link
Reference in a new issue