diff --git a/configure-searxng-safesearch.sh b/configure-searxng-safesearch.sh index c7bcd52..cd86022 100755 --- a/configure-searxng-safesearch.sh +++ b/configure-searxng-safesearch.sh @@ -55,8 +55,14 @@ done SETTINGS="$BASE/searxng/settings.yml" COMPOSE="$BASE/docker-compose.yml" -# Ensure settings directory exists -mkdir -p "$(dirname "$SETTINGS")" +# Ensure settings directory exists (fix ownership if Docker created it as root) +mkdir -p "$(dirname "$SETTINGS")" 2>/dev/null || \ + sudo mkdir -p "$(dirname "$SETTINGS")" +if [[ -e "$SETTINGS" ]] && [[ ! -w "$SETTINGS" ]]; then + warn "settings.yml not writable — fixing ownership" + sudo chown "$(id -u):$(id -g)" "$SETTINGS" || \ + die "Cannot write to $SETTINGS — run: sudo chown $USER $SETTINGS" +fi # ── Level → integer ─────────────────────────────────────────────────────────── case "$LEVEL" in diff --git a/laptop_full_setup.sh b/laptop_full_setup.sh index 6840215..788b855 100755 --- a/laptop_full_setup.sh +++ b/laptop_full_setup.sh @@ -290,52 +290,126 @@ if $SVC_KIWIX; then unset _MPTS _MP _i _KIWIX_CHOICE # ── Q4: Download ZIMs now? ───────────────────────────────────────────────── - echo "" - echo -e " ${BOLD}[4/6] Download ZIM files? (offline Wikipedia, Stack Overflow, etc.)${NC}" - echo " Downloads run in the background — safe to start now and leave overnight." - echo " Total: ~130GB (Wikipedia 46GB, Project Gutenberg 60GB, others smaller)" - echo "" - echo " 1) Yes — download all ZIMs overnight (~130GB)" - echo " 2) Select — choose which ZIMs to download" - echo " 3) No — skip for now (run ./kiwix_download.sh later)" - echo "" - read -rp " Choice [3]: " ZIM_CHOICE - ZIM_CHOICE="${ZIM_CHOICE:-3}" + # ON if any matching ZIM file already exists in KIWIX_DIR + _zimon() { ls "$KIWIX_DIR/${1}"*.zim 2>/dev/null | grep -q . && echo ON || echo OFF; } - # ── Q4a: ZIM selection (only if choice == 2) ────────────────────────────── + ZIM_CHOICE="3" ZIM_PICKS="" - if [[ "$ZIM_CHOICE" == "2" ]]; then - # Helper: show [done] if a ZIM matching a glob pattern already exists - _zim_tag() { - local pattern="$1" - ls "$KIWIX_DIR"/${pattern}*.zim 2>/dev/null | grep -q . && echo " ${GREEN}[downloaded]${NC}" || echo "" - } + + if command -v whiptail &>/dev/null && [[ -t 0 ]]; then + if _ZIM_MODE=$(whiptail --backtitle "Kiwix" \ + --title "[4/6] Kiwix ZIM Downloads" \ + --radiolist "Download offline Wikipedia, Stack Overflow, etc.? (runs in background)" \ + 11 68 3 \ + "select" "Choose individual ZIMs " ON \ + "all" "Download everything (~130 GB) " OFF \ + "skip" "Skip — run kiwix_download.sh later " OFF \ + 3>&1 1>&2 2>&3 2>/dev/null); then + _ZIM_MODE="${_ZIM_MODE//\"/}" + case "$_ZIM_MODE" in + all) ZIM_CHOICE="1" ;; + select|*) + ZIM_CHOICE="2" + if _ZIM_SEL=$(whiptail --backtitle "Kiwix" \ + --title "Select ZIMs to Download" \ + --checklist "SPACE = toggle ENTER = confirm ESC = skip\nPre-checked = already downloaded" \ + 24 72 16 \ + "wikipedia" "$(printf '%-30s %7s' 'Wikipedia' '~46 GB')" "$(_zimon wikipedia_en_all_nopic)" \ + "stackoverflow" "$(printf '%-30s %7s' 'Stack Overflow' '~3 GB')" "$(_zimon stackoverflow.com_en_all)" \ + "archlinux" "$(printf '%-30s %7s' 'Arch Linux Wiki' '~30 MB')" "$(_zimon archlinux_en_all)" \ + "wiktionary" "$(printf '%-30s %7s' 'Wiktionary' '~2 GB')" "$(_zimon wiktionary_en_all_nopic)" \ + "wikibooks" "$(printf '%-30s %7s' 'Wikibooks' '~500 MB')" "$(_zimon wikibooks_en_all_nopic)" \ + "wikisource" "$(printf '%-30s %7s' 'Wikisource' '~4 GB')" "$(_zimon wikisource_en_all_nopic)" \ + "wikivoyage" "$(printf '%-30s %7s' 'Wikivoyage' '~200 MB')" "$(_zimon wikivoyage_en_all_nopic)" \ + "wikiversity" "$(printf '%-30s %7s' 'Wikiversity' '~500 MB')" "$(_zimon wikiversity_en_all_nopic)" \ + "wikinews" "$(printf '%-30s %7s' 'WikiNews' '~300 MB')" "$(_zimon wikinews_en_all_nopic)" \ + "wikiquote" "$(printf '%-30s %7s' 'Wikiquote' '~300 MB')" "$(_zimon wikiquote_en_all_nopic)" \ + "vikidia" "$(printf '%-30s %7s' 'Vikidia (kids K-8)' '~66 MB')" "$(_zimon vikidia_en_all_nopic)" \ + "ted" "$(printf '%-30s %7s' 'TED Talks' '~5 GB')" "$(_zimon ted_mul_youth)" \ + "phet" "$(printf '%-30s %7s' 'PhET Simulations' '~500 MB')" "$(_zimon phet_en_all)" \ + "devdocs" "$(printf '%-30s %7s' 'DevDocs' '~1 GB')" "$(_zimon devdocs_en_zig)" \ + "freecodecamp" "$(printf '%-30s %7s' 'FreeCodeCamp' 'small')" "$(_zimon freecodecamp_en_all)" \ + "ifixit" "$(printf '%-30s %7s' 'iFixit' '~2 GB')" "$(_zimon ifixit_en_all)" \ + "libretexts" "$(printf '%-30s %7s' 'LibreTexts' 'varies')" "$(_zimon libretexts.org_en)" \ + "gutenberg" "$(printf '%-30s %7s' 'Project Gutenberg' '~60 GB')" "$(_zimon gutenberg_en_all)" \ + 3>&1 1>&2 2>&3 2>/dev/null); then + if [[ -n "$_ZIM_SEL" ]]; then + ZIM_PICKS=$(tr -d '"' <<< "$_ZIM_SEL") + else + ZIM_CHOICE="3" # Enter with nothing checked → skip + fi + else + ZIM_CHOICE="3" # ESC → skip + fi + ;; + esac + fi # ESC on radiolist → ZIM_CHOICE stays "3" + else + # Text fallback echo "" - echo " Select ZIMs to download (space-separated numbers, e.g. 1 3 5):" - echo " ZIMs already in $KIWIX_DIR are marked [downloaded]." + echo -e " ${BOLD}[4/6] Download ZIM files? (offline Wikipedia, Stack Overflow, etc.)${NC}" + echo " Downloads run in the background — safe to start now and leave overnight." + echo " Total: ~130GB (Wikipedia 46GB, Project Gutenberg 60GB, others smaller)" echo "" - printf " %2s) %-26s %6s %s\n" 1 "Wikipedia" "~46GB" "$(_zim_tag "wikipedia_en_all_nopic")" - printf " %2s) %-26s %6s %s\n" 2 "Stack Overflow" "~3GB" "$(_zim_tag "stackoverflow.com_en_all")" - printf " %2s) %-26s %6s %s\n" 3 "Arch Linux Wiki" "~30MB" "$(_zim_tag "archlinux_en_all")" - printf " %2s) %-26s %6s %s\n" 4 "Wiktionary" "~2GB" "$(_zim_tag "wiktionary_en_all_nopic")" - printf " %2s) %-26s %6s %s\n" 5 "Wikibooks" "~500MB" "$(_zim_tag "wikibooks_en_all_nopic")" - printf " %2s) %-26s %6s %s\n" 6 "Wikisource" "~4GB" "$(_zim_tag "wikisource_en_all_nopic")" - printf " %2s) %-26s %6s %s\n" 7 "Wikivoyage" "~200MB" "$(_zim_tag "wikivoyage_en_all_nopic")" - printf " %2s) %-26s %6s %s\n" 8 "Wikiversity" "~500MB" "$(_zim_tag "wikiversity_en_all_nopic")" - printf " %2s) %-26s %6s %s\n" 9 "WikiNews" "~300MB" "$(_zim_tag "wikinews_en_all_nopic")" - printf " %2s) %-26s %6s %s\n" 10 "Wikiquote" "~300MB" "$(_zim_tag "wikiquote_en_all_nopic")" - printf " %2s) %-26s %6s %s\n" 11 "Vikidia (kids K-8)" "~66MB" "$(_zim_tag "vikidia_en_all_nopic")" - printf " %2s) %-26s %6s %s\n" 12 "TED Talks" "~5GB" "$(_zim_tag "ted_mul_youth")" - printf " %2s) %-26s %6s %s\n" 13 "PhET Simulations" "~500MB" "$(_zim_tag "phet_en_all")" - printf " %2s) %-26s %6s %s\n" 14 "DevDocs" "~1GB" "$(_zim_tag "devdocs_en_zig")" - printf " %2s) %-26s %6s %s\n" 15 "FreeCodeCamp" "~small" "$(_zim_tag "freecodecamp_en_all")" - printf " %2s) %-26s %6s %s\n" 16 "iFixit" "~2GB" "$(_zim_tag "ifixit_en_all")" - printf " %2s) %-26s %6s %s\n" 17 "LibreTexts" "~varies" "$(_zim_tag "libretexts.org_en")" - printf " %2s) %-26s %6s %s\n" 18 "Project Gutenberg" "~60GB" "$(_zim_tag "gutenberg_en_all")" + echo " 1) Yes — download all ZIMs overnight (~130GB)" + echo " 2) Select — choose which ZIMs to download" + echo " 3) No — skip for now (run ./kiwix_download.sh later)" echo "" - read -rp " Your choices (e.g. 1 2 3): " ZIM_PICKS - unset -f _zim_tag + read -rp " Choice [3]: " ZIM_CHOICE + ZIM_CHOICE="${ZIM_CHOICE:-3}" + + if [[ "$ZIM_CHOICE" == "2" ]]; then + _zim_tag() { + ls "$KIWIX_DIR/${1}"*.zim 2>/dev/null | grep -q . && echo " ${GREEN}[downloaded]${NC}" || echo "" + } + echo "" + echo " Select ZIMs to download (space-separated numbers, e.g. 1 3 5):" + printf " %2s) %-26s %7s %s\n" 1 "Wikipedia" "~46 GB" "$(_zim_tag wikipedia_en_all_nopic)" + printf " %2s) %-26s %7s %s\n" 2 "Stack Overflow" "~3 GB" "$(_zim_tag stackoverflow.com_en_all)" + printf " %2s) %-26s %7s %s\n" 3 "Arch Linux Wiki" "~30 MB" "$(_zim_tag archlinux_en_all)" + printf " %2s) %-26s %7s %s\n" 4 "Wiktionary" "~2 GB" "$(_zim_tag wiktionary_en_all_nopic)" + printf " %2s) %-26s %7s %s\n" 5 "Wikibooks" "~500 MB" "$(_zim_tag wikibooks_en_all_nopic)" + printf " %2s) %-26s %7s %s\n" 6 "Wikisource" "~4 GB" "$(_zim_tag wikisource_en_all_nopic)" + printf " %2s) %-26s %7s %s\n" 7 "Wikivoyage" "~200 MB" "$(_zim_tag wikivoyage_en_all_nopic)" + printf " %2s) %-26s %7s %s\n" 8 "Wikiversity" "~500 MB" "$(_zim_tag wikiversity_en_all_nopic)" + printf " %2s) %-26s %7s %s\n" 9 "WikiNews" "~300 MB" "$(_zim_tag wikinews_en_all_nopic)" + printf " %2s) %-26s %7s %s\n" 10 "Wikiquote" "~300 MB" "$(_zim_tag wikiquote_en_all_nopic)" + printf " %2s) %-26s %7s %s\n" 11 "Vikidia (kids K-8)" "~66 MB" "$(_zim_tag vikidia_en_all_nopic)" + printf " %2s) %-26s %7s %s\n" 12 "TED Talks" "~5 GB" "$(_zim_tag ted_mul_youth)" + printf " %2s) %-26s %7s %s\n" 13 "PhET Simulations" "~500 MB" "$(_zim_tag phet_en_all)" + printf " %2s) %-26s %7s %s\n" 14 "DevDocs" "~1 GB" "$(_zim_tag devdocs_en_zig)" + printf " %2s) %-26s %7s %s\n" 15 "FreeCodeCamp" "small" "$(_zim_tag freecodecamp_en_all)" + printf " %2s) %-26s %7s %s\n" 16 "iFixit" "~2 GB" "$(_zim_tag ifixit_en_all)" + printf " %2s) %-26s %7s %s\n" 17 "LibreTexts" "varies" "$(_zim_tag libretexts.org_en)" + printf " %2s) %-26s %7s %s\n" 18 "Project Gutenberg" "~60 GB" "$(_zim_tag gutenberg_en_all)" + echo "" + read -rp " Your choices (e.g. 1 2 3): " _ZIM_NUMS + for _n in $_ZIM_NUMS; do + case "$_n" in + 1) ZIM_PICKS+="${ZIM_PICKS:+ }wikipedia" ;; + 2) ZIM_PICKS+="${ZIM_PICKS:+ }stackoverflow" ;; + 3) ZIM_PICKS+="${ZIM_PICKS:+ }archlinux" ;; + 4) ZIM_PICKS+="${ZIM_PICKS:+ }wiktionary" ;; + 5) ZIM_PICKS+="${ZIM_PICKS:+ }wikibooks" ;; + 6) ZIM_PICKS+="${ZIM_PICKS:+ }wikisource" ;; + 7) ZIM_PICKS+="${ZIM_PICKS:+ }wikivoyage" ;; + 8) ZIM_PICKS+="${ZIM_PICKS:+ }wikiversity" ;; + 9) ZIM_PICKS+="${ZIM_PICKS:+ }wikinews" ;; + 10) ZIM_PICKS+="${ZIM_PICKS:+ }wikiquote" ;; + 11) ZIM_PICKS+="${ZIM_PICKS:+ }vikidia" ;; + 12) ZIM_PICKS+="${ZIM_PICKS:+ }ted" ;; + 13) ZIM_PICKS+="${ZIM_PICKS:+ }phet" ;; + 14) ZIM_PICKS+="${ZIM_PICKS:+ }devdocs" ;; + 15) ZIM_PICKS+="${ZIM_PICKS:+ }freecodecamp" ;; + 16) ZIM_PICKS+="${ZIM_PICKS:+ }ifixit" ;; + 17) ZIM_PICKS+="${ZIM_PICKS:+ }libretexts" ;; + 18) ZIM_PICKS+="${ZIM_PICKS:+ }gutenberg" ;; + esac + done + unset -f _zim_tag + fi fi + unset -f _zimon else ZIM_CHOICE="3" fi @@ -513,12 +587,16 @@ if $INSTALL_AI && $SVC_SEARXNG; then *) SEARXNG_SAFE_LEVEL="none"; SEARXNG_SAFE_INT=0 ;; esac - # Default ON/OFF for an engine given the chosen safe-search level + # Default ON/OFF for an engine given the chosen safe-search level. + # Engines without safe-search support default OFF for moderate/strict. _sxst() { [[ "$SEARXNG_SAFE_LEVEL" == "none" ]] && echo ON && return case "$1" in - mojeek|yandex|baidu|naver|invidious|piped|peertube|sepiasearch|\ - dailymotion|vimeo|imgur|deviantart|flickr) echo OFF ;; + mojeek|"mojeek images"|"mojeek news"|\ + yandex|baidu|naver|\ + invidious|piped|peertube|sepiasearch|\ + vimeo|bitchute|rumble|odysee|\ + imgur|deviantart|artstation) echo OFF ;; *) echo ON ;; esac } @@ -531,7 +609,7 @@ if $INSTALL_AI && $SVC_SEARXNG; then local -a _n=() _s=() _a=(); local _i=1 while [[ $# -ge 3 ]]; do _n+=("$1"); _s+=("$3") - _a+=("$_i" "$(printf '%-22s %s' "$1" "$2")" "$3") + _a+=("$_i" "$(printf '%-26s %s' "$1" "$2")" "$3") _i=$(( _i + 1 )); shift 3 done local _h=$(( ${#_n[@]} + 9 > 24 ? 24 : ${#_n[@]} + 9 )) @@ -540,7 +618,7 @@ if $INSTALL_AI && $SVC_SEARXNG; then if ! _o=$(whiptail --backtitle "SearXNG — $SEARXNG_SAFE_LEVEL" \ --title "$_t" --checklist \ "SPACE = toggle ENTER = confirm ESC = use defaults" \ - "$_h" 72 "$_lh" "${_a[@]}" 3>&1 1>&2 2>&3 2>/dev/null); then + "$_h" 76 "$_lh" "${_a[@]}" 3>&1 1>&2 2>&3 2>/dev/null); then for _j in "${!_n[@]}"; do [[ "${_s[$_j]}" == "ON" ]] && printf '%s\n' "${_n[$_j]}" done @@ -554,69 +632,130 @@ if $INSTALL_AI && $SVC_SEARXNG; then _SX_AUTOFF=(mojeek yandex baidu naver invidious piped peertube sepiasearch) if command -v whiptail &>/dev/null && [[ -t 0 ]]; then + # ── Web search ───────────────────────────────────────────────────────── _SX_W=$(_sxmenu "Web Search Engines" \ - "google" "Google" ON \ - "bing" "Microsoft Bing" ON \ - "duckduckgo" "DuckDuckGo" ON \ - "brave" "Brave Search" ON \ - "startpage" "Startpage (Google proxy)" ON \ - "qwant" "Qwant" ON \ - "yahoo" "Yahoo" ON \ - "ecosia" "Ecosia" ON \ - "mojeek" "Mojeek [no safe-search]" "$(_sxst mojeek)" \ - "yandex" "Yandex [unreliable filter]" "$(_sxst yandex)" \ - "baidu" "Baidu [no safe-search]" "$(_sxst baidu)" \ - "naver" "Naver [no safe-search]" "$(_sxst naver)") + "google" "Google" ON \ + "bing" "Microsoft Bing" ON \ + "duckduckgo" "DuckDuckGo" ON \ + "brave" "Brave Search" ON \ + "startpage" "Startpage (Google proxy)" ON \ + "qwant" "Qwant" ON \ + "yahoo" "Yahoo" ON \ + "ecosia" "Ecosia" ON \ + "presearch" "Presearch" ON \ + "yep" "Yep" ON \ + "wiby" "Wiby (classic/indie web)" ON \ + "mojeek" "Mojeek [no safe-search]" "$(_sxst mojeek)" \ + "yandex" "Yandex [unreliable filter]" "$(_sxst yandex)" \ + "baidu" "Baidu [no safe-search]" "$(_sxst baidu)" \ + "naver" "Naver (Korean) [no safe-search]" "$(_sxst naver)") + # ── Images ───────────────────────────────────────────────────────────── _SX_I=$(_sxmenu "Image Search Engines" \ - "google images" "Google Images" ON \ - "bing images" "Bing Images" ON \ - "duckduckgo images" "DuckDuckGo Images" ON \ - "brave images" "Brave Images" ON \ - "qwant images" "Qwant Images" ON \ - "openverse" "Openverse (open license)" ON \ - "unsplash" "Unsplash (stock photos)" ON \ - "flickr" "Flickr [no safe-search]" "$(_sxst flickr)" \ - "imgur" "Imgur [no safe-search]" "$(_sxst imgur)" \ - "deviantart" "DeviantArt [no filter]" "$(_sxst deviantart)") + "google images" "Google Images" ON \ + "bing images" "Bing Images" ON \ + "duckduckgo images" "DuckDuckGo Images" ON \ + "brave images" "Brave Images" ON \ + "qwant images" "Qwant Images" ON \ + "startpage images" "Startpage Images" ON \ + "mojeek images" "Mojeek Images [no safe-search]" "$(_sxst 'mojeek images')" \ + "presearch images" "Presearch Images" ON \ + "openverse" "Openverse (open license)" ON \ + "unsplash" "Unsplash (stock photos)" ON \ + "pexels" "Pexels (stock photos)" ON \ + "pixabay images" "Pixabay Images" ON \ + "pinterest" "Pinterest" ON \ + "flickr" "Flickr" ON \ + "wikcommons.images" "Wikimedia Commons Images" ON \ + "imgur" "Imgur [adult content]" "$(_sxst imgur)" \ + "deviantart" "DeviantArt [adult content]" "$(_sxst deviantart)" \ + "artstation" "ArtStation [adult content]" "$(_sxst artstation)" \ + "adobe stock" "Adobe Stock" ON) + # ── Videos ───────────────────────────────────────────────────────────── _SX_V=$(_sxmenu "Video Search Engines" \ - "youtube" "YouTube (via Google)" ON \ - "bing videos" "Bing Videos" ON \ - "duckduckgo videos" "DuckDuckGo Videos" ON \ - "google videos" "Google Videos" ON \ - "invidious" "Invidious [no filter]" "$(_sxst invidious)" \ - "piped" "Piped [no filter]" "$(_sxst piped)" \ - "peertube" "PeerTube [no filter]" "$(_sxst peertube)" \ - "sepiasearch" "SepiaSearch [no filter]" "$(_sxst sepiasearch)" \ - "dailymotion" "Dailymotion [no filter]" "$(_sxst dailymotion)" \ - "vimeo" "Vimeo [no filter]" "$(_sxst vimeo)") + "youtube" "YouTube" ON \ + "bing videos" "Bing Videos" ON \ + "brave videos" "Brave Videos" ON \ + "duckduckgo videos" "DuckDuckGo Videos" ON \ + "google videos" "Google Videos" ON \ + "qwant videos" "Qwant Videos" ON \ + "dailymotion" "Dailymotion" ON \ + "media.ccc.de" "media.ccc.de (tech talks)" ON \ + "wikcommons.videos" "Wikimedia Commons Videos" ON \ + "vimeo" "Vimeo [no safe-search]" "$(_sxst vimeo)" \ + "odysee" "Odysee [no safe-search]" "$(_sxst odysee)" \ + "rumble" "Rumble [no safe-search]" "$(_sxst rumble)" \ + "bitchute" "BitChute [no safe-search]" "$(_sxst bitchute)" \ + "invidious" "Invidious (YT) [no safe-search]" "$(_sxst invidious)" \ + "piped" "Piped (YT) [no safe-search]" "$(_sxst piped)" \ + "peertube" "PeerTube [no safe-search]" "$(_sxst peertube)" \ + "sepiasearch" "SepiaSearch [no safe-search]" "$(_sxst sepiasearch)") + # ── News ─────────────────────────────────────────────────────────────── _SX_N=$(_sxmenu "News Search Engines" \ - "google news" "Google News" ON \ - "bing news" "Bing News" ON \ - "duckduckgo news" "DuckDuckGo News" ON \ - "brave news" "Brave News" ON \ - "qwant news" "Qwant News" ON) + "google news" "Google News" ON \ + "bing news" "Bing News" ON \ + "duckduckgo news" "DuckDuckGo News" ON \ + "brave news" "Brave News" ON \ + "qwant news" "Qwant News" ON \ + "startpage news" "Startpage News" ON \ + "presearch news" "Presearch News" ON \ + "mojeek news" "Mojeek News [no safe-search]" "$(_sxst 'mojeek news')" \ + "reuters" "Reuters" ON \ + "yahoo news" "Yahoo News" ON \ + "wikinews" "WikiNews" ON \ + "yep news" "Yep News" ON) + # ── Reference & Knowledge ────────────────────────────────────────────── + _SX_R=$(_sxmenu "Reference & Knowledge" \ + "wikipedia" "Wikipedia" ON \ + "wikidata" "Wikidata" ON \ + "wolframalpha" "Wolfram|Alpha" ON \ + "ask" "Ask.com" ON \ + "ddg definitions" "DuckDuckGo Definitions" ON \ + "encyclopsearch" "Encyclopsearch" ON \ + "wikibooks" "Wikibooks" ON \ + "wikiquote" "Wikiquote" ON \ + "wikisource" "Wikisource" ON \ + "wikispecies" "Wikispecies" ON \ + "wikiversity" "Wikiversity" ON \ + "wikivoyage" "Wikivoyage" ON) + + # ── Science ──────────────────────────────────────────────────────────── _SX_S=$(_sxmenu "Science / Academic" \ - "arxiv" "arXiv (preprints)" ON \ - "semantic scholar" "Semantic Scholar" ON \ - "pubmed" "PubMed (medical)" ON \ - "crossref" "Crossref (DOI/papers)" ON \ - "base" "BASE (open access)" ON) + "arxiv" "arXiv (preprints)" ON \ + "semantic scholar" "Semantic Scholar" ON \ + "pubmed" "PubMed (medical)" ON \ + "crossref" "Crossref (DOI/papers)" ON \ + "base" "BASE (open access)" ON) _SX_ALL=( + # Web "google" "bing" "duckduckgo" "brave" "startpage" "qwant" "yahoo" "ecosia" + "presearch" "yep" "wiby" "mojeek" "yandex" "baidu" "naver" + # Images "google images" "bing images" "duckduckgo images" "brave images" "qwant images" - "openverse" "unsplash" "flickr" "imgur" "deviantart" - "youtube" "bing videos" "duckduckgo videos" "google videos" - "invidious" "piped" "peertube" "sepiasearch" "dailymotion" "vimeo" + "startpage images" "mojeek images" "presearch images" + "openverse" "unsplash" "pexels" "pixabay images" "pinterest" "flickr" + "wikcommons.images" "imgur" "deviantart" "artstation" "adobe stock" + # Videos + "youtube" "bing videos" "brave videos" "duckduckgo videos" "google videos" "qwant videos" + "dailymotion" "media.ccc.de" "wikcommons.videos" + "vimeo" "odysee" "rumble" "bitchute" + "invidious" "piped" "peertube" "sepiasearch" + # News "google news" "bing news" "duckduckgo news" "brave news" "qwant news" + "startpage news" "presearch news" "mojeek news" + "reuters" "yahoo news" "wikinews" "yep news" + # Reference + "wikipedia" "wikidata" "wolframalpha" "ask" "ddg definitions" "encyclopsearch" + "wikibooks" "wikiquote" "wikisource" "wikispecies" "wikiversity" "wikivoyage" + # Science "arxiv" "semantic scholar" "pubmed" "crossref" "base" ) - _SX_SEL=$(printf '%s\n' "$_SX_W" "$_SX_I" "$_SX_V" "$_SX_N" "$_SX_S") + _SX_SEL=$(printf '%s\n' "$_SX_W" "$_SX_I" "$_SX_V" "$_SX_N" "$_SX_R" "$_SX_S") for _e in "${_SX_ALL[@]}"; do if printf '%s\n' "$_SX_SEL" | grep -qxF "$_e"; then @@ -635,9 +774,10 @@ if $INSTALL_AI && $SVC_SEARXNG; then # Fallback: no whiptail / non-interactive terminal echo "" echo " (whiptail not available — text entry)" - echo " Web: google bing duckduckgo brave startpage qwant yahoo" + echo " Web: google bing duckduckgo brave startpage qwant yahoo presearch" echo " Imgs: google_images bing_images duckduckgo_images flickr imgur" - echo " Vids: youtube invidious piped peertube dailymotion vimeo" + echo " Vids: youtube dailymotion vimeo rumble odysee bitchute" + echo " News: google_news bing_news reuters yahoo_news wikinews" read -rp " Engines to disable (space-separated, Enter for defaults): " _ENGS SEARXNG_DISABLE_ENGINES="${_ENGS// /,}" fi @@ -680,8 +820,11 @@ if $INSTALL_AI && $SVC_SEARXNG; then echo " ✓ SearXNG → $_sx" fi $PULL_MODELS && echo " ✓ Pull models : $EMBED_MODEL + $FAST_MODEL + $CHAT_MODEL + $CODE_MODEL${REASON_MODEL:+ + $REASON_MODEL}" -[[ "$ZIM_CHOICE" == "1" ]] && echo " ✓ Download all ZIMs in background (~130GB)" -[[ "$ZIM_CHOICE" == "2" ]] && echo " ✓ Select ZIMs to download (prompted after stack starts)" +[[ "$ZIM_CHOICE" == "1" ]] && echo " ✓ Download all ZIMs in background (~130 GB)" +if [[ "$ZIM_CHOICE" == "2" ]]; then + _nzim=$(wc -w <<< "$ZIM_PICKS") + echo " ✓ Download ${_nzim} ZIM(s): $ZIM_PICKS" +fi echo "" read -rp " Proceed? [Y/n]: " CONFIRM [[ "${CONFIRM,,}" == "n" ]] && echo "Aborted." && exit 0 @@ -1388,28 +1531,28 @@ if $SVC_KIWIX && [[ "$ZIM_CHOICE" != "3" ]]; then GUT=$(latest_zim "$MIRROR2/gutenberg" "gutenberg_en_all") if [[ "$ZIM_CHOICE" == "2" ]]; then - # ZIM_PICKS was captured during the wizard — just dispatch + # ZIM_PICKS contains space-separated ZIM names selected during the wizard rm -f "$KIWIX_DIR/.download_pids" - for n in $ZIM_PICKS; do - case "$n" in - 1) dl_zim "wikipedia" "$WIKI" "Wikipedia" ;; - 2) dl_zim "stack_exchange" "$SO" "Stack Overflow" ;; - 3) dl_zim "other" "$ARCH" "Arch Linux Wiki" ;; - 4) dl_zim "wiktionary" "$WIKT" "Wiktionary" ;; - 5) dl_zim "wikibooks" "$WIKB" "Wikibooks" ;; - 6) dl_zim "wikisource" "$WIKS" "Wikisource" ;; - 7) dl_zim "wikivoyage" "$WIKV" "Wikivoyage" ;; - 8) dl_zim "wikiversity" "$WIKUNI" "Wikiversity" ;; - 9) dl_zim "wikinews" "$WIKNEWS" "WikiNews" ;; - 10) dl_zim "wikiquote" "$WIKQ" "Wikiquote" ;; - 11) dl_zim "vikidia" "$VIKIDIA" "Vikidia (kids K-8)" ;; - 12) dl_zim "ted" "$TED" "TED Talks" ;; - 13) dl_zim "phet" "$PHET" "PhET Simulations" ;; - 14) dl_zim "devdocs" "$DEVDOCS" "DevDocs" ;; - 15) dl_zim "freecodecamp" "$FCC" "FreeCodeCamp" ;; - 16) dl_zim "ifixit" "$IFIX" "iFixit" ;; - 17) dl_zim "libretexts" "$LIBRE" "LibreTexts" ;; - 18) dl_zim "gutenberg" "$GUT" "Project Gutenberg" "$MIRROR2" ;; + for _zn in $ZIM_PICKS; do + case "$_zn" in + wikipedia) dl_zim "wikipedia" "$WIKI" "Wikipedia" ;; + stackoverflow) dl_zim "stack_exchange" "$SO" "Stack Overflow" ;; + archlinux) dl_zim "other" "$ARCH" "Arch Linux Wiki" ;; + wiktionary) dl_zim "wiktionary" "$WIKT" "Wiktionary" ;; + wikibooks) dl_zim "wikibooks" "$WIKB" "Wikibooks" ;; + wikisource) dl_zim "wikisource" "$WIKS" "Wikisource" ;; + wikivoyage) dl_zim "wikivoyage" "$WIKV" "Wikivoyage" ;; + wikiversity) dl_zim "wikiversity" "$WIKUNI" "Wikiversity" ;; + wikinews) dl_zim "wikinews" "$WIKNEWS" "WikiNews" ;; + wikiquote) dl_zim "wikiquote" "$WIKQ" "Wikiquote" ;; + vikidia) dl_zim "vikidia" "$VIKIDIA" "Vikidia (kids K-8)" ;; + ted) dl_zim "ted" "$TED" "TED Talks" ;; + phet) dl_zim "phet" "$PHET" "PhET Simulations" ;; + devdocs) dl_zim "devdocs" "$DEVDOCS" "DevDocs" ;; + freecodecamp) dl_zim "freecodecamp" "$FCC" "FreeCodeCamp" ;; + ifixit) dl_zim "ifixit" "$IFIX" "iFixit" ;; + libretexts) dl_zim "libretexts" "$LIBRE" "LibreTexts" ;; + gutenberg) dl_zim "gutenberg" "$GUT" "Project Gutenberg" "$MIRROR2" ;; esac done else diff --git a/local-ai-setup.sh b/local-ai-setup.sh index f161ee9..f7a3745 100755 --- a/local-ai-setup.sh +++ b/local-ai-setup.sh @@ -60,12 +60,16 @@ case "${_SAFE_PICK:-0}" in *) SEARXNG_SAFE_LEVEL="none"; SEARXNG_SAFE_INT=0 ;; esac -# Default ON/OFF for an engine given the chosen safe-search level +# Default ON/OFF for an engine given the chosen safe-search level. +# Engines without safe-search support default OFF for moderate/strict. _sxst() { [[ "$SEARXNG_SAFE_LEVEL" == "none" ]] && echo ON && return case "$1" in - mojeek|yandex|baidu|naver|invidious|piped|peertube|sepiasearch|\ - dailymotion|vimeo|imgur|deviantart|flickr) echo OFF ;; + mojeek|"mojeek images"|"mojeek news"|\ + yandex|baidu|naver|\ + invidious|piped|peertube|sepiasearch|\ + vimeo|bitchute|rumble|odysee|\ + imgur|deviantart|artstation) echo OFF ;; *) echo ON ;; esac } @@ -77,7 +81,7 @@ _sxmenu() { local -a _n=() _s=() _a=(); local _i=1 while [[ $# -ge 3 ]]; do _n+=("$1"); _s+=("$3") - _a+=("$_i" "$(printf '%-22s %s' "$1" "$2")" "$3") + _a+=("$_i" "$(printf '%-26s %s' "$1" "$2")" "$3") _i=$(( _i + 1 )); shift 3 done local _h=$(( ${#_n[@]} + 9 > 24 ? 24 : ${#_n[@]} + 9 )) @@ -86,7 +90,7 @@ _sxmenu() { if ! _o=$(whiptail --backtitle "SearXNG — $SEARXNG_SAFE_LEVEL" \ --title "$_t" --checklist \ "SPACE = toggle ENTER = confirm ESC = use defaults" \ - "$_h" 72 "$_lh" "${_a[@]}" 3>&1 1>&2 2>&3 2>/dev/null); then + "$_h" 76 "$_lh" "${_a[@]}" 3>&1 1>&2 2>&3 2>/dev/null); then for _j in "${!_n[@]}"; do [[ "${_s[$_j]}" == "ON" ]] && printf '%s\n' "${_n[$_j]}" done @@ -98,69 +102,130 @@ _sxmenu() { _SX_AUTOFF=(mojeek yandex baidu naver invidious piped peertube sepiasearch) if command -v whiptail &>/dev/null && [[ -t 0 ]]; then + # ── Web search ───────────────────────────────────────────────────────────── _SX_W=$(_sxmenu "Web Search Engines" \ - "google" "Google" ON \ - "bing" "Microsoft Bing" ON \ - "duckduckgo" "DuckDuckGo" ON \ - "brave" "Brave Search" ON \ - "startpage" "Startpage (Google proxy)" ON \ - "qwant" "Qwant" ON \ - "yahoo" "Yahoo" ON \ - "ecosia" "Ecosia" ON \ - "mojeek" "Mojeek [no safe-search]" "$(_sxst mojeek)" \ - "yandex" "Yandex [unreliable filter]" "$(_sxst yandex)" \ - "baidu" "Baidu [no safe-search]" "$(_sxst baidu)" \ - "naver" "Naver [no safe-search]" "$(_sxst naver)") + "google" "Google" ON \ + "bing" "Microsoft Bing" ON \ + "duckduckgo" "DuckDuckGo" ON \ + "brave" "Brave Search" ON \ + "startpage" "Startpage (Google proxy)" ON \ + "qwant" "Qwant" ON \ + "yahoo" "Yahoo" ON \ + "ecosia" "Ecosia" ON \ + "presearch" "Presearch" ON \ + "yep" "Yep" ON \ + "wiby" "Wiby (classic/indie web)" ON \ + "mojeek" "Mojeek [no safe-search]" "$(_sxst mojeek)" \ + "yandex" "Yandex [unreliable filter]" "$(_sxst yandex)" \ + "baidu" "Baidu [no safe-search]" "$(_sxst baidu)" \ + "naver" "Naver (Korean) [no safe-search]" "$(_sxst naver)") + # ── Images ───────────────────────────────────────────────────────────────── _SX_I=$(_sxmenu "Image Search Engines" \ - "google images" "Google Images" ON \ - "bing images" "Bing Images" ON \ - "duckduckgo images" "DuckDuckGo Images" ON \ - "brave images" "Brave Images" ON \ - "qwant images" "Qwant Images" ON \ - "openverse" "Openverse (open license)" ON \ - "unsplash" "Unsplash (stock photos)" ON \ - "flickr" "Flickr [no safe-search]" "$(_sxst flickr)" \ - "imgur" "Imgur [no safe-search]" "$(_sxst imgur)" \ - "deviantart" "DeviantArt [no filter]" "$(_sxst deviantart)") + "google images" "Google Images" ON \ + "bing images" "Bing Images" ON \ + "duckduckgo images" "DuckDuckGo Images" ON \ + "brave images" "Brave Images" ON \ + "qwant images" "Qwant Images" ON \ + "startpage images" "Startpage Images" ON \ + "mojeek images" "Mojeek Images [no safe-search]" "$(_sxst 'mojeek images')" \ + "presearch images" "Presearch Images" ON \ + "openverse" "Openverse (open license)" ON \ + "unsplash" "Unsplash (stock photos)" ON \ + "pexels" "Pexels (stock photos)" ON \ + "pixabay images" "Pixabay Images" ON \ + "pinterest" "Pinterest" ON \ + "flickr" "Flickr" ON \ + "wikcommons.images" "Wikimedia Commons Images" ON \ + "imgur" "Imgur [adult content]" "$(_sxst imgur)" \ + "deviantart" "DeviantArt [adult content]" "$(_sxst deviantart)" \ + "artstation" "ArtStation [adult content]" "$(_sxst artstation)" \ + "adobe stock" "Adobe Stock" ON) + # ── Videos ───────────────────────────────────────────────────────────────── _SX_V=$(_sxmenu "Video Search Engines" \ - "youtube" "YouTube (via Google)" ON \ - "bing videos" "Bing Videos" ON \ - "duckduckgo videos" "DuckDuckGo Videos" ON \ - "google videos" "Google Videos" ON \ - "invidious" "Invidious [no filter]" "$(_sxst invidious)" \ - "piped" "Piped [no filter]" "$(_sxst piped)" \ - "peertube" "PeerTube [no filter]" "$(_sxst peertube)" \ - "sepiasearch" "SepiaSearch [no filter]" "$(_sxst sepiasearch)" \ - "dailymotion" "Dailymotion [no filter]" "$(_sxst dailymotion)" \ - "vimeo" "Vimeo [no filter]" "$(_sxst vimeo)") + "youtube" "YouTube" ON \ + "bing videos" "Bing Videos" ON \ + "brave videos" "Brave Videos" ON \ + "duckduckgo videos" "DuckDuckGo Videos" ON \ + "google videos" "Google Videos" ON \ + "qwant videos" "Qwant Videos" ON \ + "dailymotion" "Dailymotion" ON \ + "media.ccc.de" "media.ccc.de (tech talks)" ON \ + "wikcommons.videos" "Wikimedia Commons Videos" ON \ + "vimeo" "Vimeo [no safe-search]" "$(_sxst vimeo)" \ + "odysee" "Odysee [no safe-search]" "$(_sxst odysee)" \ + "rumble" "Rumble [no safe-search]" "$(_sxst rumble)" \ + "bitchute" "BitChute [no safe-search]" "$(_sxst bitchute)" \ + "invidious" "Invidious (YT) [no safe-search]" "$(_sxst invidious)" \ + "piped" "Piped (YT) [no safe-search]" "$(_sxst piped)" \ + "peertube" "PeerTube [no safe-search]" "$(_sxst peertube)" \ + "sepiasearch" "SepiaSearch [no safe-search]" "$(_sxst sepiasearch)") + # ── News ─────────────────────────────────────────────────────────────────── _SX_N=$(_sxmenu "News Search Engines" \ - "google news" "Google News" ON \ - "bing news" "Bing News" ON \ - "duckduckgo news" "DuckDuckGo News" ON \ - "brave news" "Brave News" ON \ - "qwant news" "Qwant News" ON) + "google news" "Google News" ON \ + "bing news" "Bing News" ON \ + "duckduckgo news" "DuckDuckGo News" ON \ + "brave news" "Brave News" ON \ + "qwant news" "Qwant News" ON \ + "startpage news" "Startpage News" ON \ + "presearch news" "Presearch News" ON \ + "mojeek news" "Mojeek News [no safe-search]" "$(_sxst 'mojeek news')" \ + "reuters" "Reuters" ON \ + "yahoo news" "Yahoo News" ON \ + "wikinews" "WikiNews" ON \ + "yep news" "Yep News" ON) + # ── Reference & Knowledge ────────────────────────────────────────────────── + _SX_R=$(_sxmenu "Reference & Knowledge" \ + "wikipedia" "Wikipedia" ON \ + "wikidata" "Wikidata" ON \ + "wolframalpha" "Wolfram|Alpha" ON \ + "ask" "Ask.com" ON \ + "ddg definitions" "DuckDuckGo Definitions" ON \ + "encyclopsearch" "Encyclopsearch" ON \ + "wikibooks" "Wikibooks" ON \ + "wikiquote" "Wikiquote" ON \ + "wikisource" "Wikisource" ON \ + "wikispecies" "Wikispecies" ON \ + "wikiversity" "Wikiversity" ON \ + "wikivoyage" "Wikivoyage" ON) + + # ── Science ──────────────────────────────────────────────────────────────── _SX_S=$(_sxmenu "Science / Academic" \ - "arxiv" "arXiv (preprints)" ON \ - "semantic scholar" "Semantic Scholar" ON \ - "pubmed" "PubMed (medical)" ON \ - "crossref" "Crossref (DOI/papers)" ON \ - "base" "BASE (open access)" ON) + "arxiv" "arXiv (preprints)" ON \ + "semantic scholar" "Semantic Scholar" ON \ + "pubmed" "PubMed (medical)" ON \ + "crossref" "Crossref (DOI/papers)" ON \ + "base" "BASE (open access)" ON) _SX_ALL=( + # Web "google" "bing" "duckduckgo" "brave" "startpage" "qwant" "yahoo" "ecosia" + "presearch" "yep" "wiby" "mojeek" "yandex" "baidu" "naver" + # Images "google images" "bing images" "duckduckgo images" "brave images" "qwant images" - "openverse" "unsplash" "flickr" "imgur" "deviantart" - "youtube" "bing videos" "duckduckgo videos" "google videos" - "invidious" "piped" "peertube" "sepiasearch" "dailymotion" "vimeo" + "startpage images" "mojeek images" "presearch images" + "openverse" "unsplash" "pexels" "pixabay images" "pinterest" "flickr" + "wikcommons.images" "imgur" "deviantart" "artstation" "adobe stock" + # Videos + "youtube" "bing videos" "brave videos" "duckduckgo videos" "google videos" "qwant videos" + "dailymotion" "media.ccc.de" "wikcommons.videos" + "vimeo" "odysee" "rumble" "bitchute" + "invidious" "piped" "peertube" "sepiasearch" + # News "google news" "bing news" "duckduckgo news" "brave news" "qwant news" + "startpage news" "presearch news" "mojeek news" + "reuters" "yahoo news" "wikinews" "yep news" + # Reference + "wikipedia" "wikidata" "wolframalpha" "ask" "ddg definitions" "encyclopsearch" + "wikibooks" "wikiquote" "wikisource" "wikispecies" "wikiversity" "wikivoyage" + # Science "arxiv" "semantic scholar" "pubmed" "crossref" "base" ) - _SX_SEL=$(printf '%s\n' "$_SX_W" "$_SX_I" "$_SX_V" "$_SX_N" "$_SX_S") + _SX_SEL=$(printf '%s\n' "$_SX_W" "$_SX_I" "$_SX_V" "$_SX_N" "$_SX_R" "$_SX_S") for _e in "${_SX_ALL[@]}"; do if printf '%s\n' "$_SX_SEL" | grep -qxF "$_e"; then @@ -177,9 +242,10 @@ if command -v whiptail &>/dev/null && [[ -t 0 ]]; then else echo "" echo " (whiptail not available — text entry)" - echo " Web: google bing duckduckgo brave startpage qwant yahoo" + echo " Web: google bing duckduckgo brave startpage qwant yahoo presearch" echo " Imgs: google_images bing_images duckduckgo_images flickr imgur" - echo " Vids: youtube invidious piped peertube dailymotion vimeo" + echo " Vids: youtube dailymotion vimeo rumble odysee bitchute" + echo " News: google_news bing_news reuters yahoo_news wikinews" read -rp " Engines to disable (space-separated, Enter for defaults): " _ENGS SEARXNG_DISABLE_ENGINES="${_ENGS// /,}" fi