From cc8ffcfcc277e0172d9f0d0ea9979a2dea2fc160 Mon Sep 17 00:00:00 2001 From: pika Date: Mon, 14 Apr 2025 09:22:15 +0200 Subject: [PATCH] batman --- bash/README.md | 2 + bash/arch-hyprland.sh | 190 ++++++++++ bash/bash_tui.sh | 106 ++++++ bash/debian-major.sh | 157 ++++++++ bash/docker-network.sh | 110 ++++++ bash/fix.sh | 3 + bash/games/2048.sh | 378 +++++++++++++++++++ bash/games/wordle.sh | 50 +++ bash/gitsetup.sh | 246 +++++++++++++ bash/installs/forgejo-runner.sh | 160 ++++++++ bash/postinstall.sh | 357 ++++++++++++++++++ bash/realmjoin.sh | 143 ++++++++ bash/setup/hlpush.sh | 38 ++ bash/setup/homelapGitSetup.sh | 152 ++++++++ bash/setup/tuiDots.sh | 207 +++++++++++ bash/unattendet-upgrades.sh | 86 +++++ bash/updates.sh | 157 ++++++++ installs/README.md | 105 ++++++ installs/docker.sh | 180 +++++++++ installs/flatpak.sh | 152 ++++++++ installs/ghostty.sh | 310 ++++++++++++++++ installs/hyprland.sh | 632 ++++++++++++++++++++++++++++++++ installs/hyprpanel.sh | 97 +++++ installs/install-blesh.sh | 71 ++++ installs/neovide.sh | 131 +++++++ installs/neovim.sh | 223 +++++++++++ installs/virt-manager.sh | 208 +++++++++++ installs/xmrig.sh | 187 ++++++++++ installs/yazi.sh | 149 ++++++++ installs/ytgo.sh | 157 ++++++++ logging.sh | 76 ++++ python/Caddy/addEntry.py | 331 +++++++++++++++++ python/README.md | 2 + python/checkpkg.py | 354 ++++++++++++++++++ python/dev/codedex/loops.py | 16 + python/dev/fonts.py | 76 ++++ python/dev/test.py | 5 + python/mergefiles.py | 42 +++ 38 files changed, 6046 insertions(+) create mode 100644 bash/README.md create mode 100644 bash/arch-hyprland.sh create mode 100755 bash/bash_tui.sh create mode 100644 bash/debian-major.sh create mode 100644 bash/docker-network.sh create mode 100644 bash/fix.sh create mode 100755 bash/games/2048.sh create mode 100755 bash/games/wordle.sh create mode 100755 bash/gitsetup.sh create mode 100755 bash/installs/forgejo-runner.sh create mode 100755 bash/postinstall.sh create mode 100644 bash/realmjoin.sh create mode 100755 bash/setup/hlpush.sh create mode 100755 bash/setup/homelapGitSetup.sh create mode 100755 bash/setup/tuiDots.sh create mode 100644 bash/unattendet-upgrades.sh create mode 100755 bash/updates.sh create mode 100644 installs/README.md create mode 100755 installs/docker.sh create mode 100755 installs/flatpak.sh create mode 100644 installs/ghostty.sh create mode 100644 installs/hyprland.sh create mode 100644 installs/hyprpanel.sh create mode 100755 installs/install-blesh.sh create mode 100755 installs/neovide.sh create mode 100755 installs/neovim.sh create mode 100755 installs/virt-manager.sh create mode 100755 installs/xmrig.sh create mode 100644 installs/yazi.sh create mode 100644 installs/ytgo.sh create mode 100644 logging.sh create mode 100755 python/Caddy/addEntry.py create mode 100644 python/README.md create mode 100755 python/checkpkg.py create mode 100644 python/dev/codedex/loops.py create mode 100755 python/dev/fonts.py create mode 100644 python/dev/test.py create mode 100644 python/mergefiles.py diff --git a/bash/README.md b/bash/README.md new file mode 100644 index 0000000..1a9321f --- /dev/null +++ b/bash/README.md @@ -0,0 +1,2 @@ +# bash + diff --git a/bash/arch-hyprland.sh b/bash/arch-hyprland.sh new file mode 100644 index 0000000..297962b --- /dev/null +++ b/bash/arch-hyprland.sh @@ -0,0 +1,190 @@ +#!/bin/bash -e + +# ╭───────────────╮ +# │ env functions │ +# ╰───────────────╯ +# ───────────────────────────────────< ANSI color codes >─────────────────────────────────── +RED='\033[0;31m' +CYAN='\033[0;36m' +YELLOW='\033[0;33m' +LIGHT_GREEN='\033[0;92m' +BOLD='\033[1m' +NC='\033[0m' # No Color + +# ERROR: -- Message +echo_error() { + printf "${BOLD}${RED}ERROR: ${NC}${RED}%s${NC}\n" "$1" >&2 +} + +# INFO: -- Message +echo_info() { + printf "${BOLD}${CYAN}INFO: ${NC}${CYAN}%s${NC}\n" "$1" +} + +# WARNING: -- Message +echo_warning() { + printf "${BOLD}${YELLOW}WARNING: ${NC}${YELLOW}%s${NC}\n" "$1" +} + +# NOTE: -- Message +echo_note() { + printf "${BOLD}${LIGHT_GREEN}NOTE: ${NC}${LIGHT_GREEN}%s${NC}\n" "$1" +} + +# ──────────────────────< Check if the given command exists silently >────────────────────── +command_exists() { + command -v "$@" >/dev/null 2>&1 +} + +# ─────────────< Check if the user is root and set sudo variable if necessary >───────────── +check_root() { + if [[ "$(id -u)" -ne 0 ]]; then + if command_exists sudo; then + echo_info "User is not root. Using sudo for privileged operations." + _sudo="sudo" + else + echo_error "No sudo found and you're not root! Can't install packages." + return 1 + fi + else + echo_info "Root access confirmed." + _sudo="" + fi +} + +# ─< Distribution detection and installation >──────────────────────────────────────── +get_packager() { + $_sudo pacman -Sy + if command_exists paru; then + _install() { paru -S --noconfirm "$@"; } + elif command_exists yay; then + _install() { yay -S --noconfirm "$@"; } + elif command_exists pacman; then + _install() { "$_sudo" pacman -S --noconfirm "$@"; } + fi +} + +check_deps() { + deps=( + "hyprland" + "hyprpicker" + "hyprlang" + "hyprutils" + "hyprwayland-scanner" + "xdg-desktop-portal-hyprland" + "$BarOfChoise" + "${MenuOfChoise[@]}" + "swww" + "wlogout" + "libnotify" + ) + + for dependency in "${deps[@]}"; do + if ! command_exists "$dependency"; then + echo_note "Installing $dependency.." + _install "$dependency" || echo_error "Error installing $dependency!" + else + echo_info "$dependency is already installed" + fi + done +} + +ask_bar() { + echo_note "Which bar do you want to use?" + echo_note "[g]Bar, [H]yprpanel, [W]aybar" + read -r ask_bar ─────────────────────────────── +main() { + if check_root; then + if check_aur; then + get_packager + fi + else + echo_error "Something went terribly wrong!" + exit 1 + fi + + ask_bar + ask_menu + check_deps + ask_dotfiles +} + +if ! command_exists hyprland; then + main +else + echo_warning "Hyprland is already installed!" +fi diff --git a/bash/bash_tui.sh b/bash/bash_tui.sh new file mode 100755 index 0000000..8b5dc57 --- /dev/null +++ b/bash/bash_tui.sh @@ -0,0 +1,106 @@ +#!/bin/bash + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Menu options +declare -a options=( + "Dotfiles" + "CLI Tool Installation" + "Sudo-Options" + "Optimizations" + "Exit" +) +# declare -a options="Dotfiles CLI_Tool_Installation Sudo-Options Optimizations Exit" + +# Function to print colored text +print_color() { + printf "%b%s%b\n" "$1" "$2" "$NC" +} + +# Function to display the menu +display_menu() { + clear + print_color "$BLUE" "=== Environment Setup Menu ===" + for i in "${!options[@]}"; do + if [[ $i -eq $selected ]]; then + print_color "$GREEN" "> ${options[$i]}" + else + echo " ${options[$i]}" + fi + done +} + +# Function to handle dotfiles setup +dotfiles_setup() { + print_color "$YELLOW" "Setting up dotfiles..." + # Add your dotfiles setup logic here + sleep 2 +} + +# Function to handle CLI tool installation +cli_tool_installation() { + print_color "$YELLOW" "Installing CLI tools..." + # Add your CLI tool installation logic here + sleep 2 +} + +# Function to handle optimizations +optimizations() { + print_color "$YELLOW" "Performing optimizations..." + # Add your optimization logic here + sleep 2 +} + +sudo_options() { + if [[ -e /etc/sudoers ]]; then + echo "Defaults pwfeedback" | tee -a /etc/sudoers + echo "Defaults insults" | tee -a /etc/sudoers + else + echo_error "There is no /etc/sudoers file." + fi +} + +# Main menu loop +main_menu() { + local selected=0 + local key="" + + while true; do + display_menu + + # Read a single character + read -rsn1 key + + case $key in + A | k) # Up arrow or k + ((selected--)) + if [[ $selected -lt 0 ]]; then + selected=$((${#options[@]} - 1)) + fi + ;; + B | j) # Down arrow or j + ((selected++)) + if [[ $selected -ge ${#options[@]} ]]; then + selected=0 + fi + ;; + "") # Enter key + case $selected in + 0) dotfiles_setup ;; + 1) cli_tool_installation ;; + 2) sudo_options ;; + 3) optimizations ;; + 4) exit 0 ;; + esac + ;; + esac + done +} + +# Start the main menu +main_menu ─────────────────────────────────── +RED='\033[0;31m' +CYAN='\033[0;36m' +YELLOW='\033[0;33m' +LIGHT_GREEN='\033[0;92m' +BOLD='\033[1m' +NC='\033[0m' # No Color + +echo_error() { + printf "${BOLD}${RED}ERROR: ${NC}${RED}%s${NC}\n" "$1" >&2 +} + +echo_info() { + printf "${BOLD}${CYAN}INFO: ${NC}${CYAN}%s${NC}\n" "$1" +} + +echo_warning() { + printf "${BOLD}${YELLOW}WARNING: ${NC}${YELLOW}%s${NC}\n" "$1" +} + +echo_note() { + printf "${BOLD}${LIGHT_GREEN}NOTE: ${NC}${LIGHT_GREEN}%s${NC}\n" "$1" +} + +command_exists() { + command -v "$@" >/dev/null 2>&1 +} + +# ─────────────< Check if the user is root and set sudo variable if necessary >───────────── +check_root() { + if [ "$(id -u)" -ne 0 ]; then + if command_exists sudo; then + echo_info "User is not root. Using sudo for privileged operations." + _sudo="sudo" + else + echo_error "No sudo found and you're not root! Can't install packages." + return 1 + fi + else + echo_info "Root access confirmed." + _sudo="" + fi +} + +# ──────────────────────< Check if the given command exists silently >────────────────────── +command_exists() { + command -v "$@" >/dev/null 2>&1 +} + +# ╭────────────────────────────────────╮ +# │ insert your scripts/functions here │ +# ╰────────────────────────────────────╯ + +full_update_and_upgrade() { + if command_exists apt-get; then + echo_info "Updating sources.." + $_sudo apt-get update || echo_error "Something went wrong, please check your connection and permissions!" + $_sudo apt-get upgrade --assume-yes || echo_error "Something went wrong, please check your connection and permissions!" + $_sudo apt-get full-upgrade --assume-yes || echo_error "Something went wrong, please check your connection and permissions!" + else + echo_error "The OS is not suitable for this script!" + fi +} + +clean_and_full_upgrade() { + if command_exists apt-get; then + echo_info "Cleaning the environment.." + $_sudo apt-get clean --assume-yes + full_update_and_upgrade + else + echo_error "The OS is not suitable for this script!" + fi +} + +post_clean() { + if command_exists apt-get; then + $_sudo apt-get autoremove --assume-yes + else + echo_error "The OS is not suitable for this script!" + fi +} + +detect_version() { + . /etc/os-release + case "$VERSION_CODENAME" in + bookworm) + cur_os="bookworm" + tar_os="trixie" + ;; + buster) + cur_os="buster" + tar_os="bullseye" + ;; + bullseye) + cur_os="bullseye" + tar_os="bookworm" + ;; + *) + echo_error "$VERSION_CODENAME is either not a debian version, or just simply not defined" + return 1 + ;; + esac +} + +update_sources() { + # Create backup directory if it doesn't exist + BACKUP_DIR="/var/backups/apt-sources" + echo_info "Creating backup directory at $BACKUP_DIR..." + $_sudo mkdir -p "$BACKUP_DIR" + + echo_info "Backing up current sources lists..." + $_sudo cp /etc/apt/sources.list "$BACKUP_DIR/sources.list.backup.$(date +%Y%m%d)" + + echo_info "Updating sources from Bookworm to Trixie..." + # Replace bookworm with trixie in main sources.list + $_sudo sed -i "s/$cur_os/$tar_os/g" /etc/apt/sources.list + + # Check and update any additional source files in sources.list.d + if [ -d "/etc/apt/sources.list.d" ]; then + for sourcefile in /etc/apt/sources.list.d/*.list; do + if [ -f "$sourcefile" ]; then + filename=$(basename "$sourcefile") + echo_info "Backing up and updating $sourcefile..." + $_sudo cp "$sourcefile" "$BACKUP_DIR/${filename}.backup.$(date +%Y%m%d)" + $_sudo sed -i "s/$cur_os/$tar_os/g" "$sourcefile" + fi + done + fi + + echo_note "Sources have been updated to Trixie. Please run a full system update." + echo_warning "Make sure to review the changes and ensure all repositories are compatible with Trixie!" + echo_info "Backups stored in $BACKUP_DIR" + echo "" + __lsb_release__="$(lsb_release -a)" + echo_info "$__lsb_release__" +} + +# ───────────────────────────────< main function to execute >─────────────────────────────── +main() { + if check_root; then + full_update_and_upgrade + if detect_version; then + update_sources + fi + clean_and_full_upgrade + post_clean + else + echo_error "Something went terribly wrong!" + fi +} + +main diff --git a/bash/docker-network.sh b/bash/docker-network.sh new file mode 100644 index 0000000..3ff2deb --- /dev/null +++ b/bash/docker-network.sh @@ -0,0 +1,110 @@ +#!/bin/sh + +# ╭───────────────╮ +# │ env functions │ +# ╰───────────────╯ +# ───────────────────────────────────< ANSI color codes >─────────────────────────────────── +RED='\033[0;31m' +CYAN='\033[0;36m' +YELLOW='\033[0;33m' +LIGHT_GREEN='\033[0;92m' +BOLD='\033[1m' +NC='\033[0m' # No Color + +echo_error() { + printf "${BOLD}${RED}ERROR: ${NC}${RED}%s${NC}\n" "$1" >&2 +} + +echo_info() { + printf "${BOLD}${CYAN}INFO: ${NC}${CYAN}%s${NC}\n" "$1" +} + +echo_warning() { + printf "${BOLD}${YELLOW}WARNING: ${NC}${YELLOW}%s${NC}\n" "$1" +} + +echo_note() { + printf "${BOLD}${LIGHT_GREEN}NOTE: ${NC}${LIGHT_GREEN}%s${NC}\n" "$1" +} + +command_exists() { + command -v "$@" >/dev/null 2>&1 +} + +# ─────────────< Check if the user is root and set sudo variable if necessary >───────────── +check_root() { + if [ "$(id -u)" -ne 0 ]; then + if command_exists sudo; then + echo_info "User is not root. Using sudo for privileged operations." + _sudo="sudo" + else + echo_error "No sudo found and you're not root! Can't install packages." + return 1 + fi + else + echo_info "Root access confirmed." + _sudo="" + fi +} + +# ──────────────────────< Check if the given command exists silently >────────────────────── +command_exists() { + command -v "$@" >/dev/null 2>&1 +} + +# ╭────────────────────────────────────╮ +# │ insert your scripts/functions here │ +# ╰────────────────────────────────────╯ + +# Function to initialize or update the Docker daemon configuration +dnetwork_init() { + if ! command_exists docker; then + echo_error "No docker was found! Cannot continue!" + return 1 + fi + + CONFIG_FILE="/etc/docker/daemon.json" + + echo_info "Checking Docker daemon configuration..." + + # Check if the configuration file exists + if [ ! -f "$CONFIG_FILE" ]; then + echo_warning "Docker daemon configuration file not found. Creating it." + ${_sudo} mkdir -p /etc/docker + ${_sudo} tee "$CONFIG_FILE" >/dev/null </dev/null + ${_sudo} mv "$CONFIG_FILE.tmp" "$CONFIG_FILE" + echo_note "Default address pool added to configuration." + fi + fi + + echo_info "Restarting Docker to apply changes..." + ${_sudo} systemctl restart docker && echo_note "Docker restarted successfully." || echo_error "Failed to restart Docker." +} + +# ───────────────────────────────< main function to execute >─────────────────────────────── +main() { + if check_root; then + dnetwork_init + else + echo_error "Something went terribly wrong!" + fi +} + +main diff --git a/bash/fix.sh b/bash/fix.sh new file mode 100644 index 0000000..bd320b6 --- /dev/null +++ b/bash/fix.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +sudo reflector --verbose --latest 10 --sort rate --save /etc/pacman.d/mirrorlist diff --git a/bash/games/2048.sh b/bash/games/2048.sh new file mode 100755 index 0000000..81cb076 --- /dev/null +++ b/bash/games/2048.sh @@ -0,0 +1,378 @@ +#!/usr/bin/env bash + +#important variables +declare -ia board # array that keeps track of game status +declare -i pieces # number of pieces present on board +declare -i score=0 # score variable +declare -i flag_skip # flag that prevents doing more than one operation on +# single field in one step +declare -i moves # stores number of possible moves to determine if player lost +# the game +declare ESC=$'\e' # escape byte +declare header="Bash 2048 v1.1 (https://github.com/mydzor/bash2048)" + +declare -i start_time=$(date +%s) + +#default config +declare -i board_size=4 +declare -i target=2048 +declare -i reload_flag=0 +declare config_dir="$HOME/.bash2048" + +#for colorizing numbers +declare -a colors +colors[2]=33 # yellow text +colors[4]=32 # green text +colors[8]=34 # blue text +colors[16]=36 # cyan text +colors[32]=35 # purple text +colors[64]="33m\033[7" # yellow background +colors[128]="32m\033[7" # green background +colors[256]="34m\033[7" # blue background +colors[512]="36m\033[7" # cyan background +colors[1024]="35m\033[7" # purple background +colors[2048]="31m\033[7" # red background (won with default target) + +exec 3>/dev/null # no logging by default + +trap "end_game 0 1" INT #handle INT signal + +#simplified replacement of seq command +function _seq { + local cur=1 + local max + local inc=1 + case $# in + 1) let max=$1 ;; + 2) + let cur=$1 + let max=$2 + ;; + 3) + let cur=$1 + let inc=$2 + let max=$3 + ;; + esac + while test $max -ge $cur; do + printf "$cur " + let cur+=inc + done +} + +# print currect status of the game, last added pieces are marked red +function print_board { + clear + printf "$header pieces=$pieces target=$target score=$score\n" + printf "Board status:\n" >&3 + printf "\n" + printf '/------' + for l in $(_seq 1 $index_max); do + printf '+------' + done + printf '\\\n' + for l in $(_seq 0 $index_max); do + printf '|' + for m in $(_seq 0 $index_max); do + if let ${board[l * $board_size + m]}; then + if let '(last_added==(l*board_size+m))|(first_round==(l*board_size+m))'; then + printf '\033[1m\033[31m %4d \033[0m|' ${board[l * $board_size + m]} + else + printf "\033[1m\033[${colors[${board[l * $board_size + m]}]}m %4d\033[0m |" ${board[l * $board_size + m]} + fi + printf " %4d |" ${board[l * $board_size + m]} >&3 + else + printf ' |' + printf ' |' >&3 + fi + done + let l==$index_max || { + printf '\n|------' + for l in $(_seq 1 $index_max); do + printf '+------' + done + printf '|\n' + printf '\n' >&3 + } + done + printf '\n\\------' + for l in $(_seq 1 $index_max); do + printf '+------' + done + printf '/\n' +} + +# Generate new piece on the board +# inputs: +# $board - original state of the game board +# $pieces - original number of pieces +# outputs: +# $board - new state of the game board +# $pieces - new number of pieces +function generate_piece { + while true; do + let pos=RANDOM%fields_total + let board[$pos] || { + let value=RANDOM%10?2:4 + board[$pos]=$value + last_added=$pos + printf "Generated new piece with value $value at position [$pos]\n" >&3 + break + } + done + let pieces++ +} + +# perform push operation between two pieces +# inputs: +# $1 - push position, for horizontal push this is row, for vertical column +# $2 - recipient piece, this will hold result if moving or joining +# $3 - originator piece, after moving or joining this will be left empty +# $4 - direction of push, can be either "up", "down", "left" or "right" +# $5 - if anything is passed, do not perform the push, only update number +# of valid moves +# $board - original state of the game board +# outputs: +# $change - indicates if the board was changed this round +# $flag_skip - indicates that recipient piece cannot be modified further +# $board - new state of the game board +function push_pieces { + case $4 in + "up") + let "first=$2*$board_size+$1" + let "second=($2+$3)*$board_size+$1" + ;; + "down") + let "first=(index_max-$2)*$board_size+$1" + let "second=(index_max-$2-$3)*$board_size+$1" + ;; + "left") + let "first=$1*$board_size+$2" + let "second=$1*$board_size+($2+$3)" + ;; + "right") + let "first=$1*$board_size+(index_max-$2)" + let "second=$1*$board_size+(index_max-$2-$3)" + ;; + esac + let ${board[$first]} || { + let ${board[$second]} && { + if test -z $5; then + board[$first]=${board[$second]} + let board[$second]=0 + let change=1 + printf "move piece with value ${board[$first]} from [$second] to [$first]\n" >&3 + else + let moves++ + fi + return + } + return + } + let ${board[$second]} && let flag_skip=1 + let "${board[$first]}==${board[second]}" && { + if test -z $5; then + let board[$first]*=2 + let "board[$first]==$target" && end_game 1 + let board[$second]=0 + let pieces-=1 + let change=1 + let score+=${board[$first]} + printf "joined piece from [$second] with [$first], new value=${board[$first]}\n" >&3 + else + let moves++ + fi + } +} + +function apply_push { + printf "\n\ninput: $1 key\n" >&3 + for i in $(_seq 0 $index_max); do + for j in $(_seq 0 $index_max); do + flag_skip=0 + let increment_max=index_max-j + for k in $(_seq 1 $increment_max); do + let flag_skip && break + push_pieces $i $j $k $1 $2 + done + done + done +} + +function check_moves { + let moves=0 + apply_push up fake + apply_push down fake + apply_push left fake + apply_push right fake +} + +function key_react { + let change=0 + read -d '' -sn 1 + test "$REPLY" = "$ESC" && { + read -d '' -sn 1 -t1 + test "$REPLY" = "[" && { + read -d '' -sn 1 -t1 + case $REPLY in + A) apply_push up ;; + B) apply_push down ;; + C) apply_push right ;; + D) apply_push left ;; + esac + } + } || { + case $REPLY in + k) apply_push up ;; + j) apply_push down ;; + l) apply_push right ;; + h) apply_push left ;; + + w) apply_push up ;; + s) apply_push down ;; + d) apply_push right ;; + a) apply_push left ;; + esac + } +} + +function save_game { + rm -rf "$config_dir" + mkdir "$config_dir" + echo "${board[@]}" >"$config_dir/board" + echo "$board_size" >"$config_dir/board_size" + echo "$pieces" >"$config_dir/pieces" + echo "$target" >"$config_dir/target" + # echo "$log_file" > "$config_dir/log_file" + echo "$score" >"$config_dir/score" + echo "$first_round" >"$config_dir/first_round" +} + +function reload_game { + printf "Loading saved game...\n" >&3 + + if test ! -d "$config_dir"; then + return + fi + board=($(cat "$config_dir/board")) + board_size=($(cat "$config_dir/board_size")) + board=($(cat "$config_dir/board")) + pieces=($(cat "$config_dir/pieces")) + first_round=($(cat "$config_dir/first_round")) + target=($(cat "$config_dir/target")) + score=($(cat "$config_dir/score")) + + fields_total=board_size*board_size + index_max=board_size-1 +} + +function end_game { + # count game duration + end_time=$(date +%s) + let total_time=end_time-start_time + + print_board + printf "Your score: $score\n" + + printf "This game lasted " + + $(date --version >/dev/null 2>&1) + if [[ "$?" -eq 0 ]]; then + date -u -d @${total_time} +%T + else + date -u -r ${total_time} +%T + fi + + stty echo + let $1 && { + printf "Congratulations you have achieved $target\n" + exit 0 + } + let test -z $2 && { + read -n1 -p "Do you want to overwrite saved game? [y|N]: " + test "$REPLY" = "Y" || test "$REPLY" = "y" && { + save_game + printf "\nGame saved. Use -r option next to load this game.\n" + exit 0 + } + test "$REPLY" = "" && { + printf "\nGame not saved.\n" + exit 0 + } + } + printf "\nYou have lost, better luck next time.\033[0m\n" + exit 0 +} + +function help { + cat <=3)&(board_size<=9)' || { + printf "Invalid board size, please choose size between 3 and 9\n" + exit -1 + } + ;; + t) + target="$OPTARG" + printf "obase=2;$target\n" | bc | grep -e '^1[^1]*$' + let $? && { + printf "Invalid target, has to be power of two\n" + exit -1 + } + ;; + r) reload_flag="1" ;; + h) + help $0 + exit 0 + ;; + l) exec 3>$OPTARG ;; + \?) + printf "Invalid option: -"$opt", try $0 -h\n" >&2 + exit 1 + ;; + :) + printf "Option -"$opt" requires an argument, try $0 -h\n" >&2 + exit 1 + ;; + esac +done + +#init board +let fields_total=board_size*board_size +let index_max=board_size-1 +for i in $(_seq 0 $fields_total); do board[$i]="0"; done +let pieces=0 +generate_piece +first_round=$last_added +generate_piece + +#load saved game if flag is set +if test $reload_flag = "1"; then + reload_game +fi + +while true; do + print_board + key_react + let change && generate_piece + first_round=-1 + let pieces==fields_total && { + check_moves + let moves==0 && end_game 0 #lose the game + } +done diff --git a/bash/games/wordle.sh b/bash/games/wordle.sh new file mode 100755 index 0000000..674cdd0 --- /dev/null +++ b/bash/games/wordle.sh @@ -0,0 +1,50 @@ +words=($(grep '^\w\w\w\w\w$' /usr/share/dict/words | tr '[a-z]' '[A-Z]')) +actual=${words[$(($RANDOM % ${#words[@]}))]} end=false guess_count=0 max_guess=6 +if [[ $1 == "unlimit" ]]; then + max_guess=999999 +fi +while [[ $end != true ]]; do + guess_count=$(($guess_count + 1)) + if [[ $guess_count -le $max_guess ]]; then + echo "Enter your guess ($guess_count / $max_guess):" + read guess + guess=$(echo $guess | tr '[a-z]' '[A-Z]') + if [[ " ${words[*]} " =~ " $guess " ]]; then + output="" remaining="" + if [[ $actual == $guess ]]; then + echo "You guessed right!" + for ((i = 0; i < ${#actual}; i++)); do + output+="\033[30;102m ${guess:$i:1} \033[0m" + done + printf "$output\n" + end=true + else + for ((i = 0; i < ${#actual}; i++)); do + if [[ "${actual:$i:1}" != "${guess:$i:1}" ]]; then + remaining+=${actual:$i:1} + fi + done + for ((i = 0; i < ${#actual}; i++)); do + if [[ "${actual:$i:1}" != "${guess:$i:1}" ]]; then + if [[ "$remaining" == *"${guess:$i:1}"* ]]; then + output+="\033[30;103m ${guess:$i:1} \033[0m" + remaining=${remaining/"${guess:$i:1}"/} + else + output+="\033[30;107m ${guess:$i:1} \033[0m" + fi + else + output+="\033[30;102m ${guess:$i:1} \033[0m" + fi + done + printf "$output\n" + fi + else + echo "Please enter a valid word with 5 letters!" + guess_count=$(($guess_count - 1)) + fi + else + echo "You lose! The word is:" + echo $actual + end=true + fi +done diff --git a/bash/gitsetup.sh b/bash/gitsetup.sh new file mode 100755 index 0000000..b3e0c23 --- /dev/null +++ b/bash/gitsetup.sh @@ -0,0 +1,246 @@ +#!/bin/bash + +# Get the current git config list +gc_ls="$(git config --list)" + +# ANSI color codes +RED='\033[0;31m' +CYAN='\033[0;36m' +YELLOW='\033[0;33m' +GREEN='\033[0;32m' +BLUE='\033[0;34m' +LIGHT_GREEN='\033[0;92m' +BOLD='\033[1m' +NC='\033[0m' # No Color + +echo_error() { + printf "${BOLD}${RED}ERROR: ${NC}${RED}%s${NC}\n" "$1" >&2 +} + +echo_warning() { + printf "${BOLD}${YELLOW}WARNING: ${NC}${YELLOW}%s${NC}\n" "$1" +} + +echo_gls() { + printf "${BOLD}${YELLOW}%s${NC}\n" "$1" +} + +echo_note() { + printf "${BOLD}${LIGHT_GREEN}NOTE: ${NC}${LIGHT_GREEN}%s${NC}\n" "$1" +} + +# Function to print colored text +print_color() { + printf "%b%s%b\n" "$1" "$2" "$NC" +} + +# Check if the given command exists silently +command_exists() { + command -v "$@" >/dev/null 2>&1 +} + +# Function to install a package if `curl` is available +if command_exists curl; then + install_pkg() { + sh -c "$(curl -sSL https://git.k4li.de/pika/scripts/raw/branch/main/bash/snippets/install_pkg.sh)" -- "$@" + } +else + echo_error "curl is not installed, universal install disabled!" +fi + +# Function for barebones Git setup +gitBareBonesSetup() { + echo_gls "Please enter your username: " + read -r g_username + echo_gls "Please enter your email: " + read -r g_mail + echo_gls "Please enter your default branch name " + read -r g_branch + git config --global user.name "$g_username" + git config --global user.email "$g_mail" + git config --global init.defaultBranch "$g_branch" + echo_note "Barebones Git setup complete!" + read >"$CREDENTIALS_FILE" + + echo "Credentials added for $g_domain in $CREDENTIALS_FILE" + + git config --global credential.helper store + + chmod 600 "$HOME/.git-credentials" + + read ${options[$i]}" + else + echo " ${options[$i]}" + fi + done +} + +# Main function +main() { + if command_exists git; then + main_menu ─────────────────────────────────────────────────────────────────── +RED='\033[0;31m' +CYAN='\033[0;36m' +YELLOW='\033[0;33m' +LIGHT_GREEN='\033[0;92m' +BOLD='\033[1m' +NC='\033[0m' + +# ─< Initialize storage variables >─────────────────────────────────────────────────────── +_STORED_ERRORS="" +_STORED_WARNINGS="" +_STORED_INFOS="" +_STORED_NOTES="" + +# ─< echo functions that store and display messages >──────────────────────────── +echo_error() { + local message="${RED}$1${NC}\n" + printf "$message" >&2 + _STORED_ERRORS="${_STORED_ERRORS}${message}" +} + +echo_warning() { + local message="${YELLOW}$1${NC}\n" + printf "$message" + _STORED_WARNINGS="${_STORED_WARNINGS}${message}" +} + +echo_info() { + local message="${CYAN}$1${NC}\n" + printf "$message" + _STORED_INFOS="${_STORED_INFOS}${message}" +} + +echo_note() { + local message="${LIGHT_GREEN}$1${NC}\n" + printf "$message" + _STORED_NOTES="${_STORED_NOTES}${message}" +} + +# ─< Improved display function that only shows categories with content >────────────────── +display_stored_messages() { + local has_messages=0 + + # ─< First check if we have any messages at all >───────────────────────────────────────── + if [ -z "$_STORED_ERRORS" ] && [ -z "$_STORED_WARNINGS" ] && [ -z "$_STORED_INFOS" ] && [ -z "$_STORED_NOTES" ]; then + return 0 + fi + + # ─< Now display each non-empty category with proper spacing >──────────────────────────── + if [ -n "$_STORED_ERRORS" ]; then + printf "\n${BOLD}${RED}=== Errors ===${NC}\n" + printf "$_STORED_ERRORS" + has_messages=1 + fi + + if [ -n "$_STORED_WARNINGS" ]; then + [ "$has_messages" -eq 1 ] && printf "\n" + printf "${BOLD}${YELLOW}=== Warnings ===${NC}\n" + printf "$_STORED_WARNINGS" + has_messages=1 + fi + + if [ -n "$_STORED_INFOS" ]; then + [ "$has_messages" -eq 1 ] && printf "\n" + printf "${BOLD}${CYAN}=== Info ===${NC}\n" + printf "$_STORED_INFOS" + has_messages=1 + fi + + if [ -n "$_STORED_NOTES" ]; then + [ "$has_messages" -eq 1 ] && printf "\n" + printf "${BOLD}${LIGHT_GREEN}=== Notes ===${NC}\n" + printf "$_STORED_NOTES" + fi +} + +_exit() { + display_stored_messages + exit 1 +} + +# ─< Check if the given command exists silently >───────────────────────────────────────── +command_exists() { + command -v "$@" >/dev/null 2>&1 +} + +# ─< Check if the user is root and set sudo variable if necessary >─────────────────────── +check_root() { + if [ "$(id -u)" -ne 0 ]; then + if command_exists sudo; then + echo_info "User is not root. Using sudo for privileged operations." + _sudo="sudo" + else + echo_error "No sudo found and you're not root! Can't install packages." + return 1 + fi + else + echo_info "Root access confirmed." + _sudo="" + fi +} + +getRunner() { + # ╭─────────────────────────────────────────────────────────╮ + # │ should output something like this │ + # │ ╭─────────────────────────────────────────────────────╮ │ + # │ │ Good signature from "Forgejo " │ │ + # │ │ aka "Forgejo Releases " │ │ + # │ ╰─────────────────────────────────────────────────────╯ │ + # ╰─────────────────────────────────────────────────────────╯ + # + # ─< get the runner version >───────────────────────────────────────────────────────────── + export RUNNER_VERSION=$(curl -X 'GET' https://data.forgejo.org/api/v1/repos/forgejo/runner/releases/latest | jq .name -r | cut -c 2-) + # ─< get the runner binary >────────────────────────────────────────────────────────────── + wget -O forgejo-runner https://code.forgejo.org/forgejo/runner/releases/download/v${RUNNER_VERSION}/forgejo-runner-${RUNNER_VERSION}-linux-amd64 + # ─< make it executable >───────────────────────────────────────────────────────────────── + chmod +x forgejo-runner + # ─< get the verification hashes >──────────────────────────────────────────────────────── + wget -O forgejo-runner.asc https://code.forgejo.org/forgejo/runner/releases/download/v${RUNNER_VERSION}/forgejo-runner-${RUNNER_VERSION}-linux-amd64.asc + gpg --keyserver keys.openpgp.org --recv EB114F5E6C0DC2BCDD183550A4B61A2DC5923710 + gpg --verify forgejo-runner.asc forgejo-runner +} + +userCreation() { + $_sudo useradd --create-home runner + $_sudo usermod -aG docker runner +} + +envCheck() { + if ! command_exists curl; then + echo_error "You have no curl installed" + _exit + fi + + if ! command_exists wget; then + echo_error "You have no wget installed" + _exit + fi + + if ! command_exists docker; then + echo_warning "Sorry, you have no docker installed.." + _exit + fi + + if command_exists forgejo-runner; then + echo_warning "forgejo-runner binary is already callable.." + _exit + fi +} + +if envCheck; then + getRunner + if ! grep -iq "runner" /etc/passwd; then + userCreation + fi + + forgejo-runner generate-config >config.yml && $_sudo rsync -avP config.yml /home/runner/config.yml +fi diff --git a/bash/postinstall.sh b/bash/postinstall.sh new file mode 100755 index 0000000..e79f838 --- /dev/null +++ b/bash/postinstall.sh @@ -0,0 +1,357 @@ +{ + #!/bin/sh + + # ╭──────────────╮ + # │ dependencies │ + # ╰──────────────╯ + deps="7zip bc btop exa fzf gawk gdu git make pv ripgrep rsync stow tmux trash-cli unzip zoxide zsh" + + # ╭─────────────╮ + # │ ENVIRONMENT │ + # ╰─────────────╯ + # ANSI color codes + RED='\033[0;31m' + CYAN='\033[0;36m' + YELLOW='\033[0;33m' + LIGHT_GREEN='\033[0;92m' + BOLD='\033[1m' + NC='\033[0m' + + # Initialize storage variables + _STORED_ERRORS="" + _STORED_WARNINGS="" + _STORED_INFOS="" + _STORED_NOTES="" + + # Modified echo functions that store and display messages + echo_error() { + message="${RED}$1${NC}\n" + printf "$message" >&2 + _STORED_ERRORS="${_STORED_ERRORS}${message}" + } + + echo_warning() { + message="${YELLOW}$1${NC}\n" + printf "$message" + _STORED_WARNINGS="${_STORED_WARNINGS}${message}" + } + + echo_info() { + message="${CYAN}$1${NC}\n" + printf "$message" + _STORED_INFOS="${_STORED_INFOS}${message}" + } + + echo_note() { + message="${LIGHT_GREEN}$1${NC}\n" + printf "$message" + _STORED_NOTES="${_STORED_NOTES}${message}" + } + + # ─< Check if the given command exists silently >───────────────────────────────────────── + command_exists() { + command -v "$@" >/dev/null 2>&1 + } + + # ─────────────────────────────────────< get packager >───────────────────────────────────── + checkPkg() { + 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 + } + + # ─────────────────────────────────< check for root/sudo >─────────────────────────────── + # checkRoot() { + 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 1 + fi + else + echo_info "Root access confirmed." + _sudo="" + fi + # } + + # ╭─────╮ + # │ apt │ + # ╰─────╯ + aptCommentCDinSources() { + # Path to sources.list + sources_file="/etc/apt/sources.list" + + # Check if file exists + if [ ! -f "$sources_file" ]; then + echo_error "Error: $sources_file not found" + return 1 + fi + + # Comment out CD-ROM entries using sudo + $_sudo sed -i 's/^[[:space:]]*deb[[:space:]]\+cdrom:/#&/' "$sources_file" + echo_info "CD-ROM entries have been commented out in $sources_file" + } + + aptBase() { + aptCommentCDinSources + echo_info "Updating sources.." + $_sudo apt update + + if ! command_exists sudo; then + echo_note "Installing sudo" + apt install sudo --assume-yes + fi + + echo_note "Installing base packages: $deps" + + for _deps in $deps; do + if ! command_exists "$_deps"; then + echo_info "Installing $_deps.." + if ! $_sudo apt install "$_deps" --assume-yes; then + echo_error "$_deps - failed to install!" + fi + else + echo_note "$_deps - was already installed!" + fi + done + } + + aptOptimize() { + if command_exists nala; then + echo_info "Nala is already present, fetching mirros now! (This might take a minute or two, depending on your internet speed)" + $_sudo nala fetch --auto --assume-yes --https-only + else + echo_note "Nala is not installed on the system, do you want to install it now? (Y/n): " + read -r inst_nala ─────────────────────────────────── +RED='\033[0;31m' +CYAN='\033[0;36m' +YELLOW='\033[0;33m' +LIGHT_GREEN='\033[0;92m' +BOLD='\033[1m' +NC='\033[0m' # No Color + +echo_error() { + printf "${BOLD}${RED}ERROR: ${NC}${RED}%s${NC}\n" "$1" >&2 +} + +echo_info() { + printf "${BOLD}${CYAN}INFO: ${NC}${CYAN}%s${NC}\n" "$1" +} + +echo_warning() { + printf "${BOLD}${YELLOW}WARNING: ${NC}${YELLOW}%s${NC}\n" "$1" +} + +echo_note() { + printf "${BOLD}${LIGHT_GREEN}NOTE: ${NC}${LIGHT_GREEN}%s${NC}\n" "$1" +} + +# ────────────────< function to check if the given command exists silently >──────────────── +command_exists() { + command -v "$@" >/dev/null 2>&1 +} + +# ─────────────< Check if the user is root and set sudo variable if necessary >───────────── +check_root() { + if [ "$(id -u)" -ne 0 ]; then + if command_exists sudo; then + echo_info "User is not root. Using sudo for privileged operations." + _sudo="sudo" + else + echo_error "No sudo found and you're not root! Can't install packages." + return 1 + fi + else + echo_info "Root access confirmed." + _sudo="" + fi +} + +# ─< Distribution detection and installation >──────────────────────────────────────── +get_packager() { + if [ -e /etc/os-release ]; then + echo_info "Detecting distribution..." + . /etc/os-release + + ID=$(printf "%s" "$ID" | tr '[:upper:]' '[:lower:]') + ID_LIKE=$(printf "%s" "$ID_LIKE" | tr '[:upper:]' '[:lower:]') + + case "$ID" in + ubuntu | pop) _install() { $_sudo apt-get install --assume-yes "$@"; } ;; + debian) _install() { $_sudo apt-get install --assume-yes "$@"; } ;; + fedora) _install() { $_sudo dnf install -y "$@"; } ;; + alpine) _install() { $_sudo apk add "$@"; } ;; + arch | manjaro | garuda | endeavour) _install() { $_sudo pacman -S --noconfirm "$@"; } ;; + opensuse*) _install() { $_sudo zypper in -y "$@"; } ;; + *) + if echo "$ID_LIKE" | grep -q "debian"; then + _install() { $_sudo apt-get install --assume-yes "$@"; } + elif echo "$ID_LIKE" | grep -q "ubuntu"; then + _install() { $_sudo apt-get install --assume-yes "$@"; } + elif echo "$ID_LIKE" | grep -q "arch"; then + _install() { $_sudo pacman -S --noconfirm "$@"; } + elif echo "$ID_LIKE" | grep -q "fedora"; then + _install() { $_sudo dnf install -y "$@"; } + elif echo "$ID_LIKE" | grep -q "suse"; then + _install() { $_sudo zypper in -y "$@"; } + else + echo_error "Unsupported distribution: $ID" + return 1 + fi + ;; + esac + else + echo_error "Unable to detect distribution. /etc/os-release not found." + return 1 + fi +} + +# ──────────────────────────< define your functions/script here >──────────────────────── +dependencies() { + _deps="krb5-user realmd sssd-tools sssd libnss-sss libpam-sss adcli" + + for dependency in $_deps; do + if ! command_exists "$dependency"; then + echo_info "Installing $dependency.." + sleep 0.3 + if ! _install "$dependency"; then + echo_error "$dependency - could not be installed!" + else + echo_note "$dependency - was installed successfully!" + fi + else + echo_note "$dependency is already installed." + fi + done +} + +_join() { + domain="swu.dom" + echo_note "You are trying to connect to $domain.." + sleep 1 + echo_note "Please enter an administrator user like this: [example-user]" + printf "Admin User: " >&2 + read -r _admin ─────────────────────────────── +main() { + if check_root; then + get_packager && + dependencies && + _join + else + echo_error "Root privileges are required. Exiting." + return 1 + fi +} + +# ──────────────────────────────< execute the main function >──────────────────────────── +main diff --git a/bash/setup/hlpush.sh b/bash/setup/hlpush.sh new file mode 100755 index 0000000..64080e9 --- /dev/null +++ b/bash/setup/hlpush.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +# ─< ANSI color codes >─────────────────────────────────────────────────────────────────── +RED='\033[0;31m' +CYAN='\033[0;36m' +YELLOW='\033[0;33m' +LIGHT_GREEN='\033[0;92m' +BOLD='\033[1m' +NC='\033[0m' # No Color + +echo_error() { + printf "${BOLD}${RED}ERROR: ${NC}${RED}%s${NC}\n" "$1" >&2 +} + +echo_info() { + printf "${BOLD}${CYAN}INFO: ${NC}${CYAN}%s${NC}\n" "$1" +} + +echo_warning() { + printf "${BOLD}${YELLOW}WARNING: ${NC}${YELLOW}%s${NC}\n" "$1" +} + +echo_note() { + printf "${BOLD}${LIGHT_GREEN}NOTE: ${NC}${LIGHT_GREEN}%s${NC}\n" "$1" +} + +main() { + local dir="/opt/docker" + + cd $dir || echo_error "Can't navigate to $dir" + + git add . + + git commit -m "Automatic push on $(date)" + + git push +} + +main diff --git a/bash/setup/homelapGitSetup.sh b/bash/setup/homelapGitSetup.sh new file mode 100755 index 0000000..d4a5e18 --- /dev/null +++ b/bash/setup/homelapGitSetup.sh @@ -0,0 +1,152 @@ +#!/usr/bin/env bash +# ─< ANSI color codes >─────────────────────────────────────────────────────────────────── +RED='\033[0;31m' +CYAN='\033[0;36m' +YELLOW='\033[0;33m' +LIGHT_GREEN='\033[0;92m' +BOLD='\033[1m' +NC='\033[0m' # No Color + +echo_error() { + printf "${BOLD}${RED}ERROR: ${NC}${RED}%s${NC}\n" "$1" >&2 +} + +echo_info() { + printf "${BOLD}${CYAN}INFO: ${NC}${CYAN}%s${NC}\n" "$1" +} + +echo_warning() { + printf "${BOLD}${YELLOW}WARNING: ${NC}${YELLOW}%s${NC}\n" "$1" +} + +echo_note() { + printf "${BOLD}${LIGHT_GREEN}NOTE: ${NC}${LIGHT_GREEN}%s${NC}\n" "$1" +} + +# ─< Check if the given command exists silently >───────────────────────────────────────── +command_exists() { + command -v "$@" >/dev/null 2>&1 +} + +# ─< Check if the user is root and set sudo variable if necessary >─────────────────────── +check_root() { + if [[ "$(id -u)" -ne 0 ]]; then + if command_exists sudo; then + echo_info "User is not root. Using sudo for privileged operations." + _sudo="sudo" + else + echo_error "No sudo found and you're not root! Can't install packages." + return 1 + fi + else + echo_info "Root access confirmed." + _sudo="" + fi +} + +check_root + +gitUserSetup() { + local g_username="server-agent" + local g_mail="info@team-pieck.de" + local g_branch="main" + local g_domain="git.k4li.de" + + local CREDENTIALS_FILE="$HOME/.git-credentials" + + git config --global user.name "$g_username" + git config --global user.email "$g_mail" + git config --global init.defaultBranch "$g_branch" + + if [[ ! -e "$CREDENTIALS_FILE" ]]; then + echo_note "Enter your authentication token:" + read -r -s g_token >"$CREDENTIALS_FILE" + + echo "Credentials added for $g_domain in $CREDENTIALS_FILE" + + git config --global credential.helper store + + chmod 600 "$HOME/.git-credentials" + fi +} + +gitDirSetup() { + cd /opt/docker || echo_error "could not cd /opt/docker" + + if $_sudo ping -w2 10.255.255.1; then + local location="hl" + elif $_sudo ping -w2 10.69.69.2; then + location="vps" + fi + + git init . + + git branch -m main + + if git remote add origin "https://git.k4li.de/homelab/${location}-$(hostname)"; then + + git add . + + git commit -m "Initial script commit" + + git push -u origin main + else + echo_error 'Failed setting the git repo up with git remote add "$(hostname)" "https://git.k4li.de/homelab/${location}-$(hostname).git"' + fi +} + +set_cronjob() { + + # Configuration + CRON_COMMAND="/opt/scripts/hlpush.sh" + CRON_SCHEDULE="0 3,15 * * *" + CRON_LOG="./cronjobs.log" + CRON_ENTRY="$CRON_SCHEDULE $CRON_COMMAND >> $CRON_LOG 2>&1" + + # Check for existing entry + EXISTING_ENTRIES=$(crontab -l 2>/dev/null) + + # Add entry if not exists + if ! echo "$EXISTING_ENTRIES" | grep -qF "$CRON_ENTRY"; then + # Create temporary cron file + TMPFILE=$(mktemp) + + # Preserve existing entries + [ -n "$EXISTING_ENTRIES" ] && echo "$EXISTING_ENTRIES" >"$TMPFILE" + + # Add header and new entry + echo -e "\n# Daily 3AM/3PM job added $(date)" >>"$TMPFILE" + echo "$CRON_ENTRY" >>"$TMPFILE" + + # Install new cron file + crontab "$TMPFILE" + rm -f "$TMPFILE" + + echo_info "Success: Cronjob installed" + echo_note "Verify with: crontab -l" + else + echo_warning "Notice: Cronjob already exists" + exit 0 + fi +} + +if ! command_exists git; then + return 1 + echo_error "You don't have git installed!" +fi + +gitUserSetup + +if [[ -d /opt/docker/ ]]; then + gitDirSetup +fi + +if [[ -d /opt/scripts/bash ]]; then + set_cronjob +else + if command_exists curl; then + curl -o /opt/scripts/hlpush.sh https://git.k4li.de/scripts/bash/raw/branch/main/setup/hlpush.sh + fi +fi diff --git a/bash/setup/tuiDots.sh b/bash/setup/tuiDots.sh new file mode 100755 index 0000000..35d5d9e --- /dev/null +++ b/bash/setup/tuiDots.sh @@ -0,0 +1,207 @@ +#!/bin/bash + +# ─< ANSI color codes >─────────────────────────────────────────────────────────────────── +RED='\033[0;31m' +BLUE='\033[0;34m' +CYAN='\033[0;36m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +LIGHT_GREEN='\033[0;92m' +BOLD='\033[1m' +NC='\033[0m' # No Color + +echo_error() { + printf "${BOLD}${RED}ERROR: ${NC}${RED}%s${NC}\n" "$1" >&2 +} + +echo_info() { + printf "${BOLD}${CYAN}INFO: ${NC}${CYAN}%s${NC}\n" "$1" +} + +echo_warning() { + printf "${BOLD}${YELLOW}WARNING: ${NC}${YELLOW}%s${NC}\n" "$1" +} + +echo_note() { + printf "${BOLD}${LIGHT_GREEN}NOTE: ${NC}${LIGHT_GREEN}%s${NC}\n" "$1" +} + +# ─< Check if the given command exists silently >───────────────────────────────────────── +command_exists() { + command -v "$@" >/dev/null 2>&1 +} + +# ─< Check if the user is root and set sudo variable if necessary >─────────────────────── +check_root() { + if [ "$(id -u)" -ne 0 ]; then + if command_exists sudo; then + echo_info "User is not root. Using sudo for privileged operations." + _sudo="sudo" + else + echo_error "No sudo found and you're not root! Can't install packages." + return 1 + fi + else + echo_info "Root access confirmed." + _sudo="" + fi +} + +# Function to print colored text +print_color() { + printf "%b%s%b\n" "$1" "$2" "$NC" +} + +# Function to return to the main menu +return_to_menu() { + echo_info "Returning to the main menu in 3 seconds..." + sleep 3 +} + +gitDir="$HOME/git/dotfiles" +dotRemote="https://git.k4li.de/dotfiles" +instRemote="https://git.k4li.de/scripts/sh/raw/branch/main/installs" + +if [ ! -d "$gitDir" ]; then + print_color "$RED" "=== git dir created - $gitDir ===" + mkdir -p "$gitDir" +fi + +d_="git curl" +for dependency in $d_; do + if ! command_exists "$dependency"; then + print_color "$RED" "You're missing some dependencies!" + print_color "$RED" "Install $dependency and start the script again" + exit 1 + fi +done + +# Function to display the menu +display_menu() { + clear + print_color "$BLUE" "=== Environment Setup Menu ===" + for i in "${!options[@]}"; do + if [[ $i -eq $selected ]]; then + print_color "$GREEN" "> ${options[$i]}" + else + echo " ${options[$i]}" + fi + done +} + +# Function to handle dotfiles setup +nvimSetup() { + print_color "$YELLOW" "Setting up neovim..." + if [ ! -d "$HOME/.config/nvim" ]; then + echo_note "Installing into .config directly" + git clone --branch minimal --recurse-submodule --depth=1 "${dotRemote}/nvim.git" "$HOME/.config/nvim" + else + if [ -d "$gitDir/nvim" ]; then + cd "$gitDir/nvim" || { + echo_error "The given path - $gitDir/nvim - was not found!" + return 1 + } + git pull --recurse-submodule + else + echo_note "Installing into $gitDir/nvim" + git clone --branch minimal --recurse-submodule --depth=1 "${dotRemote}/nvim.git" "$gitDir/nvim" + fi + fi + + return_to_menu +} + +# Function to handle CLI tool installation +nvimMinimalSetup() { + print_color "$YELLOW" "Setting up neovim minimal branch..." + if [ ! -d "$HOME/.config/nvim" ]; then + echo_note "Installing into .config directly" + git clone --branch minimal --recurse-submodule --depth=1 "${dotRemote}/nvim.git" "$HOME/.config/nvim" + else + if [ -d "$gitDir/nvim-minimal" ]; then + cd "$gitDir/nvim-minimal" || { + echo_error "The given path - $gitDir/nvim-minimal - was not found!" + return 1 + } + git pull --recurse-submodule + else + echo_note "Installing into $gitDir/nvim-minimal" + git clone --branch minimal --recurse-submodule --depth=1 "${dotRemote}/nvim.git" "$gitDir/nvim-minimal" + fi + fi + + return_to_menu +} + +installStuff() { + echo_info "I want to install.." + read -r gitPackage &2 +} + +echo_info() { + printf "${BOLD}${CYAN}INFO: ${NC}${CYAN}%s${NC}\n" "$1" +} + +echo_warning() { + printf "${BOLD}${YELLOW}WARNING: ${NC}${YELLOW}%s${NC}\n" "$1" +} + +echo_note() { + printf "${BOLD}${LIGHT_GREEN}NOTE: ${NC}${LIGHT_GREEN}%s${NC}\n" "$1" +} + +# ─< Check if the given command exists silently >───────────────────────────────────────── +command_exists() { + command -v "$@" >/dev/null 2>&1 +} + +run_checks() { + echo_info "Checking if unattended-upgrades is active..." + + if command_exists unattended-upgrades; then + # if dpkg-query -W -f='${Status}' unattended-upgrades 2>/dev/null | grep -q "install ok installed"; then + echo_note "unattended-upgrades is already installed." + else + echo_warning "unattended-upgrades is not installed. Attempting to install..." + if command_exists apt-get; then + if apt-get update && apt-get install --assume-yes unattended-upgrades; then + echo_note "unattended-upgrades successfully installed." + else + echo_error "Failed to install unattended-upgrades. Exiting." + exit 1 + fi + else + echo_error "apt is not available on this system. Exiting." + exit 1 + fi + fi + + # Enable unattended-upgrades + UNATTENDED_UPGRADES_FILE="/etc/apt/apt.conf.d/50unattended-upgrades" + if [ -f "$UNATTENDED_UPGRADES_FILE" ]; then + echo_info "Configuring unattended upgrades in $UNATTENDED_UPGRADES_FILE" + # Add or modify configurations as needed + # Example: $_sudo sed -i 's/old_value/new_value/' "$UNATTENDED_UPGRADES_FILE" + else + echo_error "Unattended upgrades file not found!" + fi +} + +run_setup() { + if command_exists unattended-upgrades; then + systemctl enable --now unattended-upgrades || echo_error "Something went wrong! Could not setup the service/autostart" + fi +} + +# Main script +main() { + echo_info "Starting unattended-upgrades check script..." + + if [ "$(id -u)" -ne 0 ]; then + echo_error "This script must be run as root. Please run with sudo." + exit 1 + fi + + run_checks + + run_setup && echo_note "Script completed successfully!" +} + +main diff --git a/bash/updates.sh b/bash/updates.sh new file mode 100755 index 0000000..430e519 --- /dev/null +++ b/bash/updates.sh @@ -0,0 +1,157 @@ +#!/bin/sh + +# ─< ANSI color codes >─────────────────────────────────────────────────────────────────── +RED='\033[0;31m' +CYAN='\033[0;36m' +YELLOW='\033[0;33m' +LIGHT_GREEN='\033[0;92m' +BOLD='\033[1m' +NC='\033[0m' # No Color + +echo_error() { + printf "${BOLD}${RED}ERROR: ${NC}${RED}%s${NC}\n" "$1" >&2 +} + +echo_info() { + printf "${BOLD}${CYAN}INFO: ${NC}${CYAN}%s${NC}\n" "$1" +} + +echo_warning() { + printf "${BOLD}${YELLOW}WARNING: ${NC}${YELLOW}%s${NC}\n" "$1" +} + +echo_note() { + printf "${BOLD}${LIGHT_GREEN}NOTE: ${NC}${LIGHT_GREEN}%s${NC}\n" "$1" +} + +# ─< Check if the given command exists silently >───────────────────────────────────────── +command_exists() { + command -v "$@" >/dev/null 2>&1 +} + +# ─< Check if the user is root and set sudo variable if necessary >─────────────────────── +check_root() { + if [ "$(id -u)" -ne 0 ]; then + if command_exists sudo; then + echo_info "User is not root. Using sudo for privileged operations." + _sudo="sudo" + else + echo_error "No sudo found and you're not root! Can't install packages." + return 1 + fi + else + echo_info "Root access confirmed." + _sudo="" + fi +} + +# ─< Distribution detection and installation >──────────────────────────────────────── +get_packager() { + 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) packager="apt" ;; + debian) packager="apt" ;; + fedora) packager="dnf" ;; + alpine) packager="apk" ;; + arch | manjaro | garuda | endeavour) packager="pacman" ;; + opensuse*) packager="zypper" ;; + *) + if [ "${ID_LIKE#*debian}" != "$ID_LIKE" ]; then + packager="apt" + elif [ "${ID_LIKE#*ubuntu}" != "$ID_LIKE" ]; then + packager="apt" + elif [ "${ID_LIKE#*arch}" != "$ID_LIKE" ]; then + packager="pacman" + elif [ "${ID_LIKE#*fedora}" != "$ID_LIKE" ]; then + packager="dnf" + elif [ "${ID_LIKE#*suse}" != "$ID_LIKE" ]; then + packager="zypper" + else + echo_error "Unsupported distribution: $ID" + exit 1 + fi + ;; + esac + else + echo_error "Unable to detect distribution. /etc/os-release not found." + exit 1 + fi +} + +_update() { + case "$packager" in + apt) + if command_exists nala; then + echo_note "Using nala to update packages.. Please be patient.." + sleep 1 + $_sudo nala update + $_sudo nala upgrade -y + $_sudo nala autoremove -y + $_sudo apt-get autoclean -y + else + echo_note "Using nala to update packages.. Please be patient.." + sleep 1 + $_sudo apt-get update + $_sudo apt-get upgrade -y + $_sudo apt-get autoremove -y + $_sudo apt-get autoclean -y + fi + ;; + dnf) + echo_note "Using dnf to update packages.. Please be patient.." + sleep 1 + $_sudo dnf update + ;; + pacman) + echo_note "Using pacman to update packages.. Please be patient.." + sleep 1 + $_sudo pacman -Syu --noconfirm + ;; + apk) + echo_note "Using apk to update packages.. Please be patient.." + sleep 1 + $_sudo apk update + $_sudo apk upgrade + ;; + zypper) + echo_note "Using zypper to update packages.. Please be patient.." + sleep 1 + $_sudo zypper dup + ;; + *) + if [ -z "$packager" ]; then + echo_error "The packager variable is not declared.." + else + echo_error "$packager is not a known packager.." + fi + ;; + esac +} + +_flatpak() { + if command_exists flatpak; then + echo_info "Trying to update flatpaks.." + sleep 1 + flatpak update + else + echo_note "No flatpaks found" + fi +} + +main() { + check_root + sleep 1 + if get_packager; then + _update + _flatpak + fi +} + +main diff --git a/installs/README.md b/installs/README.md new file mode 100644 index 0000000..4e2a7cc --- /dev/null +++ b/installs/README.md @@ -0,0 +1,105 @@ +## sh + +# 🛠️ **Script Collection** + +> [!TIP] +> Feel free to use and modify these scripts to suit your needs! + +--- + +## 🚀 **Quick Start** + +Clone the repository and start using the scripts: + +```bash +git clone https://git.k4li.de/scripts/sh.git scripts && cd scripts +``` + +Or run individual scripts directly: + +```bash +curl -fsSL | sh +``` + +--- + +## 📁 **Utility Scripts** + +- **🔑 `ssh-keyperm.sh`** + Fixes permissions for `.ssh/` keys. + + ```bash + curl -fsSL https://git.k4li.de/pika/scripts/raw/branch/main/bash/snippets/ssh-keyperm.sh | sh + ``` + +- **👽️ `updates.sh`** + Updates system packages + flatpaks. + + ```bash + curl -sSL https://git.k4li.de/pika/scripts/raw/branch/main/bash/setups/updates.sh | sh + ``` + +- **🚀 `postinstall.sh`** + Sets up basic post-install tasks. + + ```bash + curl -sSL https://git.k4li.de/pika/scripts/raw/branch/main/bash/setup/postinstall.sh | sh -s -- -- + ``` + + | **Available Flag** | Description | + | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | + | --install-base | Installs base packages like zsh and tmux, zoxide and trash etc. | + | --optimize-os | Currently only supported by apt based systems. Installs nala and fetches best mirrors. Equivalent options might be made in the future for other packagemanagers. | + +> [!TIP] +> You can run all options together, with the `all` flag. +> +> ```bash +> curl -sSL https://git.k4li.de/scripts/sh/raw/branch/main/setup/postinstall.sh | sh -s -- --all +> ``` + +--- + +## 📦 **Install Scripts** + +- **🐋 `docker.sh`** + Installs Docker (Debian, Ubuntu, Fedora). + + ```bash + curl -sSL https://git.k4li.de/scripts/sh/raw/branch/main/installs/docker.sh | sh + ``` + +- **✨ `neovim.sh`** + Installs Neovim 10.0+ (Debian, Ubuntu, Fedora). + + ```bash + curl -sSL https://git.k4li.de/scripts/sh/raw/branch/main/installs/neovim.sh | sh + ``` + +- **🎨 `neovide.sh`** + Installs Neovide with Cargo (includes Cargo setup). + + ```bash + curl -sSL https://git.k4li.de/scripts/sh/raw/branch/main/installs/neovide.sh | sh + ``` + +- **⚡️`xmrig.sh`** + Installs xmrig in `$HOME/.bin/xmrig/`. + + ```bash + curl -sSL https://git.k4li.de/scripts/sh/raw/branch/main/installs/xmrig.sh | sh + ``` + +- **🗃️ `yazi.sh`** + Installs [yazi](https://github.com/sxyazi/yazi) with Cargo. + ```bash + curl -fsSL https://git.k4li.de/scripts/sh/raw/branch/main/installs/yazi.sh | sh + ``` + +--- + +## 📚 **Browse More** + +Explore additional scripts in the repository. Modify them or use them as-is to streamline your workflow! + +--- diff --git a/installs/docker.sh b/installs/docker.sh new file mode 100755 index 0000000..b07d514 --- /dev/null +++ b/installs/docker.sh @@ -0,0 +1,180 @@ +#!/bin/sh -e + +# ─< ANSI color codes >─────────────────────────────────────────────────────────────────── +RED='\033[0;31m' +CYAN='\033[0;36m' +YELLOW='\033[0;33m' +LIGHT_GREEN='\033[0;92m' +BOLD='\033[1m' +NC='\033[0m' # No Color + +echo_error() { + printf "${BOLD}${RED}ERROR: ${NC}${RED}%s${NC}\n" "$1" >&2 +} + +echo_info() { + printf "${BOLD}${CYAN}INFO: ${NC}${CYAN}%s${NC}\n" "$1" +} + +echo_warning() { + printf "${BOLD}${YELLOW}WARNING: ${NC}${YELLOW}%s${NC}\n" "$1" +} + +echo_note() { + printf "${BOLD}${LIGHT_GREEN}NOTE: ${NC}${LIGHT_GREEN}%s${NC}\n" "$1" +} + +check_sudo() { + # check for $su + if [ "$USER" != "root" ]; then + if command -v sudo >/dev/null 2>&1; then + su="sudo" + else + echo "Are you sure you can handle this? You're not root and sudo cannot be found.. [y/n]" + read -r sud ──────────────────────────────────────── +check_dist() { + 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) _ubuntu ;; + debian) _debian ;; + fedora) _fedora ;; + # alpine) _alpine ;; + arch | manjaro | garuda | endeavour) _arch ;; + opensuse*) inst_opensuse ;; + *) + if [ "${ID_LIKE#*debian}" != "$ID_LIKE" ]; then + _debian + elif [ "${ID_LIKE#*ubuntu}" != "$ID_LIKE" ]; then + _ubuntu + elif [ "${ID_LIKE#*arch}" != "$ID_LIKE" ]; then + _arch + elif [ "${ID_LIKE#*fedora}" != "$ID_LIKE" ]; then + _fedora + # elif [ "${ID_LIKE#*suse}" != "$ID_LIKE" ]; then + # _opensuse + else + echo_error "Unsupported distribution: $ID" + exit 1 + fi + ;; + esac + else + echo_error "Unable to detect distribution. /etc/os-release not found." + exit 1 + fi +} + +_debian() { + clear + echo_info "executing debian" + sleep 2 + $su apt-get update && + $su apt-get install -y ca-certificates curl && + $su install -m 0755 -d /etc/apt/keyrings && + $su curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc && + $su chmod a+r /etc/apt/keyrings/docker.asc && + sleep 0.5 + if [ "$VERSION_CODENAME" == "trixie" ]; then + VERSION_CODENAME="bookworm" + fi + echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \ + $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | $su tee /etc/apt/sources.list.d/docker.list >/dev/null + clear && + echo_info "Addet repository. Updating and installing now.." + sleep 1 + $su apt-get update + $su apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin +} + +_ubuntu() { + clear + echo_info "executing ubuntu" + sleep 2 + $su apt-get update && + $su apt-get install -y ca-certificates curl && + $su install -m 0755 -d /etc/apt/keyrings && + $su curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc && + $su chmod a+r /etc/apt/keyrings/docker.asc + echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ + $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | $su tee /etc/apt/sources.list.d/docker.list >/dev/null + clear && + echo_info "Addet repository. Updating and installing now.." + sleep 0.5 + $su apt-get update + $su apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin +} + +_fedora() { + clear + echo_info "executing fedora" + sleep 2 + $su dnf -y install dnf-plugins-core + $su dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo + $su dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin +} + +_arch() { + clear + echo_info "executing arch" + sleep 2 + $su pacman -S docker docker-compose --noconfirm +} + +init_docker() { + if command -v docker >/dev/null 2>&1; then + echo_info "Docker was installed correctly. Do you want to add $(whoami) to the docker group? (y/n)" + read -r dgroup &2 +} + +echo_info() { + printf "${BOLD}${CYAN}INFO: ${NC}${CYAN}%s${NC}\n" "$1" +} + +echo_warning() { + printf "${BOLD}${YELLOW}WARNING: ${NC}${YELLOW}%s${NC}\n" "$1" +} + +echo_note() { + printf "${BOLD}${LIGHT_GREEN}NOTE: ${NC}${LIGHT_GREEN}%s${NC}\n" "$1" +} + +# ─< Silent execution >───────────────────────────────────────────────────────────────── +silentexec() { + "$@" >/dev/null 2>&1 +} + +# ─< Check if the given command exists silently >───────────────────────────────────────── +command_exists() { + command -v "$@" >/dev/null 2>&1 +} + +# Check if the user is root and set sudo variable if necessary +check_root() { + if [ "$(id -u)" -ne 0 ]; then + if command_exists sudo; then + echo_note "User is not root. Using sudo for privileged operations." + _sudo="sudo" + else + echo_error "No sudo found and you're not root! Can't install packages." + return 1 + fi + else + echo_note "Root access confirmed." + _sudo="" + fi +} + +flatpak_init() { + if command_exists flatpak; then + echo_info "Flatpak exists, initializing flathub repository!" + flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo + else + echo_error "Flatpak was not found!" + fi +} + +inst_arch() { + echo_note "Using Arch script, btw!" + + if command_exists yay; then + i_arch="yay" + elif command_exists paru; then + i_arch="paru" + elif command_exists pacman; then + i_arch="$_sudo pacman" + fi + + if [ -n "$i_arch" ]; then + i_arch -S flatpak + else + echo_error "No packager for installation found.. (not even pacman...)" + fi + +} + +inst_debian() { + echo_note "Using Debian script!" + if command_exists nala; then + $_sudo nala update + $_sudo nala install flatpak -y + elif command_exists apt-get; then + echo_info "Couldn't find nala, falling back to apt-get" + $_sudo apt-get update + $_sudo apt-get install flatpak -y + fi +} + +inst_ubuntu() { + echo_note "Using Ubuntu script!" + if command_exists nala; then + $_sudo nala update + $_sudo nala install flatpak -y + elif command_exists apt-get; then + echo_info "Couldn't find nala, falling back to apt-get" + $_sudo apt-get update + $_sudo apt-get install flatpak -y + fi +} + +# ─< Distribution detection and installation >──────────────────────────────────────── +get_packager() { + 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) inst_ubuntu ;; + debian) inst_debian ;; + fedora) inst_fedora ;; + alpine) inst_alpine ;; + arch | manjaro | garuda | endeavour) inst_arch ;; + opensuse*) inst_opensuse ;; + *) + # Use standard [ ] syntax for string matching + if [ "${ID_LIKE#*debian}" != "$ID_LIKE" ]; then + inst_debian + elif [ "${ID_LIKE#*ubuntu}" != "$ID_LIKE" ]; then + inst_ubuntu + elif [ "${ID_LIKE#*arch}" != "$ID_LIKE" ]; then + inst_arch + elif [ "${ID_LIKE#*fedora}" != "$ID_LIKE" ]; then + inst_fedora + elif [ "${ID_LIKE#*suse}" != "$ID_LIKE" ]; then + inst_opensuse + else + echo_error "Unsupported distribution: $ID" + exit 1 + fi + ;; + esac + else + echo_error "Unable to detect distribution. /etc/os-release not found." + exit 1 + fi +} + +install_flatpak() { + check_root && + get_packager && + flatpak_init +} + +install_flatpak diff --git a/installs/ghostty.sh b/installs/ghostty.sh new file mode 100644 index 0000000..47ee6e5 --- /dev/null +++ b/installs/ghostty.sh @@ -0,0 +1,310 @@ +#!/bin/sh + +# ╭───────────────╮ +# │ env functions │ +# ╰───────────────╯ +# ───────────────────────────────────< ANSI color codes >─────────────────────────────────── +RED='\033[0;31m' +CYAN='\033[0;36m' +YELLOW='\033[0;33m' +LIGHT_GREEN='\033[0;92m' +BOLD='\033[1m' +NC='\033[0m' # No Color + +echo_error() { + printf "${BOLD}${RED}ERROR: ${NC}${RED}%s${NC}\n" "$1" >&2 +} + +echo_info() { + printf "${BOLD}${CYAN}INFO: ${NC}${CYAN}%s${NC}\n" "$1" +} + +echo_warning() { + printf "${BOLD}${YELLOW}WARNING: ${NC}${YELLOW}%s${NC}\n" "$1" +} + +echo_note() { + printf "${BOLD}${LIGHT_GREEN}NOTE: ${NC}${LIGHT_GREEN}%s${NC}\n" "$1" +} + +command_exists() { + command -v "$@" >/dev/null 2>&1 +} + +# ─────────────< Check if the user is root and set sudo variable if necessary >───────────── +check_root() { + if [ "$(id -u)" -ne 0 ]; then + if command_exists sudo; then + echo_info "User is not root. Using sudo for privileged operations." + _sudo="sudo" + else + echo_error "No sudo found and you're not root! Can't install packages." + return 1 + fi + else + echo_info "Root access confirmed." + _sudo="" + fi +} + +# ──────────────────────< Check if the given command exists silently >────────────────────── +command_exists() { + command -v "$@" >/dev/null 2>&1 +} + +_cd() { + cd "$1" || echo_error "Could not cd into $1!" +} + +# ─< Distribution detection and installation >──────────────────────────────────────── +# checks for variable dist={debian,ubuntu,fedora,arch,suse} +get_packager() { + 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 | linuxmint | elementary) dist="ubuntu" ;; + debian | kali | zorin | parrot | deepin | raspbian | devuan) dist="debian" ;; + fedora | nobara | rhel | centos) dist="fedora" ;; + arch | manjaro | garuda | endeavour | artix) dist="arch" ;; + opensuse*) dist="suse" ;; + *) + if [ "${ID_LIKE#*debian}" != "$ID_LIKE" ]; then + dist="debian" + echo_note "Detected Debian-based distribution" + elif [ "${ID_LIKE#*ubuntu}" != "$ID_LIKE" ]; then + dist="ubuntu" + echo_note "Detected Ubuntu-based distribution" + elif [ "${ID_LIKE#*arch}" != "$ID_LIKE" ]; then + dist="arch" + echo_note "Detected Arch-based distribution" + elif [ "${ID_LIKE#*fedora}" != "$ID_LIKE" ]; then + dist="fedora" + echo_note "Detected Fedora-based distribution" + elif [ "${ID_LIKE#*suse}" != "$ID_LIKE" ]; then + dist="suse" + echo_note "Detected SUSE-based distribution" + else + echo_error "Unsupported distribution: $ID" + echo_note "Please report this issue with your distribution details" + exit 1 + fi + ;; + esac + else + echo_error "Unable to detect distribution. /etc/os-release not found." + exit 1 + fi +} + +# ╭────────────────────────────────────╮ +# │ insert your scripts/functions here │ +# ╰────────────────────────────────────╯ +# ─────────────────────────────────────< dependencies >───────────────────────────────────── +deps_common="git curl tar" +deps_arch="$deps_common gtk4 libadwaita" +deps_deb="$deps_common libgtk-4-dev libadwaita-1-dev" +deps_fedora="$deps_common gtk4-devel zig libadwaita-devel" +deps_suse="$deps_common gtk4-tools libadwaita-devel pkgconf-pkg-config zig" + +checkDeps="" +checkDeps() { + get_packager + case "$dist" in + debian | ubuntu) + pkg="apt-get" + echo "Detected packagemanager ${RED}${pkg}" + echo_info "Updating sources.." + $_sudo apt-get update + + echo_info "Checking dependencies now.." + + sleep 3 + + for dep in $deps_deb; do + if ! command_exists $dep; then + echo_info "Installing $dep.." + $_sudo apt-get install "$dep" --assume-yes /dev/null 2>&1 + $_sudo ln -rs ./zig/zig /bin/zig +} + +cloneGhostty() { + if [ ! "$checkDeps" = "done" ]; then + echo_error "Dependencies are not installed, aborting now!" + exit 1 + fi + + # buildDir=$(mktemp -d) + buildDir="$HOME/.local/ghostty-build" + if [ -d "$buildDir" ] && [ -n "$(ls -A "$buildDir")" ]; then + echo_warning "Ghostty build directory already exists at ${buildDir}, do you want to remove it? (y/n)" + read -r removeBuildDir ─────────────────────────────── +main() { + if check_root; then + checkDeps || ErrorExit "Step 1/3" + checkZig || ErrorExit "Step 2/3" + cloneGhostty || ErrorExit "Step 3/3" + else + echo_error "Something went terribly wrong!" + fi +} + +main ─────────────────────────────────── +RED='\033[0;31m' +CYAN='\033[0;36m' +YELLOW='\033[0;33m' +LIGHT_GREEN='\033[0;92m' +BOLD='\033[1m' +NC='\033[0m' # No Color + +echo_error() { + printf "${BOLD}${RED}ERROR: ${NC}${RED}%s${NC}\n" "$1" >&2 +} + +echo_info() { + printf "${BOLD}${CYAN}INFO: ${NC}${CYAN}%s${NC}\n" "$1" +} + +echo_warning() { + printf "${BOLD}${YELLOW}WARNING: ${NC}${YELLOW}%s${NC}\n" "$1" +} + +echo_note() { + printf "${BOLD}${LIGHT_GREEN}NOTE: ${NC}${LIGHT_GREEN}%s${NC}\n" "$1" +} + +# ─────────────< Check if the user is root and set sudo variable if necessary >───────────── +check_root() { + if [ "$(id -u)" -ne 0 ]; then + if command_exists sudo; then + echo_info "User is not root. Using sudo for privileged operations." + _sudo="sudo" + else + echo_error "No sudo found and you're not root! Can't install packages." + return 1 + fi + else + echo_info "Root access confirmed." + _sudo="" + fi +} + +# ──────────────────────< Check if the given command exists silently >────────────────────── +command_exists() { + command -v "$@" >/dev/null 2>&1 +} + +# ╭────────────────────────────────────╮ +# │ insert your scripts/functions here │ +# ╰────────────────────────────────────╯ +hyprSlim="hyprland hyprland-protocols hyprwayland-scanner libhyprcursor-dev wayland-utils wayland-protocols wl-clipboard nwg-look xdg-desktop-portal-hyprland liblz4" +hyprAdvanced="$menu pavucontrol pamixer btop bluez wlogout wob" + +OPTIONAL_SCREENSHOT="grimshot slurp swappy" +OPTIONAL_SCREENRECORD="wf-recorder" +OPTIONAL_AUDIO="pulseaudio pavucontrol" +OPTIONAL_NOTIFY="sway-notification-center libnotify" +OPTIONAL_UTILS="brightnessctl network-manager-gnome gnome-keyring swayidle playerctl" +OPTIONAL_FILES="xdg-user-dirs nautilus gvfs" +OPTIONAL_SDDM_DEPS="qml6-module-qtquick-controls qml6-module-qtquick-effects sddm" + +BUILD_DEPS="git gcc make cmake meson ninja-build pkg-config" +RUST_DEPS="cargo rustc" # Separate rust dependencies + +askThings() { + echo_note "Do you want to install hyprland? (y/N)" + read -r askHyprland ─────────────────────────────── +main() { + if check_root; then + askThings + if [ "$askHyprland" = "true" ]; then + checkDependencies + instDeps + instTools + checkConfig + fi + else + echo_error "Something went terribly wrong!" + fi +} + +main diff --git a/installs/hyprpanel.sh b/installs/hyprpanel.sh new file mode 100644 index 0000000..8a2c7a1 --- /dev/null +++ b/installs/hyprpanel.sh @@ -0,0 +1,97 @@ +#!/bin/sh -c + +# ─< ANSI color codes >─────────────────────────────────────────────────────────────────── +RED='\033[0;31m' +CYAN='\033[0;36m' +YELLOW='\033[0;33m' +LIGHT_GREEN='\033[0;92m' +BOLD='\033[1m' +NC='\033[0m' # No Color + +echo_error() { + printf "${BOLD}${RED}ERROR: ${NC}${RED}%s${NC}\n" "$1" >&2 +} + +echo_info() { + printf "${BOLD}${CYAN}INFO: ${NC}${CYAN}%s${NC}\n" "$1" +} + +echo_warning() { + printf "${BOLD}${YELLOW}WARNING: ${NC}${YELLOW}%s${NC}\n" "$1" +} + +echo_note() { + printf "${BOLD}${LIGHT_GREEN}NOTE: ${NC}${LIGHT_GREEN}%s${NC}\n" "$1" +} + +# ─< Check if the given command exists silently >───────────────────────────────────────── +command_exists() { + command -v "$@" >/dev/null 2>&1 +} + +# ─< Check if the user is root and set sudo variable if necessary >─────────────────────── +check_root() { + if [ "$(id -u)" -ne 0 ]; then + if command_exists sudo; then + echo_info "User is not root. Using sudo for privileged operations." + _sudo="sudo" + else + echo_error "No sudo found and you're not root! Can't install packages." + return 1 + fi + else + echo_info "Root access confirmed." + _sudo="" + fi +} + +inst_arch() { + dependencies="aylurs-gtk-shell grimblast hyprpicker" + if command_exists curl; then + if [ ! -d "$HOME/.bun" ]; then + echo_info "Downloading bun and linking it.." + curl -fsSL https://bun.sh/install | bash && $_sudo ln -s $HOME/.bun/bin/bun /usr/local/bin/bun + else + echo_note "Bun is already installed" + fi + + $_sudo pacman -S pipewire libgtop bluez bluez-utils btop networkmanager dart-sass wl-clipboard brightnessctl swww python gnome-bluetooth-3.0 pacman-contrib power-profiles-daemon gvfs --noconfirm + + if command_exists yay; then + echo_info "Using yay to install $dependencies" + yay -S --noconfirm $dependencies + elif command_exists paru; then + echo_info "Using paru to install $dependencies" + paru -S --noconfirm $dependencies + else + echo_error "No aur helper found.. Cannot continue!" + exit 1 + fi + else + echo_warning "No curl was found, cannot continue!" + exit 1 + fi + +} + +clone_to_ags() { + if [ ! -d "$HOME/.config/ags" ]; then + if command_exists git; then + git clone --depth=1 https://github.com/Jas-SinghFSU/HyprPanel "$HOME/.config/ags" + else + echo_error "There was no git found, cannot continue!" + exit 1 + fi + else + echo_note "ags is already present, try running 'ags' in your terminal" + fi +} + +main() { + if check_root; then + inst_arch + clone_to_ags + fi +} + +main diff --git a/installs/install-blesh.sh b/installs/install-blesh.sh new file mode 100755 index 0000000..4e03c4e --- /dev/null +++ b/installs/install-blesh.sh @@ -0,0 +1,71 @@ +{ + #!/bin/bash + # ─< Helper functions >───────────────────────────────────────────────────────────────── + echo_error() { echo -e "\033[0;1;31mError: \033[0;31m\t${*}\033[0m"; } + echo_binfo() { echo -e "\033[0;1;34mINFO:\033[0;34m\t${*}\033[0m"; } + echo_info() { echo -e "\033[0;1;35mInfo: \033[0;35m${*}\033[0m"; } + + # ─< Check if the given command exists silently >───────────────────────────────────────── + command_exists() { + command -v "$@" >/dev/null 2>&1 + } + + # ─< Check root and set sudo variable if necessary >─────────────────────────────────────────────── + check_root() { + if [[ "${EUID}" -ne 0 ]]; then + if command_exists sudo; then + echo_binfo "User is not root. Using sudo for privileged operations." + _sudo="sudo" + else + echo_error "No sudo found and you're not root! Can't install packages." + return 1 + fi + else + echo_binfo "Root access confirmed." + _sudo="" + fi + } + + install_pkg() { + bash -c "$(curl -sSL https://git.k4li.de/pika/scripts/raw/branch/main/bash/snippets/install_pkg.sh)" -- "$@" + } + + i_blesh() { + dir="$(mktemp -d)" + local deps=("bash" "git" "make" "gawk") + for pkg in "${deps[@]}"; do + if ! command_exists "$pkg"; then + install_pkg "$pkg" + fi + done && + git clone --recursive --depth 1 --shallow-submodules https://github.com/akinomyoga/ble.sh.git "$dir" && + make -C "$dir" install PREFIX=$HOME/.local + } + + cleanup() { + echo_info "Do you want to clear the temp dir ($dir/) which was created for installation? [Y|n]" && read -r ask_dir + case "$ask_dir" in + [Nn]) + echo_info "All right, didn't clean anything!" + ;; + [Yy] | *) + $_sudo command rm -rf "$dir/" + ;; + esac + } + + main() { + # Check root access and set _sudo + if ! check_root; then + return 1 + fi + if [[ ! -f $HOME/.local/share/blesh/ble.sh ]]; then + i_blesh + cleanup + else + echo_info "Blesh is already installed" + fi + } + + main +} diff --git a/installs/neovide.sh b/installs/neovide.sh new file mode 100755 index 0000000..faebbd2 --- /dev/null +++ b/installs/neovide.sh @@ -0,0 +1,131 @@ +#!/bin/sh + +# ─< ANSI color codes >─────────────────────────────────────────────────────────────────── +RED='\033[0;31m' +CYAN='\033[0;36m' +YELLOW='\033[0;33m' +LIGHT_GREEN='\033[0;92m' +BOLD='\033[1m' +NC='\033[0m' # No Color + +echo_error() { + printf "${BOLD}${RED}ERROR: ${NC}${RED}%s${NC}\n" "$1" >&2 +} + +echo_info() { + printf "${BOLD}${CYAN}INFO: ${NC}${CYAN}%s${NC}\n" "$1" +} + +echo_warning() { + printf "${BOLD}${YELLOW}WARNING: ${NC}${YELLOW}%s${NC}\n" "$1" +} + +echo_note() { + printf "${BOLD}${LIGHT_GREEN}NOTE: ${NC}${LIGHT_GREEN}%s${NC}\n" "$1" +} + +# ─< check if command exists silently >─────────────────────────────────────────────────── +command_exists() { + command -v "$@" >/dev/null 2>&1 +} + +# ─< Silent execution >───────────────────────────────────────────────────────────────── +silentexec() { + "$@" >/dev/null 2>&1 +} + +# ─< Check if the user is root and set _sudo variable if necessary >─────────────────────── +checkRoot() { + if [ "$(id -u)" -ne 0 ]; then + if command_exists sudo; then + echo_info "User is not root. Using sudo for privileged operations." + _sudo="sudo" + else + echo_error "No sudo found and you're not root! Can't install packages." + return 1 + fi + else + echo_info "Root access confirmed." + _sudo="" + fi +} + +installNeovide() { + if ! command_exists cargo; then + curl --proto '=https' --tlsv1.2 -sSf "https://sh.rustup.rs" | sh + "$HOME/.cargo/bin/cargo" install --git https://github.com/neovide/neovide + else + cargo install --git https://github.com/neovide/neovide + fi + + if [ -e "$HOME/.cargo/bin/neovide" ]; then + $_sudo ln -rs "$HOME/.cargo/bin/neovide" /bin/neovide + fi +} + +i_arch() { + deps="base-devel fontconfig freetype2 libglvnd sndio cmake git gtk3 python sdl2 vulkan-intel libxkbcommon-x11" + $_sudo pacman -Sy + for dep in $deps; do + if ! command_exists $dep; then + silentexec $_sudo pacman --noconfirm -S "$dep" || echo_error "Couldn't install $dep" + fi + done +} + +i_debian() { + $_sudo apt-get update + deps="curl gnupg ca-certificates git gcc-multilib g++-multilib cmake libssl-dev pkg-config libfreetype6-dev libasound2-dev libexpat1-dev libxcb-composite0-dev libbz2-dev libsndio-dev freeglut3-dev libxmu-dev libxi-dev libfontconfig1-dev libxcursor-dev" + for dep in $deps; do + if ! command_exists $dep; then + silentexec $_sudo apt-get install --assume-yes "$dep" || echo_error "Couldn't install $dep" + fi + done +} + +i_fedora() { + deps="fontconfig-devel freetype-devel libX11-xcb libX11-devel libstdc++-static libstdc++-devel" + $_sudo dnf update + for dep in $deps; do + if ! command_exists $dep; then + silentexec $_sudo dnf install "$dep" || echo_error "Couldn't install $dep" + fi + done + $_sudo dnf groupinstall "Development Tools" "Development Libraries" + $_sudo dnf install dnf-plugins-core +} + +checkDistrosAndDependencies() { + if [ -f /etc/os-release ]; then + echo_info "Sourcing /etc/os-release to determine the distribution..." + . /etc/os-release + + case "$ID" in + debian | ubuntu | kali | linuxmint | pop | elementary | zorin | kubuntu | neon | kdeneon | deepin | linuxlite | linuxmintdebian | linuxmintubuntu | linuxmintkali | linuxmintpop | linuxmintelementary | linuxmintzorin | linuxmintkubuntu | linuxmintneon | linuxmintkdeneon | linuxmintdeepin | linuxmintlinuxlite) i_debian ;; + arch | manjaro | endeavouros) i_arch ;; + fedora | centos | rhel | rocky | almalinux) i_fedora ;; + *) + case "$ID_LIKE" in + *debian*) i_debian ;; + *arch*) i_arch ;; + *fedora*) i_fedora ;; + *) + echo_error "Unsupported distribution: $ID" + exit 1 + ;; + esac + ;; + esac + else + echo_error "No os-release file found under /etc/. Exiting now!" + exit 1 + fi +} + +main() { + if checkRoot; then + checkDistrosAndDependencies && installNeovide + fi +} + +main diff --git a/installs/neovim.sh b/installs/neovim.sh new file mode 100755 index 0000000..fff14a1 --- /dev/null +++ b/installs/neovim.sh @@ -0,0 +1,223 @@ +{ + #!/bin/sh -e + + # ANSI color codes + RED='\033[0;31m' + CYAN='\033[0;36m' + YELLOW='\033[0;33m' + LIGHT_GREEN='\033[0;92m' + BOLD='\033[1m' + NC='\033[0m' # No Color + + echo_error() { + printf "${BOLD}${RED}ERROR: ${NC}${RED}%s${NC}\n" "$1" >&2 + } + + echo_info() { + printf "${BOLD}${CYAN}INFO: ${NC}${CYAN}%s${NC}\n" "$1" + } + + echo_warning() { + printf "${BOLD}${YELLOW}WARNING: ${NC}${YELLOW}%s${NC}\n" "$1" + } + + echo_note() { + printf "${BOLD}${LIGHT_GREEN}NOTE: ${NC}${LIGHT_GREEN}%s${NC}\n" "$1" + } + + # ─< Check if the given command exists silently >───────────────────────────────────────── + command_exists() { + command -v "$@" >/dev/null 2>&1 + } + + # Check if the user is root and set sudo variable if necessary + check_root() { + if [ "$(id -u)" -ne 0 ]; then + echo_note "checked $(id -u)" + if command_exists sudo; then + echo_note "Checking sudo" + echo_warning "User is not root. Using sudo for privileged operations." + _sudo="sudo" + else + echo_error "No sudo found and you're not root! Can't install packages." + return 1 + fi + else + echo_info "Root access confirmed." + _sudo="" + fi + if [ -n "$_sudo" ]; then + echo_info "--- check_root done --- echo '$_sudo' |" + else + echo_warning "sudo variable is empty: $_sudo" + fi + } + + # ─< Dependencies >───────────────────────────────────────────────────────────────────── + deps="git cargo meson luarocks pipx curl ripgrep make composer npm gcc g++ unzip zip" + + # ─< Distribution-specific installation functions >───────────────────────────────────── + inst_ubuntu() { + $_sudo apt-get update + for _deps in $deps; do + $_sudo apt-get install -y "$_deps" ──────────────────────────────────────── + get_packager() { + 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) inst_ubuntu ;; + debian) inst_debian ;; + fedora) inst_fedora ;; + alpine) inst_alpine ;; + arch | manjaro | garuda | endeavour) inst_arch ;; + opensuse*) inst_opensuse ;; + *) + if [ "${ID_LIKE#*debian}" != "$ID_LIKE" ]; then + inst_debian + elif [ "${ID_LIKE#*ubuntu}" != "$ID_LIKE" ]; then + inst_ubuntu + elif [ "${ID_LIKE#*arch}" != "$ID_LIKE" ]; then + inst_arch + elif [ "${ID_LIKE#*fedora}" != "$ID_LIKE" ]; then + inst_fedora + elif [ "${ID_LIKE#*suse}" != "$ID_LIKE" ]; then + inst_opensuse + else + echo_error "Unsupported distribution: $ID" + exit 1 + fi + ;; + esac + else + echo_error "Unable to detect distribution. /etc/os-release not found." + exit 1 + fi + } + + # ─< Main function >───────────────────────────────────────────────────────────────── + main() { + if command_exists nvim; then + checkVersion + if [ "$(printf '%s\n' "$latest_version" "$currentVersion" | sort -V | head -n1)" = "$latest_version" ]; then + echo_warning "Neovim is already installed in version: $currentVersion" + echo_error "Exiting now!" + exit 0 + fi + fi + + echo_info "Starting Neovim installation script..." + get_packager + if command -v nvim >/dev/null 2>&1; then + echo_note "Neovim has been successfully installed!" + echo_info "Neovim version: $(nvim --version | head -n1)" + else + echo_error "Neovim installation failed." + exit 1 + fi + } + + # ─< Script execution >───────────────────────────────────────────────────────────── + check_root && main +} diff --git a/installs/virt-manager.sh b/installs/virt-manager.sh new file mode 100755 index 0000000..88a56ef --- /dev/null +++ b/installs/virt-manager.sh @@ -0,0 +1,208 @@ +#!/bin/sh + +# ─< ANSI color codes >─────────────────────────────────────────────────────────────────── +RED='\033[0;31m' +CYAN='\033[0;36m' +YELLOW='\033[0;33m' +LIGHT_GREEN='\033[0;92m' +BOLD='\033[1m' +NC='\033[0m' + +# ─< Initialize storage variables >─────────────────────────────────────────────────────── +_STORED_ERRORS="" +_STORED_WARNINGS="" +_STORED_INFOS="" +_STORED_NOTES="" + +# ─< echo functions that store and display messages >──────────────────────────── +echo_error() { + message="${RED}$1${NC}\n" + printf "$message" >&2 + _STORED_ERRORS="${_STORED_ERRORS}${message}" +} + +echo_warning() { + message="${YELLOW}$1${NC}\n" + printf "$message" + _STORED_WARNINGS="${_STORED_WARNINGS}${message}" +} + +echo_info() { + message="${CYAN}$1${NC}\n" + printf "$message" + _STORED_INFOS="${_STORED_INFOS}${message}" +} + +echo_note() { + message="${LIGHT_GREEN}$1${NC}\n" + printf "$message" + _STORED_NOTES="${_STORED_NOTES}${message}" +} + +# ─< Improved display function that only shows categories with content >────────────────── +display_stored_messages() { + has_messages=0 + + # ─< First check if we have any messages at all >───────────────────────────────────────── + if [ -z "$_STORED_ERRORS" ] && [ -z "$_STORED_WARNINGS" ] && [ -z "$_STORED_INFOS" ] && [ -z "$_STORED_NOTES" ]; then + return 0 + fi + + # ─< Now display each non-empty category with proper spacing >──────────────────────────── + if [ -n "$_STORED_ERRORS" ]; then + printf "\n${BOLD}${RED}=== Errors ===${NC}\n" + printf "$_STORED_ERRORS" + has_messages=1 + fi + + if [ -n "$_STORED_WARNINGS" ]; then + [ "$has_messages" -eq 1 ] && printf "\n" + printf "${BOLD}${YELLOW}=== Warnings ===${NC}\n" + printf "$_STORED_WARNINGS" + has_messages=1 + fi + + if [ -n "$_STORED_INFOS" ]; then + [ "$has_messages" -eq 1 ] && printf "\n" + printf "${BOLD}${CYAN}=== Info ===${NC}\n" + printf "$_STORED_INFOS" + has_messages=1 + fi + + if [ -n "$_STORED_NOTES" ]; then + [ "$has_messages" -eq 1 ] && printf "\n" + printf "${BOLD}${LIGHT_GREEN}=== Notes ===${NC}\n" + printf "$_STORED_NOTES" + fi +} + +# ─< Check if the given command exists silently >───────────────────────────────────────── +command_exists() { + command -v "$@" >/dev/null 2>&1 +} + +# ─< Check if the user is root and set $_sudo variable if necessary >─────────────────────── +check_root() { + if [ "$(id -u)" -ne 0 ]; then + if command_exists sudo; then + echo_binfo "User is not root. Using $_sudo for privileged operations." + _sudo="sudo" + else + echo_error "No sudo found and you're not root! Can't install packages." + return 1 + fi + else + echo_binfo "Root access confirmed." + _sudo="" + fi +} + +# ─< Distribution detection and installation >──────────────────────────────────────── +get_packager() { + 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) install_debian ;; + debian) install_debian ;; + fedora) install_fedora ;; + # alpine) inst_alpine ;; + arch | manjaro | garuda | endeavour) install_arch ;; + # opensuse*) inst_opensuse ;; + *) + if [ "${ID_LIKE#*debian}" != "$ID_LIKE" ]; then + install_debian + elif [ "${ID_LIKE#*ubuntu}" != "$ID_LIKE" ]; then + install_debian + elif [ "${ID_LIKE#*arch}" != "$ID_LIKE" ]; then + inst_arch + elif [ "${ID_LIKE#*fedora}" != "$ID_LIKE" ]; then + install_fedora + # elif [ "${ID_LIKE#*suse}" != "$ID_LIKE" ]; then + # inst_opensuse + else + echo_error "Unsupported distribution: $ID" + exit 1 + fi + ;; + esac + else + echo_error "Unable to detect distribution. /etc/os-release not found." + exit 1 + fi +} + +# Function to add user to the 'libvirt' group and start services +configure_libvirt() { + echo_note "Adding user to 'libvirt' group..." + $_sudo usermod -aG libvirt "$(whoami)" + + echo_note "Starting and enabling libvirt service..." + if command -v systemctl &>/dev/null; then + $_sudo systemctl start libvirtd + $_sudo systemctl enable libvirtd + else + echo_warning "systemctl command not found, skipping service management." + fi + + echo_note "Configuration complete. You might need to log out and log back in for group changes to take effect." +} + +# Install packages for Debian/Ubuntu/Pop!_OS +install_debian() { + echo_info "Updating package list..." + $_sudo apt update -y + + echo_info "Installing virt-manager, qemu-full, and related packages..." + $_sudo apt install -y virt-manager qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils + + echo_note "Installation complete on Debian/Ubuntu/Pop!_OS!" +} + +# Install packages for Fedora +install_fedora() { + echo_info "Updating package list..." + $_sudo dnf check-update -y + + echo_info "Installing virt-manager, qemu-full, and related packages..." + $_sudo dnf install -y virt-manager qemu-kvm libvirt libvirt-client bridge-utils + + echo_note "Installation complete on Fedora!" +} + +# Install packages for Arch Linux/Manjaro/EndeavourOS +install_arch() { + echo_info "Updating package list..." + $_sudo pacman -Syu --noconfirm + + echo_info "Installing virt-manager, qemu-full, and related packages..." + $_sudo pacman -S --noconfirm virt-manager qemu-full libvirt dnsmasq bridge-utils + + echo_note "Installation complete on Arch Linux/Manjaro/EndeavourOS!" +} + +# Install packages for openSUSE +install_opensuse() { + echo_info "Updating package list..." + $_sudo zypper refresh + + echo_info "Installing virt-manager, qemu-full, and related packages..." + $_sudo zypper install -y virt-manager qemu-kvm libvirt libvirt-client bridge-utils + + echo_note "Installation complete on openSUSE!" +} + +main() { + check_root && + get_packager && + configure_libvirt + + display_stored_messages +} + +main diff --git a/installs/xmrig.sh b/installs/xmrig.sh new file mode 100755 index 0000000..1a680e3 --- /dev/null +++ b/installs/xmrig.sh @@ -0,0 +1,187 @@ +{ + #!/bin/sh + + # ANSI color codes + RED='\033[0;31m' + CYAN='\033[0;36m' + YELLOW='\033[0;33m' + LIGHT_GREEN='\033[0;92m' + BOLD='\033[1m' + NC='\033[0m' # No Color + + echo_error() { + printf "${BOLD}${RED}ERROR: ${NC}${RED}%s${NC}\n" "$1" >&2 + } + + echo_info() { + printf "${BOLD}${CYAN}INFO: ${NC}${CYAN}%s${NC}\n" "$1" + } + + echo_warning() { + printf "${BOLD}${YELLOW}WARNING: ${NC}${YELLOW}%s${NC}\n" "$1" + } + + echo_note() { + printf "${BOLD}${LIGHT_GREEN}NOTE: ${NC}${LIGHT_GREEN}%s${NC}\n" "$1" + } + + # Check if the user is root and set sudo variable if necessary + check_root() { + if [ "$(id -u)" -ne 0 ]; then + if command_exists sudo; then + echo_info "User is not root. Using sudo for privileged operations." + _sudo="sudo" + else + echo_error "No sudo found and you're not root! Can't install packages." + return 1 + fi + else + echo_info "Root access confirmed." + _sudo="" + fi + } + + # < Distribution detection and installation > + get_packager() { + 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) _install() { + $_sudo apt-get install "$@" --assume-yes + } ;; + debian) _install() { + $_sudo apt-get install "$@" --assume-yes + } ;; + fedora) _install() { + $_sudo dnf install "$@" -y + } ;; + alpine) _install() { + $_sudo apk add "$@" + } ;; + arch | manjaro | garuda | endeavour) _install() { + $_sudo pacman -S "$@" --noconfirm + } ;; + opensuse*) _install() { $_sudo zypper in "$@" -y; } ;; + *) + if [ "${ID_LIKE#*debian}" != "$ID_LIKE" ]; then + _install() { $_sudo apt-get install "$@" --assume-yes; } + elif [ "${ID_LIKE#*ubuntu}" != "$ID_LIKE" ]; then + _install() { $_sudo apt-get install "$@" --assume-yes; } + elif [ "${ID_LIKE#*arch}" != "$ID_LIKE" ]; then + _install() { $_sudo pacman -S "$@" --noconfirm; } + elif [ "${ID_LIKE#*fedora}" != "$ID_LIKE" ]; then + _install() { $_sudo dnf install "$@" -y; } + elif [ "${ID_LIKE#*suse}" != "$ID_LIKE" ]; then + _install() { $_sudo zypper in "$@" -y; } + else + echo_error "Unsupported distribution: $ID" + exit 1 + fi + ;; + esac + else + echo_error "Unable to detect distribution. /etc/os-release not found." + exit 1 + fi + } + + # Check if a command exists + command_exists() { + command -v "$@" >/dev/null 2>&1 + } + + # Install dependencies + _dependencies() { + tools="git cmake make" + packages="libuv1-dev libssl-dev libhwloc-dev argon2" + + for tool in $tools; do + if command_exists "$tool"; then + echo_note "$tool is already installed" + else + echo_info "Installing $tool.." + _install "$tool" || echo_error "Failed to install $tool" + fi + done + + for package in $packages; do + echo_info "Installing $package" + _install "$package" || echo_error "Failed to install $package" + done + + echo_note "Dependency check completed!" + } + + # Clone the repository and prepare build directory + _git() { + xmrig_dir="$HOME/.bin/xmrig" + + if [ -d "$xmrig_dir" ]; then + echo_warning "$xmrig_dir already exists. Skipping clone." + else + echo_info "Cloning xmrig repository to $xmrig_dir" + mkdir -p "$HOME/.bin" + if ! git clone --depth=1 https://github.com/xmrig/xmrig.git "$xmrig_dir"; then + echo_error "Failed to clone xmrig repository." + return 1 + fi + fi + + build_dir="$xmrig_dir/build" + mkdir -p "$build_dir" || { + echo_error "Failed to create build directory: $build_dir" + return 1 + } + + cd "$build_dir" || { + echo_error "Failed to navigate to build directory: $build_dir" + return 1 + } + } + + # Initialize and build the application + _appinit() { + echo_info "Running cmake .." + if ! cmake ..; then + echo_error "CMake failed." + return 1 + fi + + echo_info "Running make (this could take a while)" + if ! make; then + echo_error "Make failed." + return 1 + fi + + $_sudo ln -s ./xmrig /usr/bin/xmrig || "Link of application failed hard! Is not accessible at /usr/bin/xmrig" + } + + # Main function + main() { + if ! check_root; then + echo_error "Root check failed. Exiting." + return 1 + fi + + if ! get_packager; then + echo_error "Failed to detect distribution or set packager." + return 1 + fi + + _dependencies || return 1 + + if _git; then + _appinit || echo_error "Build initialization failed." + else + echo_error "Failed during Git operations." + fi + } + + main +} diff --git a/installs/yazi.sh b/installs/yazi.sh new file mode 100644 index 0000000..518e6e0 --- /dev/null +++ b/installs/yazi.sh @@ -0,0 +1,149 @@ +{ + #!/bin/sh -e + + # ─< ANSI color codes >─────────────────────────────────────────────────────────────────── + RED='\033[0;31m' + CYAN='\033[0;36m' + YELLOW='\033[0;33m' + LIGHT_GREEN='\033[0;92m' + BOLD='\033[1m' + NC='\033[0m' # No Color + + echo_error() { + printf "${BOLD}${RED}ERROR: ${NC}${RED}%s${NC}\n" "$1" >&2 + } + + echo_info() { + printf "${BOLD}${CYAN}INFO: ${NC}${CYAN}%s${NC}\n" "$1" + } + + echo_warning() { + printf "${BOLD}${YELLOW}WARNING: ${NC}${YELLOW}%s${NC}\n" "$1" + } + + echo_note() { + printf "${BOLD}${LIGHT_GREEN}NOTE: ${NC}${LIGHT_GREEN}%s${NC}\n" "$1" + } + + # ─< Check if the given command exists silently >───────────────────────────────────────── + command_exists() { + command -v "$@" >/dev/null 2>&1 + } + + # ─< Check if the user is root and set sudo variable if necessary >─────────────────────── + check_root() { + if [ "$(id -u)" -ne 0 ]; then + if command_exists sudo; then + echo_info "User is not root. Using sudo for privileged operations." + _sudo="sudo" + else + echo_error "No sudo found and you're not root! Can't install packages." + return 1 + fi + else + echo_info "Root access confirmed." + _sudo="" + fi + } + + evalCargo() { + if [ -e "$HOME/.cargo/env" ]; then + echo_note "Using $HOME/.cargo/env.." + . "$HOME/.cargo/env" + fi + } + + i_cargo() { + # if ! command_exists make || ! command_exists gcc; then + # echo_error "The script might run into issues, because of make and gcc not being installed. Please install it, and run the script again, if it fails!" + # fi + evalCargo + if command_exists cargo; then + echo_info "Installing yazi through cargo" + elif command_exists curl; then + echo_note "no cargo found, using curl to install rustup" + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + + evalCargo + + rustup update + evalCargo + + echo_info "Installing yazi through cargo" + else + echo_warning "neither cargo, nor curl were found. Cannot continue!" + fi + + cargo install --locked yazi-fm yazi-cli + + c_yazi + } + + i_arch() { + $_sudo pacman -S yazi --noconfirm + c_yazi + } + + i_opensuse() { + $_sudo zypper install yazi + c_yazi + } + + c_yazi() { + if [ -e "$HOME/.config/yazi/package.toml" ]; then + if command_exists ya; then + ya pack -i + fi + else + echo_warning "There was no yazi config found.. " + fi + } + + # ─< Distribution detection and installation >──────────────────────────────────────── + get_packager() { + 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) i_cargo ;; + debian) i_cargo ;; + fedora) i_cargo ;; + alpine) i_cargo ;; + arch | manjaro | garuda | endeavour) i_arch ;; + opensuse*) i_opensuse ;; + *) + if [ "${ID_LIKE#*debian}" != "$ID_LIKE" ]; then + i_cargo + elif [ "${ID_LIKE#*ubuntu}" != "$ID_LIKE" ]; then + i_cargo + elif [ "${ID_LIKE#*arch}" != "$ID_LIKE" ]; then + i_arch + elif [ "${ID_LIKE#*fedora}" != "$ID_LIKE" ]; then + i_cargo + elif [ "${ID_LIKE#*suse}" != "$ID_LIKE" ]; then + i_opensuse + else + echo_error "Unsupported distribution: $ID" + exit 1 + fi + ;; + esac + else + echo_error "Unable to detect distribution. /etc/os-release not found." + exit 1 + fi + } + + main() { + if check_root; then + get_packager + fi + } + + main +} diff --git a/installs/ytgo.sh b/installs/ytgo.sh new file mode 100644 index 0000000..091e2d8 --- /dev/null +++ b/installs/ytgo.sh @@ -0,0 +1,157 @@ +#!/bin/sh + +# ╭───────────────╮ +# │ env functions │ +# ╰───────────────╯ +# ───────────────────────────────────< ANSI color codes >─────────────────────────────────── +RED='\033[0;31m' +CYAN='\033[0;36m' +YELLOW='\033[0;33m' +LIGHT_GREEN='\033[0;92m' +BOLD='\033[1m' +NC='\033[0m' # No Color + +echo_error() { + printf "${BOLD}${RED}ERROR: ${NC}${RED}%s${NC}\n" "$1" >&2 +} + +echo_info() { + printf "${BOLD}${CYAN}INFO: ${NC}${CYAN}%s${NC}\n" "$1" +} + +echo_warning() { + printf "${BOLD}${YELLOW}WARNING: ${NC}${YELLOW}%s${NC}\n" "$1" +} + +echo_note() { + printf "${BOLD}${LIGHT_GREEN}NOTE: ${NC}${LIGHT_GREEN}%s${NC}\n" "$1" +} + +command_exists() { + command -v "$@" >/dev/null 2>&1 +} + +# ─────────────< Check if the user is root and set sudo variable if necessary >───────────── +check_root() { + if [ "$(id -u)" -ne 0 ]; then + if command_exists sudo; then + echo_info "User is not root. Using sudo for privileged operations." + _sudo="sudo" + else + echo_error "No sudo found and you're not root! Can't install packages." + return 1 + fi + else + echo_info "Root access confirmed." + _sudo="" + fi +} + +# ──────────────────────< Check if the given command exists silently >────────────────────── +command_exists() { + command -v "$@" >/dev/null 2>&1 +} + +# ╭────────────────────────────────────╮ +# │ insert your scripts/functions here │ +# ╰────────────────────────────────────╯ + +# ─< Distribution detection and installation >──────────────────────────────────────── +get_packager() { + 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) _install() { + $_sudo apt-get install --assume-yes "$@" + } ;; + debian) _install() { + $_sudo apt-get install --assume-yes "$@" + } ;; + fedora) _install() { + $_sudo dnf install -y "$@" + } ;; + alpine) inst_alpine ;; + arch | manjaro | garuda | endeavour) _install() { + $_sudo pacman -S --noconfirm "$@" + } ;; + opensuse*) inst_opensuse ;; + *) + if [ "${ID_LIKE#*debian}" != "$ID_LIKE" ]; then + _install() { + $_sudo apt-get install --assume-yes "$@" + } + elif [ "${ID_LIKE#*ubuntu}" != "$ID_LIKE" ]; then + _install() { + $_sudo apt-get install --assume-yes "$@" + } + elif [ "${ID_LIKE#*arch}" != "$ID_LIKE" ]; then + _install() { + $_sudo pacman -S --noconfirm "$@" + } + elif [ "${ID_LIKE#*fedora}" != "$ID_LIKE" ]; then + _install() { + $_sudo dnf install -y "$@" + } + elif [ "${ID_LIKE#*suse}" != "$ID_LIKE" ]; then + inst_opensuse + else + echo_error "Unsupported distribution: $ID" + exit 1 + fi + ;; + esac + else + echo_error "Unable to detect distribution. /etc/os-release not found." + exit 1 + fi +} + +_dependencies() { + get_packager + if [[ "$ID" == "arch" || "$ID_LIKE" == *"arch"* ]]; then + _deps="go git mpv yt-dlp" + else + _deps="golang git mpv yt-dlp" + fi + + for dependency in $_deps; do + if ! command_exists "$dependency"; then + echo_info "Installing $dependency" + _install "$dependency" || echo_error "$dependency could not be installed!" + else + echo_note "$dependency - was already installed." + fi + done +} + +_clone() { + tmpdir="$(mktemp --dir)" + repo="https://git.k4li.de/pika/ytgo.git" + + cd "$tmpdir" || echo_error "$tmpdir is not a valid directory!" + git clone --depth=1 "$repo" + cd ytgo || echo_error "$tmpdir/ytgo is not a valid directory!" +} + +_build() { + $_sudo make install +} + +# ───────────────────────────────< main function to execute >─────────────────────────────── +main() { + if check_root; then + _dependencies || echo_error "dependency function failed hard!" + _clone || echo_error "clone function failed hard!" + _build || echo_error "build function failed hard!" + else + echo_error "Something went terribly wrong!" + fi +} + +main diff --git a/logging.sh b/logging.sh new file mode 100644 index 0000000..0739b62 --- /dev/null +++ b/logging.sh @@ -0,0 +1,76 @@ +#!/bin/sh + +# POSIX-compliant color codes +RED='\033[0;31m' +YELLOW='\033[1;33m' +GREEN='\033[0;32m' +CYAN='\033[0;36m' +NC='\033[0m' # No Color + +# Simple echo functions without any arrays or typeset +echo_error() { + printf "${RED}❌ %s${NC}\n" "$1" >&2 +} + +echo_warning() { + printf "${YELLOW}⚠️ %s${NC}\n" "$1" +} + +echo_info() { + printf "${GREEN}ℹ️ %s${NC}\n" "$1" +} + +echo_note() { + printf "${CYAN}📝 %s${NC}\n" "$1" +} + +# ─< Check if the given command exists silently >───────────────────────────────────────── +command_exists() { + for i in which command; do + if command_exists $i; then + case $i in + command) command -v "$@" >/dev/null 2>&1 ;; + which) which "$@" >/dev/null 2>&1 ;; + esac + fi + done +} + +_cd() { + cd "$1" || { echo_error "Cannot navigate to the directory: $1"; return 1; } +} + +_exit() { + echo_error "There was an error, which caused the script to exit immediately" + echo_error "$1" + echo_error "Exiting now!" + exit 1 +} + +confirm_action() { + read -p "$1 - [y/n]: " confirm + case $confirm in + [yY] ) return 0 ;; + [nN] ) return 1 ;; + * ) echo_warning "Invalid input. Action cancelled." ; return 1 ;; + esac +} + +create_dir() { + if [ ! -d "$1" ]; then + echo_info "Creating directory: $1" + mkdir -p "$1" || _exit "Failed to create directory $1" + else + echo_info "Directory $1 already exists" + fi +} + +check_disk_space() { + threshold=1000000 # Minimum space in KB (e.g., 1GB) + available_space=$(df / | awk 'NR==2 {print $4}') + if [ "$available_space" -lt "$threshold" ]; then + echo_warning "Not enough disk space. Only $((available_space / 1024))MB remaining." + return 1 + fi + echo_info "Sufficient disk space available." +} \ No newline at end of file diff --git a/python/Caddy/addEntry.py b/python/Caddy/addEntry.py new file mode 100755 index 0000000..9e5e652 --- /dev/null +++ b/python/Caddy/addEntry.py @@ -0,0 +1,331 @@ +#!/usr/bin/env python3 +import os +import re +import socket + +def get_host_ip(): + """Get the host IP address""" + try: + # Create a socket to determine the outgoing IP address + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.connect(("8.8.8.8", 80)) # Connect to Google DNS (doesn't send data) + host_ip = s.getsockname()[0] + s.close() + return host_ip + except Exception: + return "127.0.0.1" # Fallback to localhost + +def get_user_input(prompt, default=None): + """Interactive prompt with default values""" + value = input(f"{prompt} [{default}]: ") or default + return value + +def find_caddyfile(): + """Check if the Caddyfile exists, otherwise ask for the path""" + default_path = "./conf/Caddyfile" + if os.path.exists(default_path): + return default_path + + print("⚠ No Caddyfile found!") + while True: + custom_path = get_user_input("Enter the path to your Caddyfile") + if os.path.exists(custom_path): + return custom_path + print("❌ File not found, please try again.") + +def parse_existing_entries(caddyfile_path): + """Parse the existing Caddyfile to extract all configured domains""" + existing_entries = {} + try: + with open(caddyfile_path, "r") as file: + content = file.read() + + # First, normalize the content to make parsing more reliable + # This removes comments and normalizes whitespace + lines = [] + in_comment = False + for line in content.splitlines(): + line = line.strip() + if not line or line.startswith('#'): + continue + + # Handle inline comments + if '#' in line and not in_comment: + line = line[:line.index('#')].strip() + + lines.append(line) + + normalized_content = '\n'.join(lines) + + # Use brace matching to properly extract domain blocks + blocks = [] + current_position = 0 + + while current_position < len(normalized_content): + # Find the next domain block start + block_start = normalized_content.find('{', current_position) + if block_start == -1: + break + + # Find corresponding domain definition + domain_start = normalized_content.rfind('\n', 0, block_start) + if domain_start == -1: + domain_start = 0 + else: + domain_start += 1 # Skip the newline + + domain_def = normalized_content[domain_start:block_start].strip() + + # Find end of this block (accounting for nested braces) + brace_count = 1 + block_end = block_start + 1 + + while brace_count > 0 and block_end < len(normalized_content): + if normalized_content[block_end] == '{': + brace_count += 1 + elif normalized_content[block_end] == '}': + brace_count -= 1 + block_end += 1 + + if brace_count == 0: + # We found a complete block + block_content = normalized_content[domain_start:block_end] + + # Only process blocks with reverse_proxy directives + if 'reverse_proxy' in block_content: + blocks.append((domain_def, block_content)) + + current_position = block_end + + # Process the extracted blocks + for domain_def, block_content in blocks: + # Extract target from reverse_proxy directive + proxy_match = re.search(r'reverse_proxy\s+(https?:\/\/[\d\.]+:\d+|[\d\.]+:\d+)', block_content) + if not proxy_match: + continue + + target = proxy_match.group(1).strip() + + # Process domains (handle comma-separated lists correctly) + domains = [d.strip() for d in domain_def.split(',')] + + # Process each domain + for domain in domains: + # Skip if it looks like a directive rather than a domain + if '{' in domain or '}' in domain or not domain: + continue + + # Skip literal "Host" that are likely from host header directives rather than domains + if domain == "Host" or domain == "{host}": + continue + + # Verify domain format (basic check) + if not re.match(r'^[a-zA-Z0-9][-a-zA-Z0-9.]*[a-zA-Z0-9]$', domain) and not domain.startswith('*.'): + print(f"⚠️ Skipping invalid domain format: '{domain}'") + continue + + # Determine proxy type + proxy_type = 'standard' + if "https://" in target and "tls_insecure_skip_verify" in block_content: + if "versions h1.1" in block_content: + proxy_type = 'opnsense' + else: + proxy_type = 'https_skip_verify' + + # Store the entry + existing_entries[domain] = { + 'target': target, + 'content': block_content, + 'proxy_type': proxy_type + } + + # Debug output for special cases + if domain.lower() == "host": + print(f"⚠️ Warning: Found domain named 'host': {domain}") + + except Exception as e: + print(f"❌ Error reading Caddyfile: {e}") + import traceback + print(traceback.format_exc()) + + return existing_entries + +def format_caddy_entry(domains, target_ip, target_port, proxy_type): + """Generate a properly formatted Caddy entry based on proxy type""" + domain_list = ", ".join(domains) # Multiple domains in a single line + + if proxy_type == "standard": + return f""" +{domain_list} {{ + tls {{ + dns cloudflare {{env.CLOUDFLARE_API_TOKEN}} + }} + reverse_proxy {target_ip}:{target_port} +}} +""" + elif proxy_type == "https_skip_verify": + return f""" +{domain_list} {{ + tls {{ + dns cloudflare {{env.CLOUDFLARE_API_TOKEN}} + }} + reverse_proxy https://{target_ip}:{target_port} {{ + transport http {{ + tls + tls_insecure_skip_verify + }} + }} +}} +""" + elif proxy_type == "opnsense": + return f""" +{domain_list} {{ + tls {{ + dns cloudflare {{env.CLOUDFLARE_API_TOKEN}} + }} + reverse_proxy https://{target_ip}:{target_port} {{ + transport http {{ + tls + tls_insecure_skip_verify + versions h1.1 # Enforce HTTP/1.1 + }} + header_up Host {{host}} + header_up X-Real-IP {{remote_host}} + header_up X-Forwarded-Proto {{scheme}} + header_up X-Forwarded-For {{remote}} + header_down Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" + + # Remove problematic headers + header_up -Connection + header_up -Upgrade + }} +}} +""" + +def update_existing_entry(caddyfile_path, domain, new_entry): + """Replace an existing entry for the given domain""" + try: + with open(caddyfile_path, "r") as file: + content = file.read() + + # New improved pattern to correctly match complete domain blocks + # This regex matches the domain block from start to finish, including all braces + domain_pattern = fr'(?m)^(?:(?:{re.escape(domain)}|[^{{,\s]+(?:,\s*{re.escape(domain)})(?:,\s*[^{{,\s]+)*|{re.escape(domain)}(?:,\s*[^{{,\s]+)+))\s*{{(?:[^{{}}]|{{(?:[^{{}}]|{{[^{{}}]*}})*}})*}}' + + pattern = re.compile(domain_pattern, re.DOTALL) + match = pattern.search(content) + + if match: + # Replace the block containing this domain with the new entry + new_content = content[:match.start()] + new_entry.strip() + content[match.end():] + + with open(caddyfile_path, "w") as file: + file.write(new_content) + + print(f"✅ Updated entry for {domain}") + else: + print(f"⚠ Could not find exact entry for {domain}. Adding as new entry.") + with open(caddyfile_path, "a") as file: + file.write(new_entry) + + except Exception as e: + print(f"❌ Error updating Caddyfile: {e}") + print(f"Error details: {str(e)}") + +def add_caddy_entry(caddyfile_path): + """Add new Caddy reverse proxy entries, showing existing entries first""" + host_ip = get_host_ip() + existing_entries = parse_existing_entries(caddyfile_path) + + print("\n📌 Existing Caddy Entries:") + if existing_entries: + for domain, data in existing_entries.items(): + print(f" 🔹 {domain} → {data['target']}") + else: + print(" ⚠ No entries found.") + + while True: + domain = get_user_input("\nEnter the domain you want to configure", "") + + if not domain: + print("❌ No domain provided. Skipping entry.") + continue + + # If domain exists, extract its current values + existing_ip = host_ip + existing_port = "8080" + proxy_type = "standard" + + if domain in existing_entries: + print(f"⚠ The domain {domain} already exists.") + edit_existing = get_user_input("Do you want to edit this entry? (y/n)", "y").lower() == "y" + if not edit_existing: + continue + + existing_target = existing_entries[domain]['target'] + proxy_type = existing_entries[domain]['proxy_type'] + target_without_protocol = existing_target.replace("https://", "").replace("http://", "") + + if ":" in target_without_protocol: + existing_ip, existing_port = target_without_protocol.split(":") + else: + existing_ip = target_without_protocol + existing_port = "80" + + # Show host IP as an option + target_ip_prompt = f"Enter the target IP (type 'host' for {host_ip})" + target_ip = get_user_input(target_ip_prompt, existing_ip) + + # Replace 'host' with actual host IP + if target_ip.lower() == 'host': + target_ip = host_ip + + target_port = get_user_input("Enter the target port", existing_port) + + print("\nChoose the proxy mode:") + print("1️⃣ Standard (No HTTPS changes)") + print("2️⃣ Internal HTTPS (skip verify)") + print("3️⃣ OPNsense Mode (skip verify + enforce HTTP/1.1)") + + # Pre-fill proxy type based on detected configuration + mode_choice_default = "1" + if proxy_type == "https_skip_verify": + mode_choice_default = "2" + elif proxy_type == "opnsense": + mode_choice_default = "3" + + mode_choice = get_user_input("Enter option (1/2/3)", mode_choice_default) + + proxy_type = "standard" + if mode_choice == "2": + proxy_type = "https_skip_verify" + elif mode_choice == "3": + proxy_type = "opnsense" + + new_entry = format_caddy_entry([domain], target_ip, target_port, proxy_type) + + if domain in existing_entries: + update_existing_entry(caddyfile_path, domain, new_entry) + else: + try: + with open(caddyfile_path, "a") as file: + file.write(new_entry) + print(f"\n✅ New entry added: {domain} → {target_ip}:{target_port}") + except Exception as e: + print(f"\n❌ Error writing to Caddyfile: {e}") + return + + # Ask if another entry should be added + more_entries = get_user_input("\nDo you want to add or edit another entry? (y/n)", "n").lower() == "y" + if not more_entries: + break + + # Restart Caddy container + restart_caddy = get_user_input("\nDo you want to restart the Caddy container? (y/n)", "y").lower() == "y" + if restart_caddy: + os.system("docker compose restart caddy") + print("🔄 Caddy container restarted!") + +if __name__ == "__main__": + caddyfile_path = find_caddyfile() + add_caddy_entry(caddyfile_path) diff --git a/python/README.md b/python/README.md new file mode 100644 index 0000000..6376748 --- /dev/null +++ b/python/README.md @@ -0,0 +1,2 @@ +# python + diff --git a/python/checkpkg.py b/python/checkpkg.py new file mode 100755 index 0000000..064c3b1 --- /dev/null +++ b/python/checkpkg.py @@ -0,0 +1,354 @@ +#!/usr/bin/env python3 +import argparse +import urllib.request +import json +import signal +import re +import shutil +import textwrap +from concurrent.futures import ThreadPoolExecutor, as_completed +from urllib.error import HTTPError, URLError + +# Color codes +COLORS = { + 'reset': '\033[0m', + 'bold': '\033[1m', + 'red': '\033[91m', + 'green': '\033[92m', + 'yellow': '\033[93m', + 'header': '\033[94m' +} + +def colorize(text, color): + """Add ANSI color codes if output is a terminal""" + if not hasattr(colorize, 'is_tty'): + colorize.is_tty = __import__('sys').stdout.isatty() + return f"{COLORS[color]}{text}{COLORS['reset']}" if colorize.is_tty else text + +# def get_terminal_width(default=80): +# """Get terminal width with fallback""" +# try: +# return shutil.get_terminal_size().columns +# except: +# return default + +signal.signal(signal.SIGINT, lambda s, f: exit(1)) + +REQUEST_HEADERS = { + 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) checkpkg/1.0', + 'Accept': 'application/json' +} + +PM_MAPPINGS = { + 'apt': ['debian_', 'ubuntu_'], + 'dnf': ['fedora_'], + 'pacman': ['arch'], + 'aur': ['aur'], + 'apk': ['alpine_'], + 'zypper': ['opensuse_'] +} + +REPO_FORMATS = { + 'debian_': "Debian {}", + 'ubuntu_': "Ubuntu {}", + 'fedora_': "Fedora {}", + 'arch': "Arch", + 'aur': "AUR", + 'alpine_': "Alpine {}", + 'opensuse_': "openSUSE {}" +} + +def version_key(version): + """Create a sorting key for version comparison""" + return [ + (0, int(part)) if part.isdigit() else (1, part.lower()) + for part in re.findall(r'(\d+|\D+)', version) + ] + +def get_package_manager(repo): + for pm, patterns in PM_MAPPINGS.items(): + if any(repo.startswith(p) for p in patterns): + return pm + return None + +def format_repository(repo): + for pattern, fmt in REPO_FORMATS.items(): + if repo.startswith(pattern): + parts = repo.split('_') + return fmt.format(parts[1] if len(parts) > 1 else '') + return repo + +def fetch_package_data(package): + try: + req = urllib.request.Request( + f'https://repology.org/api/v1/project/{package}', + headers=REQUEST_HEADERS + ) + with urllib.request.urlopen(req, timeout=10) as response: + return json.load(response) + except HTTPError as e: + if e.code == 403: + print(colorize(f"Error: Repology blocked the request for {package} (try again later)", 'red')) + return None + except Exception: + return None + +def print_table(output, headers, selected_pms, args): + """Print formatted table with consistent alignment or list for small terminals""" + # Terminal dimensions + terminal_width = shutil.get_terminal_size().columns + + # Calculate package availability for coloring + pkg_availability = {} + for pkg in args.packages: + versions = output.get(pkg, {}) + available_count = sum(1 for pm in selected_pms if versions.get(pm, 'Not found') != 'Not found') + + if available_count == 0: + pkg_availability[pkg] = 'red' # Not available anywhere + elif available_count == len(selected_pms): + pkg_availability[pkg] = 'green' # Available everywhere + else: + pkg_availability[pkg] = 'yellow' # Available in some places + + # Determine minimum required widths + min_pkg_width = max(len(pkg) for pkg in args.packages) + 2 + min_pm_width = 10 + min_required_width = min_pkg_width + (min_pm_width * len(selected_pms)) + (3 * len(selected_pms)) + + # If terminal is too narrow for the table, use list format instead + if terminal_width < min_required_width and len(selected_pms) > 1: + print_list_format(output, headers, selected_pms, args, pkg_availability) + return + + # Calculate column widths + padding = 1 # Space on each side of content + + # Package column width + pkg_col_width = min(min_pkg_width + 4, max(min_pkg_width, terminal_width // (len(selected_pms) + 3))) + + # PM column widths (divide remaining space equally) + remaining_width = terminal_width - pkg_col_width - (3 * len(selected_pms)) + pm_col_width = max(min_pm_width, remaining_width // len(selected_pms)) + + col_widths = [pkg_col_width] + [pm_col_width] * len(selected_pms) + + # Print header row + header_cells = [] + for i, header in enumerate(headers): + text = header.center(col_widths[i] - (2 * padding)) + cell = " " * padding + colorize(text, 'header') + " " * padding + header_cells.append(cell) + + print(" | ".join(header_cells)) + + # Print separator line + total_width = sum(col_widths) + (3 * (len(col_widths) - 1)) + print("-" * total_width) + + # Print each package row + for pkg_idx, pkg in enumerate(args.packages): + versions = output.get(pkg, {}) + + # First collect all data for this package + package_data = [] + + # Package name (first column) + package_data.append([colorize(pkg, pkg_availability[pkg])]) + + # Version data for each package manager + for pm in selected_pms: + version = versions.get(pm, 'Not found') + + if version == 'Not found': + package_data.append([colorize('-', 'red')]) + continue + + # Extract version number and repositories + version_parts = [] + match = re.match(r'(.*?)\s+\((.*)\)$', version) + + if match: + ver_num, repos = match.groups() + version_parts.append(colorize(ver_num, 'green')) + + # Format repositories + repo_lines = [] + repo_text = "(" + repos + ")" + + # Wrap repository text if needed + avail_width = col_widths[len(package_data)] - (2 * padding) + if len(repo_text) <= avail_width: + repo_lines.append(colorize(repo_text, 'green')) + else: + # Handle wrapping for repositories + repo_parts = repos.split(', ') + current_line = "(" + + for repo in repo_parts: + if len(current_line) + len(repo) + 2 <= avail_width: + if current_line != "(": + current_line += ", " + current_line += repo + else: + if current_line != "(": + current_line += ")" + repo_lines.append(colorize(current_line, 'green')) + current_line = " " + repo + + if current_line != "(": + current_line += ")" if not current_line.startswith(" ") else "" + repo_lines.append(colorize(current_line, 'green')) + + # Combined version and repo lines + package_data.append([version_parts[0]] + repo_lines) + else: + # Simple version string + package_data.append([colorize(version, 'green')]) + + # Determine max number of lines needed + max_lines = max(len(column) for column in package_data) + + # Print all lines for this package + for line_idx in range(max_lines): + row_cells = [] + + for col_idx, col_data in enumerate(package_data): + if line_idx < len(col_data): + # Actual content + content = col_data[line_idx] + content_plain = re.sub(r'\033\[\d+m', '', content) + + # Calculate padding + left_pad = padding + right_pad = max(0, col_widths[col_idx] - len(content_plain) - left_pad) + + cell = " " * left_pad + content + " " * right_pad + else: + # Empty cell + cell = " " * col_widths[col_idx] + + row_cells.append(cell) + + print(" | ".join(row_cells)) + + # Add separator between packages + if pkg_idx < len(args.packages) - 1: + print("·" * total_width) + +def print_list_format(output, headers, selected_pms, args, pkg_availability): + """Print packages in a vertical list format for narrow terminals""" + terminal_width = shutil.get_terminal_size().columns + + for pkg_idx, pkg in enumerate(args.packages): + pkg_color = pkg_availability[pkg] + versions = output.get(pkg, {}) + + # Print package header with color based on availability + print(f"\n{colorize('Package:', 'bold')} {colorize(pkg, pkg_color)}") + print("-" * min(40, terminal_width - 2)) + + # Print versions for each package manager + for pm in selected_pms: + pm_name = headers[selected_pms.index(pm) + 1] # Get friendly display name + version = versions.get(pm, 'Not found') + + if version == 'Not found': + print(f"{colorize(pm_name, 'header')}: {colorize('-', 'red')}") + else: + # Extract version and repo information + match = re.match(r'(.*?)\s+\((.*)\)$', version) + if match: + ver_num, repos = match.groups() + + # Handle long repository lists with wrapping + if len(pm_name) + len(ver_num) + len(repos) + 5 > terminal_width: + print(f"{colorize(pm_name, 'header')}: {colorize(ver_num, 'green')}") + # Wrap repositories with proper indentation + wrapper = textwrap.TextWrapper( + width=terminal_width - 4, + initial_indent=" ", + subsequent_indent=" " + ) + wrapped = wrapper.fill(f"({repos})") + print(colorize(wrapped, 'green')) + else: + print(f"{colorize(pm_name, 'header')}: {colorize(ver_num, 'green')} ({repos})") + else: + print(f"{colorize(pm_name, 'header')}: {colorize(version, 'green')}") + + # Add separator between packages + if pkg_idx < len(args.packages) - 1: + print("\n" + "-" * min(40, terminal_width - 2)) + +def main(): + parser = argparse.ArgumentParser(description='Package search tool') + parser.add_argument('--all', action='store_true') + parser.add_argument('--apt', action='store_true') + parser.add_argument('--dnf', action='store_true') + parser.add_argument('--pacman', action='store_true') + parser.add_argument('--apk', action='store_true') + parser.add_argument('--zypper', action='store_true') + parser.add_argument('--aur', action='store_true') + parser.add_argument('packages', nargs='+') + args = parser.parse_args() + + selected_pms = [pm for pm, flag in [ + ('apt', args.apt or args.all), + ('dnf', args.dnf or args.all), + ('pacman', args.pacman or args.all), + ('apk', args.apk or args.all), + ('zypper', args.zypper or args.all), + ('aur', args.aur or args.all) + ] if flag] + + if not selected_pms: + print(colorize("Error: No package managers selected", 'red')) + return + + results = {} + with ThreadPoolExecutor(max_workers=5) as executor: + futures = {executor.submit(fetch_package_data, pkg): pkg for pkg in args.packages} + for future in as_completed(futures): + pkg = futures[future] + try: + data = future.result() + results[pkg] = data or [] + except Exception as e: + print(colorize(f"Error processing {pkg}: {str(e)}", 'red')) + results[pkg] = [] + + output = {} + for pkg, entries in results.items(): + pm_versions = {pm: {'version': '', 'repos': set(), 'key': []} for pm in selected_pms} + + for entry in entries: + repo = entry.get('repo', '') + version = entry.get('version', 'N/A') + pm = get_package_manager(repo) + + if pm in selected_pms and version != 'N/A': + repo_fmt = format_repository(repo) + current_key = version_key(version) + stored = pm_versions[pm] + + if not stored['key'] or current_key > stored['key']: + stored['version'] = version + stored['repos'] = {repo_fmt} + stored['key'] = current_key + elif current_key == stored['key']: + stored['repos'].add(repo_fmt) + + output[pkg] = {} + for pm in selected_pms: + data = pm_versions[pm] + if data['version']: + repos = ', '.join(sorted(data['repos'])) + output[pkg][pm] = f"{data['version']} ({repos})" + else: + output[pkg][pm] = 'Not found' + + print_table(output, ['Package'] + selected_pms, selected_pms, args) + +if __name__ == '__main__': + main() diff --git a/python/dev/codedex/loops.py b/python/dev/codedex/loops.py new file mode 100644 index 0000000..96a3a2d --- /dev/null +++ b/python/dev/codedex/loops.py @@ -0,0 +1,16 @@ +print('BANK OF DEDEDEX') + +pin1 = int(input("Enter your first PIN: ")) + +pin2 = int(input("Enter your PIN again, to confirm: ")) + +if pin1 == pin2: + password = pin1 + +pin = int(input('Enter your PIN: ')) + +while pin != password: + pin = int(input('Incorrect PIN. Enter your PIN again: ')) + +if pin == password: + print('PIN was entered successfully!') diff --git a/python/dev/fonts.py b/python/dev/fonts.py new file mode 100755 index 0000000..ea38443 --- /dev/null +++ b/python/dev/fonts.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 + +import os +import subprocess +from concurrent.futures import ThreadPoolExecutor, as_completed +from colorama import init, Fore, Style +import requests + +# Initialize colorama +init(autoreset=True) + +# List of font repositories +FONT_REPOS = { + "JetBrainsMono": "https://github.com/ryanoasis/nerd-fonts/releases/download/v3.3.0/JetBrainsMono.zip", + "CaskaydiaCove": "https://github.com/ryanoasis/nerd-fonts/releases/download/v3.3.0/CascadiaCode.zip", + # Add more repositories here +} + +def display_menu(options, existing_fonts): + print(Fore.CYAN + "Select Font Repositories to Download:") + for i, option in enumerate(options, 1): + icon = Fore.GREEN + "✓" if option in existing_fonts else Fore.RED + " " + print(f"{i}. {option} {icon}") + print(Fore.YELLOW + "0. Exit") + +def get_user_selection(options): + selected_indices = [] + while True: + try: + choices = input(Fore.YELLOW + "Enter the numbers of your choices separated by spaces (q to quit): ") + if choices.strip().lower() == "q": + break + indices = [int(choice.strip()) - 1 for choice in choices.split() if choice.strip().isdigit()] + for index in indices: + if 0 <= index < len(options): + selected_indices.append(index) + else: + print(Fore.RED + f"Invalid choice: {index + 1}. Please try again.") + except ValueError: + print(Fore.RED + "Invalid input. Please enter numbers separated by spaces.") + return selected_indices + +def download_font(url, download_path): + response = requests.get(url) + with open(download_path, 'wb') as file: + file.write(response.content) + +def clone_repos(selected_repos, base_clone_directory): + with ThreadPoolExecutor(max_workers=4) as executor: + future_to_repo = { + executor.submit(download_font, FONT_REPOS[repo], os.path.join(base_clone_directory, f"{repo}.zip")): repo + for repo in selected_repos + } + for future in as_completed(future_to_repo): + repo = future_to_repo[future] + try: + future.result() + print(Fore.GREEN + f"Successfully downloaded {repo}") + except Exception as e: + print(Fore.RED + f"Failed to download {repo}: {e}") + +def check_existing_fonts(clone_directory): + return {repo for repo in FONT_REPOS if os.path.exists(os.path.join(clone_directory, f"{repo}.zip"))} + +def main(): + base_clone_directory = os.path.expanduser("~/.local/share/fonts/") + os.makedirs(base_clone_directory, exist_ok=True) + existing_fonts = check_existing_fonts(base_clone_directory) + options = list(FONT_REPOS.keys()) + display_menu(options, existing_fonts) + selected_indices = get_user_selection(options) + selected_repos = [options[i] for i in selected_indices if options[i] not in existing_fonts] + clone_repos(selected_repos, base_clone_directory) + +if __name__ == "__main__": + main() diff --git a/python/dev/test.py b/python/dev/test.py new file mode 100644 index 0000000..c8901b6 --- /dev/null +++ b/python/dev/test.py @@ -0,0 +1,5 @@ +from datetime import datetime + +current_year = datetime.now().year + +print(current_year) diff --git a/python/mergefiles.py b/python/mergefiles.py new file mode 100644 index 0000000..e459677 --- /dev/null +++ b/python/mergefiles.py @@ -0,0 +1,42 @@ +import os +from datetime import datetime + +def merge_files(file_paths): + # Dictionary to hold file contents by extension + files_by_extension = {} + + # Read each file and group contents by extension + for file_path in file_paths: + _, ext = os.path.splitext(file_path) + if ext not in files_by_extension: + files_by_extension[ext] = [] + with open(file_path, 'r') as file: + files_by_extension[ext].append(file.read()) + + # Ensure the .old directory exists + old_dir = '.old' + if not os.path.exists(old_dir): + os.makedirs(old_dir) + + # Write merged contents to new files + for ext, contents in files_by_extension.items(): + current_date = datetime.now().strftime("%Y-%m-%d") + merged_file_path = f'{current_date}{ext}' + + # Move existing merged file to .old directory + if os.path.exists(merged_file_path): + os.rename(merged_file_path, os.path.join(old_dir, f'{current_date}{ext}')) + + with open(merged_file_path, 'w') as merged_file: + for content in contents: + merged_file.write(content) + +if __name__ == "__main__": + # Example usage: specify the file paths you want to merge + file_paths = [ + '/test/first.csv', + '/test/second.csv', + '/test/third.csv' + ] + merge_files(file_paths) +