mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-07-04 16:23:04 +02:00
* Initial plan * Add bachelor thesis work tracker system - core implementation Co-authored-by: kuhyx <147418882+kuhyx@users.noreply.github.com> * Add status script and improve installer for thesis tracker Co-authored-by: kuhyx <147418882+kuhyx@users.noreply.github.com> * Security improvements: fix sourcing, temp files, validation, and error handling Co-authored-by: kuhyx <147418882+kuhyx@users.noreply.github.com> * Update README to clarify bachelor vs master's thesis naming Co-authored-by: kuhyx <147418882+kuhyx@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: kuhyx <147418882+kuhyx@users.noreply.github.com>
366 lines
12 KiB
Bash
Executable File
366 lines
12 KiB
Bash
Executable File
#!/bin/bash
|
|
# Bachelor Thesis Work Tracker - One-Shot Installer
|
|
#
|
|
# This script installs a system that:
|
|
# 1. Monitors active windows for thesis-related work (Unreal Engine, Unity, Nvidia Omniverse, VS Code with specific repo)
|
|
# 2. Tracks accumulated work time with protection against tampering
|
|
# 3. Blocks Steam and other distractions via /etc/hosts until work quota is met
|
|
# 4. Provides psychological friction against circumvention
|
|
#
|
|
# The system is designed to be as hard to circumvent as possible:
|
|
# - State files are immutable (chattr +i)
|
|
# - Runs as a systemd service that auto-restarts
|
|
# - Integrated with hosts guard system
|
|
# - Protected against easy time manipulation
|
|
#
|
|
# Usage:
|
|
# sudo ./setup_thesis_work_tracker.sh [options]
|
|
#
|
|
# Options:
|
|
# --work-quota MINUTES Set required work time in minutes (default: 120 = 2 hours)
|
|
# --decay-rate MINUTES Set decay rate per hour of distraction usage (default: 30)
|
|
# --vscode-repo NAME Set required VS Code repository name (default: praca_magisterska)
|
|
# --dry-run Show what would be done without making changes
|
|
# --uninstall Remove the thesis work tracker system
|
|
# -h|--help Show this help
|
|
#
|
|
# Exit codes:
|
|
# 0 = success
|
|
# 1 = general failure
|
|
# 2 = argument error
|
|
|
|
set -euo pipefail
|
|
|
|
######################################################################
|
|
# Configuration Defaults
|
|
######################################################################
|
|
WORK_QUOTA_MINUTES=120 # 2 hours of work required
|
|
DECAY_RATE_MINUTES=30 # Lose 30 minutes per hour of Steam usage
|
|
VSCODE_REPO="praca_magisterska"
|
|
DRY_RUN=0
|
|
UNINSTALL=0
|
|
|
|
######################################################################
|
|
# Paths
|
|
######################################################################
|
|
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
|
|
TRACKER_SCRIPT="$SCRIPT_DIR/thesis_work_tracker.sh"
|
|
STATUS_SCRIPT="$SCRIPT_DIR/thesis_work_status.sh"
|
|
SERVICE_FILE="$SCRIPT_DIR/systemd/thesis-work-tracker@.service"
|
|
INSTALL_BIN="/usr/local/bin/thesis_work_tracker.sh"
|
|
INSTALL_STATUS="/usr/local/bin/thesis_work_status"
|
|
INSTALL_SERVICE="/etc/systemd/system/thesis-work-tracker@.service"
|
|
STATE_DIR="/var/lib/thesis-work-tracker"
|
|
LOG_DIR="/var/log/thesis-work-tracker"
|
|
|
|
######################################################################
|
|
# Colors and Logging
|
|
######################################################################
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[0;33m'
|
|
BLUE='\033[0;34m'
|
|
CYAN='\033[0;36m'
|
|
BOLD='\033[1m'
|
|
NC='\033[0m' # No Color
|
|
|
|
msg() { printf "${GREEN}[+]${NC} %s\n" "$*"; }
|
|
note() { printf "${BLUE}[i]${NC} %s\n" "$*"; }
|
|
warn() { printf "${YELLOW}[!]${NC} %s\n" "$*"; }
|
|
err() { printf "${RED}[x]${NC} %s\n" "$*" >&2; }
|
|
|
|
run() {
|
|
if [[ $DRY_RUN -eq 1 ]]; then
|
|
printf '%s[DRY-RUN]%s ' "${CYAN}" "${NC}"
|
|
printf '%q ' "$@"
|
|
printf '\n'
|
|
else
|
|
"$@"
|
|
fi
|
|
}
|
|
|
|
######################################################################
|
|
# Helpers
|
|
######################################################################
|
|
require_root() {
|
|
if [[ $EUID -ne 0 ]]; then
|
|
exec sudo -E bash "$0" "$@"
|
|
fi
|
|
}
|
|
|
|
usage() {
|
|
head -n 31 "$0" | tail -n +2 | sed 's/^# \{0,1\}//'
|
|
}
|
|
|
|
check_dependencies() {
|
|
local missing=()
|
|
|
|
for cmd in xdotool systemctl; do
|
|
if ! command -v "$cmd" &> /dev/null; then
|
|
missing+=("$cmd")
|
|
fi
|
|
done
|
|
|
|
if [[ ${#missing[@]} -gt 0 ]]; then
|
|
err "Missing required dependencies: ${missing[*]}"
|
|
note "Install them with: sudo pacman -S ${missing[*]}"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
get_current_user() {
|
|
# Get the user who invoked sudo, or current user if not using sudo
|
|
if [[ -n ${SUDO_USER:-} ]]; then
|
|
echo "$SUDO_USER"
|
|
else
|
|
whoami
|
|
fi
|
|
}
|
|
|
|
######################################################################
|
|
# Parse Arguments
|
|
######################################################################
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--work-quota)
|
|
WORK_QUOTA_MINUTES="${2:-}"
|
|
[[ -z $WORK_QUOTA_MINUTES ]] && {
|
|
err "--work-quota requires a value"
|
|
exit 2
|
|
}
|
|
if ! [[ $WORK_QUOTA_MINUTES =~ ^[0-9]+$ ]] || [[ $WORK_QUOTA_MINUTES -le 0 ]]; then
|
|
err "--work-quota must be a positive integer (got: $WORK_QUOTA_MINUTES)"
|
|
exit 2
|
|
fi
|
|
shift 2
|
|
;;
|
|
--decay-rate)
|
|
DECAY_RATE_MINUTES="${2:-}"
|
|
[[ -z $DECAY_RATE_MINUTES ]] && {
|
|
err "--decay-rate requires a value"
|
|
exit 2
|
|
}
|
|
if ! [[ $DECAY_RATE_MINUTES =~ ^[0-9]+$ ]] || [[ $DECAY_RATE_MINUTES -lt 0 ]]; then
|
|
err "--decay-rate must be a non-negative integer (got: $DECAY_RATE_MINUTES)"
|
|
exit 2
|
|
fi
|
|
shift 2
|
|
;;
|
|
--vscode-repo)
|
|
VSCODE_REPO="${2:-}"
|
|
[[ -z $VSCODE_REPO ]] && {
|
|
err "--vscode-repo requires a value"
|
|
exit 2
|
|
}
|
|
shift 2
|
|
;;
|
|
--dry-run)
|
|
DRY_RUN=1
|
|
shift
|
|
;;
|
|
--uninstall)
|
|
UNINSTALL=1
|
|
shift
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
err "Unknown option: $1"
|
|
usage
|
|
exit 2
|
|
;;
|
|
esac
|
|
done
|
|
|
|
######################################################################
|
|
# Main Functions
|
|
######################################################################
|
|
|
|
uninstall_tracker() {
|
|
msg "Uninstalling thesis work tracker..."
|
|
|
|
# Get current user for service name
|
|
local user
|
|
user=$(get_current_user)
|
|
|
|
# Stop and disable service
|
|
if systemctl is-active --quiet "thesis-work-tracker@$user.service" 2>/dev/null; then
|
|
run systemctl stop "thesis-work-tracker@$user.service"
|
|
fi
|
|
|
|
if systemctl is-enabled --quiet "thesis-work-tracker@$user.service" 2>/dev/null; then
|
|
run systemctl disable "thesis-work-tracker@$user.service"
|
|
fi
|
|
|
|
# Remove service file
|
|
if [[ -f $INSTALL_SERVICE ]]; then
|
|
run rm -f "$INSTALL_SERVICE"
|
|
run systemctl daemon-reload
|
|
fi
|
|
|
|
# Remove tracker script
|
|
if [[ -f $INSTALL_BIN ]]; then
|
|
run rm -f "$INSTALL_BIN"
|
|
fi
|
|
|
|
# Remove status script
|
|
if [[ -f $INSTALL_STATUS ]]; then
|
|
run rm -f "$INSTALL_STATUS"
|
|
fi
|
|
|
|
# Remove state directory (with immutable flags removed)
|
|
if [[ -d $STATE_DIR ]]; then
|
|
run chattr -i -R "$STATE_DIR" 2>/dev/null || true
|
|
note "State directory preserved at: $STATE_DIR"
|
|
note "To completely remove state: sudo rm -rf $STATE_DIR"
|
|
fi
|
|
|
|
msg "Thesis work tracker uninstalled successfully"
|
|
note "Log files preserved at: $LOG_DIR"
|
|
}
|
|
|
|
install_tracker() {
|
|
msg "Installing thesis work tracker..."
|
|
|
|
# Check dependencies
|
|
check_dependencies || exit 1
|
|
|
|
# Verify source files exist
|
|
if [[ ! -f $TRACKER_SCRIPT ]]; then
|
|
err "Tracker script not found: $TRACKER_SCRIPT"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! -f $STATUS_SCRIPT ]]; then
|
|
err "Status script not found: $STATUS_SCRIPT"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! -f $SERVICE_FILE ]]; then
|
|
err "Service file not found: $SERVICE_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
# Create directories
|
|
msg "Creating directories..."
|
|
run mkdir -p "$LOG_DIR"
|
|
run chmod 755 "$LOG_DIR"
|
|
|
|
# Install tracker script with configuration
|
|
msg "Installing tracker script to $INSTALL_BIN..."
|
|
|
|
# Copy script and update configuration values
|
|
run cp "$TRACKER_SCRIPT" "$INSTALL_BIN"
|
|
|
|
# Update configuration in the installed script
|
|
local work_quota_seconds=$((WORK_QUOTA_MINUTES * 60))
|
|
local decay_rate_seconds=$((DECAY_RATE_MINUTES * 60))
|
|
|
|
run sed -i "s/^WORK_QUOTA_REQUIRED=.*/WORK_QUOTA_REQUIRED=$work_quota_seconds # $WORK_QUOTA_MINUTES minutes/" "$INSTALL_BIN"
|
|
run sed -i "s/^WORK_DECAY_PER_HOUR=.*/WORK_DECAY_PER_HOUR=$decay_rate_seconds # $DECAY_RATE_MINUTES minutes/" "$INSTALL_BIN"
|
|
run sed -i "s/^VSCODE_REQUIRED_REPO=.*/VSCODE_REQUIRED_REPO=\"$VSCODE_REPO\"/" "$INSTALL_BIN"
|
|
|
|
run chmod 755 "$INSTALL_BIN"
|
|
|
|
# Install status script
|
|
msg "Installing status script to $INSTALL_STATUS..."
|
|
run cp "$STATUS_SCRIPT" "$INSTALL_STATUS"
|
|
|
|
# Update quota in status script to match
|
|
run sed -i "s/^WORK_QUOTA_REQUIRED=.*/WORK_QUOTA_REQUIRED=$work_quota_seconds # $WORK_QUOTA_MINUTES minutes/" "$INSTALL_STATUS"
|
|
|
|
run chmod 755 "$INSTALL_STATUS"
|
|
|
|
# Install systemd service
|
|
msg "Installing systemd service..."
|
|
run cp "$SERVICE_FILE" "$INSTALL_SERVICE"
|
|
run chmod 644 "$INSTALL_SERVICE"
|
|
run systemctl daemon-reload
|
|
|
|
# Get current user for service enablement
|
|
local user
|
|
user=$(get_current_user)
|
|
|
|
# Enable and start service
|
|
msg "Enabling and starting service for user: $user..."
|
|
run systemctl enable "thesis-work-tracker@$user.service"
|
|
run systemctl restart "thesis-work-tracker@$user.service"
|
|
|
|
# Wait a moment for service to start
|
|
sleep 2
|
|
|
|
# Check service status
|
|
if systemctl is-active --quiet "thesis-work-tracker@$user.service"; then
|
|
msg "Service started successfully!"
|
|
else
|
|
warn "Service may not have started properly. Check status with:"
|
|
warn " systemctl status thesis-work-tracker@$user.service"
|
|
fi
|
|
|
|
# Display configuration summary
|
|
echo ""
|
|
echo "╔════════════════════════════════════════════════════════════════╗"
|
|
echo "║ Bachelor Thesis Work Tracker - Installation ║"
|
|
echo "╚════════════════════════════════════════════════════════════════╝"
|
|
echo ""
|
|
echo "Configuration:"
|
|
echo " • Work quota required: ${BOLD}${WORK_QUOTA_MINUTES} minutes${NC}"
|
|
echo " • Decay rate (per hour of Steam): ${BOLD}${DECAY_RATE_MINUTES} minutes${NC}"
|
|
echo " • VS Code repository: ${BOLD}${VSCODE_REPO}${NC}"
|
|
echo ""
|
|
echo "Tracked Applications:"
|
|
echo " ✓ Unreal Engine (all versions)"
|
|
echo " ✓ Unity Editor"
|
|
echo " ✓ Nvidia Omniverse"
|
|
echo " ✓ Visual Studio Code (only when working on '$VSCODE_REPO')"
|
|
echo ""
|
|
echo "Blocked Sites (until quota met):"
|
|
echo " ⛔ Steam (all domains)"
|
|
echo " ⛔ Social media (Reddit, Twitter, Facebook, Instagram)"
|
|
echo " ⛔ Video sites (YouTube, Twitch)"
|
|
echo " ⛔ Other distractions (9gag, Imgur)"
|
|
echo ""
|
|
echo "System Protection Features:"
|
|
echo " 🔒 State files protected with immutable flags"
|
|
echo " 🔒 Auto-restart on failure"
|
|
echo " 🔒 Integrated with hosts guard system"
|
|
echo " 🔒 Continuous monitoring every 5 seconds"
|
|
echo ""
|
|
echo "How it works:"
|
|
echo " 1. Work on your thesis using the approved applications"
|
|
echo " 2. Time accumulates in the background"
|
|
echo " 3. After ${WORK_QUOTA_MINUTES} minutes of work, Steam is unblocked"
|
|
echo " 4. Steam usage decays your work time at ${DECAY_RATE_MINUTES} min/hour"
|
|
echo " 5. When work time drops below quota, Steam is blocked again"
|
|
echo ""
|
|
echo "Useful Commands:"
|
|
echo " • Check progress: thesis_work_status"
|
|
echo " • Check status: systemctl status thesis-work-tracker@$user.service"
|
|
echo " • View logs: tail -f $LOG_DIR/tracker.log"
|
|
echo " • View state: sudo cat $STATE_DIR/work-time.state"
|
|
echo " • Restart: sudo systemctl restart thesis-work-tracker@$user.service"
|
|
echo " • Uninstall: sudo $0 --uninstall"
|
|
echo ""
|
|
echo "⚠️ IMPORTANT: This system is designed to be hard to circumvent!"
|
|
echo " State files are immutable and the service auto-restarts."
|
|
echo " To legitimately modify settings, uninstall and reinstall."
|
|
echo ""
|
|
echo "Good luck with your bachelor thesis! 🎓"
|
|
echo ""
|
|
}
|
|
|
|
######################################################################
|
|
# Main
|
|
######################################################################
|
|
require_root "$@"
|
|
|
|
if [[ $UNINSTALL -eq 1 ]]; then
|
|
uninstall_tracker
|
|
else
|
|
install_tracker
|
|
fi
|
|
|
|
exit 0
|