add seed timer & re-org
This commit is contained in:
parent
a3cd2f0fdd
commit
563ad690c2
9 changed files with 131 additions and 0 deletions
48
scripts/bash/adduser.sh
Executable file
48
scripts/bash/adduser.sh
Executable file
|
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
PASSWD_FILE="/etc/squid/passwd"
|
||||
|
||||
# Ensure htpasswd is installed
|
||||
if ! command -v htpasswd &>/dev/null; then
|
||||
echo "❌ 'htpasswd' not found. Please install apache2-utils (Debian/Ubuntu) or httpd-tools (RHEL/CentOS)."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Ensure script is run as root
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo "❌ This script must be run as root."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Prompt for username
|
||||
read -rp "👤 Enter Squid proxy username: " username
|
||||
if [[ -z "$username" ]]; then
|
||||
echo "❌ Username cannot be empty."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create the password file only if it doesn't exist
|
||||
if [[ ! -f "$PASSWD_FILE" ]]; then
|
||||
echo "🔧 Creating new password file at $PASSWD_FILE"
|
||||
htpasswd -c "$PASSWD_FILE" "$username"
|
||||
else
|
||||
# Check if user exists
|
||||
if grep -q "^$username:" "$PASSWD_FILE"; then
|
||||
echo "⚠️ User '$username' already exists."
|
||||
read -rp "🔄 Update password? (y/N): " answer
|
||||
if [[ "$answer" =~ ^[Yy]$ ]]; then
|
||||
htpasswd "$PASSWD_FILE" "$username"
|
||||
else
|
||||
echo "❌ Aborted."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
htpasswd "$PASSWD_FILE" "$username"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Fix permissions
|
||||
chmod 640 "$PASSWD_FILE"
|
||||
chown proxy:proxy "$PASSWD_FILE" 2>/dev/null || chown squid:squid "$PASSWD_FILE" 2>/dev/null
|
||||
|
||||
echo "✅ User '$username' is set up for Squid."
|
||||
38
scripts/bash/dock.sh
Executable file
38
scripts/bash/dock.sh
Executable file
|
|
@ -0,0 +1,38 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Function to check dock size
|
||||
check_dock() {
|
||||
echo "Current Dock tile size:"
|
||||
defaults read com.apple.dock tilesize
|
||||
}
|
||||
|
||||
# Function to reset dock
|
||||
reset_dock() {
|
||||
echo "Resetting Dock to default settings..."
|
||||
defaults delete com.apple.dock tilesize
|
||||
killall Dock
|
||||
echo "Dock has been reset and restarted."
|
||||
}
|
||||
|
||||
# Show usage if no arguments provided
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "Usage: $0 [check|reset]"
|
||||
echo " check - Show current Dock tile size"
|
||||
echo " reset - Reset Dock to default settings"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Process command line arguments
|
||||
case "$1" in
|
||||
"check")
|
||||
check_dock
|
||||
;;
|
||||
"reset")
|
||||
reset_dock
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option: $1"
|
||||
echo "Usage: $0 [check|reset]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
118
scripts/bash/movefiles.sh
Executable file
118
scripts/bash/movefiles.sh
Executable file
|
|
@ -0,0 +1,118 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Default values
|
||||
VERBOSE=false
|
||||
INCLUDE_PART=false
|
||||
|
||||
# Function to display usage
|
||||
usage() {
|
||||
echo "Usage: $0 [options] <search_word> <source_directory> <destination_directory>"
|
||||
echo "Options:"
|
||||
echo " -v, --verbose Show detailed output"
|
||||
echo " -p, --include-part Include files ending in .part (excluded by default)"
|
||||
echo " -h, --help Show this help message"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Parse command line options
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-v|--verbose)
|
||||
VERBOSE=true
|
||||
shift
|
||||
;;
|
||||
-p|--include-part)
|
||||
INCLUDE_PART=true
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Check if we have exactly 3 arguments after options
|
||||
if [ "$#" -ne 3 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
SEARCH_WORD=$1
|
||||
SOURCE_DIR=$2
|
||||
DEST_DIR=$3
|
||||
|
||||
# Validate search word
|
||||
if [ -z "$SEARCH_WORD" ]; then
|
||||
echo "Error: Search word cannot be empty"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Ensure source directory exists
|
||||
if [ ! -d "$SOURCE_DIR" ]; then
|
||||
echo "Error: Source directory '$SOURCE_DIR' does not exist."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Initialize counter
|
||||
moved_count=0
|
||||
|
||||
# Function to process files
|
||||
process_files() {
|
||||
local find_cmd="find \"$SOURCE_DIR\" -maxdepth 1 -type f -iname \"*$SEARCH_WORD*\""
|
||||
|
||||
# Exclude .part files and macOS resource fork files by default
|
||||
if [ "$INCLUDE_PART" = false ]; then
|
||||
find_cmd="$find_cmd -not -name \"*.part\""
|
||||
fi
|
||||
find_cmd="$find_cmd -not -name \"._*\""
|
||||
|
||||
# First, show what would be moved
|
||||
echo "The following files would be moved:"
|
||||
eval "$find_cmd"
|
||||
|
||||
# Count files that would be moved
|
||||
local file_count=$(eval "$find_cmd" | wc -l)
|
||||
|
||||
if [ "$file_count" -eq 0 ]; then
|
||||
echo "No matching files found."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Show what actions will be taken
|
||||
echo
|
||||
if [ ! -d "$DEST_DIR" ]; then
|
||||
echo "The destination directory '$DEST_DIR' will be created."
|
||||
fi
|
||||
echo "Files will be moved to: '$DEST_DIR'"
|
||||
|
||||
# Prompt for confirmation
|
||||
echo -n "Do you want to proceed? (y/n): "
|
||||
read -r response
|
||||
|
||||
if [[ "$response" =~ ^[Yy]$ ]]; then
|
||||
# Create destination directory if needed
|
||||
if [ ! -d "$DEST_DIR" ]; then
|
||||
mkdir -p "$DEST_DIR"
|
||||
fi
|
||||
|
||||
while IFS= read -r file; do
|
||||
if [ "$VERBOSE" = true ]; then
|
||||
echo "Moving: $file"
|
||||
fi
|
||||
if mv "$file" "$DEST_DIR"; then
|
||||
((moved_count++))
|
||||
else
|
||||
echo "Error: Failed to move '$file'" >&2
|
||||
fi
|
||||
done < <(eval "$find_cmd")
|
||||
|
||||
echo "Operation completed. $moved_count file(s) moved to '$DEST_DIR'"
|
||||
else
|
||||
echo "Operation cancelled."
|
||||
fi
|
||||
}
|
||||
|
||||
# Execute the move operation
|
||||
process_files
|
||||
26
scripts/bash/rclone-sync.sh
Executable file
26
scripts/bash/rclone-sync.sh
Executable file
|
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Set timezone to US Eastern (handles both EST and EDT correctly)
|
||||
export TZ="America/New_York"
|
||||
|
||||
# Define source and destination
|
||||
SOURCE="$HOME/files/media"
|
||||
DEST="goji-hetzner:"
|
||||
|
||||
# Create timestamped log file
|
||||
TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S")
|
||||
LOGFILE="$HOME/logs/rclone-sync-$TIMESTAMP.log"
|
||||
LOCKFILE="/tmp/rclone-sync.lock"
|
||||
|
||||
exec 9>"$LOCKFILE"
|
||||
if ! flock -n 9; then
|
||||
echo "rclone sync is already running. exiting...." | tee "$LOGFILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Run rclone and log output to both screen and file using tee (no --log-file!)
|
||||
{
|
||||
echo "=== rclone sync started at $(date) ==="
|
||||
/usr/bin/rclone sync "$SOURCE" "$DEST" --log-level=INFO
|
||||
echo "=== rclone sync finished at $(date) ==="
|
||||
} 2>&1 | tee "$LOGFILE"
|
||||
14
scripts/bash/toggle-metal-hud.sh
Executable file
14
scripts/bash/toggle-metal-hud.sh
Executable file
|
|
@ -0,0 +1,14 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Check if the Metal HUD is currently enabled
|
||||
MTL_STATUS=$(/bin/launchctl getenv MTL_HUD_ENABLED 2>/dev/null)
|
||||
|
||||
if [ "$MTL_STATUS" = "1" ]; then
|
||||
# If enabled, disable it
|
||||
/bin/launchctl unsetenv MTL_HUD_ENABLED
|
||||
echo "Metal HUD disabled"
|
||||
else
|
||||
# If disabled, enable it
|
||||
/bin/launchctl setenv MTL_HUD_ENABLED 1
|
||||
echo "Metal HUD enabled"
|
||||
fi
|
||||
122
scripts/bash/toggle-ota.sh
Executable file
122
scripts/bash/toggle-ota.sh
Executable file
|
|
@ -0,0 +1,122 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# toggle_apple_updates.sh
|
||||
# Toggles Apple OTA update domains in /etc/hosts between blocked and unblocked.
|
||||
|
||||
HOSTS_FILE="/etc/hosts"
|
||||
|
||||
APPLE_DOMAINS=(
|
||||
"swscan.apple.com"
|
||||
"swdownload.apple.com"
|
||||
"swcdn.apple.com"
|
||||
"swdist.apple.com"
|
||||
"appldnld.apple.com"
|
||||
"mesu.apple.com"
|
||||
"gdmf.apple.com"
|
||||
)
|
||||
|
||||
BLOCK_IP="0.0.0.0"
|
||||
SECTION_COMMENT="# Block OTA"
|
||||
|
||||
# ── Colours ──────────────────────────────────────────────────────────────────
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
CYAN='\033[0;36m'
|
||||
BOLD='\033[1m'
|
||||
RESET='\033[0m'
|
||||
|
||||
# ── Banner ────────────────────────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo -e "${BOLD}+----------------------------------------------+${RESET}"
|
||||
echo -e "${BOLD}| Apple OTA Update Toggle Utility |${RESET}"
|
||||
echo -e "${BOLD}+----------------------------------------------+${RESET}"
|
||||
echo ""
|
||||
|
||||
# ── Root warning ──────────────────────────────────────────────────────────────
|
||||
echo -e "${YELLOW}⚠ WARNING: This script modifies ${HOSTS_FILE}.${RESET}"
|
||||
echo -e "${YELLOW} Root (administrator) privileges are required.${RESET}"
|
||||
echo ""
|
||||
|
||||
# ── Authenticate via sudo ─────────────────────────────────────────────────────
|
||||
echo -e "${CYAN}Please enter your password to continue:${RESET}"
|
||||
sudo -v 2>/dev/null
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo -e "${RED}✖ Authentication failed or was cancelled. Exiting.${RESET}"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# ── Detect current state ──────────────────────────────────────────────────────
|
||||
# Check if the first domain is currently blocked (present and uncommented)
|
||||
FIRST_DOMAIN="${APPLE_DOMAINS[0]}"
|
||||
if sudo grep -qE "^${BLOCK_IP}[[:space:]]+${FIRST_DOMAIN}" "${HOSTS_FILE}"; then
|
||||
CURRENT_STATE="blocked"
|
||||
else
|
||||
CURRENT_STATE="unblocked"
|
||||
fi
|
||||
|
||||
CURRENT_STATE_UPPER=$(echo "${CURRENT_STATE}" | tr '[:lower:]' '[:upper:]')
|
||||
echo -e " Current state: ${BOLD}Apple updates are ${CURRENT_STATE_UPPER}${RESET}"
|
||||
echo ""
|
||||
|
||||
# ── Toggle ────────────────────────────────────────────────────────────────────
|
||||
if [[ "${CURRENT_STATE}" == "blocked" ]]; then
|
||||
# ── UNBLOCK: comment out the block section ────────────────────────────────
|
||||
echo -e "${CYAN}→ Unblocking Apple update domains...${RESET}"
|
||||
|
||||
# Comment out the section header and each domain line
|
||||
sudo sed -i '.bak' "s|^${SECTION_COMMENT}$|#${SECTION_COMMENT}|g" "${HOSTS_FILE}"
|
||||
for domain in "${APPLE_DOMAINS[@]}"; do
|
||||
sudo sed -i '.bak' "s|^${BLOCK_IP}[[:space:]][[:space:]]*${domain}|# ${BLOCK_IP} ${domain}|g" "${HOSTS_FILE}"
|
||||
done
|
||||
|
||||
NEW_STATE="UNBLOCKED"
|
||||
STATE_COLOR="${GREEN}"
|
||||
STATE_MSG="Apple software updates are now ${GREEN}${BOLD}ENABLED${RESET}."
|
||||
STATE_DETAIL="Your Mac can reach Apple's update servers normally."
|
||||
|
||||
else
|
||||
# ── BLOCK: uncomment or add the block section ─────────────────────────────
|
||||
echo -e "${CYAN}→ Blocking Apple update domains...${RESET}"
|
||||
|
||||
# Uncomment lines that were previously commented out by this script
|
||||
sudo sed -i '.bak' "s|^#${SECTION_COMMENT}$|${SECTION_COMMENT}|g" "${HOSTS_FILE}"
|
||||
for domain in "${APPLE_DOMAINS[@]}"; do
|
||||
# If the commented-out version exists, uncomment it
|
||||
if sudo grep -qE "^#[[:space:]]*${BLOCK_IP}[[:space:]]+${domain}" "${HOSTS_FILE}"; then
|
||||
sudo sed -i '.bak' "s|^#[[:space:]]*${BLOCK_IP}[[:space:]][[:space:]]*${domain}|${BLOCK_IP} ${domain}|g" "${HOSTS_FILE}"
|
||||
# If the domain isn't present at all, append the block section
|
||||
elif ! sudo grep -qE "${domain}" "${HOSTS_FILE}"; then
|
||||
# Append section header if it doesn't exist
|
||||
if ! sudo grep -q "^${SECTION_COMMENT}$" "${HOSTS_FILE}"; then
|
||||
echo "" | sudo tee -a "${HOSTS_FILE}" > /dev/null
|
||||
echo "${SECTION_COMMENT}" | sudo tee -a "${HOSTS_FILE}" > /dev/null
|
||||
fi
|
||||
echo "${BLOCK_IP} ${domain}" | sudo tee -a "${HOSTS_FILE}" > /dev/null
|
||||
fi
|
||||
done
|
||||
|
||||
NEW_STATE="BLOCKED"
|
||||
STATE_COLOR="${RED}"
|
||||
STATE_MSG="Apple software updates are now ${RED}${BOLD}BLOCKED${RESET}."
|
||||
STATE_DETAIL="Your Mac cannot reach Apple's update servers."
|
||||
fi
|
||||
|
||||
# ── Result ────────────────────────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo -e "${BOLD}+----------------------------------------------+${RESET}"
|
||||
printf "${BOLD}|${RESET} New state: ${STATE_COLOR}%-33s${RESET}${BOLD}|${RESET}\n" "${NEW_STATE}"
|
||||
echo -e "${BOLD}+----------------------------------------------+${RESET}"
|
||||
echo ""
|
||||
echo -e " ${STATE_MSG}"
|
||||
echo -e " ${STATE_DETAIL}"
|
||||
echo ""
|
||||
echo -e " Domains affected:"
|
||||
for domain in "${APPLE_DOMAINS[@]}"; do
|
||||
echo -e " ${STATE_COLOR}•${RESET} ${domain}"
|
||||
done
|
||||
echo ""
|
||||
echo -e " A backup of your previous hosts file was saved as:"
|
||||
echo -e " ${BOLD}${HOSTS_FILE}.bak${RESET}"
|
||||
echo ""
|
||||
100
scripts/bash/update-forgejo.sh
Normal file
100
scripts/bash/update-forgejo.sh
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# ── helpers ────────────────────────────────────────────────────────────────────
|
||||
|
||||
die() { echo "Error: $*" >&2; exit 1; }
|
||||
|
||||
# Returns the latest vX.Y.Z tag for a given X.Y prefix (or overall latest if no prefix)
|
||||
fetch_latest_version() {
|
||||
local prefix="$1" # e.g. "11.0" or "" for absolute latest
|
||||
local tags
|
||||
|
||||
tags=$(curl -fsSL \
|
||||
"https://codeberg.org/api/v1/repos/forgejo/forgejo/tags?limit=50" \
|
||||
2>/dev/null) || die "Could not reach Codeberg API — check your connection."
|
||||
|
||||
# Extract tag names, filter to release tags (vX.Y.Z, no pre-release suffix)
|
||||
local versions
|
||||
versions=$(echo "$tags" | grep -oP '"name"\s*:\s*"\Kv[0-9]+\.[0-9]+\.[0-9]+"' \
|
||||
| tr -d '"' | sort -V)
|
||||
|
||||
if [[ -z "$prefix" ]]; then
|
||||
echo "$versions" | tail -1
|
||||
else
|
||||
echo "$versions" | grep "^v${prefix}\." | tail -1
|
||||
fi
|
||||
}
|
||||
|
||||
# ── detect architecture ────────────────────────────────────────────────────────
|
||||
|
||||
case "$(uname -m)" in
|
||||
x86_64) ARCH="amd64" ;;
|
||||
aarch64) ARCH="arm64" ;;
|
||||
armv7l) ARCH="arm-6" ;;
|
||||
*) die "Unsupported architecture: $(uname -m)" ;;
|
||||
esac
|
||||
|
||||
# ── version prompt ─────────────────────────────────────────────────────────────
|
||||
|
||||
echo "Fetching latest Forgejo release…"
|
||||
LATEST_OVERALL=$(fetch_latest_version "")
|
||||
LATEST_OVERALL="${LATEST_OVERALL#v}" # strip leading 'v'
|
||||
|
||||
echo
|
||||
echo "Latest available release: ${LATEST_OVERALL}"
|
||||
echo
|
||||
read -rp "Version to install [MAJOR.MINOR or MAJOR.MINOR.PATCH, Enter = ${LATEST_OVERALL}]: " INPUT
|
||||
INPUT="${INPUT:-$LATEST_OVERALL}"
|
||||
|
||||
# Normalise: strip a leading 'v' if the user typed one
|
||||
INPUT="${INPUT#v}"
|
||||
|
||||
# Determine if the user gave a full version (X.Y.Z) or a partial one (X.Y)
|
||||
if [[ "$INPUT" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
# Full version supplied — use as-is
|
||||
VERSION="$INPUT"
|
||||
elif [[ "$INPUT" =~ ^[0-9]+\.[0-9]+$ ]]; then
|
||||
# Partial (X.Y) — resolve the latest patch on that line
|
||||
echo "Resolving latest patch for ${INPUT}.x…"
|
||||
RESOLVED=$(fetch_latest_version "$INPUT")
|
||||
[[ -z "$RESOLVED" ]] && die "No releases found for ${INPUT}.x"
|
||||
VERSION="${RESOLVED#v}"
|
||||
echo "→ Using ${VERSION}"
|
||||
else
|
||||
die "Unrecognised version format '${INPUT}'. Use X.Y or X.Y.Z"
|
||||
fi
|
||||
|
||||
# ── confirm ────────────────────────────────────────────────────────────────────
|
||||
|
||||
BINARY="forgejo-${VERSION}-linux-${ARCH}"
|
||||
echo
|
||||
echo " Version : ${VERSION}"
|
||||
echo " Binary : ${BINARY}"
|
||||
echo " Arch : ${ARCH}"
|
||||
echo
|
||||
read -rp "Proceed with installation? [Y/n]: " CONFIRM
|
||||
CONFIRM="${CONFIRM:-Y}"
|
||||
[[ "$CONFIRM" =~ ^[Yy]$ ]] || { echo "Aborted."; exit 0; }
|
||||
|
||||
# ── download & install ─────────────────────────────────────────────────────────
|
||||
|
||||
URL="https://codeberg.org/forgejo/forgejo/releases/download/v${VERSION}/${BINARY}"
|
||||
echo
|
||||
echo "Downloading ${URL}…"
|
||||
wget --show-progress -q "$URL" || die "Download failed — is v${VERSION} a valid release?"
|
||||
|
||||
chmod +x "$BINARY"
|
||||
|
||||
echo "Stopping forgejo…"
|
||||
systemctl stop forgejo
|
||||
|
||||
echo "Installing binary…"
|
||||
cp "$BINARY" /usr/local/bin/forgejo
|
||||
rm -f "$BINARY" # clean up the downloaded file
|
||||
|
||||
echo "Starting forgejo…"
|
||||
systemctl start forgejo
|
||||
|
||||
echo
|
||||
echo "Done — Forgejo ${VERSION} is running."
|
||||
Loading…
Add table
Add a link
Reference in a new issue