From fc72eb75776afa98b142b660b3f63920ac1d2d65 Mon Sep 17 00:00:00 2001 From: pika Date: Fri, 23 May 2025 19:24:13 +0200 Subject: [PATCH] Addet a dream.sh import script (about 1k lines..) --- dream.sh | 923 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 923 insertions(+) create mode 100644 dream.sh diff --git a/dream.sh b/dream.sh new file mode 100644 index 0000000..770f559 --- /dev/null +++ b/dream.sh @@ -0,0 +1,923 @@ +# NOTE: +# ──────────────────────────────────────< distros.sh >────────────────────────────────────── +# ╭──────────────────────────────╮ +# │ User variables and functions │ +# ╰──────────────────────────────╯ +distro="" +ubuntu="false" +debian="false" +arch="false" +fedora="false" +alpine="false" +opensuse="false" + +# Basic Colors +BLACK=$'\e[30m' +RED=$'\e[31m' +GREEN=$'\e[32m' +YELLOW=$'\e[33m' +BLUE=$'\e[34m' +MAGENTA=$'\e[35m' +CYAN=$'\e[36m' +WHITE=$'\e[37m' + +# Bright Colors +BRIGHT_BLACK=$'\e[90m' +BRIGHT_RED=$'\e[91m' +BRIGHT_GREEN=$'\e[92m' +BRIGHT_YELLOW=$'\e[93m' +BRIGHT_BLUE=$'\e[94m' +BRIGHT_MAGENTA=$'\e[95m' +BRIGHT_CYAN=$'\e[96m' +BRIGHT_WHITE=$'\e[97m' + +# Background Colors (standard) +BG_BLACK=$'\e[40m' +BG_RED=$'\e[41m' +BG_GREEN=$'\e[42m' +BG_YELLOW=$'\e[43m' +BG_BLUE=$'\e[44m' +BG_MAGENTA=$'\e[45m' +BG_CYAN=$'\e[46m' +BG_WHITE=$'\e[47m' + +# Background Bright Colors +BG_BRIGHT_BLACK=$'\e[100m' +BG_BRIGHT_RED=$'\e[101m' +BG_BRIGHT_GREEN=$'\e[102m' +BG_BRIGHT_YELLOW=$'\e[103m' +BG_BRIGHT_BLUE=$'\e[104m' +BG_BRIGHT_MAGENTA=$'\e[105m' +BG_BRIGHT_CYAN=$'\e[106m' +BG_BRIGHT_WHITE=$'\e[107m' + +# Styles +BOLD=$'\e[1m' +ITALIC=$'\e[3m' +UNDERLINE=$'\e[4m' +BLINK=$'\e[5m' # May not work in all terminals +INVERT=$'\e[7m' # Invert foreground/background +STRIKE=$'\e[9m' # Strikethrough + +# Reset +NC=$'\e[0m' # Reset all styles/colors + +# INFO: +# ↓ should get set in the install script itself +# ↓ +# echo with $PACKAGE and first argument, if 2 exist +echo_pkg() { + # if arg 2 does not exist, use normal echo + if [[ -z $2 ]]; then + case "$1" in + build) + echo "${BOLD}${BRIGHT_RED}${PACKAGE:-PKG}-build:${NC}${BRIGHT_BLUE} Building $PACKAGE ${NC}" + ;; + clone) + echo "${BOLD}${BRIGHT_RED}${PACKAGE:-PKG}-clone:${NC}${BRIGHT_YELLOW} Cloning $PACKAGE sources..${NC}" + ;; + install) + echo "${BOLD}${BRIGHT_RED}${PACKAGE:-PKG}-install:${NC}${BRIGHT_GREEN} Installing $PACKAGE now!${NC}" + ;; + *) + echo "${BOLD}${BRIGHT_RED}${PACKAGE:-PKG}:${NC}${YELLOW} $1 ${NC}" + ;; + esac + else + case "$1" in + deps | dep | dependencies) + echo "${BOLD}${BRIGHT_RED}${PACKAGE:-PKG}-${pkger:-dependencies}:${BRIGHT_YELLOW} $2 ${NC}" + ;; + *) + echo "${BOLD}${BRIGHT_RED}${PACKAGE:-PKG}-$1:${NC}${BRIGHT_YELLOW} $2 ${NC}" + ;; + esac + fi +} + +echo-pkg() { + echo_pkg "$@" +} + +echo-error() { + echo "${BOLD}${RED}${UNDERLINE}ERROR:${NC}${BRIGHT_RED} $1 ${NC}" >&2 +} + +command-exists() { + command -v "$@" >/dev/null 2>&1 +} + +silentexec() { + "$@" >/dev/null 2>&1 +} + +run-silent() { + if [[ -z $silent ]] || ! $silent; then + "$@" + else + silentexec "$@" + fi +} + +# if given an array, it checks if the command is available, and if not - installs all packages in that array one by one +check-and-install() { + local pkg=$1 + # echo "DEBUG:: GOT ARRAY :: ${@}" + # INFO: if it's not a list, then just check and install the package.. + if [[ -z $2 ]]; then + spin bold yellow "Installing $pkg" + if ! command_exists "$pkg"; then + if run pkg-install "$pkg"; then + check "Installed $pkg" + else + throw bold red "Error installing $pkg" + fi + else + check "$pkg $(pen grey bold 'already installed')" + # echo_pkg deps "skipping $pkg - as it's ${RED}already installed.." + fi + else + local pkgs="${#@}" + # ─< else go though the list of items and do the same >─────────────────────────────────── + pen grey "Packages to install: $(pen green bold $pkgs)" + for pkg in "$@"; do + if ! command_exists $pkg; then + spin bold "$(pen bold yellow Installing) $pkg" + if run --err err pkg-install $pkg; then + check "$(pen bold green Installed) $pkg" + else + throw "Something went wrong! Could not install $(pen bold red $pkg)" + echo-error "${err:-}" + fi + else + check "$pkg $(pen grey already installed)" + fi + done + fi +} + +# ─< Check if the user is root and set sudo variable if necessary >─────────────────────── +check_env() { + if [ "$(id -u)" -ne 0 ]; then + if command_exists sudo; then + # echo_info "User is not root. Using sudo for privileged operations." + _sudo="sudo -E" + else + echo_error "No sudo found and you're not root! Can't install packages." + return 69 + fi + else + pen bold red "Root access confirmed." + _sudo="" + fi + + checkFileAge() { + local file="$1" + [[ ! -e "$file" ]] && return 2 # File doesn't exist + + if [[ $(find "$file" -mtime +7 -print) ]]; then + return 69 # File is older than 1 week + else + return 0 # File is within 1 week + fi + } + + pikaCheckFile="$HOME/.cache/pika_script_detection" + + if [ -f "$pikaCheckFile" ]; then + if checkFileAge $pikaCheckFile; then + PIKA_INIT=true + else + unset PIKA_INIT + fi + else + unset PIKA_INIT + fi +} + +# CAUTION: +# ╭─────────────────────────────────────────────────────────────────────╮ +# │ This can break really quickly, since the pkg-remove() function removes │ +# │ without confirmation! use with CAUTION!! │ +# ╰─────────────────────────────────────────────────────────────────────╯ +_setup() { + case "$1" in + debian | ubuntu) + pkg-install() { + # $_sudo apt-get install --assume-yes "$@" + if command_exists nala; then + pkger=nala + $_sudo nala install --assume-yes "$@" + else + pkger=apt-get + $_sudo apt-get install --assume-yes "$@" + fi + } + + # CAUTION: + pkg-remove() { + if command_exists nala; then + pkger=nala + $_sudo nala remove --assume-yes "$@" + $_sudo nala autoremove --assume-yes + $_sudo nala autopurge --assume-yes + else + pkger=apt-get + # echo_pkg "Using pacman" + $_sudo apt-get remove --assume-yes "$@" + $_sudo apt-get autoremove --assume-yes + fi + } + ;; + fedora) + pkg-install() { + pkger=dnf + $_sudo dnf -y install "$@" + } + + # CAUTION: + pkg-remove() { + pkger=dnf + $_sudo dnf -y remove "$@" + } + ;; + arch) + checkAUR() { + if ! command_exists yay && ! command_exists paru; then + return 69 + else + return 0 + fi + } + + pkg-install() { + if command_exists paru; then + pkger=paru + # echo_pkg "Using paru" + paru -S --color always --noconfirm --needed "$@" + elif command_exists yay; then + pkger=yay + # echo_pkg "Using yay" + yay -S --color always --noconfirm --needed "$@" + else + pkger=pacman + # echo_pkg "Using pacman" + $_sudo pacman -S --color always --noconfirm --needed "$@" + fi + } + + # CAUTION: + pkg-remove() { + if command_exists paru; then + pkger=paru + # echo_info "Using paru" + paru -R --color always --noconfirm "$@" + elif command_exists yay; then + pkger=yay + # echo_info "Using yay" + yay -R --color always --noconfirm "$@" + else + pkger=pacman + # echo_warning "Using pacman" + $_sudo pacman -R --color always --noconfirm "$@" + fi + } + ;; + opensuse) + pkg-install() { + pkger=zypper + $_sudo zypper in "$@" + } + + # CAUTION: + pkg-remove() { + pkger=zypper + $_sudo zypper rem "$@" + } + ;; + alpine) + pkg-install() { + pkger=apk + apk add "$@" + } + + # CAUTION: + pkg-remove() { + pkger=apk + apk remove "$@" + } + ;; + esac +} + +# ─< Distribution detection and installation >──────────────────────────────────────── +get_packager() { + # ─< define fallback function >─────────────────────────────────────────────────────────── + fallback() { + # ─────────────────────────────────────< get packager >───────────────────────────────────── + local pkger="" + for pkg in apt-get dnf pacman apk zypper; do + if command_exists $pkg; then + printf "Using ${RED}${pkg}${NC} method.." + pkger="$pkg" + + # break + return 0 + fi + done + + case "$pkger" in + apt-get) + ubuntu="true" + debian="true" + distro="debian" + ;; + dnf) + fedora="true" + distro="fedora" + ;; + apk) + alpine="true" + distro="alpine" + ;; + pacman) + arch="true" + distro="arch" + ;; + zypper) + opensuse="true" + distro="opensuse" + ;; + *) + pen red bold "Can not detect distribution correctly!" + # echo_error "DEBUG:: $pkger ::" + return 69 + ;; + esac + } + + if [ -e /etc/os-release ]; then + echo_info "Detecting distribution..." + . /etc/os-release + + # ─< Convert $ID and $ID_LIKE to lowercase >────────────────────────────────────────────── + ID=$(printf "%s" "$ID" | tr '[:upper:]' '[:lower:]') + ID_LIKE=$(printf "%s" "$ID_LIKE" | tr '[:upper:]' '[:lower:]') + + case "$ID" in + ubuntu | pop | zorin | kubuntu | linuxmintubuntu) + ubuntu="true" + distro="ubuntu" + ;; + debian | kali | linuxmint | elementary | neon | kdeneon | deepin) + debian="true" + distro="debian" + ;; + fedora | centos | rhel | rocky | almalinux) + fedora="true" + distro="fedora" + ;; + alpine) + alpine="true" + distro="alpine" + ;; + arch | manjaro | garuda | endeavour) + arch="true" + distro="arch" + ;; + opensuse*) + opensuse="true" + distro="opensuse" + ;; + *) + if [ "${ID_LIKE#*debian}" != "$ID_LIKE" ]; then + debian="true" + distro="debian" + elif [ "${ID_LIKE#*ubuntu}" != "$ID_LIKE" ]; then + ubuntu="true" + distro="ubuntu" + elif [ "${ID_LIKE#*arch}" != "$ID_LIKE" ]; then + arch="true" + distro="arch" + elif [ "${ID_LIKE#*fedora}" != "$ID_LIKE" ]; then + fedora="true" + distro="fedora" + elif [ "${ID_LIKE#*suse}" != "$ID_LIKE" ]; then + opensuse="true" + distro="opensuse" + else + pen bold red "Unsupported distribution: $ID" + + spin bold "Trying other methods.." + sleep 1 + + run fallback && check "Got packager.." || throw "No chance helping you now buddy!" + fi + ;; + esac + else + pen red bold "Unable to detect distribution - /etc/os-release not found." + spin bold "Trying other methods.." + + sleep 1 + + run fallback && check "Got packager.." || throw "No chance helping you now buddy!" + fi +} + +# INFO: +# ╭────────────────────────────────────────────────────────────────────────────────────────╮ +# │ Automated setup for refreshing repositories and overall getting the variables to setup │ +# ╰────────────────────────────────────────────────────────────────────────────────────────╯ + +dist_setup() { + case "$distro" in + debian) + echo "${BOLD}Found ${RED}debian${NC}" + _setup debian + # Codename support + if [ -n $VERSION_CODENAME ]; then + case "$VERSION_CODENAME" in + trixie) trixie=true ;; + bookworm) bookworm=true ;; + bullseye) bullseye=true ;; + buster) buster=true ;; + esac + fi + ;; + ubuntu) + echo "${BOLD}Found ${BRIGHT_YELLOW}ubuntu${NC}" + _setup ubuntu + # Codename support + if [ -n $VERSION_CODENAME ]; then + case "$VERSION_CODENAME" in + noble) noble=true ;; + jammy) jammy=true ;; + focal) focal=true ;; + bionic) bionic=true ;; + esac + fi + ;; + fedora) + echo "${BOLD}Found ${BRIGHT_BLUE}fedora${NC}" + _setup fedora + # Add version-specific var like: fedora_40=true + fedora_version="fedora_${VERSION_ID//./_}" + eval "$fedora_version=true" + ;; + arch) + echo "${BOLD}Found ${BLUE}arch${NC}" + _setup arch + if command_exists yay || command_exists paru; then + aur=true + else + aur=false + fi + ;; + alpine) + echo "${BOLD}Found ${BLUE}alpine${NC}" + _setup $distro + ;; + opensuse) + echo "${BOLD}Found ${GREEN}opensuse${NC}" + _setup $distro + ;; + esac +} + +update-package-list() { + local USER="${USER:-$(whoami)}" + + repo::check() { + check "${distro}-repositories up to date" || throw "Error while updating $distro repositories.." + } + + case "$distro" in + ubuntu | debian) + spin bold red "Refreshing $distro sources.." + run $_sudo apt-get update || repo::check + ;; + fedora) + spin blue bold "Refreshing $distro repositories.." + run $_sudo dnf update || repo::check + ;; + arch) + if command_exists pacman; then + if ! checkAUR; then + pen grey bold "If this is your first time after boot (or simmilarly soon) then this might take a while.." + spin bold grey "You don't have an AUR helper, gonna install one for ya!" + + local paruBuildDir="/opt/builds" + silentexec $_sudo mkdir -p "$paruBuildDir" + + # echo "${YELLOW}Installing paru as AUR helper...${NC}" + run $_sudo pacman -S --needed --noconfirm base-devel git || throw "Error installing dependencies.." + + local url="https://aur.archlinux.org/paru-bin.git" + cd "$paruBuildDir" # && echo "${YELLOW} Cloning paru from ${NC}https://aur.archlinux.org/paru-bin.git" + run $_sudo git clone $url paru || throw "Error cloning sources from $url" + + run $_sudo chown -R "$USER": "$paruBuildDir/paru" + cd "$paruBuildDir/paru" + + local err + if run --err err makepkg --noconfirm -si; then + check "Successfully installed $(pen red bold paru)" + else + throw "Couldn't install paru!" + echo-error "${err:-}" + fi + + if command_exists paru; then + pen green bold "Paru is installed" + else + echo-error "Something went wrong when installing paru!" + fi + fi + fi + + spin blue bold "Refreshing $distro repositories.." + sleep 0.01 + + if command_exists paru; then + run paru -Sy || repo::check + elif command_exists yay; then + run yay -Sy || repo::check + else + run $_sudo pacman -Sy || repo::check + fi + ;; + opensuse) + run $_sudo zypper ref || repo::check + ;; + alpine) run $_sudo apk update || repo::check ;; + *) + echo-error "Unsupported distribution: ${BRIGHT_RED}$distro" + return 69 + ;; + esac +} + +if check_env; then + get_packager + dist_setup + + # WHY: + # ╭─────────────────────────────────────────────────────────────────────────╮ + # │ check if the script has run at least once, so that the sources dont │ + # │ have to get updated again.. │ + # ╰─────────────────────────────────────────────────────────────────────────╯ + if [[ -z "$PIKA_INIT" ]]; then + pen bold grey "First time importing.." + + if update-package-list; then + silentexec touch "$pikaCheckFile" + fi + else + echo_pkg "Skipping repo refresh" + fi +fi +# NOTE: +# ────────────────────────────────────< end distros.sh >──────────────────────────────────── +# ───────────────────────────────────────< beddu.sh >─────────────────────────────────────── +# +# shellcheck disable=all +# +# beddu.sh - A lightweight bash framework for interactive scripts and pretty output +# Version: v1.1.0 +# +# Copyright © 2025 Manuele Sarfatti +# Licensed under the MIT license +# See https://github.com/mjsarfatti/beddu + +readonly _q='?' +readonly _a='❯' +readonly _o='◌' +readonly _O='●' +readonly _mark='✓' +readonly _warn='!' +readonly _cross='✗' +readonly _spinner='⣷⣯⣟⡿⢿⣻⣽⣾' # See for alternatives: https://antofthy.gitlab.io/info/ascii/Spinners.txt +readonly _spinner_frame_duration=0.15 + +up() { + printf "\033[A" +} +down() { + printf "\033[B" +} +bol() { + printf "\r" +} +eol() { + printf "\033[999C" +} +cl() { + printf "\033[2K" +} +upclear() { + up + bol + cl +} +line() { + printf "\n" +} +show_cursor() { + printf "\033[?25h" +} +hide_cursor() { + printf "\033[?25l" +} + +pen() { + local new_line="\n" + local text="${*: -1}" + local args=("${@:1:$#-1}") + local format_code="" + local reset_code="\033[0m" + for arg in "${args[@]}"; do + arg=${arg,,} + case "$arg" in + -n) new_line="" ;; + bold) format_code+="\033[1m" ;; + italic) format_code+="\033[3m" ;; + underline) format_code+="\033[4m" ;; + black) format_code+="\033[30m" ;; + red) format_code+="\033[31m" ;; + green) format_code+="\033[32m" ;; + yellow) format_code+="\033[33m" ;; + blue) format_code+="\033[34m" ;; + purple) format_code+="\033[35m" ;; + cyan) format_code+="\033[36m" ;; + white) format_code+="\033[37m" ;; + grey | gray) format_code+="\033[90m" ;; + [0-9]*) + if [[ "$arg" =~ ^[0-9]+$ ]] && [ "$arg" -ge 0 ] && [ "$arg" -le 255 ]; then + format_code+="\033[38;5;${arg}m" + fi + ;; + *) ;; + esac + done + printf "%b%s%b%b" "${format_code}" "${text}" "${reset_code}" "${new_line}" +} + +run() { + local outvar_name errvar_name + local -n outvar errvar # Declare namerefs (will be assigned below if needed) + local cmd + while [[ $# -gt 0 ]]; do + case "$1" in + --out) + outvar_name="$2" + shift 2 + ;; + --err) + errvar_name="$2" + shift 2 + ;; + *) + cmd=("$@") + break + ;; + esac + done + [[ -n "${outvar_name}" ]] && local -n outvar="${outvar_name}" + [[ -n "${errvar_name}" ]] && local -n errvar="${errvar_name}" + local stdout_file stderr_file + stdout_file=$(mktemp) + stderr_file=$(mktemp) + "${cmd[@]}" >"${stdout_file}" 2>"${stderr_file}" + local exit_code=$? + [[ -n "${outvar_name}" ]] && outvar="$(<"$stdout_file")" + [[ -n "${errvar_name}" ]] && errvar="$(<"$stderr_file")" + rm -f "${stdout_file}" "${stderr_file}" + return $exit_code +} + +check() { + if spinning; then + spop + upclear + fi + pen -n green "${_mark:-✓} " + pen "$@" +} + +repen() { + upclear + pen "$@" +} + +trap "spop; show_cursor" EXIT INT TERM +_spinner_pid="" +_frame_duration="${_spinner_frame_duration:-0.1}" +spin() { + local message=("$@") + local spinner="${_spinner:-⣷⣯⣟⡿⢿⣻⣽⣾}" + if spinning; then + spop --keep-cursor-hidden + fi + ( + hide_cursor + trap "exit 0" USR1 + pen -n cyan "${spinner:0:1} " + pen "${message[@]}" + while true; do + for ((i = 0; i < ${#spinner}; i++)); do + frame="${spinner:$i:1}" + up + bol + pen -n cyan "${frame} " + pen "${message[@]}" + sleep "$_frame_duration" + done + done + ) & + _spinner_pid=$! +} +spop() { + local keep_cursor_hidden=false + [[ "$1" == "--keep-cursor-hidden" ]] && keep_cursor_hidden=true + if spinning; then + kill -USR1 "${_spinner_pid}" 2>/dev/null + sleep "$_frame_duration" + if ps -p "${_spinner_pid}" >/dev/null 2>&1; then + kill "${_spinner_pid}" 2>/dev/null + fi + if [[ "$keep_cursor_hidden" == false ]]; then + show_cursor + fi + _spinner_pid="" + fi +} +spinning() { + [[ -n "${_spinner_pid}" ]] +} + +throw() { + if spinning; then + spop + upclear + fi + pen -n red "${_cross:-✗} " + pen "$@" +} + +warn() { + if spinning; then + spop + upclear + fi + pen -n yellow bold italic "${_warn:-!} " + pen italic "$@" +} + +choose() { + local -n outvar="$1" + local prompt + local options=("${@:3}") + local current=0 + local count=${#options[@]} + prompt=$( + pen -n blue "${_q:-?} " + pen -n "${2} " + pen gray "[↑↓]" + ) + hide_cursor + trap 'show_cursor; return' INT TERM + pen "$prompt" + while true; do + local index=0 + for item in "${options[@]}"; do + if ((index == current)); then + pen -n blue "${_O:-●} " + pen "${item}" + else + pen gray "${_o:-◌} ${item}" + fi + ((index++)) + done + read -s -r -n1 key + if [[ $key == $'\e' ]]; then + read -s -r -n2 -t 0.0001 escape + key+="$escape" + fi + case "$key" in + $'\e[A' | 'k') + ((current--)) + [[ $current -lt 0 ]] && current=$((count - 1)) + ;; + $'\e[B' | 'j') + ((current++)) + [[ $current -ge "$count" ]] && current=0 + ;; + 'q') + upclear + pen red bold "User exited the session with exit code 69!" + pen red "This is $(pen bold red 'NOT') an accident!" + exit 69 + ;; + '') + break + ;; + esac + echo -en "\e[${count}A\e[J" + done + outvar="${options[$current]}" +} + +confirm() { + local default="y" + local hint="[Y/n]" + local prompt + local response + while [[ $# -gt 0 ]]; do + case "$1" in + --default-no) + default="n" + hint="[y/N]" + shift + ;; + --default-yes) + shift + ;; + *) break ;; + esac + done + prompt=$( + pen -n blue "${_q:-?} " + pen -n "$1" + pen gray " $hint" + pen -n blue "${_a:-❯} " + ) + show_cursor + while true; do + read -r -p "$prompt" response + response="${response:-$default}" + case "$response" in + [Yy] | [Yy][Ee][Ss]) + upclear + pen -n blue "${_a:-❯} " + pen "yes" + return 0 + ;; + [Nn] | [Nn][Oo]) + upclear + pen -n blue "${_a:-❯} " + pen "no" + return 1 + ;; + [qQ] | quit) + upclear + pen red bold "User exited the session with exit code 69!" + pen red "This is $(pen bold red 'NOT') an accident!" + exit 69 + ;; + *) + echo + warn "Please answer yes or no." + ;; + esac + done +} + +request() { + local -n outvar="$1" + local prompt + local answer + prompt=$( + pen -n blue "${_q:-?} " + pen "${2}" + pen -n blue "${_a:-❯} " + ) + show_cursor + while true; do + read -r -p "$prompt" answer + case "$answer" in + "") + echo + warn "Please type your answer." + ;; + *) break ;; + esac + done + outvar="$answer" +} + +seek() { + local -n outvar="$1" + local prompt + local answer + prompt=$( + pen -n blue "${_q:-?} " + pen "${2}" + pen -n blue "${_a:-❯} " + ) + show_cursor + read -r -p "$prompt" answer + outvar="$answer" +} +# NOTE: +# ──────────────────────────────────────< end beddu >────────────────────────────────────