More
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
__pycache__/
|
||||||
188
build.sh
188
build.sh
@@ -1,115 +1,141 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
ORIG_PWD=$(pwd)
|
|
||||||
|
|
||||||
# Elevate to root if needed
|
# === Colors ===
|
||||||
|
RED="\033[1;31m"
|
||||||
|
GREEN="\033[1;32m"
|
||||||
|
YELLOW="\033[1;33m"
|
||||||
|
BLUE="\033[1;34m"
|
||||||
|
MAGENTA="\033[1;35m"
|
||||||
|
CYAN="\033[1;36m"
|
||||||
|
RESET="\033[0m"
|
||||||
|
|
||||||
|
log_info() { printf "${CYAN}[*]${RESET} %s\n" "$1"; }
|
||||||
|
log_success() { printf "${GREEN}[✓]${RESET} %s\n" "$1"; }
|
||||||
|
log_warn() { printf "${YELLOW}[!]${RESET} %s\n" "$1"; }
|
||||||
|
log_error() { printf "${RED}[✗]${RESET} %s\n" "$1"; }
|
||||||
|
|
||||||
|
ORIG_PWD=$(pwd)
|
||||||
|
ORIG_USER=$(logname)
|
||||||
|
ORIG_HOME=$(getent passwd "$ORIG_USER" | cut -d: -f6)
|
||||||
|
|
||||||
|
# === Elevate to root if needed ===
|
||||||
if [ "$(id -u)" -ne 0 ]; then
|
if [ "$(id -u)" -ne 0 ]; then
|
||||||
exec sudo "$0" "$@"
|
exec sudo "$0" "$@"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ORIG_USER=$(logname)
|
# === Package groups ===
|
||||||
ORIG_HOME=$(getent passwd "$ORIG_USER" | cut -d: -f6)
|
|
||||||
|
|
||||||
# === Update system ===
|
|
||||||
echo "Updating system..."
|
|
||||||
pacman -Syu --noconfirm
|
|
||||||
|
|
||||||
# === Essential tools ===
|
|
||||||
ESSENTIAL_PACKAGES="
|
ESSENTIAL_PACKAGES="
|
||||||
python3
|
base-devel python3 vim neovim ranger firefox
|
||||||
vim
|
|
||||||
neovim
|
|
||||||
ranger
|
|
||||||
firefox
|
|
||||||
"
|
"
|
||||||
|
|
||||||
# === Display manager ===
|
|
||||||
DISPLAY_MANAGER="
|
DISPLAY_MANAGER="
|
||||||
sddm
|
sddm qt5-graphicaleffects
|
||||||
"
|
"
|
||||||
|
|
||||||
# === Wayland & Hyprland environment ===
|
|
||||||
WAYLAND_ENVIRONMENT="
|
WAYLAND_ENVIRONMENT="
|
||||||
hyprland
|
hyprland hyprpaper waybar kitty wofi mako libnotify grim slurp
|
||||||
hyprpaper
|
wl-clipboard wl-clip-persist wayland-utils xorg-xwayland
|
||||||
waybar
|
|
||||||
kitty
|
|
||||||
wofi
|
|
||||||
mako
|
|
||||||
libnotify
|
|
||||||
grim
|
|
||||||
slurp
|
|
||||||
wl-clipboard
|
|
||||||
wayland-utils
|
|
||||||
xorg-xwayland
|
|
||||||
"
|
"
|
||||||
|
|
||||||
# === Audio ===
|
|
||||||
AUDIO_PACKAGES="
|
AUDIO_PACKAGES="
|
||||||
pipewire
|
pipewire wireplumber pipewire-pulse pavucontrol
|
||||||
wireplumber
|
|
||||||
pipewire-pulse
|
|
||||||
pavucontrol
|
|
||||||
"
|
"
|
||||||
|
|
||||||
# === Fonts & theming ===
|
|
||||||
FONTS_AND_THEME="
|
FONTS_AND_THEME="
|
||||||
otf-font-awesome
|
otf-font-awesome noto-fonts noto-fonts-cjk ttf-jetbrains-mono orchis-theme
|
||||||
noto-fonts
|
|
||||||
noto-fonts-cjk
|
|
||||||
ttf-jetbrains-mono
|
|
||||||
orchis-theme
|
|
||||||
"
|
"
|
||||||
|
|
||||||
# === Multimedia ===
|
|
||||||
MEDIA_PACKAGES="
|
MEDIA_PACKAGES="
|
||||||
mpv
|
mpv eog ffmpeg
|
||||||
eog
|
|
||||||
ffmpeg
|
|
||||||
"
|
"
|
||||||
|
|
||||||
# === Install all packages ===
|
# === Functions ===
|
||||||
echo "Installing packages..."
|
update_system() {
|
||||||
pacman -S --noconfirm --needed \
|
log_info "Updating system..."
|
||||||
$ESSENTIAL_PACKAGES \
|
pacman -Syu --noconfirm
|
||||||
$DISPLAY_MANAGER \
|
}
|
||||||
$WAYLAND_ENVIRONMENT \
|
|
||||||
$AUDIO_PACKAGES \
|
|
||||||
$FONTS_AND_THEME \
|
|
||||||
$MEDIA_PACKAGES
|
|
||||||
|
|
||||||
# === Enable display manager ===
|
install_packages() {
|
||||||
echo "Enabling SDDM..."
|
log_info "Installing packages..."
|
||||||
systemctl enable sddm
|
pacman -S --noconfirm --needed \
|
||||||
# === Apply GTK settings for theme and color scheme ===
|
$ESSENTIAL_PACKAGES \
|
||||||
echo "Applying GTK settings..."
|
$DISPLAY_MANAGER \
|
||||||
|
$WAYLAND_ENVIRONMENT \
|
||||||
|
$AUDIO_PACKAGES \
|
||||||
|
$FONTS_AND_THEME \
|
||||||
|
$MEDIA_PACKAGES
|
||||||
|
}
|
||||||
|
|
||||||
# Extract DBus address from the user's environment
|
apply_gtk_settings() {
|
||||||
USER_DBUS_ENV=$(sudo -u "$ORIG_USER" -- dbus-launch)
|
log_info "Applying GTK settings..."
|
||||||
eval "$USER_DBUS_ENV"
|
export XDG_RUNTIME_DIR="/run/user/$(id -u "$ORIG_USER")"
|
||||||
|
DBUS_ADDR="unix:path=${XDG_RUNTIME_DIR}/bus"
|
||||||
|
|
||||||
export DBUS_SESSION_BUS_ADDRESS
|
for setting in \
|
||||||
export XDG_RUNTIME_DIR="/run/user/$(id -u $ORIG_USER)"
|
"org.gnome.desktop.interface gtk-theme Orchis-Dark-Compact" \
|
||||||
|
"org.gnome.desktop.interface icon-theme Orchis-Dark-Compact" \
|
||||||
|
"org.gnome.desktop.interface color-scheme prefer-dark"
|
||||||
|
do
|
||||||
|
if sudo -u "$ORIG_USER" \
|
||||||
|
DBUS_SESSION_BUS_ADDRESS="$DBUS_ADDR" \
|
||||||
|
gsettings set $setting; then
|
||||||
|
log_success "Set $setting"
|
||||||
|
else
|
||||||
|
log_warn "Failed to set $setting"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
sudo -u "$ORIG_USER" DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS" \
|
enable_sddm() {
|
||||||
XDG_RUNTIME_DIR="$XDG_RUNTIME_DIR" \
|
log_info "Enabling SDDM..."
|
||||||
gsettings set org.gnome.desktop.interface gtk-theme "Orchis-Dark-Compact"
|
systemctl enable sddm
|
||||||
|
}
|
||||||
|
|
||||||
sudo -u "$ORIG_USER" DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS" \
|
install_sddm_theme() {
|
||||||
XDG_RUNTIME_DIR="$XDG_RUNTIME_DIR" \
|
log_info "Installing SDDM theme..."
|
||||||
gsettings set org.gnome.desktop.interface icon-theme "Orchis-Dark-Compact"
|
if pacman -Q where-is-my-sddm-theme-git >/dev/null 2>&1; then
|
||||||
|
log_success "SDDM theme already installed."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
sudo -u "$ORIG_USER" DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS" \
|
sudo -u "$ORIG_USER" mkdir -p "$ORIG_HOME/Repositories"
|
||||||
XDG_RUNTIME_DIR="$XDG_RUNTIME_DIR" \
|
cd "$ORIG_HOME/Repositories"
|
||||||
gsettings set org.gnome.desktop.interface color-scheme "prefer-dark"
|
|
||||||
|
|
||||||
echo "GTK settings applied successfully."
|
if [ ! -d "where-is-my-sddm-theme" ]; then
|
||||||
|
sudo -u "$ORIG_USER" git clone https://aur.archlinux.org/where-is-my-sddm-theme-git.git where-is-my-sddm-theme
|
||||||
|
else
|
||||||
|
log_warn "Theme repo already exists, skipping clone."
|
||||||
|
fi
|
||||||
|
|
||||||
# === Run dotfiles setup ===
|
cd "$ORIG_HOME/Repositories/where-is-my-sddm-theme"
|
||||||
echo "Running dotfiles setup as $ORIG_USER..."
|
sudo -u "$ORIG_USER" makepkg -si --noconfirm
|
||||||
cd "$ORIG_PWD" || exit 1
|
}
|
||||||
sudo -u "$ORIG_USER" HOME="$ORIG_HOME" python3 setup.py
|
|
||||||
sudo -E -u "$ORIG_USER" HOME="$ORIG_HOME" mkdir -p "$ORIG_HOME/Downloads" "$ORIG_HOME/Documents" "$ORIG_HOME/Pictures" "$ORIG_HOME/Videos" "$ORIG_HOME/Repositories"
|
|
||||||
|
|
||||||
echo "Dotfiles installed successfully."
|
run_dotfiles_setup() {
|
||||||
|
log_info "Running dotfiles setup..."
|
||||||
|
cd "$ORIG_PWD"
|
||||||
|
|
||||||
|
[ -f "setup_user.py" ] && sudo -u "$ORIG_USER" HOME="$ORIG_HOME" python3 setup_user.py \
|
||||||
|
|| log_warn "setup_user.py not found."
|
||||||
|
|
||||||
|
[ -f "setup_system.py" ] && python3 setup_system.py \
|
||||||
|
|| log_warn "setup_system.py not found."
|
||||||
|
|
||||||
|
sudo -u "$ORIG_USER" mkdir -p \
|
||||||
|
"$ORIG_HOME/Downloads" \
|
||||||
|
"$ORIG_HOME/Documents" \
|
||||||
|
"$ORIG_HOME/Pictures" \
|
||||||
|
"$ORIG_HOME/Videos" \
|
||||||
|
"$ORIG_HOME/Repositories"
|
||||||
|
}
|
||||||
|
|
||||||
|
# === Main flow ===
|
||||||
|
update_system
|
||||||
|
install_packages
|
||||||
|
apply_gtk_settings
|
||||||
|
enable_sddm
|
||||||
|
install_sddm_theme
|
||||||
|
run_dotfiles_setup
|
||||||
|
|
||||||
|
log_success "Setup completed successfully."
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ $screenshot = grim -g "$(slurp -d)" - | wl-copy
|
|||||||
#################
|
#################
|
||||||
|
|
||||||
# Autostart necessary processes (like notifications daemons, status bars, etc.)
|
# Autostart necessary processes (like notifications daemons, status bars, etc.)
|
||||||
exec-once=waybar & hyprpaper
|
exec-once=waybar & hyprpaper & wl-clip-persist --clipboard both & mako
|
||||||
# & mako --config=$HOME/.config/mako/config
|
# & mako --config=$HOME/.config/mako/config
|
||||||
|
|
||||||
|
|
||||||
25
home/Documents/bookmarks.html
Normal file
25
home/Documents/bookmarks.html
Normal file
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 27 MiB After Width: | Height: | Size: 27 MiB |
77
setup.py
77
setup.py
@@ -1,77 +0,0 @@
|
|||||||
import os
|
|
||||||
import shutil
|
|
||||||
|
|
||||||
SRC_DIR = "src"
|
|
||||||
HOME_DIR = os.path.expanduser("~")
|
|
||||||
|
|
||||||
CHOICES = {
|
|
||||||
'.config/hypr/monitors.conf': ['.config/hypr/monitors-1.conf', '.config/hypr/monitors-2.conf']
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def ask_override(path):
|
|
||||||
resp = input(f"'{path}' already exists. Override? (Y/N): ").strip().lower()
|
|
||||||
return resp == 'y'
|
|
||||||
|
|
||||||
|
|
||||||
def choice_files(src_root, dst_root, choices_map, override_all=False):
|
|
||||||
for final_name, options in choices_map.items():
|
|
||||||
existing_options = [f for f in options if os.path.exists(os.path.join(src_root, f))]
|
|
||||||
if not existing_options:
|
|
||||||
print(f"No source file found among options for {final_name}. Skipping.")
|
|
||||||
continue
|
|
||||||
|
|
||||||
if len(existing_options) == 1:
|
|
||||||
chosen = existing_options[0]
|
|
||||||
else:
|
|
||||||
print(f"Choose which file to copy as '{final_name}':")
|
|
||||||
for idx, opt in enumerate(existing_options, 1):
|
|
||||||
print(f"{idx}: {opt}")
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
choice_idx = int(input(f"Enter number (1-{len(existing_options)}): "))
|
|
||||||
if 1 <= choice_idx <= len(existing_options):
|
|
||||||
chosen = existing_options[choice_idx - 1]
|
|
||||||
break
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
print("Invalid choice, try again.")
|
|
||||||
|
|
||||||
src_file = os.path.join(src_root, chosen)
|
|
||||||
dst_file = os.path.join(dst_root, final_name)
|
|
||||||
|
|
||||||
if os.path.exists(dst_file):
|
|
||||||
if not override_all and not ask_override(dst_file):
|
|
||||||
print(f"Skipped overriding {dst_file}")
|
|
||||||
continue
|
|
||||||
|
|
||||||
shutil.copy2(src_file, dst_file)
|
|
||||||
print(f"Copied {chosen} -> {final_name}")
|
|
||||||
|
|
||||||
def copy_with_structure(src_root, dst_root, override_all=False):
|
|
||||||
for root, dirs, files in os.walk(src_root):
|
|
||||||
rel_path = os.path.relpath(root, src_root)
|
|
||||||
target_dir = os.path.join(dst_root, rel_path)
|
|
||||||
|
|
||||||
os.makedirs(target_dir, exist_ok=True)
|
|
||||||
|
|
||||||
for file in files:
|
|
||||||
src_file = os.path.join(root, file)
|
|
||||||
dst_file = os.path.join(target_dir, file)
|
|
||||||
|
|
||||||
if os.path.exists(dst_file):
|
|
||||||
if not override_all and not ask_override(dst_file):
|
|
||||||
continue
|
|
||||||
|
|
||||||
shutil.copy2(src_file, dst_file)
|
|
||||||
print(f"Copied: {src_file} -> {dst_file}")
|
|
||||||
|
|
||||||
def main():
|
|
||||||
override_all = input('Override all existing files? (Y/N): ').strip().lower() == 'y'
|
|
||||||
|
|
||||||
choice_files(SRC_DIR, HOME_DIR, CHOICES, override_all)
|
|
||||||
|
|
||||||
copy_with_structure(SRC_DIR, HOME_DIR, override_all)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
17
setup_system.py
Normal file
17
setup_system.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import sys
|
||||||
|
from utils import choice_files, copy_with_structure, require_root, log_info, log_error, CYAN, RESET
|
||||||
|
|
||||||
|
SRC_DIR = "system_files"
|
||||||
|
DST_DIR = "/"
|
||||||
|
CHOICES = {}
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
require_root()
|
||||||
|
override_all = input(f"{CYAN}Override all existing system files? (Y/N): {RESET}").strip().lower() == 'y'
|
||||||
|
choice_files(SRC_DIR, DST_DIR, CHOICES, override_all)
|
||||||
|
copy_with_structure(SRC_DIR, DST_DIR, override_all)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
22
setup_user.py
Normal file
22
setup_user.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import os
|
||||||
|
from utils import choice_files, copy_with_structure, CYAN, RESET
|
||||||
|
|
||||||
|
|
||||||
|
SRC_DIR = "home"
|
||||||
|
HOME_DIR = os.path.expanduser("~")
|
||||||
|
CHOICES = {
|
||||||
|
'.config/hypr/monitors.conf': [
|
||||||
|
'.config/hypr/monitors-1.conf',
|
||||||
|
'.config/hypr/monitors-2.conf'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
override_all = input(f"{CYAN}Override all existing files for user (mainly .config)? (Y/N): {RESET}").strip().lower() == 'y'
|
||||||
|
choice_files(SRC_DIR, HOME_DIR, CHOICES, override_all)
|
||||||
|
copy_with_structure(SRC_DIR, HOME_DIR, override_all)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
139
system_files/usr/lib/sddm/sddm.conf.d/default.conf
Normal file
139
system_files/usr/lib/sddm/sddm.conf.d/default.conf
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
[Autologin]
|
||||||
|
# Whether sddm should automatically log back into sessions when they exit
|
||||||
|
Relogin=false
|
||||||
|
|
||||||
|
# Name of session file for autologin session (if empty try last logged in)
|
||||||
|
Session=
|
||||||
|
|
||||||
|
# Username for autologin session
|
||||||
|
User=
|
||||||
|
|
||||||
|
|
||||||
|
[General]
|
||||||
|
# Which display server should be used.
|
||||||
|
# Valid values are: x11, x11-user, wayland. Wayland support is experimental
|
||||||
|
DisplayServer=x11
|
||||||
|
|
||||||
|
# Comma-separated list of environment variables to be set
|
||||||
|
GreeterEnvironment=
|
||||||
|
|
||||||
|
# Halt command
|
||||||
|
HaltCommand=/usr/bin/systemctl poweroff
|
||||||
|
|
||||||
|
# Input method module
|
||||||
|
InputMethod=
|
||||||
|
|
||||||
|
# Comma-separated list of Linux namespaces for user session to enter
|
||||||
|
Namespaces=
|
||||||
|
|
||||||
|
# Initial NumLock state. Can be on, off or none.
|
||||||
|
# If property is set to none, numlock won't be changed
|
||||||
|
# NOTE: Currently ignored if autologin is enabled.
|
||||||
|
Numlock=none
|
||||||
|
|
||||||
|
# Reboot command
|
||||||
|
RebootCommand=/usr/bin/systemctl reboot
|
||||||
|
|
||||||
|
|
||||||
|
[Theme]
|
||||||
|
# Current theme name
|
||||||
|
Current=where_is_my_sddm_theme
|
||||||
|
|
||||||
|
# Cursor size used in the greeter
|
||||||
|
CursorSize=
|
||||||
|
|
||||||
|
# Cursor theme used in the greeter
|
||||||
|
CursorTheme=
|
||||||
|
|
||||||
|
# Number of users to use as threshold
|
||||||
|
# above which avatars are disabled
|
||||||
|
# unless explicitly enabled with EnableAvatars
|
||||||
|
DisableAvatarsThreshold=7
|
||||||
|
|
||||||
|
# Enable display of custom user avatars
|
||||||
|
EnableAvatars=true
|
||||||
|
|
||||||
|
# Global directory for user avatars
|
||||||
|
# The files should be named <username>.face.icon
|
||||||
|
FacesDir=/usr/share/sddm/faces
|
||||||
|
|
||||||
|
# Font used in the greeter
|
||||||
|
Font=
|
||||||
|
|
||||||
|
# Theme directory path
|
||||||
|
ThemeDir=/usr/share/sddm/themes
|
||||||
|
|
||||||
|
|
||||||
|
[Users]
|
||||||
|
# Default $PATH for logged in users
|
||||||
|
DefaultPath=/usr/local/sbin:/usr/local/bin:/usr/bin
|
||||||
|
|
||||||
|
# Comma-separated list of shells.
|
||||||
|
# Users with these shells as their default won't be listed
|
||||||
|
HideShells=
|
||||||
|
|
||||||
|
# Comma-separated list of users that should not be listed
|
||||||
|
HideUsers=
|
||||||
|
|
||||||
|
# Maximum user id for displayed users
|
||||||
|
MaximumUid=60513
|
||||||
|
|
||||||
|
# Minimum user id for displayed users
|
||||||
|
MinimumUid=1000
|
||||||
|
|
||||||
|
# Remember the session of the last successfully logged in user
|
||||||
|
RememberLastSession=true
|
||||||
|
|
||||||
|
# Remember the last successfully logged in user
|
||||||
|
RememberLastUser=true
|
||||||
|
|
||||||
|
# When logging in as the same user twice, restore the original session, rather than create a new one
|
||||||
|
ReuseSession=true
|
||||||
|
|
||||||
|
|
||||||
|
[Wayland]
|
||||||
|
# Path of the Wayland compositor to execute when starting the greeter
|
||||||
|
CompositorCommand=weston --shell=kiosk
|
||||||
|
|
||||||
|
# Enable Qt's automatic high-DPI scaling
|
||||||
|
EnableHiDPI=true
|
||||||
|
|
||||||
|
# Path to a script to execute when starting the desktop session
|
||||||
|
SessionCommand=/usr/share/sddm/scripts/wayland-session
|
||||||
|
|
||||||
|
# Comma-separated list of directories containing available Wayland sessions
|
||||||
|
SessionDir=/usr/local/share/wayland-sessions,/usr/share/wayland-sessions
|
||||||
|
|
||||||
|
# Path to the user session log file
|
||||||
|
SessionLogFile=.local/share/sddm/wayland-session.log
|
||||||
|
|
||||||
|
|
||||||
|
[X11]
|
||||||
|
# Path to a script to execute when starting the display server
|
||||||
|
DisplayCommand=/usr/share/sddm/scripts/Xsetup
|
||||||
|
|
||||||
|
# Path to a script to execute when stopping the display server
|
||||||
|
DisplayStopCommand=/usr/share/sddm/scripts/Xstop
|
||||||
|
|
||||||
|
# Enable Qt's automatic high-DPI scaling
|
||||||
|
EnableHiDPI=true
|
||||||
|
|
||||||
|
# Arguments passed to the X server invocation
|
||||||
|
ServerArguments=-nolisten tcp
|
||||||
|
|
||||||
|
# Path to X server binary
|
||||||
|
ServerPath=/usr/bin/X
|
||||||
|
|
||||||
|
# Path to a script to execute when starting the desktop session
|
||||||
|
SessionCommand=/usr/share/sddm/scripts/Xsession
|
||||||
|
|
||||||
|
# Comma-separated list of directories containing available X sessions
|
||||||
|
SessionDir=/usr/local/share/xsessions,/usr/share/xsessions
|
||||||
|
|
||||||
|
# Path to the user session log file
|
||||||
|
SessionLogFile=.local/share/sddm/xorg-session.log
|
||||||
|
|
||||||
|
# Path to Xephyr binary
|
||||||
|
XephyrPath=/usr/bin/Xephyr
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
[General]
|
||||||
|
# Password mask character
|
||||||
|
passwordCharacter=*
|
||||||
|
# Mask password characters or not ("true" or "false")
|
||||||
|
passwordMask=true
|
||||||
|
# value "1" is all display width, "0.5" is a half of display width etc.
|
||||||
|
passwordInputWidth=0.5
|
||||||
|
# Background color of password input
|
||||||
|
passwordInputBackground=
|
||||||
|
# Radius of password input corners
|
||||||
|
passwordInputRadius=
|
||||||
|
# Width of the border for the password input
|
||||||
|
passwordInputBorderWidth=0
|
||||||
|
# Border color for the password input
|
||||||
|
passwordInputBorderColor=
|
||||||
|
# "true" for visible cursor, "false"
|
||||||
|
passwordInputCursorVisible=true
|
||||||
|
# Font size of password (in points)
|
||||||
|
passwordFontSize=96
|
||||||
|
passwordCursorColor=random
|
||||||
|
passwordTextColor=
|
||||||
|
# Allow blank password (e.g., if authentication is done by another PAM module)
|
||||||
|
passwordAllowEmpty=false
|
||||||
|
|
||||||
|
# Radius of the border which is displayed upon wrong authentication attempt
|
||||||
|
wrongPasswordBorderRadius=
|
||||||
|
# Color of the border which is displayed upon wrong authentication attempt
|
||||||
|
wrongPasswordBorderColor=
|
||||||
|
|
||||||
|
# Enable or disable cursor blink animation ("true" or "false")
|
||||||
|
cursorBlinkAnimation=true
|
||||||
|
|
||||||
|
# Show or not sessions choose label
|
||||||
|
showSessionsByDefault=false
|
||||||
|
# Font size of sessions choose label (in points).
|
||||||
|
sessionsFontSize=24
|
||||||
|
|
||||||
|
# Show or not users choose label
|
||||||
|
showUsersByDefault=false
|
||||||
|
# Font size of users choose label (in points)
|
||||||
|
usersFontSize=48
|
||||||
|
# Show user real name on label by default
|
||||||
|
showUserRealNameByDefault=true
|
||||||
|
|
||||||
|
# Path to background image
|
||||||
|
background=
|
||||||
|
# Or use just one color
|
||||||
|
backgroundFill=#000000
|
||||||
|
# Fill mode for image background
|
||||||
|
# Value must be on of: aspect, fill, tile, pad
|
||||||
|
backgroundFillMode=aspect
|
||||||
|
|
||||||
|
# Default text color for all labels
|
||||||
|
basicTextColor=#ffffff
|
||||||
|
|
||||||
|
# Blur radius for background image
|
||||||
|
blurRadius=0
|
||||||
|
|
||||||
|
# Hide cursor
|
||||||
|
hideCursor=false
|
||||||
|
|
||||||
|
# Default font
|
||||||
|
font=monospace
|
||||||
|
|
||||||
|
# Font of help message
|
||||||
|
helpFont=monospace
|
||||||
|
# Font size of help message (in points)
|
||||||
|
helpFontSize=18
|
||||||
83
utils.py
Normal file
83
utils.py
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
RED = "\033[1;31m"
|
||||||
|
GREEN = "\033[1;32m"
|
||||||
|
YELLOW = "\033[1;33m"
|
||||||
|
CYAN = "\033[1;36m"
|
||||||
|
RESET = "\033[0m"
|
||||||
|
|
||||||
|
|
||||||
|
def log_info(msg): print(f"{CYAN}[*]{RESET} {msg}")
|
||||||
|
def log_success(msg): print(f"{GREEN}[✓]{RESET} {msg}")
|
||||||
|
def log_warn(msg): print(f"{YELLOW}[!]{RESET} {msg}")
|
||||||
|
def log_error(msg): print(f"{RED}[✗]{RESET} {msg}")
|
||||||
|
|
||||||
|
|
||||||
|
def ask_override(path):
|
||||||
|
resp = input(f"{YELLOW}'{path}' already exists. Override? (Y/N): {RESET}").strip().lower()
|
||||||
|
return resp == 'y'
|
||||||
|
|
||||||
|
|
||||||
|
def choice_files(src_root, dst_root, choices_map, override_all=False):
|
||||||
|
for final_name, options in choices_map.items():
|
||||||
|
existing_options = [
|
||||||
|
f for f in options
|
||||||
|
if os.path.exists(os.path.join(src_root, f.lstrip('/')))
|
||||||
|
]
|
||||||
|
if not existing_options:
|
||||||
|
log_warn(f"No source file found among options for {final_name}. Skipping.")
|
||||||
|
continue
|
||||||
|
|
||||||
|
if len(existing_options) == 1:
|
||||||
|
chosen = existing_options[0]
|
||||||
|
else:
|
||||||
|
log_info(f"Choose which file to copy as '{final_name}':")
|
||||||
|
for idx, opt in enumerate(existing_options, 1):
|
||||||
|
print(f"{idx}: {opt}")
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
choice_idx = int(input(f"{CYAN}Enter number (1-{len(existing_options)}): {RESET}"))
|
||||||
|
if 1 <= choice_idx <= len(existing_options):
|
||||||
|
chosen = existing_options[choice_idx - 1]
|
||||||
|
break
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
log_warn("Invalid choice, try again.")
|
||||||
|
|
||||||
|
src_file = os.path.join(src_root, chosen.lstrip('/'))
|
||||||
|
dst_file = os.path.join(dst_root, final_name.lstrip('/'))
|
||||||
|
|
||||||
|
if os.path.exists(dst_file):
|
||||||
|
if not override_all and not ask_override(dst_file):
|
||||||
|
log_warn(f"Skipped overriding {dst_file}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
shutil.copy2(src_file, dst_file)
|
||||||
|
log_success(f"Copied {chosen} -> {final_name}")
|
||||||
|
|
||||||
|
def copy_with_structure(src_root, dst_root, override_all=False):
|
||||||
|
for root, dirs, files in os.walk(src_root):
|
||||||
|
rel_path = os.path.relpath(root, src_root)
|
||||||
|
target_dir = os.path.join(dst_root, rel_path) if rel_path != '.' else dst_root
|
||||||
|
|
||||||
|
os.makedirs(target_dir, exist_ok=True)
|
||||||
|
|
||||||
|
for file in files:
|
||||||
|
src_file = os.path.join(root, file)
|
||||||
|
dst_file = os.path.join(target_dir, file)
|
||||||
|
|
||||||
|
if os.path.exists(dst_file):
|
||||||
|
if not override_all and not ask_override(dst_file):
|
||||||
|
log_warn(f"Skipped overriding {dst_file}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
shutil.copy2(src_file, dst_file)
|
||||||
|
log_success(f"Copied: {src_file} -> {dst_file}")
|
||||||
|
|
||||||
|
def require_root():
|
||||||
|
if os.geteuid() != 0:
|
||||||
|
log_error("This script must be run as root (sudo). Exiting.")
|
||||||
|
sys.exit(1)
|
||||||
Reference in New Issue
Block a user