mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-07-04 14:43:01 +02:00
leechblock: switch defaults to gist JSON, seed LevelDB directly, block unsupported browsers
- Replace leechblock_defaults.js with LeechBlockOptions.json fetched from private gist (30 block sets, 1568 keys) - Add seed_leechblock_storage.js: writes settings directly into Chrome's LevelDB via classic-level, bypassing content-verification entirely - Supports both .json and legacy .js defaults files - Chunked writes (individual db.put) to avoid batch size limits - Per-profile error isolation; Thorium LevelDB warning demoted to non-fatal - Add package.json (type:module + classic-level dep) and .gitignore for node_modules - install_leechblock.sh: drop background.js patching, call seeder instead; auto-installs classic-level if node_modules absent - install_pacman_wrapper.sh: deploy .json defaults, seeder, and package.json to /usr/local/share/digital_wellbeing; run npm install there - pacman_blocked_keywords.txt: add browsers not handled by install script (Microsoft Edge family, firefox-esr/nightly, opera-beta/dev, iridium, slimjet, chromium-dev, qutebrowser, midori)
This commit is contained in:
parent
21c9180b00
commit
720a291388
1
linux_configuration/scripts/digital_wellbeing/.gitignore
vendored
Normal file
1
linux_configuration/scripts/digital_wellbeing/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
node_modules/
|
||||
@ -199,70 +199,53 @@ fi
|
||||
EXT_PATH="$CURRENT_LINK" # stable path used by wrappers
|
||||
|
||||
# ── Inject default blocking configuration ─────────────────────────────
|
||||
# Copy leechblock_defaults.js alongside the extension and patch
|
||||
# background.js to import it and seed storage on first run.
|
||||
# Write default blocking rules directly into Chrome's LevelDB extension
|
||||
# storage via Node.js (classic-level). This is content-verification-proof:
|
||||
# we never touch any extension JS file, so Chrome cannot detect tampering.
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
DEFAULTS_SRC="$SCRIPT_DIR/leechblock_defaults.js"
|
||||
DEFAULTS_SRC="$SCRIPT_DIR/leechblock_defaults.json"
|
||||
|
||||
if [[ -f $DEFAULTS_SRC ]]; then
|
||||
cp "$DEFAULTS_SRC" "$VERSION_DIR/defaults.js"
|
||||
info "Copied default blocking configuration into extension"
|
||||
|
||||
BG_JS="$VERSION_DIR/background.js"
|
||||
if [[ -f $BG_JS ]]; then
|
||||
# 1) Add importScripts("defaults.js") right after importScripts("common.js")
|
||||
if ! grep -q 'importScripts("defaults.js")' "$BG_JS"; then
|
||||
sed -i 's|importScripts("common.js");|importScripts("common.js");\nimportScripts("defaults.js");|' "$BG_JS"
|
||||
info "Patched background.js to import defaults.js"
|
||||
fi
|
||||
# Ensure classic-level is available next to this script.
|
||||
if [[ ! -d "$SCRIPT_DIR/node_modules/classic-level" ]]; then
|
||||
info "Installing classic-level npm package into $SCRIPT_DIR ..."
|
||||
npm install --prefix "$SCRIPT_DIR" 2>&1 | grep -v '^npm warn' || true
|
||||
fi
|
||||
|
||||
# 2) Inject first-run seeding logic after cleanTimeData(gOptions)
|
||||
if ! grep -q 'LEECHBLOCK_DEFAULTS' "$BG_JS"; then
|
||||
sed -i '/cleanTimeData(gOptions);/a\
|
||||
\
|
||||
\t\t// ── Seed default blocking rules on first run ──\
|
||||
\t\tif (typeof LEECHBLOCK_DEFAULTS !== "undefined") {\
|
||||
\t\t\tlet hasAnySites = false;\
|
||||
\t\t\tfor (let s = 1; s <= +gOptions["numSets"]; s++) {\
|
||||
\t\t\t\tif (gOptions["sites" + s]) { hasAnySites = true; break; }\
|
||||
\t\t\t}\
|
||||
\t\t\tif (!hasAnySites) {\
|
||||
\t\t\t\tfor (let key in LEECHBLOCK_DEFAULTS) {\
|
||||
\t\t\t\t\tgOptions[key] = LEECHBLOCK_DEFAULTS[key];\
|
||||
\t\t\t\t}\
|
||||
\t\t\t\tcleanOptions(gOptions);\
|
||||
\t\t\t\tcleanTimeData(gOptions);\
|
||||
\t\t\t\tgNumSets = +gOptions["numSets"];\
|
||||
\t\t\t\tgStorage.set(gOptions).catch(\
|
||||
\t\t\t\t\tfunction (e) { warn("Cannot seed defaults: " + e); }\
|
||||
\t\t\t\t);\
|
||||
\t\t\t\tlog("Seeded default blocking configuration");\
|
||||
\t\t\t}\
|
||||
\t\t}' "$BG_JS"
|
||||
info "Patched background.js with first-run seeding logic"
|
||||
fi
|
||||
# Chrome locks its LevelDB files while running — close all Chromium browsers
|
||||
# so the write succeeds.
|
||||
pkill -f 'google-chrome|chromium|brave-browser|vivaldi|thorium' 2>/dev/null || true
|
||||
sleep 1
|
||||
|
||||
# Seed defaults into every Chrome/Chromium profile found on this machine.
|
||||
if node "$SCRIPT_DIR/seed_leechblock_storage.js" "$DEFAULTS_SRC"; then
|
||||
info "Seeded default LeechBlock settings into browser storage"
|
||||
else
|
||||
warn "Could not seed LeechBlock defaults — run manually after install:"
|
||||
warn " node $SCRIPT_DIR/seed_leechblock_storage.js $DEFAULTS_SRC"
|
||||
fi
|
||||
else
|
||||
warn "leechblock_defaults.js not found at $DEFAULTS_SRC — skipping default config"
|
||||
warn "leechblock_defaults.json not found at $DEFAULTS_SRC — skipping default config"
|
||||
fi
|
||||
|
||||
# Detect browsers
|
||||
declare -A BROWSERS
|
||||
BROWSERS=(
|
||||
[chromium]="Chromium"
|
||||
[google - chrome - stable]="Google Chrome"
|
||||
[google - chrome]="Google Chrome"
|
||||
[brave - browser]="Brave"
|
||||
[vivaldi - stable]="Vivaldi"
|
||||
[google-chrome-stable]="Google Chrome"
|
||||
[google-chrome]="Google Chrome"
|
||||
[brave-browser]="Brave"
|
||||
[vivaldi-stable]="Vivaldi"
|
||||
[vivaldi]="Vivaldi"
|
||||
[opera]="Opera"
|
||||
[thorium - browser]="Thorium"
|
||||
[thorium-browser]="Thorium"
|
||||
)
|
||||
|
||||
declare -A FIREFOXES
|
||||
FIREFOXES=(
|
||||
[firefox]="Firefox"
|
||||
[firefox - developer - edition]="Firefox Developer Edition"
|
||||
[firefox-developer-edition]="Firefox Developer Edition"
|
||||
[librewolf]="LibreWolf"
|
||||
)
|
||||
|
||||
@ -272,32 +255,69 @@ found_any=0
|
||||
user_apps_dir="${XDG_DATA_HOME:-$HOME/.local/share}/applications"
|
||||
mkdir -p "$user_apps_dir"
|
||||
|
||||
# Replace the system browser launcher in-place so every launch includes LeechBlock.
|
||||
# The original script/binary is backed up as <path>.orig.
|
||||
# Requires sudo for system paths (/usr/bin).
|
||||
# Inject --load-extension into a browser launcher so every launch includes LeechBlock.
|
||||
# Handles two cases:
|
||||
# 1) The binary is a shell script with an "exec" line — patch it in-place.
|
||||
# 2) The binary is a compiled ELF — wrap it with a shell script.
|
||||
# Follows symlinks only one level to avoid breaking shared wrapper scripts
|
||||
# (e.g. browser-preexec-wrapper used by multiple browser symlinks).
|
||||
# Requires sudo for system paths.
|
||||
replace_browser_in_place() {
|
||||
local bin="$1"
|
||||
shift
|
||||
local pretty="$1"
|
||||
shift
|
||||
|
||||
local bin_path
|
||||
bin_path=$(command -v "$bin" || true)
|
||||
[[ -z $bin_path ]] && return
|
||||
|
||||
# Resolve symlinks to find the actual file to patch.
|
||||
# Use readlink -f to get the canonical path.
|
||||
local real_bin
|
||||
real_bin=$(command -v "$bin" || true)
|
||||
[[ -z $real_bin ]] && return
|
||||
real_bin=$(readlink -f "$bin_path")
|
||||
|
||||
# Resolve to absolute path (handles symlinks etc.)
|
||||
real_bin=$(readlink -f "$real_bin")
|
||||
local load_ext_flag="--load-extension=\"$EXT_PATH\""
|
||||
|
||||
local orig_backup="${real_bin}.orig"
|
||||
|
||||
# If already wrapped, skip (idempotent)
|
||||
if grep -q '__LEECHBLOCK_WRAPPER__' "$real_bin" 2>/dev/null; then
|
||||
info "$pretty ($bin) already wrapped — skipping"
|
||||
# If already patched, skip (idempotent)
|
||||
if grep -q -- "$load_ext_flag" "$real_bin" 2>/dev/null; then
|
||||
info "$pretty ($bin) already has LeechBlock --load-extension — skipping"
|
||||
found_any=1
|
||||
return
|
||||
fi
|
||||
|
||||
# Kill running instances so the new wrapper takes effect
|
||||
# Case 1: Shell script with an exec line — patch the exec line directly.
|
||||
# This preserves the original script's logic (e.g. basename routing,
|
||||
# hosts enforcement) and avoids breaking shared wrapper scripts.
|
||||
if file "$real_bin" 2>/dev/null | grep -qi 'text\|script'; then
|
||||
if grep -qE '^exec ' "$real_bin"; then
|
||||
info "Patching exec line in $real_bin to add LeechBlock…"
|
||||
|
||||
# Kill running instances so the patched script takes effect
|
||||
pkill -f "$real_bin" 2>/dev/null || true
|
||||
sleep 1
|
||||
|
||||
# Back up before patching (only once)
|
||||
local orig_backup="${real_bin}.orig"
|
||||
if [[ ! -f $orig_backup ]]; then
|
||||
info "Backing up $real_bin → $orig_backup"
|
||||
sudo cp -a "$real_bin" "$orig_backup"
|
||||
fi
|
||||
|
||||
# Insert --load-extension right after "exec <command>" on the exec line.
|
||||
# Matches: exec "$real_bin" "$@" or exec /path/to/bin $FLAGS "$@"
|
||||
sudo sed -i "s|^exec \(.*\) \"\\\$@\"|exec \1 $load_ext_flag \"\\\$@\"|" "$real_bin"
|
||||
|
||||
info "✓ $pretty exec line patched with LeechBlock"
|
||||
found_any=1
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
# Case 2: Binary or script without a recognisable exec line — wrap it.
|
||||
local orig_backup="${real_bin}.orig"
|
||||
|
||||
# Kill running instances
|
||||
info "Killing running $pretty instances…"
|
||||
pkill -f "$real_bin" 2>/dev/null || true
|
||||
pkill -f "$(basename "$real_bin")" 2>/dev/null || true
|
||||
|
||||
@ -1,151 +0,0 @@
|
||||
/* LeechBlock NG default blocking configuration.
|
||||
*
|
||||
* Loaded by background.js via importScripts().
|
||||
* On first run (no sites configured), these defaults are seeded into
|
||||
* chrome.storage.local so the extension starts pre-configured.
|
||||
*
|
||||
* Mirrors the domains blocked in linux_configuration/hosts/install.sh.
|
||||
* With matchSubdomains=true, listing "youtube.com" automatically covers
|
||||
* www.youtube.com, m.youtube.com, etc.
|
||||
*
|
||||
* Maintained by install_leechblock.sh — edit THIS file then re-run the
|
||||
* installer to push changes into the extension.
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const LEECHBLOCK_DEFAULTS = {
|
||||
|
||||
// ── General options ────────────────────────────────────────────────
|
||||
numSets: "6",
|
||||
matchSubdomains: true,
|
||||
|
||||
// ── Set 1 — YouTube & alternative front-ends ───────────────────────
|
||||
setName1: "YouTube",
|
||||
sites1: [
|
||||
// Core YouTube
|
||||
"youtube.com",
|
||||
"youtu.be",
|
||||
"youtube-nocookie.com",
|
||||
"youtubei.googleapis.com",
|
||||
"youtube.googleapis.com",
|
||||
"yt3.ggpht.com",
|
||||
"ytimg.com",
|
||||
"googlevideo.com",
|
||||
// Invidious instances
|
||||
"invidious.io",
|
||||
"invidio.us",
|
||||
"vid.puffyan.us",
|
||||
"yewtu.be",
|
||||
"invidious.kavin.rocks",
|
||||
"inv.riverside.rocks",
|
||||
"invidious.namazso.eu",
|
||||
"invidious.nerdvpn.de",
|
||||
"invidious.projectsegfau.lt",
|
||||
"invidious.slipfox.xyz",
|
||||
"invidious.privacydev.net",
|
||||
"invidious.perennialte.ch",
|
||||
"invidious.protokoll-11.de",
|
||||
"invidious.einfachzocken.eu",
|
||||
"invidious.fdn.fr",
|
||||
"inv.in.projectsegfau.lt",
|
||||
"invidious.tiekoetter.com",
|
||||
"invidious.lunar.icu",
|
||||
"iv.ggtyler.dev",
|
||||
"iv.melmac.space",
|
||||
"invidious.incogniweb.net",
|
||||
"invidious.drgns.space",
|
||||
"invidious.io.lol",
|
||||
"inv.n8pjl.ca",
|
||||
"inv.zzls.xyz",
|
||||
"inv.tux.pizza",
|
||||
// Piped instances
|
||||
"piped.video",
|
||||
"piped.kavin.rocks",
|
||||
"piped.mha.fi",
|
||||
"piped.mint.lgbt",
|
||||
"piped.projectsegfau.lt",
|
||||
"piped.privacydev.net",
|
||||
"piped.smnz.de",
|
||||
"piped.adminforge.de",
|
||||
"watch.whatever.social",
|
||||
"piped.lunar.icu",
|
||||
// Other alternative clients / front-ends
|
||||
"viewtube.io",
|
||||
"freetube.io",
|
||||
"tubo.media",
|
||||
"materialious.nadeko.net",
|
||||
"clipious.org",
|
||||
"newpipe.net",
|
||||
"newpipe.schabi.org",
|
||||
"grayjay.app",
|
||||
"libretube.dev",
|
||||
"hyperion.deishelon.com",
|
||||
].join(" "),
|
||||
times1: "0000-2400",
|
||||
days1: [true, true, true, true, true, true, true],
|
||||
|
||||
// ── Set 2 — Food delivery services ─────────────────────────────────
|
||||
setName2: "Food Delivery",
|
||||
sites2: [
|
||||
// Polish services
|
||||
"pyszne.pl",
|
||||
"glovo.com",
|
||||
"glovoapp.com",
|
||||
"bolt.eu",
|
||||
"woltwojta.pl",
|
||||
"wolt.com",
|
||||
"jush.pl",
|
||||
"delio.pl",
|
||||
"delio.com",
|
||||
"delio.com.pl",
|
||||
"lisek.app",
|
||||
"stava.app",
|
||||
"biedronka.pl",
|
||||
"barbora.pl",
|
||||
"frisco.pl",
|
||||
"swiatkwiatow.pl",
|
||||
"szama.pl",
|
||||
"auchandirect.pl",
|
||||
// International services
|
||||
"ubereats.com",
|
||||
"uber.com",
|
||||
"deliveroo.com",
|
||||
"deliveroo.co.uk",
|
||||
"foodpanda.com",
|
||||
"grubhub.com",
|
||||
"doordash.com",
|
||||
"justeat.com",
|
||||
"justeat.co.uk",
|
||||
"postmates.com",
|
||||
"seamless.com",
|
||||
"menulog.com.au",
|
||||
"delivery.com",
|
||||
"getir.com",
|
||||
"flink.com",
|
||||
"gorillas.io",
|
||||
"gopuff.com",
|
||||
"instacart.com",
|
||||
"takeaway.com",
|
||||
].join(" "),
|
||||
times2: "0000-2400",
|
||||
days2: [true, true, true, true, true, true, true],
|
||||
|
||||
// ── Set 3 — Fast food chain websites ───────────────────────────────
|
||||
setName3: "Fast Food",
|
||||
sites3: [
|
||||
"mcdonalds.com",
|
||||
"mcdonalds.pl",
|
||||
"kfc.com",
|
||||
"kfc.pl",
|
||||
"burgerking.com",
|
||||
"burgerking.pl",
|
||||
"pizzahut.com",
|
||||
"pizzahut.pl",
|
||||
"dominos.com",
|
||||
"dominos.pl",
|
||||
"subway.com",
|
||||
"subway.pl",
|
||||
].join(" "),
|
||||
times3: "0000-2400",
|
||||
days3: [true, true, true, true, true, true, true],
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
214
linux_configuration/scripts/digital_wellbeing/package-lock.json
generated
Normal file
214
linux_configuration/scripts/digital_wellbeing/package-lock.json
generated
Normal file
@ -0,0 +1,214 @@
|
||||
{
|
||||
"name": "digital-wellbeing-tools",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "digital-wellbeing-tools",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"classic-level": "^1.4.1"
|
||||
}
|
||||
},
|
||||
"node_modules/abstract-level": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/abstract-level/-/abstract-level-1.0.4.tgz",
|
||||
"integrity": "sha512-eUP/6pbXBkMbXFdx4IH2fVgvB7M0JvR7/lIL33zcs0IBcwjdzSSl31TOJsaCzmKSSDF9h8QYSOJux4Nd4YJqFg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"buffer": "^6.0.3",
|
||||
"catering": "^2.1.0",
|
||||
"is-buffer": "^2.0.5",
|
||||
"level-supports": "^4.0.0",
|
||||
"level-transcoder": "^1.0.1",
|
||||
"module-error": "^1.0.1",
|
||||
"queue-microtask": "^1.2.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/buffer": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
|
||||
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base64-js": "^1.3.1",
|
||||
"ieee754": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/catering": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/catering/-/catering-2.1.1.tgz",
|
||||
"integrity": "sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/classic-level": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/classic-level/-/classic-level-1.4.1.tgz",
|
||||
"integrity": "sha512-qGx/KJl3bvtOHrGau2WklEZuXhS3zme+jf+fsu6Ej7W7IP/C49v7KNlWIsT1jZu0YnfzSIYDGcEWpCa1wKGWXQ==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"abstract-level": "^1.0.2",
|
||||
"catering": "^2.1.0",
|
||||
"module-error": "^1.0.1",
|
||||
"napi-macros": "^2.2.2",
|
||||
"node-gyp-build": "^4.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/is-buffer": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
|
||||
"integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/level-supports": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/level-supports/-/level-supports-4.0.1.tgz",
|
||||
"integrity": "sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/level-transcoder": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/level-transcoder/-/level-transcoder-1.0.1.tgz",
|
||||
"integrity": "sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"buffer": "^6.0.3",
|
||||
"module-error": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/module-error": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/module-error/-/module-error-1.0.2.tgz",
|
||||
"integrity": "sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/napi-macros": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.2.2.tgz",
|
||||
"integrity": "sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-gyp-build": {
|
||||
"version": "4.8.4",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
|
||||
"integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"node-gyp-build": "bin.js",
|
||||
"node-gyp-build-optional": "optional.js",
|
||||
"node-gyp-build-test": "build-test.js"
|
||||
}
|
||||
},
|
||||
"node_modules/queue-microtask": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
}
|
||||
10
linux_configuration/scripts/digital_wellbeing/package.json
Normal file
10
linux_configuration/scripts/digital_wellbeing/package.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "digital-wellbeing-tools",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"description": "Node.js helpers for the digital-wellbeing scripts (e.g. LeechBlock storage seeder).",
|
||||
"scripts": {},
|
||||
"dependencies": {
|
||||
"classic-level": "^1.4.1"
|
||||
}
|
||||
}
|
||||
@ -30,6 +30,14 @@ WHITELIST_DEST="${INSTALL_DIR}/pacman_whitelist.txt"
|
||||
GREYLIST_DEST="${INSTALL_DIR}/pacman_greylist.txt"
|
||||
INTEGRITY_DIR="/var/lib/pacman-wrapper"
|
||||
INTEGRITY_FILE="${INTEGRITY_DIR}/policy.sha256"
|
||||
LEECHBLOCK_INSTALLER_SOURCE="$(dirname "$0")/../install_leechblock.sh"
|
||||
LEECHBLOCK_DEFAULTS_SOURCE="$(dirname "$0")/../leechblock_defaults.json"
|
||||
LEECHBLOCK_SEEDER_SOURCE="$(dirname "$0")/../seed_leechblock_storage.js"
|
||||
LEECHBLOCK_PKG_SOURCE="$(dirname "$0")/../package.json"
|
||||
LEECHBLOCK_INSTALL_DIR="/usr/local/share/digital_wellbeing"
|
||||
LEECHBLOCK_INSTALLER_DEST="${LEECHBLOCK_INSTALL_DIR}/install_leechblock.sh"
|
||||
LEECHBLOCK_DEFAULTS_DEST="${LEECHBLOCK_INSTALL_DIR}/leechblock_defaults.json"
|
||||
LEECHBLOCK_SEEDER_DEST="${LEECHBLOCK_INSTALL_DIR}/seed_leechblock_storage.js"
|
||||
VBOX_ENFORCE_SOURCE="$(dirname "$0")/../virtualbox/enforce_vbox_hosts.sh"
|
||||
VBOX_INSTALL_DIR="/usr/local/share/digital_wellbeing/virtualbox"
|
||||
VBOX_ENFORCE_DEST="${VBOX_INSTALL_DIR}/enforce_vbox_hosts.sh"
|
||||
@ -133,6 +141,30 @@ else
|
||||
echo -e "${YELLOW}Warning: chattr not available, policy files will not be immutable${NC}"
|
||||
fi
|
||||
|
||||
# Install LeechBlock installer and defaults if available
|
||||
mkdir -p "$LEECHBLOCK_INSTALL_DIR"
|
||||
if [ -f "$LEECHBLOCK_INSTALLER_SOURCE" ]; then
|
||||
echo -e "${BLUE}Installing LeechBlock installer to ${LEECHBLOCK_INSTALLER_DEST}...${NC}"
|
||||
cp "$LEECHBLOCK_INSTALLER_SOURCE" "$LEECHBLOCK_INSTALLER_DEST"
|
||||
chmod +x "$LEECHBLOCK_INSTALLER_DEST"
|
||||
echo -e "${GREEN}LeechBlock installer deployed to ${LEECHBLOCK_INSTALLER_DEST}${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}LeechBlock installer not found at ${LEECHBLOCK_INSTALLER_SOURCE}, skipping...${NC}"
|
||||
fi
|
||||
if [ -f "$LEECHBLOCK_DEFAULTS_SOURCE" ]; then
|
||||
cp "$LEECHBLOCK_DEFAULTS_SOURCE" "$LEECHBLOCK_DEFAULTS_DEST"
|
||||
echo -e "${GREEN}LeechBlock defaults deployed to ${LEECHBLOCK_DEFAULTS_DEST}${NC}"
|
||||
fi
|
||||
if [ -f "$LEECHBLOCK_SEEDER_SOURCE" ]; then
|
||||
cp "$LEECHBLOCK_SEEDER_SOURCE" "$LEECHBLOCK_SEEDER_DEST"
|
||||
echo -e "${GREEN}LeechBlock seeder deployed to ${LEECHBLOCK_SEEDER_DEST}${NC}"
|
||||
fi
|
||||
if [ -f "$LEECHBLOCK_PKG_SOURCE" ]; then
|
||||
cp "$LEECHBLOCK_PKG_SOURCE" "${LEECHBLOCK_INSTALL_DIR}/package.json"
|
||||
echo -e "${BLUE}Installing Node.js deps in ${LEECHBLOCK_INSTALL_DIR}...${NC}"
|
||||
npm install --prefix "$LEECHBLOCK_INSTALL_DIR" 2>&1 | grep -v '^npm warn' || true
|
||||
fi
|
||||
|
||||
# Install VirtualBox enforcement script if available
|
||||
if [ -f "$VBOX_ENFORCE_SOURCE" ]; then
|
||||
echo -e "${BLUE}Installing VirtualBox hosts enforcement script...${NC}"
|
||||
|
||||
@ -53,10 +53,26 @@ netsurf
|
||||
amfora
|
||||
tartube
|
||||
youtube
|
||||
# Chrome/Chromium variants
|
||||
# Chrome/Chromium variants not handled by install_leechblock.sh
|
||||
google-chrome
|
||||
chromium
|
||||
ungoogled-chromium
|
||||
microsoft-edge
|
||||
microsoft-edge-stable
|
||||
microsoft-edge-beta
|
||||
microsoft-edge-dev
|
||||
iridium
|
||||
slimjet
|
||||
chromium-dev
|
||||
# Firefox variants not handled by install_leechblock.sh
|
||||
firefox-esr
|
||||
firefox-nightly
|
||||
# Opera variants not in BROWSERS array
|
||||
opera-beta
|
||||
opera-developer
|
||||
# Qt/WebKit/other GUI browsers not handled by install_leechblock.sh
|
||||
qutebrowser
|
||||
midori
|
||||
# VirtualBox (can bypass /etc/hosts restrictions)
|
||||
virtualbox
|
||||
vbox
|
||||
|
||||
@ -738,12 +738,10 @@ auto_install_leechblock() {
|
||||
script_dir="$(dirname "$(readlink -f "$0")")"
|
||||
local leechblock_installer=""
|
||||
|
||||
if [[ -f "$script_dir/../install_leechblock.sh" ]]; then
|
||||
leechblock_installer="$script_dir/../install_leechblock.sh"
|
||||
elif [[ -f "$HOME/linux-configuration/scripts/digital_wellbeing/install_leechblock.sh" ]]; then
|
||||
leechblock_installer="$HOME/linux-configuration/scripts/digital_wellbeing/install_leechblock.sh"
|
||||
elif [[ -f "/usr/local/share/digital_wellbeing/install_leechblock.sh" ]]; then
|
||||
if [[ -f "/usr/local/share/digital_wellbeing/install_leechblock.sh" ]]; then
|
||||
leechblock_installer="/usr/local/share/digital_wellbeing/install_leechblock.sh"
|
||||
elif [[ -f "$script_dir/../install_leechblock.sh" ]]; then
|
||||
leechblock_installer="$script_dir/../install_leechblock.sh"
|
||||
fi
|
||||
|
||||
if [[ -z $leechblock_installer ]]; then
|
||||
|
||||
125
linux_configuration/scripts/digital_wellbeing/seed_leechblock_storage.js
Executable file
125
linux_configuration/scripts/digital_wellbeing/seed_leechblock_storage.js
Executable file
@ -0,0 +1,125 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* seed_leechblock_storage.js
|
||||
*
|
||||
* Writes LeechBlock NG default settings directly into Chrome's extension
|
||||
* LevelDB storage. This bypasses Chrome's content-verification and service
|
||||
* worker caching entirely.
|
||||
*
|
||||
* Usage:
|
||||
* node seed_leechblock_storage.js <path/to/defaults.js> [--force]
|
||||
*
|
||||
* Must be run while Chrome is NOT open.
|
||||
*
|
||||
* Requires: classic-level (npm install classic-level)
|
||||
*/
|
||||
|
||||
import { ClassicLevel } from "classic-level";
|
||||
import { readFileSync, existsSync } from "fs";
|
||||
import path from "path";
|
||||
import os from "os";
|
||||
|
||||
// ── CLI args ─────────────────────────────────────────────────────────
|
||||
const args = process.argv.slice(2);
|
||||
const force = args.includes("--force");
|
||||
const defaultsPath = args.find((a) => !a.startsWith("--"));
|
||||
|
||||
if (!defaultsPath) {
|
||||
console.error("Usage: node seed_leechblock_storage.js <defaults.js> [--force]");
|
||||
process.exit(1);
|
||||
}
|
||||
if (!existsSync(defaultsPath)) {
|
||||
console.error(`defaults.js not found: ${defaultsPath}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// ── Load defaults from .json or .js file ────────────────────────────
|
||||
const src = readFileSync(defaultsPath, "utf8");
|
||||
let DEFAULTS;
|
||||
try {
|
||||
if (defaultsPath.endsWith(".json")) {
|
||||
DEFAULTS = JSON.parse(src);
|
||||
} else {
|
||||
// Legacy .js format: const LEECHBLOCK_DEFAULTS = { ... }
|
||||
// eslint-disable-next-line no-new-func
|
||||
DEFAULTS = new Function(src + "\nreturn LEECHBLOCK_DEFAULTS;")();
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Failed to load defaults file:", e.message);
|
||||
process.exit(1);
|
||||
}
|
||||
console.log(`Loaded ${Object.keys(DEFAULTS).length} keys from ${defaultsPath}`);
|
||||
|
||||
// ── Known CWS extension ID for LeechBlock NG ─────────────────────────
|
||||
const EXT_ID = "blaaajhemilngeeffpbfkdjjoefldkok";
|
||||
|
||||
// ── Find all Chrome/Chromium profile dirs with this extension ────────
|
||||
const configDirs = [
|
||||
path.join(os.homedir(), ".config/google-chrome"),
|
||||
path.join(os.homedir(), ".config/chromium"),
|
||||
path.join(os.homedir(), ".config/BraveSoftware/Brave-Browser"),
|
||||
path.join(os.homedir(), ".config/vivaldi"),
|
||||
path.join(os.homedir(), ".config/thorium"),
|
||||
];
|
||||
|
||||
async function seedProfile(storageDir) {
|
||||
const db = new ClassicLevel(storageDir, { createIfMissing: true });
|
||||
try {
|
||||
// Check for existing sites unless --force
|
||||
if (!force) {
|
||||
let hasAnySites = false;
|
||||
const numSets = +(DEFAULTS.numSets ?? 6);
|
||||
for (let s = 1; s <= numSets; s++) {
|
||||
try {
|
||||
const val = await db.get(`sites${s}`);
|
||||
if (val && JSON.parse(val)) {
|
||||
hasAnySites = true;
|
||||
break;
|
||||
}
|
||||
} catch (_) {
|
||||
/* key doesn't exist */
|
||||
}
|
||||
}
|
||||
if (hasAnySites) {
|
||||
console.log(` Skipping ${storageDir} — sites already configured (use --force to override).`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const entries = Object.entries(DEFAULTS);
|
||||
for (const [key, value] of entries) {
|
||||
await db.put(key, JSON.stringify(value));
|
||||
}
|
||||
console.log(` ✓ Seeded ${entries.length} settings into ${storageDir}`);
|
||||
} finally {
|
||||
await db.close();
|
||||
}
|
||||
}
|
||||
|
||||
let found = false;
|
||||
const { readdirSync } = await import("fs");
|
||||
for (const configDir of configDirs) {
|
||||
if (!existsSync(configDir)) continue;
|
||||
// Walk profiles: Default, Profile 1, Profile 2, ...
|
||||
for (const profile of readdirSync(configDir)) {
|
||||
const storageDir = path.join(
|
||||
configDir, profile, "Local Extension Settings", EXT_ID
|
||||
);
|
||||
const extDir = path.join(configDir, profile, "Extensions", EXT_ID);
|
||||
// Only seed profiles where LeechBlock is actually installed
|
||||
if (existsSync(extDir) || existsSync(storageDir)) {
|
||||
console.log(`Seeding ${configDir}/${profile}...`);
|
||||
try {
|
||||
await seedProfile(storageDir);
|
||||
found = true;
|
||||
} catch (e) {
|
||||
console.warn(` ⚠ Failed to seed ${storageDir}: ${e.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
console.log("No LeechBlock NG installations found.");
|
||||
process.exit(0);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user