Files
KoalaSync/shared/blacklist.js
T
2026-08-12 02:07:34 +02:00

251 lines
5.7 KiB
JavaScript

/**
* blacklist.js
*
* ⚠️ WARNING: This is the SINGLE SOURCE OF TRUTH.
* If you edit this file, you MUST run: node scripts/build-extension.cjs
* to propagate changes to the extension and relay server.
*
* Domains to be filtered out from the tab selection dropdown to reduce "noise".
* These are typically sites that won't contain shareable video content.
*/
export const BLACKLIST_DOMAINS = [
// Search Engines & Portals
'google.com',
'bing.com',
'duckduckgo.com',
'yahoo.com',
'msn.com',
'baidu.com',
'yandex.ru',
'ecosia.org',
'startpage.com',
'search.brave.com',
'qwant.com',
'you.com',
'perplexity.ai',
'ask.com',
'search.yahoo.com',
'swisscows.ch',
'mojeek.com',
// Mail Providers
'mail.google.com',
'gmail.com',
'outlook.live.com',
'outlook.office.com',
'mail.yahoo.com',
'gmx.net',
'gmx.de',
'gmx.com',
'web.de',
'protonmail.com',
'proton.me',
't-online.de',
'posteo.de',
'mailbox.org',
'mail.de',
'zoho.com',
'fastmail.com',
'tutanota.com',
'mail.ru',
// Cloud Storage & Documents
'docs.google.com',
'sheets.google.com',
'slides.google.com',
// Messengers
'web.whatsapp.com',
'web.telegram.org',
'discord.com',
'element.io',
'app.slack.com',
// Productivity & Project Management
'atlassian.net',
'trello.com',
'notion.so',
'monday.com',
'asana.com',
'github.com',
'gitlab.com',
'bitbucket.org',
'stackoverflow.com',
// Social Media & Forums
'linkedin.com',
'twitter.com',
'x.com',
'facebook.com',
'instagram.com',
'reddit.com',
'quora.com',
'threads.net',
'bsky.app',
'mastodon.social',
'vk.com',
'weibo.com',
'9gag.com',
'imgur.com',
// E-Commerce
'ebay.com',
'aliexpress.com',
'etsy.com',
// Media Information & Reviews
'rottentomatoes.com',
'imdb.com',
'thetvdb.com',
'themoviedb.org',
'letterboxd.com',
'metacritic.com',
'myanimelist.net',
// Development & Utilities
'koalastuff.net',
'auth.koalastuff.net',
'blog.koalastuff.net',
'clicker.koalastuff.net',
'cookies.koalastuff.net',
'multibox.koalastuff.net',
'snippets.koalastuff.net',
'status.koalastuff.net',
'sync.koalastuff.net',
'timer.koalastuff.net',
'zoom.us',
'teams.microsoft.com',
'meet.google.com',
'chrome.google.com',
// Music Streaming
'music.youtube.com',
'open.spotify.com',
'soundcloud.com',
'deezer.com',
'tidal.com',
// Knowledge & Blogs
'wikipedia.org',
'medium.com',
'dev.to',
'news.ycombinator.com',
// Design & Creative Tools
'figma.com',
'canva.com',
'miro.com',
// Online IDEs & Hosting
'vscode.dev',
'replit.com',
'codesandbox.io',
'vercel.com',
'netlify.com',
// Social & Image Sharing
'pinterest.com',
'tumblr.com',
// Language Learning
'duolingo.com',
'hellotalk.com',
// Google Utilities
'calendar.google.com',
'keep.google.com',
// Finance & Payments
'paypal.com',
'stripe.com',
// Games & Idle Sites
'milkywayidle.com',
'melvoridle.com',
'orteil.dashnet.org',
'clickerheroes.com',
'kongregate.com',
'armorgames.com',
'crazygames.com',
'poki.com',
'newgrounds.com',
'krunker.io',
'slither.io',
'agar.io',
'diep.io',
'geoguessr.com',
'chess.com',
'lichess.org',
'skribbl.io'
];
export const CUSTOM_BLACKLIST_STORAGE_KEY = 'customBlacklistDomains';
export const MAX_BLACKLIST_DOMAINS = 500;
/**
* Normalize a user-entered domain or URL to a hostname.
* Returns null when the value cannot safely be used as a hostname filter.
*/
export function normalizeBlacklistDomain(value) {
if (typeof value !== 'string') return null;
const input = value.trim().toLowerCase();
if (!input) return '';
try {
const parsed = new URL(input.includes('://') ? input : `https://${input}`);
const hostname = parsed.hostname.toLowerCase().replace(/^\.+|\.+$/g, '');
if (!hostname || hostname.length > 253) return null;
const labels = hostname.split('.');
const valid = labels.every(label => (
label.length > 0
&& label.length <= 63
&& /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/.test(label)
));
return valid ? hostname : null;
} catch {
return null;
}
}
export function parseBlacklistDomains(value) {
const entries = Array.isArray(value)
? value
: String(value ?? '').split(/\r?\n/);
const domains = [];
const invalid = [];
const seen = new Set();
for (const entry of entries) {
const normalized = normalizeBlacklistDomain(entry);
if (normalized === '') continue;
if (normalized === null) {
invalid.push(String(entry).trim());
continue;
}
if (!seen.has(normalized)) {
seen.add(normalized);
domains.push(normalized);
}
}
return { domains, invalid };
}
export function getEffectiveBlacklistDomains(storedDomains) {
if (!Array.isArray(storedDomains)) return [...BLACKLIST_DOMAINS];
return parseBlacklistDomains(storedDomains).domains.slice(0, MAX_BLACKLIST_DOMAINS);
}
export function isUrlBlacklisted(rawUrl, domains = BLACKLIST_DOMAINS) {
if (typeof rawUrl !== 'string' || !rawUrl) return false;
let hostname;
try {
hostname = new URL(rawUrl).hostname.toLowerCase().replace(/\.$/, '');
} catch {
return false;
}
return domains.some(domain => hostname === domain || hostname.endsWith(`.${domain}`));
}