mirror of
https://github.com/agessaman/meshcore-bot.git
synced 2026-03-29 11:29:51 +00:00
Improve installation and uninstallation scripts. Add user to dialout group for serial port access in install-service.sh, and implement safety features in uninstall-service.sh, including backup options and confirmation prompts for destructive actions. Update error handling and messaging for clarity across both scripts.
This commit is contained in:
@@ -189,6 +189,29 @@ else
|
||||
else
|
||||
print_warning "User $SERVICE_USER already exists (skipping creation)"
|
||||
fi
|
||||
|
||||
# Add user to dialout group for serial port access (Linux)
|
||||
print_info "Configuring serial port access permissions"
|
||||
if getent group dialout > /dev/null 2>&1; then
|
||||
if groups "$SERVICE_USER" | grep -q "\bdialout\b"; then
|
||||
print_warning "User $SERVICE_USER is already in dialout group"
|
||||
else
|
||||
usermod -a -G dialout "$SERVICE_USER"
|
||||
print_success "Added $SERVICE_USER to dialout group for serial port access"
|
||||
fi
|
||||
else
|
||||
print_warning "dialout group not found - serial port access may require manual configuration"
|
||||
print_info "If using serial connection, you may need to: sudo usermod -a -G dialout $SERVICE_USER"
|
||||
fi
|
||||
|
||||
# Also check for other common serial port groups (tty, uucp, lock)
|
||||
for group in tty uucp lock; do
|
||||
if getent group "$group" > /dev/null 2>&1; then
|
||||
if ! groups "$SERVICE_USER" | grep -q "\b$group\b"; then
|
||||
usermod -a -G "$group" "$SERVICE_USER" 2>/dev/null && print_info "Added $SERVICE_USER to $group group" || true
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
print_section "Step 2: Creating Installation Directories"
|
||||
@@ -435,6 +458,11 @@ else
|
||||
echo " • Run as user '$SERVICE_USER' for security"
|
||||
echo " • Log to systemd journal (view with journalctl)"
|
||||
echo ""
|
||||
print_info "Serial port access:"
|
||||
echo " • User '$SERVICE_USER' has been added to dialout group for serial port access"
|
||||
echo " • If using serial connection, ensure the service is restarted after installation"
|
||||
echo " • Group membership changes take effect after service restart"
|
||||
echo ""
|
||||
print_info "After editing config.ini, restart the service for changes to take effect:"
|
||||
echo " ${YELLOW}sudo systemctl restart $SERVICE_NAME${NC}"
|
||||
fi
|
||||
|
||||
@@ -14,7 +14,10 @@ class HackerCommand(BaseCommand):
|
||||
|
||||
# Plugin metadata
|
||||
name = "hacker"
|
||||
keywords = ['sudo', 'ps aux', 'grep', 'ls -l', 'ls -la', 'echo $PATH']
|
||||
keywords = ['sudo', 'ps aux', 'grep', 'ls -l', 'ls -la', 'echo $PATH', 'rm', 'rm -rf',
|
||||
'cat', 'whoami', 'top', 'htop', 'netstat', 'ss', 'kill', 'killall', 'chmod',
|
||||
'find', 'history', 'passwd', 'su', 'ssh', 'wget', 'curl', 'df -h', 'free',
|
||||
'ifconfig', 'ip addr', 'uname -a']
|
||||
description = "Simulates hacking a supervillain's mainframe with hilarious error messages"
|
||||
category = "fun"
|
||||
|
||||
@@ -89,15 +92,15 @@ class HackerCommand(BaseCommand):
|
||||
# grep command errors
|
||||
elif command_lower.startswith('grep'):
|
||||
fallback = [
|
||||
"🔍 SEARCH FAILED: The One Ring has corrupted the search index. My precious...",
|
||||
"📝 PATTERN NOT FOUND: The search database has been deleted by the evil AI.",
|
||||
"🔍 SEARCH FAILED: The One Ring has corrupted the file search. My precious...",
|
||||
"📝 PATTERN NOT FOUND: The search pattern has been blocked by the evil AI.",
|
||||
"🎯 MISS: Your search pattern has been shot down by Imperial TIE fighters.",
|
||||
"🧩 PUZZLE ERROR: The search results have been scattered by the Riddler.",
|
||||
"💻 DATABASE CORRUPTED: The supervillain's search engine has crashed.",
|
||||
"💻 FILE SYSTEM CORRUPTED: The supervillain's file system has crashed.",
|
||||
"🎮 GAME OVER: The search has been defeated by the final boss.",
|
||||
"🖥️ SEARCH ENGINE DOWN: Google has been hacked by the Dark Web.",
|
||||
"🔐 ENCRYPTED RESULTS: The search results have been locked by ransomware.",
|
||||
"🌐 NETWORK TIMEOUT: The search request got lost in cyberspace.",
|
||||
"🖥️ SEARCH BLOCKED: File access has been blocked by the Dark Web.",
|
||||
"🔐 ENCRYPTED FILES: The files are encrypted and cannot be searched.",
|
||||
"🌐 READ TIMEOUT: The file read request got lost in cyberspace.",
|
||||
"⚡ SEARCH FAILED: The pattern matching algorithm has been fried by a power surge."
|
||||
]
|
||||
return get_random_error('commands.hacker.grep_errors', fallback)
|
||||
@@ -134,6 +137,292 @@ class HackerCommand(BaseCommand):
|
||||
]
|
||||
return get_random_error('commands.hacker.echo_path_errors', fallback)
|
||||
|
||||
# rm and rm -rf command errors (dangerous deletion!)
|
||||
elif command_lower.startswith('rm -rf') or command_lower.startswith('rm -r'):
|
||||
fallback = [
|
||||
"💣 DESTRUCTION BLOCKED: The Death Star's safety protocols have prevented mass deletion!",
|
||||
"🚨 EMERGENCY STOP: Dr. Evil has activated the emergency brake on file destruction.",
|
||||
"🛡️ PROTECTION MODE: The Matrix has locked all files in read-only mode. No deletion allowed.",
|
||||
"🔒 FILES LOCKED: Lex Luthor's mainframe has frozen all deletion commands.",
|
||||
"⚡ POWER FAILURE: The supervillain's delete command has been short-circuited.",
|
||||
"🎮 GAME SAVE PROTECTED: The final boss has enabled file protection mode.",
|
||||
"🖥️ DELETION DENIED: The evil AI refuses to delete its own files.",
|
||||
"🔐 ENCRYPTED FILES: All files are encrypted and cannot be deleted.",
|
||||
"🌐 CLOUD SYNC: Files are syncing to the Matrix cloud. Deletion pending...",
|
||||
"💀 SYSTEM REJECTION: The mainframe has rejected your deletion request. Files are too precious."
|
||||
]
|
||||
return get_random_error('commands.hacker.rm_errors', fallback)
|
||||
elif command_lower.startswith('rm'):
|
||||
fallback = [
|
||||
"🗑️ DELETE FAILED: The supervillain's recycle bin is full and rejecting deletions.",
|
||||
"🚫 REMOVAL BLOCKED: The Dark Overlord has protected all files from deletion.",
|
||||
"💻 FILE LOCKED: The file system has been locked by the evil corporation.",
|
||||
"🔒 PERMISSION DENIED: You don't have permission to delete files on the Death Star.",
|
||||
"⚡ DELETION ERROR: The file deletion command has been corrupted by malware.",
|
||||
"🎮 GAME OVER: The file you're trying to delete is the final boss's save file.",
|
||||
"🖥️ SYSTEM ERROR: The delete command has crashed the file manager.",
|
||||
"🔐 FILES PROTECTED: All files are protected by the supervillain's antivirus.",
|
||||
"🌐 NETWORK ERROR: The deletion request got lost in cyberspace.",
|
||||
"💀 FILE GHOST: The file has become a digital ghost and cannot be deleted."
|
||||
]
|
||||
return get_random_error('commands.hacker.rm_errors', fallback)
|
||||
|
||||
# cat command errors
|
||||
elif command_lower.startswith('cat'):
|
||||
fallback = [
|
||||
"📄 FILE READ ERROR: The file has been encrypted by the Riddler's cipher.",
|
||||
"📖 DOCUMENT CORRUPTED: The file contents have been scrambled by malware.",
|
||||
"📚 ACCESS DENIED: The supervillain has classified this file as top secret.",
|
||||
"🔍 FILE NOT FOUND: The file has been hidden by the Invisible Man.",
|
||||
"💻 READ PERMISSION DENIED: The Matrix has locked this file from reading.",
|
||||
"🎮 GAME FILE: This file belongs to the final boss and cannot be viewed.",
|
||||
"🖥️ FILE SYSTEM ERROR: The file reader has crashed due to a virus.",
|
||||
"🔐 ENCRYPTED FILE: The file contents are encrypted with ransomware.",
|
||||
"🌐 CLOUD FILE: The file is stuck in the Matrix's cloud and cannot be read.",
|
||||
"💀 FILE GHOST: The file exists but its contents have been deleted by digital ghosts."
|
||||
]
|
||||
return get_random_error('commands.hacker.cat_errors', fallback)
|
||||
|
||||
# whoami command errors
|
||||
elif command_lower.startswith('whoami'):
|
||||
fallback = [
|
||||
"👤 IDENTITY ERROR: The Matrix has erased your identity. You are nobody.",
|
||||
"🕵️ SPY DETECTED: The supervillain's system has detected an unknown user.",
|
||||
"🎭 IDENTITY THEFT: Your identity has been stolen by the Riddler.",
|
||||
"👻 GHOST USER: You are a digital ghost with no identity.",
|
||||
"🔒 CLASSIFIED: Your identity is classified by the evil corporation.",
|
||||
"🎮 GAME OVER: The final boss has deleted your player profile.",
|
||||
"🖥️ USER DATABASE CORRUPTED: The user identity system has crashed.",
|
||||
"🔐 IDENTITY ENCRYPTED: Your identity has been encrypted by ransomware.",
|
||||
"🌐 IDENTITY LOST: Your identity got lost in the Matrix's network.",
|
||||
"💀 USER DELETED: The Dark Overlord has deleted your user account."
|
||||
]
|
||||
return get_random_error('commands.hacker.whoami_errors', fallback)
|
||||
|
||||
# top and htop command errors
|
||||
elif command_lower.startswith('htop') or command_lower.startswith('top'):
|
||||
fallback = [
|
||||
"📊 MONITOR ERROR: The process monitor has been hijacked by the Borg Collective.",
|
||||
"⚙️ SYSTEM OVERLOAD: The Death Star's reactor is overheating. Monitor offline.",
|
||||
"🤖 PROCESS HIDDEN: All processes have been hidden by the evil AI.",
|
||||
"💻 MONITOR CRASHED: The system monitor has crashed due to a kernel panic.",
|
||||
"🎮 GAME PAUSED: The final boss has paused all processes.",
|
||||
"🖥️ BLUE SCREEN: The monitor has encountered a fatal error.",
|
||||
"🔐 MONITOR ENCRYPTED: The process monitor has been locked by ransomware.",
|
||||
"🌐 SYSTEM DISCONNECTED: The monitor cannot access the process table.",
|
||||
"⚡ POWER SURGE: The monitor has been fried by a power surge.",
|
||||
"💀 SYSTEM DEAD: The mainframe is dead. No processes to monitor."
|
||||
]
|
||||
return get_random_error('commands.hacker.top_errors', fallback)
|
||||
|
||||
# netstat and ss command errors
|
||||
elif command_lower.startswith('netstat') or command_lower.startswith('ss '):
|
||||
fallback = [
|
||||
"🌐 NETWORK SCAN BLOCKED: The supervillain's firewall has blocked all network queries.",
|
||||
"🔍 CONNECTION LIST CORRUPTED: The network connection table has been hacked by malware.",
|
||||
"📡 SIGNAL JAMMED: Imperial TIE fighters are jamming all network signals.",
|
||||
"💻 NETWORK DOWN: The Death Star's network stack has been destroyed.",
|
||||
"🎮 GAME OVER: All network connections have been terminated by the final boss.",
|
||||
"🖥️ NETWORK ERROR: The network stack has crashed due to a virus.",
|
||||
"🔐 CONNECTIONS HIDDEN: All network connections have been encrypted and hidden.",
|
||||
"🌐 MATRIX DISCONNECTED: The network routing table is stuck in the Matrix's void.",
|
||||
"⚡ NETWORK FRIED: The network interface has been zapped by a power surge.",
|
||||
"💀 NO CONNECTIONS: The mainframe has no active network connections. It's dead, Jim."
|
||||
]
|
||||
return get_random_error('commands.hacker.netstat_errors', fallback)
|
||||
|
||||
# kill and killall command errors
|
||||
elif command_lower.startswith('killall') or command_lower.startswith('kill'):
|
||||
fallback = [
|
||||
"💀 KILL DENIED: The supervillain's processes are immortal and cannot be killed.",
|
||||
"🚫 TERMINATION BLOCKED: The Dark Overlord has protected all processes from termination.",
|
||||
"🛡️ PROCESS PROTECTED: The Matrix has locked all processes in protected mode.",
|
||||
"🔒 KILL PERMISSION DENIED: You don't have permission to kill processes on the Death Star.",
|
||||
"⚡ TERMINATION ERROR: The kill command has been corrupted by malware.",
|
||||
"🎮 GAME OVER: The process you're trying to kill is the final boss. It's invincible.",
|
||||
"🖥️ SYSTEM ERROR: The kill signal has been blocked by the kernel.",
|
||||
"🔐 PROCESSES PROTECTED: All processes are protected and cannot be terminated.",
|
||||
"🌐 KILL REQUEST LOST: The termination signal got lost in cyberspace.",
|
||||
"💀 PROCESS GHOST: The process has become a zombie process and cannot be killed."
|
||||
]
|
||||
return get_random_error('commands.hacker.kill_errors', fallback)
|
||||
|
||||
# chmod command errors
|
||||
elif command_lower.startswith('chmod'):
|
||||
fallback = [
|
||||
"🔐 PERMISSION DENIED: The supervillain has locked all file permissions.",
|
||||
"🚫 CHMOD BLOCKED: The Dark Overlord refuses to allow permission changes.",
|
||||
"🛡️ PERMISSIONS PROTECTED: The Matrix has frozen all file permissions.",
|
||||
"🔒 PERMISSION ERROR: You don't have permission to change permissions. How meta!",
|
||||
"⚡ CHMOD CORRUPTED: The permission change command has been fried by malware.",
|
||||
"🎮 GAME OVER: The final boss has locked all file permissions.",
|
||||
"🖥️ SYSTEM ERROR: The permission system has crashed due to a virus.",
|
||||
"🔐 PERMISSIONS ENCRYPTED: All permissions are encrypted and cannot be changed.",
|
||||
"🌐 PERMISSION REQUEST LOST: The permission change got lost in the Matrix.",
|
||||
"💀 PERMISSIONS DEAD: The permission system is dead. No changes allowed."
|
||||
]
|
||||
return get_random_error('commands.hacker.chmod_errors', fallback)
|
||||
|
||||
# find command errors
|
||||
elif command_lower.startswith('find'):
|
||||
fallback = [
|
||||
"🔍 SEARCH FAILED: The file search has been blocked by the supervillain's firewall.",
|
||||
"📁 FILES HIDDEN: All files have been hidden by the Invisible Man's cloak.",
|
||||
"💻 SEARCH CORRUPTED: The find command has been corrupted by malware.",
|
||||
"🎯 TARGET NOT FOUND: The files you're searching for have been deleted by the evil AI.",
|
||||
"🎮 GAME OVER: The final boss has hidden all files in another dimension.",
|
||||
"🖥️ SEARCH ENGINE DOWN: The file search system has crashed.",
|
||||
"🔐 FILES ENCRYPTED: All files are encrypted and cannot be found.",
|
||||
"🌐 SEARCH LOST: The search request got lost in the Matrix's void.",
|
||||
"⚡ SEARCH FRIED: The file search algorithm has been zapped by a power surge.",
|
||||
"💀 NO FILES: The mainframe has no files. They've all been deleted."
|
||||
]
|
||||
return get_random_error('commands.hacker.find_errors', fallback)
|
||||
|
||||
# history command errors
|
||||
elif command_lower.startswith('history'):
|
||||
fallback = [
|
||||
"📜 HISTORY ERASED: The supervillain has deleted all command history.",
|
||||
"🕰️ TIME TRAVEL ERROR: The command history has been lost in a time paradox.",
|
||||
"💻 HISTORY CORRUPTED: The history database has been hacked by malware.",
|
||||
"🔒 ACCESS DENIED: The Dark Overlord has classified your command history as top secret.",
|
||||
"🎮 GAME OVER: The final boss has reset your command history.",
|
||||
"🖥️ HISTORY SYSTEM DOWN: The command history system has crashed.",
|
||||
"🔐 HISTORY ENCRYPTED: Your command history has been encrypted by ransomware.",
|
||||
"🌐 HISTORY LOST: Your command history got lost in the Matrix's network.",
|
||||
"⚡ HISTORY FRIED: The history database has been zapped by a power surge.",
|
||||
"💀 NO HISTORY: You have no command history. You are a blank slate."
|
||||
]
|
||||
return get_random_error('commands.hacker.history_errors', fallback)
|
||||
|
||||
# passwd command errors
|
||||
elif command_lower.startswith('passwd'):
|
||||
fallback = [
|
||||
"🔐 PASSWORD CHANGE DENIED: The supervillain has locked all password changes.",
|
||||
"🚫 PASSWORD BLOCKED: The Dark Overlord refuses to allow password modifications.",
|
||||
"🛡️ PASSWORD PROTECTED: The Matrix has frozen all password changes.",
|
||||
"🔒 PERMISSION DENIED: You don't have permission to change passwords on the Death Star.",
|
||||
"⚡ PASSWORD ERROR: The password change command has been corrupted by malware.",
|
||||
"🎮 GAME OVER: The final boss has locked all passwords.",
|
||||
"🖥️ SYSTEM ERROR: The password system has crashed due to a virus.",
|
||||
"🔐 PASSWORDS ENCRYPTED: All passwords are encrypted and cannot be changed.",
|
||||
"🌐 PASSWORD REQUEST LOST: The password change got lost in the Matrix.",
|
||||
"💀 PASSWORD SYSTEM DEAD: The password system is dead. No changes allowed."
|
||||
]
|
||||
return get_random_error('commands.hacker.passwd_errors', fallback)
|
||||
|
||||
# su command errors
|
||||
elif command_lower.startswith('su '):
|
||||
fallback = [
|
||||
"🔄 SWITCH USER DENIED: The supervillain has blocked all user switching attempts.",
|
||||
"🚫 USER SWITCH BLOCKED: The Dark Overlord refuses to allow user changes.",
|
||||
"🛡️ USER PROTECTED: The Matrix has locked all user accounts.",
|
||||
"🔒 PERMISSION DENIED: You don't have permission to switch users on the Death Star.",
|
||||
"⚡ USER SWITCH ERROR: The su command has been corrupted by malware.",
|
||||
"🎮 GAME OVER: The final boss has locked all user accounts.",
|
||||
"🖥️ SYSTEM ERROR: The user system has crashed due to a virus.",
|
||||
"🔐 USERS ENCRYPTED: All user accounts are encrypted and cannot be accessed.",
|
||||
"🌐 USER REQUEST LOST: The user switch request got lost in the Matrix.",
|
||||
"💀 USER SYSTEM DEAD: The user system is dead. No switching allowed."
|
||||
]
|
||||
return get_random_error('commands.hacker.su_errors', fallback)
|
||||
|
||||
# ssh command errors
|
||||
elif command_lower.startswith('ssh'):
|
||||
fallback = [
|
||||
"🔌 SSH CONNECTION FAILED: The supervillain's server has blocked all SSH attempts.",
|
||||
"🚫 REMOTE ACCESS DENIED: The Dark Overlord has closed all SSH ports.",
|
||||
"🛡️ CONNECTION PROTECTED: The Matrix has locked all SSH connections.",
|
||||
"🔒 SSH BLOCKED: The Death Star's firewall is blocking all SSH connections.",
|
||||
"⚡ CONNECTION ERROR: The SSH handshake has been corrupted by malware.",
|
||||
"🎮 GAME OVER: The final boss has disabled all remote access.",
|
||||
"🖥️ SYSTEM ERROR: The SSH daemon has crashed due to a virus.",
|
||||
"🔐 SSH DISABLED: All SSH connections have been disabled and blocked.",
|
||||
"🌐 CONNECTION LOST: The SSH connection got lost in the Matrix's void.",
|
||||
"💀 SSH DEAD: The SSH daemon is dead. No remote access allowed."
|
||||
]
|
||||
return get_random_error('commands.hacker.ssh_errors', fallback)
|
||||
|
||||
# wget and curl command errors
|
||||
elif command_lower.startswith('wget') or command_lower.startswith('curl'):
|
||||
fallback = [
|
||||
"📥 DOWNLOAD BLOCKED: The supervillain's firewall has blocked all HTTP requests.",
|
||||
"🚫 DOWNLOAD DENIED: The Dark Overlord refuses to allow file downloads.",
|
||||
"🛡️ DOWNLOAD PROTECTED: The Matrix has locked all download capabilities.",
|
||||
"🔒 DOWNLOAD BLOCKED: The Death Star's network is blocking all outbound connections.",
|
||||
"⚡ DOWNLOAD ERROR: The HTTP request has been corrupted by malware.",
|
||||
"🎮 GAME OVER: The final boss has disabled all downloads.",
|
||||
"🖥️ SYSTEM ERROR: The network stack has crashed due to a virus.",
|
||||
"🔐 DNS RESOLUTION FAILED: All domain names have been encrypted and blocked.",
|
||||
"🌐 CONNECTION TIMEOUT: The download request got lost in the Matrix's network.",
|
||||
"💀 DOWNLOAD DEAD: The network interface is dead. No downloads allowed."
|
||||
]
|
||||
return get_random_error('commands.hacker.download_errors', fallback)
|
||||
|
||||
# df -h command errors
|
||||
elif command_lower.startswith('df -h') or command_lower.startswith('df'):
|
||||
fallback = [
|
||||
"💾 DISK SPACE ERROR: The supervillain's file system has been corrupted by malware.",
|
||||
"📊 STORAGE SCAN FAILED: The disk space query has been hijacked by the Borg.",
|
||||
"💻 DISK CORRUPTED: The file system has been destroyed by a virus.",
|
||||
"🎮 GAME OVER: The final boss has deleted all disk space information.",
|
||||
"🖥️ SYSTEM ERROR: The file system mount table has crashed.",
|
||||
"🔐 STORAGE ENCRYPTED: All file system information has been encrypted.",
|
||||
"🌐 MOUNT FAILED: The disk mount information got lost in the Matrix's cloud.",
|
||||
"⚡ STORAGE FRIED: The disk controller has been zapped by a power surge.",
|
||||
"💀 NO STORAGE: The mainframe has no mounted file systems. It's all been deleted.",
|
||||
"🗄️ FILESYSTEM CORRUPTED: The file system superblock has been corrupted by ransomware."
|
||||
]
|
||||
return get_random_error('commands.hacker.df_errors', fallback)
|
||||
|
||||
# free command errors
|
||||
elif command_lower.startswith('free'):
|
||||
fallback = [
|
||||
"🧠 MEMORY ERROR: The supervillain's RAM has been corrupted by malware.",
|
||||
"📊 MEMORY SCAN FAILED: The memory query has been hijacked by the Cybermen.",
|
||||
"💻 MEMORY CORRUPTED: The RAM has been destroyed by a virus.",
|
||||
"🎮 GAME OVER: The final boss has deleted all memory information.",
|
||||
"🖥️ SYSTEM ERROR: The memory management system has crashed.",
|
||||
"🔐 MEMORY ENCRYPTED: All memory information has been encrypted.",
|
||||
"🌐 MEMORY LOST: The memory statistics got lost in the Matrix's void.",
|
||||
"⚡ MEMORY FRIED: The memory controller has been zapped by a power surge.",
|
||||
"💀 NO MEMORY: The mainframe has no accessible memory. It's all been wiped.",
|
||||
"🧩 MEMORY CORRUPTED: The memory mapping has been corrupted by ransomware."
|
||||
]
|
||||
return get_random_error('commands.hacker.free_errors', fallback)
|
||||
|
||||
# ifconfig and ip addr command errors
|
||||
elif command_lower.startswith('ifconfig') or command_lower.startswith('ip addr'):
|
||||
fallback = [
|
||||
"🌐 NETWORK INTERFACE ERROR: The supervillain's network interfaces have been corrupted.",
|
||||
"📡 INTERFACE SCAN FAILED: The network interface query has been hijacked by Imperial forces.",
|
||||
"💻 INTERFACE CORRUPTED: The network interface configuration has been destroyed by a virus.",
|
||||
"🎮 GAME OVER: The final boss has deleted all network interface information.",
|
||||
"🖥️ SYSTEM ERROR: The network interface driver has crashed.",
|
||||
"🔐 INTERFACES ENCRYPTED: All network interface information has been encrypted.",
|
||||
"🌐 INTERFACES LOST: The network interface data got lost in the Matrix's network.",
|
||||
"⚡ INTERFACES FRIED: The network interface hardware has been zapped by a power surge.",
|
||||
"💀 NO INTERFACES: The mainframe has no network interfaces. They've all been disabled.",
|
||||
"🔌 CONNECTION BROKEN: All network interfaces have been disconnected by the Dark Overlord."
|
||||
]
|
||||
return get_random_error('commands.hacker.ifconfig_errors', fallback)
|
||||
|
||||
# uname -a command errors
|
||||
elif command_lower.startswith('uname'):
|
||||
fallback = [
|
||||
"🖥️ SYSTEM INFO ERROR: The supervillain has classified all system information as top secret.",
|
||||
"📊 INFO SCAN FAILED: The system information query has been hidden by the Invisible Man.",
|
||||
"💻 SYSTEM CORRUPTED: The kernel version information has been destroyed by malware.",
|
||||
"🎮 GAME OVER: The final boss has deleted all system information.",
|
||||
"🖥️ SYSTEM ERROR: The kernel information system has crashed. How meta!",
|
||||
"🔐 SYSTEM ENCRYPTED: All system information has been encrypted by ransomware.",
|
||||
"🌐 SYSTEM LOST: The kernel version got lost in the Matrix's void.",
|
||||
"⚡ SYSTEM FRIED: The system call interface has been zapped by a power surge.",
|
||||
"💀 NO SYSTEM: The mainframe has no kernel information. It's a mystery.",
|
||||
"🦹♂️ CLASSIFIED: Lex Luthor has classified all system information. Access denied."
|
||||
]
|
||||
return get_random_error('commands.hacker.uname_errors', fallback)
|
||||
|
||||
# Generic hacker error for other commands
|
||||
else:
|
||||
fallback = [
|
||||
@@ -161,10 +450,14 @@ class HackerCommand(BaseCommand):
|
||||
content_lower = content.lower()
|
||||
|
||||
# Commands that should match exactly (no arguments)
|
||||
exact_match_commands = ['ls -l', 'ls -la', 'echo $PATH']
|
||||
exact_match_commands = ['ls -l', 'ls -la', 'echo $PATH', 'df -h', 'whoami', 'history',
|
||||
'top', 'htop', 'free', 'uname -a']
|
||||
|
||||
# Commands that should match as prefixes (can have arguments)
|
||||
prefix_match_commands = ['sudo', 'ps aux', 'grep']
|
||||
# Note: Longer prefixes must come first (e.g., 'rm -rf' before 'rm')
|
||||
prefix_match_commands = ['sudo', 'ps aux', 'grep', 'rm -rf', 'rm -r', 'rm', 'cat',
|
||||
'netstat', 'ss', 'killall', 'kill', 'chmod', 'find', 'passwd',
|
||||
'su', 'ssh', 'wget', 'curl', 'df', 'ifconfig', 'ip addr', 'uname']
|
||||
|
||||
# Check for exact matches first
|
||||
for keyword in exact_match_commands:
|
||||
|
||||
@@ -532,15 +532,15 @@
|
||||
"⚡ POWER SURGE: The supervillain's server farm has fried all running processes."
|
||||
],
|
||||
"grep_errors": [
|
||||
"🔍 SEARCH FAILED: The One Ring has corrupted the search index. My precious...",
|
||||
"📝 PATTERN NOT FOUND: The search database has been deleted by the evil AI.",
|
||||
"🔍 SEARCH FAILED: The One Ring has corrupted the file search. My precious...",
|
||||
"📝 PATTERN NOT FOUND: The search pattern has been blocked by the evil AI.",
|
||||
"🎯 MISS: Your search pattern has been shot down by Imperial TIE fighters.",
|
||||
"🧩 PUZZLE ERROR: The search results have been scattered by the Riddler.",
|
||||
"💻 DATABASE CORRUPTED: The supervillain's search engine has crashed.",
|
||||
"💻 FILE SYSTEM CORRUPTED: The supervillain's file system has crashed.",
|
||||
"🎮 GAME OVER: The search has been defeated by the final boss.",
|
||||
"🖥️ SEARCH ENGINE DOWN: Google has been hacked by the Dark Web.",
|
||||
"🔐 ENCRYPTED RESULTS: The search results have been locked by ransomware.",
|
||||
"🌐 NETWORK TIMEOUT: The search request got lost in cyberspace.",
|
||||
"🖥️ SEARCH BLOCKED: File access has been blocked by the Dark Web.",
|
||||
"🔐 ENCRYPTED FILES: The files are encrypted and cannot be searched.",
|
||||
"🌐 READ TIMEOUT: The file read request got lost in cyberspace.",
|
||||
"⚡ SEARCH FAILED: The pattern matching algorithm has been fried by a power surge."
|
||||
],
|
||||
"ls_errors": [
|
||||
@@ -567,6 +567,210 @@
|
||||
"🌐 NETWORK PATH DOWN: The directory paths are stuck in the Matrix's network.",
|
||||
"⚡ PATH FRIED: The system paths have been zapped by a power surge."
|
||||
],
|
||||
"rm_errors": [
|
||||
"💣 DESTRUCTION BLOCKED: The Death Star's safety protocols have prevented mass deletion!",
|
||||
"🚨 EMERGENCY STOP: Dr. Evil has activated the emergency brake on file destruction.",
|
||||
"🛡️ PROTECTION MODE: The Matrix has locked all files in read-only mode. No deletion allowed.",
|
||||
"🔒 FILES LOCKED: Lex Luthor's mainframe has frozen all deletion commands.",
|
||||
"⚡ POWER FAILURE: The supervillain's delete command has been short-circuited.",
|
||||
"🎮 GAME SAVE PROTECTED: The final boss has enabled file protection mode.",
|
||||
"🖥️ DELETION DENIED: The evil AI refuses to delete its own files.",
|
||||
"🔐 ENCRYPTED FILES: All files are encrypted and cannot be deleted.",
|
||||
"🌐 CLOUD SYNC: Files are syncing to the Matrix cloud. Deletion pending...",
|
||||
"💀 SYSTEM REJECTION: The mainframe has rejected your deletion request. Files are too precious."
|
||||
],
|
||||
"cat_errors": [
|
||||
"📄 FILE READ ERROR: The file has been encrypted by the Riddler's cipher.",
|
||||
"📖 DOCUMENT CORRUPTED: The file contents have been scrambled by malware.",
|
||||
"📚 ACCESS DENIED: The supervillain has classified this file as top secret.",
|
||||
"🔍 FILE NOT FOUND: The file has been hidden by the Invisible Man.",
|
||||
"💻 READ PERMISSION DENIED: The Matrix has locked this file from reading.",
|
||||
"🎮 GAME FILE: This file belongs to the final boss and cannot be viewed.",
|
||||
"🖥️ FILE SYSTEM ERROR: The file reader has crashed due to a virus.",
|
||||
"🔐 ENCRYPTED FILE: The file contents are encrypted with ransomware.",
|
||||
"🌐 CLOUD FILE: The file is stuck in the Matrix's cloud and cannot be read.",
|
||||
"💀 FILE GHOST: The file exists but its contents have been deleted by digital ghosts."
|
||||
],
|
||||
"whoami_errors": [
|
||||
"👤 IDENTITY ERROR: The Matrix has erased your identity. You are nobody.",
|
||||
"🕵️ SPY DETECTED: The supervillain's system has detected an unknown user.",
|
||||
"🎭 IDENTITY THEFT: Your identity has been stolen by the Riddler.",
|
||||
"👻 GHOST USER: You are a digital ghost with no identity.",
|
||||
"🔒 CLASSIFIED: Your identity is classified by the evil corporation.",
|
||||
"🎮 GAME OVER: The final boss has deleted your player profile.",
|
||||
"🖥️ USER DATABASE CORRUPTED: The user identity system has crashed.",
|
||||
"🔐 IDENTITY ENCRYPTED: Your identity has been encrypted by ransomware.",
|
||||
"🌐 IDENTITY LOST: Your identity got lost in the Matrix's network.",
|
||||
"💀 USER DELETED: The Dark Overlord has deleted your user account."
|
||||
],
|
||||
"top_errors": [
|
||||
"📊 MONITOR ERROR: The process monitor has been hijacked by the Borg Collective.",
|
||||
"⚙️ SYSTEM OVERLOAD: The Death Star's reactor is overheating. Monitor offline.",
|
||||
"🤖 PROCESS HIDDEN: All processes have been hidden by the evil AI.",
|
||||
"💻 MONITOR CRASHED: The system monitor has crashed due to a kernel panic.",
|
||||
"🎮 GAME PAUSED: The final boss has paused all processes.",
|
||||
"🖥️ BLUE SCREEN: The monitor has encountered a fatal error.",
|
||||
"🔐 MONITOR ENCRYPTED: The process monitor has been locked by ransomware.",
|
||||
"🌐 SYSTEM DISCONNECTED: The monitor cannot access the process table.",
|
||||
"⚡ POWER SURGE: The monitor has been fried by a power surge.",
|
||||
"💀 SYSTEM DEAD: The mainframe is dead. No processes to monitor."
|
||||
],
|
||||
"netstat_errors": [
|
||||
"🌐 NETWORK SCAN BLOCKED: The supervillain's firewall has blocked all network queries.",
|
||||
"🔍 CONNECTION LIST CORRUPTED: The network connection table has been hacked by malware.",
|
||||
"📡 SIGNAL JAMMED: Imperial TIE fighters are jamming all network signals.",
|
||||
"💻 NETWORK DOWN: The Death Star's network stack has been destroyed.",
|
||||
"🎮 GAME OVER: All network connections have been terminated by the final boss.",
|
||||
"🖥️ NETWORK ERROR: The network stack has crashed due to a virus.",
|
||||
"🔐 CONNECTIONS HIDDEN: All network connections have been encrypted and hidden.",
|
||||
"🌐 MATRIX DISCONNECTED: The network routing table is stuck in the Matrix's void.",
|
||||
"⚡ NETWORK FRIED: The network interface has been zapped by a power surge.",
|
||||
"💀 NO CONNECTIONS: The mainframe has no active network connections. It's dead, Jim."
|
||||
],
|
||||
"kill_errors": [
|
||||
"💀 KILL DENIED: The supervillain's processes are immortal and cannot be killed.",
|
||||
"🚫 TERMINATION BLOCKED: The Dark Overlord has protected all processes from termination.",
|
||||
"🛡️ PROCESS PROTECTED: The Matrix has locked all processes in protected mode.",
|
||||
"🔒 KILL PERMISSION DENIED: You don't have permission to kill processes on the Death Star.",
|
||||
"⚡ TERMINATION ERROR: The kill command has been corrupted by malware.",
|
||||
"🎮 GAME OVER: The process you're trying to kill is the final boss. It's invincible.",
|
||||
"🖥️ SYSTEM ERROR: The kill signal has been blocked by the kernel.",
|
||||
"🔐 PROCESSES PROTECTED: All processes are protected and cannot be terminated.",
|
||||
"🌐 KILL REQUEST LOST: The termination signal got lost in cyberspace.",
|
||||
"💀 PROCESS GHOST: The process has become a zombie process and cannot be killed."
|
||||
],
|
||||
"chmod_errors": [
|
||||
"🔐 PERMISSION DENIED: The supervillain has locked all file permissions.",
|
||||
"🚫 CHMOD BLOCKED: The Dark Overlord refuses to allow permission changes.",
|
||||
"🛡️ PERMISSIONS PROTECTED: The Matrix has frozen all file permissions.",
|
||||
"🔒 PERMISSION ERROR: You don't have permission to change permissions. How meta!",
|
||||
"⚡ CHMOD CORRUPTED: The permission change command has been fried by malware.",
|
||||
"🎮 GAME OVER: The final boss has locked all file permissions.",
|
||||
"🖥️ SYSTEM ERROR: The permission system has crashed due to a virus.",
|
||||
"🔐 PERMISSIONS ENCRYPTED: All permissions are encrypted and cannot be changed.",
|
||||
"🌐 PERMISSION REQUEST LOST: The permission change got lost in the Matrix.",
|
||||
"💀 PERMISSIONS DEAD: The permission system is dead. No changes allowed."
|
||||
],
|
||||
"find_errors": [
|
||||
"🔍 SEARCH FAILED: The file search has been blocked by the supervillain's firewall.",
|
||||
"📁 FILES HIDDEN: All files have been hidden by the Invisible Man's cloak.",
|
||||
"💻 SEARCH CORRUPTED: The find command has been corrupted by malware.",
|
||||
"🎯 TARGET NOT FOUND: The files you're searching for have been deleted by the evil AI.",
|
||||
"🎮 GAME OVER: The final boss has hidden all files in another dimension.",
|
||||
"🖥️ SEARCH ENGINE DOWN: The file search system has crashed.",
|
||||
"🔐 FILES ENCRYPTED: All files are encrypted and cannot be found.",
|
||||
"🌐 SEARCH LOST: The search request got lost in the Matrix's void.",
|
||||
"⚡ SEARCH FRIED: The file search algorithm has been zapped by a power surge.",
|
||||
"💀 NO FILES: The mainframe has no files. They've all been deleted."
|
||||
],
|
||||
"history_errors": [
|
||||
"📜 HISTORY ERASED: The supervillain has deleted all command history.",
|
||||
"🕰️ TIME TRAVEL ERROR: The command history has been lost in a time paradox.",
|
||||
"💻 HISTORY CORRUPTED: The history database has been hacked by malware.",
|
||||
"🔒 ACCESS DENIED: The Dark Overlord has classified your command history as top secret.",
|
||||
"🎮 GAME OVER: The final boss has reset your command history.",
|
||||
"🖥️ HISTORY SYSTEM DOWN: The command history system has crashed.",
|
||||
"🔐 HISTORY ENCRYPTED: Your command history has been encrypted by ransomware.",
|
||||
"🌐 HISTORY LOST: Your command history got lost in the Matrix's network.",
|
||||
"⚡ HISTORY FRIED: The history database has been zapped by a power surge.",
|
||||
"💀 NO HISTORY: You have no command history. You are a blank slate."
|
||||
],
|
||||
"passwd_errors": [
|
||||
"🔐 PASSWORD CHANGE DENIED: The supervillain has locked all password changes.",
|
||||
"🚫 PASSWORD BLOCKED: The Dark Overlord refuses to allow password modifications.",
|
||||
"🛡️ PASSWORD PROTECTED: The Matrix has frozen all password changes.",
|
||||
"🔒 PERMISSION DENIED: You don't have permission to change passwords on the Death Star.",
|
||||
"⚡ PASSWORD ERROR: The password change command has been corrupted by malware.",
|
||||
"🎮 GAME OVER: The final boss has locked all passwords.",
|
||||
"🖥️ SYSTEM ERROR: The password system has crashed due to a virus.",
|
||||
"🔐 PASSWORDS ENCRYPTED: All passwords are encrypted and cannot be changed.",
|
||||
"🌐 PASSWORD REQUEST LOST: The password change got lost in the Matrix.",
|
||||
"💀 PASSWORD SYSTEM DEAD: The password system is dead. No changes allowed."
|
||||
],
|
||||
"su_errors": [
|
||||
"🔄 SWITCH USER DENIED: The supervillain has blocked all user switching attempts.",
|
||||
"🚫 USER SWITCH BLOCKED: The Dark Overlord refuses to allow user changes.",
|
||||
"🛡️ USER PROTECTED: The Matrix has locked all user accounts.",
|
||||
"🔒 PERMISSION DENIED: You don't have permission to switch users on the Death Star.",
|
||||
"⚡ USER SWITCH ERROR: The su command has been corrupted by malware.",
|
||||
"🎮 GAME OVER: The final boss has locked all user accounts.",
|
||||
"🖥️ SYSTEM ERROR: The user system has crashed due to a virus.",
|
||||
"🔐 USERS ENCRYPTED: All user accounts are encrypted and cannot be accessed.",
|
||||
"🌐 USER REQUEST LOST: The user switch request got lost in the Matrix.",
|
||||
"💀 USER SYSTEM DEAD: The user system is dead. No switching allowed."
|
||||
],
|
||||
"ssh_errors": [
|
||||
"🔌 SSH CONNECTION FAILED: The supervillain's server has blocked all SSH attempts.",
|
||||
"🚫 REMOTE ACCESS DENIED: The Dark Overlord has closed all SSH ports.",
|
||||
"🛡️ CONNECTION PROTECTED: The Matrix has locked all SSH connections.",
|
||||
"🔒 SSH BLOCKED: The Death Star's firewall is blocking all SSH connections.",
|
||||
"⚡ CONNECTION ERROR: The SSH handshake has been corrupted by malware.",
|
||||
"🎮 GAME OVER: The final boss has disabled all remote access.",
|
||||
"🖥️ SYSTEM ERROR: The SSH daemon has crashed due to a virus.",
|
||||
"🔐 SSH DISABLED: All SSH connections have been disabled and blocked.",
|
||||
"🌐 CONNECTION LOST: The SSH connection got lost in the Matrix's void.",
|
||||
"💀 SSH DEAD: The SSH daemon is dead. No remote access allowed."
|
||||
],
|
||||
"download_errors": [
|
||||
"📥 DOWNLOAD BLOCKED: The supervillain's firewall has blocked all HTTP requests.",
|
||||
"🚫 DOWNLOAD DENIED: The Dark Overlord refuses to allow file downloads.",
|
||||
"🛡️ DOWNLOAD PROTECTED: The Matrix has locked all download capabilities.",
|
||||
"🔒 DOWNLOAD BLOCKED: The Death Star's network is blocking all outbound connections.",
|
||||
"⚡ DOWNLOAD ERROR: The HTTP request has been corrupted by malware.",
|
||||
"🎮 GAME OVER: The final boss has disabled all downloads.",
|
||||
"🖥️ SYSTEM ERROR: The network stack has crashed due to a virus.",
|
||||
"🔐 DNS RESOLUTION FAILED: All domain names have been encrypted and blocked.",
|
||||
"🌐 CONNECTION TIMEOUT: The download request got lost in the Matrix's network.",
|
||||
"💀 DOWNLOAD DEAD: The network interface is dead. No downloads allowed."
|
||||
],
|
||||
"df_errors": [
|
||||
"💾 DISK SPACE ERROR: The supervillain's file system has been corrupted by malware.",
|
||||
"📊 STORAGE SCAN FAILED: The disk space query has been hijacked by the Borg.",
|
||||
"💻 DISK CORRUPTED: The file system has been destroyed by a virus.",
|
||||
"🎮 GAME OVER: The final boss has deleted all disk space information.",
|
||||
"🖥️ SYSTEM ERROR: The file system mount table has crashed.",
|
||||
"🔐 STORAGE ENCRYPTED: All file system information has been encrypted.",
|
||||
"🌐 MOUNT FAILED: The disk mount information got lost in the Matrix's cloud.",
|
||||
"⚡ STORAGE FRIED: The disk controller has been zapped by a power surge.",
|
||||
"💀 NO STORAGE: The mainframe has no mounted file systems. It's all been deleted.",
|
||||
"🗄️ FILESYSTEM CORRUPTED: The file system superblock has been corrupted by ransomware."
|
||||
],
|
||||
"free_errors": [
|
||||
"🧠 MEMORY ERROR: The supervillain's RAM has been corrupted by malware.",
|
||||
"📊 MEMORY SCAN FAILED: The memory query has been hijacked by the Cybermen.",
|
||||
"💻 MEMORY CORRUPTED: The RAM has been destroyed by a virus.",
|
||||
"🎮 GAME OVER: The final boss has deleted all memory information.",
|
||||
"🖥️ SYSTEM ERROR: The memory management system has crashed.",
|
||||
"🔐 MEMORY ENCRYPTED: All memory information has been encrypted.",
|
||||
"🌐 MEMORY LOST: The memory statistics got lost in the Matrix's void.",
|
||||
"⚡ MEMORY FRIED: The memory controller has been zapped by a power surge.",
|
||||
"💀 NO MEMORY: The mainframe has no accessible memory. It's all been wiped.",
|
||||
"🧩 MEMORY CORRUPTED: The memory mapping has been corrupted by ransomware."
|
||||
],
|
||||
"ifconfig_errors": [
|
||||
"🌐 NETWORK INTERFACE ERROR: The supervillain's network interfaces have been corrupted.",
|
||||
"📡 INTERFACE SCAN FAILED: The network interface query has been hijacked by Imperial forces.",
|
||||
"💻 INTERFACE CORRUPTED: The network interface configuration has been destroyed by a virus.",
|
||||
"🎮 GAME OVER: The final boss has deleted all network interface information.",
|
||||
"🖥️ SYSTEM ERROR: The network interface driver has crashed.",
|
||||
"🔐 INTERFACES ENCRYPTED: All network interface information has been encrypted.",
|
||||
"🌐 INTERFACES LOST: The network interface data got lost in the Matrix's network.",
|
||||
"⚡ INTERFACES FRIED: The network interface hardware has been zapped by a power surge.",
|
||||
"💀 NO INTERFACES: The mainframe has no network interfaces. They've all been disabled.",
|
||||
"🔌 CONNECTION BROKEN: All network interfaces have been disconnected by the Dark Overlord."
|
||||
],
|
||||
"uname_errors": [
|
||||
"🖥️ SYSTEM INFO ERROR: The supervillain has classified all system information as top secret.",
|
||||
"📊 INFO SCAN FAILED: The system information query has been hidden by the Invisible Man.",
|
||||
"💻 SYSTEM CORRUPTED: The kernel version information has been destroyed by malware.",
|
||||
"🎮 GAME OVER: The final boss has deleted all system information.",
|
||||
"🖥️ SYSTEM ERROR: The kernel information system has crashed. How meta!",
|
||||
"🔐 SYSTEM ENCRYPTED: All system information has been encrypted by ransomware.",
|
||||
"🌐 SYSTEM LOST: The kernel version got lost in the Matrix's void.",
|
||||
"⚡ SYSTEM FRIED: The system call interface has been zapped by a power surge.",
|
||||
"💀 NO SYSTEM: The mainframe has no kernel information. It's a mystery.",
|
||||
"🦹♂️ CLASSIFIED: Lex Luthor has classified all system information. Access denied."
|
||||
],
|
||||
"generic_errors": [
|
||||
"💻 MAINFRAME ERROR: The supervillain's computer is having a bad day.",
|
||||
"🤖 SYSTEM MALFUNCTION: The evil AI has gone on strike.",
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
#!/bin/bash
|
||||
# MeshCore Bot Service Uninstallation Script
|
||||
# This script removes the MeshCore Bot systemd service
|
||||
# This script removes the MeshCore Bot service (systemd or launchd)
|
||||
# Supports both Linux (systemd) and macOS (launchd)
|
||||
#
|
||||
# Safety features:
|
||||
# - Backs up config.ini before removal
|
||||
# - Asks for confirmation before destructive actions
|
||||
# - Optionally preserves installation files
|
||||
|
||||
set -e
|
||||
|
||||
@@ -9,89 +15,489 @@ RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Configuration
|
||||
# Detect operating system
|
||||
OS="$(uname -s)"
|
||||
IS_MACOS=false
|
||||
IS_LINUX=false
|
||||
|
||||
if [[ "$OS" == "Darwin" ]]; then
|
||||
IS_MACOS=true
|
||||
SERVICE_TYPE="launchd"
|
||||
elif [[ "$OS" == "Linux" ]]; then
|
||||
IS_LINUX=true
|
||||
SERVICE_TYPE="systemd"
|
||||
else
|
||||
echo "Error: Unsupported operating system: $OS"
|
||||
echo "This script supports Linux (systemd) and macOS (launchd)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Configuration - OS-specific paths
|
||||
SERVICE_NAME="meshcore-bot"
|
||||
SERVICE_USER="meshcore"
|
||||
SERVICE_GROUP="meshcore"
|
||||
INSTALL_DIR="/opt/meshcore-bot"
|
||||
LOG_DIR="/var/log/meshcore-bot"
|
||||
PLIST_NAME="com.meshcore.bot"
|
||||
|
||||
echo -e "${BLUE}MeshCore Bot Service Uninstaller${NC}"
|
||||
echo "===================================="
|
||||
if [[ "$IS_MACOS" == true ]]; then
|
||||
SERVICE_USER="$(whoami)"
|
||||
SERVICE_GROUP="staff"
|
||||
INSTALL_DIR="/usr/local/meshcore-bot"
|
||||
LOG_DIR="/usr/local/var/log/meshcore-bot"
|
||||
SERVICE_FILE="com.meshcore.bot.plist"
|
||||
LAUNCHD_DIR="/Library/LaunchDaemons"
|
||||
else
|
||||
SERVICE_USER="meshcore"
|
||||
SERVICE_GROUP="meshcore"
|
||||
INSTALL_DIR="/opt/meshcore-bot"
|
||||
LOG_DIR="/var/log/meshcore-bot"
|
||||
SERVICE_FILE="meshcore-bot.service"
|
||||
SYSTEMD_DIR="/etc/systemd/system"
|
||||
fi
|
||||
|
||||
# Check if running as root
|
||||
# Capture original user before sudo (for backup location)
|
||||
ORIGINAL_USER="${SUDO_USER:-$USER}"
|
||||
if [[ -n "$ORIGINAL_USER" ]] && [[ "$ORIGINAL_USER" != "root" ]]; then
|
||||
# Try to get home directory of original user
|
||||
HOME_DIR=$(eval echo ~"$ORIGINAL_USER" 2>/dev/null || echo "/home/$ORIGINAL_USER")
|
||||
# Verify it exists and is writable
|
||||
if [[ ! -d "$HOME_DIR" ]] || [[ ! -w "$HOME_DIR" ]]; then
|
||||
HOME_DIR="/tmp"
|
||||
fi
|
||||
else
|
||||
# Fallback to /tmp if we can't determine user home
|
||||
HOME_DIR="/tmp"
|
||||
fi
|
||||
|
||||
# Function to print section headers
|
||||
print_section() {
|
||||
echo ""
|
||||
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo -e "${BLUE}$1${NC}"
|
||||
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
}
|
||||
|
||||
# Function to print info messages
|
||||
print_info() {
|
||||
echo -e "${CYAN}ℹ${NC} $1"
|
||||
}
|
||||
|
||||
# Function to print success messages
|
||||
print_success() {
|
||||
echo -e "${GREEN}✓${NC} $1"
|
||||
}
|
||||
|
||||
# Function to print warning messages
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}⚠${NC} $1"
|
||||
}
|
||||
|
||||
# Function to print error messages
|
||||
print_error() {
|
||||
echo -e "${RED}✗${NC} $1"
|
||||
}
|
||||
|
||||
# Function to ask yes/no question
|
||||
ask_yes_no() {
|
||||
local prompt="$1"
|
||||
local default="${2:-n}" # Default to 'no' for safety
|
||||
local response
|
||||
|
||||
if [[ "$default" == "y" ]]; then
|
||||
prompt="${prompt} [Y/n]: "
|
||||
else
|
||||
prompt="${prompt} [y/N]: "
|
||||
fi
|
||||
|
||||
while true; do
|
||||
read -p "$(echo -e "${YELLOW}${prompt}${NC}")" response
|
||||
response="${response:-$default}"
|
||||
case "$response" in
|
||||
[Yy]|[Yy][Ee][Ss])
|
||||
return 0
|
||||
;;
|
||||
[Nn]|[Nn][Oo])
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
echo "Please answer yes or no."
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
print_section "MeshCore Bot Service Uninstaller"
|
||||
echo ""
|
||||
if [[ "$IS_MACOS" == true ]]; then
|
||||
print_info "Detected macOS - will remove launchd service"
|
||||
else
|
||||
print_info "Detected Linux - will remove systemd service"
|
||||
fi
|
||||
print_warning "This script will remove the MeshCore Bot service"
|
||||
echo ""
|
||||
|
||||
# Check if script has execute permissions
|
||||
if [ ! -x "$0" ]; then
|
||||
print_warning "Script does not have execute permissions. Attempting to set them..."
|
||||
chmod +x "$0" 2>/dev/null || {
|
||||
print_error "Could not set execute permissions. Please run: chmod +x uninstall-service.sh"
|
||||
exit 1
|
||||
}
|
||||
print_success "Execute permissions set"
|
||||
fi
|
||||
|
||||
# Check if running as root, if not re-execute with sudo
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo -e "${RED}This script must be run as root (use sudo)${NC}"
|
||||
exit 1
|
||||
print_warning "This script requires root privileges to remove system services"
|
||||
print_info "Re-executing with sudo..."
|
||||
echo ""
|
||||
exec sudo "$0" "$@"
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}Step 1: Stopping and disabling service${NC}"
|
||||
# Stop service if running
|
||||
if systemctl is-active --quiet "$SERVICE_NAME"; then
|
||||
systemctl stop "$SERVICE_NAME"
|
||||
echo -e "${GREEN}Stopped $SERVICE_NAME service${NC}"
|
||||
# Check if service exists
|
||||
SERVICE_EXISTS=false
|
||||
if [[ "$IS_MACOS" == true ]]; then
|
||||
if [ -f "$LAUNCHD_DIR/$SERVICE_FILE" ]; then
|
||||
SERVICE_EXISTS=true
|
||||
fi
|
||||
else
|
||||
echo -e "${YELLOW}Service $SERVICE_NAME is not running${NC}"
|
||||
if [ -f "$SYSTEMD_DIR/$SERVICE_NAME.service" ]; then
|
||||
SERVICE_EXISTS=true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Disable service
|
||||
if systemctl is-enabled --quiet "$SERVICE_NAME"; then
|
||||
systemctl disable "$SERVICE_NAME"
|
||||
echo -e "${GREEN}Disabled $SERVICE_NAME service${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}Service $SERVICE_NAME is not enabled${NC}"
|
||||
if [[ "$SERVICE_EXISTS" == false ]]; then
|
||||
print_warning "Service not found - it may have already been removed"
|
||||
if [[ "$IS_MACOS" == true ]]; then
|
||||
print_info "Expected service file: $LAUNCHD_DIR/$SERVICE_FILE"
|
||||
else
|
||||
print_info "Expected service file: $SYSTEMD_DIR/$SERVICE_NAME.service"
|
||||
fi
|
||||
echo ""
|
||||
if ! ask_yes_no "Continue anyway? (will only remove files if they exist)"; then
|
||||
print_info "Uninstallation cancelled by user"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}Step 2: Removing systemd service file${NC}"
|
||||
# Remove service file
|
||||
if [ -f "/etc/systemd/system/$SERVICE_NAME.service" ]; then
|
||||
rm "/etc/systemd/system/$SERVICE_NAME.service"
|
||||
echo -e "${GREEN}Removed service file${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}Service file not found${NC}"
|
||||
fi
|
||||
|
||||
# Reload systemd
|
||||
systemctl daemon-reload
|
||||
echo -e "${GREEN}Reloaded systemd configuration${NC}"
|
||||
|
||||
echo -e "${YELLOW}Step 3: Removing installation directory${NC}"
|
||||
# Remove installation directory
|
||||
# Check if installation directory exists
|
||||
INSTALL_EXISTS=false
|
||||
if [ -d "$INSTALL_DIR" ]; then
|
||||
rm -rf "$INSTALL_DIR"
|
||||
echo -e "${GREEN}Removed installation directory: $INSTALL_DIR${NC}"
|
||||
INSTALL_EXISTS=true
|
||||
CONFIG_FILE="$INSTALL_DIR/config.ini"
|
||||
else
|
||||
echo -e "${YELLOW}Installation directory not found${NC}"
|
||||
CONFIG_FILE=""
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}Step 4: Removing log directory${NC}"
|
||||
# Remove log directory
|
||||
# Step 1: Backup config.ini if it exists
|
||||
if [[ "$INSTALL_EXISTS" == true ]] && [ -f "$CONFIG_FILE" ]; then
|
||||
print_section "Step 1: Backup Configuration File"
|
||||
print_info "Found configuration file: $CONFIG_FILE"
|
||||
|
||||
if ask_yes_no "Would you like to backup config.ini?" "y"; then
|
||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||
BACKUP_FILE="$HOME_DIR/meshcore-bot-config-backup-${TIMESTAMP}.ini"
|
||||
|
||||
# Create backup
|
||||
cp "$CONFIG_FILE" "$BACKUP_FILE"
|
||||
|
||||
# Try to set ownership to original user if possible
|
||||
if [[ -n "$ORIGINAL_USER" ]] && [[ "$ORIGINAL_USER" != "root" ]]; then
|
||||
chown "$ORIGINAL_USER:$(id -gn "$ORIGINAL_USER" 2>/dev/null || echo 'staff')" "$BACKUP_FILE" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
print_success "Configuration backed up to: $BACKUP_FILE"
|
||||
if [[ "$HOME_DIR" == "/tmp" ]]; then
|
||||
print_info "Backup saved to /tmp (home directory not accessible)"
|
||||
fi
|
||||
else
|
||||
print_info "Skipping config.ini backup"
|
||||
fi
|
||||
|
||||
# Step 1b: Backup database file
|
||||
print_section "Step 1b: Database Backup"
|
||||
|
||||
# Try to find the main database file (meshcore_bot.db by default, or from config)
|
||||
MAIN_DB_FILE=""
|
||||
|
||||
# First, try to read db_path from config.ini if it exists
|
||||
if [ -f "$CONFIG_FILE" ]; then
|
||||
DB_PATH_FROM_CONFIG=$(grep -E "^db_path\s*=" "$CONFIG_FILE" 2>/dev/null | head -1 | cut -d'=' -f2 | tr -d ' ' || echo "")
|
||||
if [ -n "$DB_PATH_FROM_CONFIG" ]; then
|
||||
# If it's a relative path, make it relative to install dir
|
||||
if [[ "$DB_PATH_FROM_CONFIG" != /* ]]; then
|
||||
MAIN_DB_FILE="$INSTALL_DIR/$DB_PATH_FROM_CONFIG"
|
||||
else
|
||||
MAIN_DB_FILE="$DB_PATH_FROM_CONFIG"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# If not found in config, try default location
|
||||
if [ -z "$MAIN_DB_FILE" ] || [ ! -f "$MAIN_DB_FILE" ]; then
|
||||
MAIN_DB_FILE="$INSTALL_DIR/meshcore_bot.db"
|
||||
fi
|
||||
|
||||
# Check if main database file exists
|
||||
if [ -f "$MAIN_DB_FILE" ]; then
|
||||
db_name=$(basename "$MAIN_DB_FILE")
|
||||
db_size=$(du -h "$MAIN_DB_FILE" 2>/dev/null | cut -f1)
|
||||
print_info "Found database file: $db_name (${db_size})"
|
||||
echo ""
|
||||
|
||||
if ask_yes_no "Would you like to backup the database file?" "y"; then
|
||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||
BACKUP_FILE="$HOME_DIR/meshcore-bot-db-backup-${TIMESTAMP}.db"
|
||||
|
||||
cp "$MAIN_DB_FILE" "$BACKUP_FILE"
|
||||
|
||||
# Try to set ownership to original user if possible
|
||||
if [[ -n "$ORIGINAL_USER" ]] && [[ "$ORIGINAL_USER" != "root" ]]; then
|
||||
chown "$ORIGINAL_USER:$(id -gn "$ORIGINAL_USER" 2>/dev/null || echo 'staff')" "$BACKUP_FILE" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
print_success "Database backed up to: $BACKUP_FILE"
|
||||
if [[ "$HOME_DIR" == "/tmp" ]]; then
|
||||
print_info "Backup saved to /tmp (home directory not accessible)"
|
||||
fi
|
||||
else
|
||||
print_info "Skipping database backup"
|
||||
fi
|
||||
else
|
||||
print_warning "Database file not found: $MAIN_DB_FILE"
|
||||
print_info "Skipping database backup"
|
||||
fi
|
||||
else
|
||||
print_section "Step 1: Configuration and Database Files"
|
||||
if [[ "$INSTALL_EXISTS" == false ]]; then
|
||||
print_warning "Installation directory not found: $INSTALL_DIR"
|
||||
else
|
||||
print_warning "Configuration file not found: $CONFIG_FILE"
|
||||
fi
|
||||
print_info "Skipping backup step"
|
||||
fi
|
||||
|
||||
# Step 2: Confirm service removal
|
||||
print_section "Step 2: Service Removal Confirmation"
|
||||
print_warning "This will stop and remove the MeshCore Bot service"
|
||||
if [[ "$IS_MACOS" == true ]]; then
|
||||
print_info "Service: $PLIST_NAME (launchd)"
|
||||
else
|
||||
print_info "Service: $SERVICE_NAME (systemd)"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
if ! ask_yes_no "Do you want to remove the service?"; then
|
||||
print_info "Service removal cancelled by user"
|
||||
echo ""
|
||||
if [[ "$INSTALL_EXISTS" == true ]]; then
|
||||
print_info "Installation files remain at: $INSTALL_DIR"
|
||||
print_info "You can remove them manually if needed"
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Step 3: Stop and remove service
|
||||
print_section "Step 3: Stopping and Removing Service"
|
||||
|
||||
if [[ "$IS_MACOS" == true ]]; then
|
||||
# macOS: Unload launchd service
|
||||
if launchctl list "$PLIST_NAME" &>/dev/null 2>&1; then
|
||||
print_info "Stopping service..."
|
||||
launchctl stop "$PLIST_NAME" 2>/dev/null || true
|
||||
launchctl unload "$LAUNCHD_DIR/$SERVICE_FILE" 2>/dev/null || true
|
||||
print_success "Service stopped and unloaded"
|
||||
else
|
||||
print_warning "Service is not currently loaded"
|
||||
fi
|
||||
|
||||
# Remove plist file
|
||||
if [ -f "$LAUNCHD_DIR/$SERVICE_FILE" ]; then
|
||||
rm "$LAUNCHD_DIR/$SERVICE_FILE"
|
||||
print_success "Removed service plist file"
|
||||
else
|
||||
print_warning "Service plist file not found"
|
||||
fi
|
||||
else
|
||||
# Linux: Stop and disable systemd service
|
||||
if systemctl is-active --quiet "$SERVICE_NAME" 2>/dev/null; then
|
||||
print_info "Stopping service..."
|
||||
systemctl stop "$SERVICE_NAME"
|
||||
print_success "Service stopped"
|
||||
else
|
||||
print_warning "Service is not currently running"
|
||||
fi
|
||||
|
||||
if systemctl is-enabled --quiet "$SERVICE_NAME" 2>/dev/null; then
|
||||
print_info "Disabling service..."
|
||||
systemctl disable "$SERVICE_NAME" >/dev/null 2>&1
|
||||
print_success "Service disabled"
|
||||
else
|
||||
print_warning "Service is not enabled"
|
||||
fi
|
||||
|
||||
# Remove service file
|
||||
if [ -f "$SYSTEMD_DIR/$SERVICE_NAME.service" ]; then
|
||||
rm "$SYSTEMD_DIR/$SERVICE_NAME.service"
|
||||
print_success "Removed service file"
|
||||
|
||||
# Reload systemd
|
||||
print_info "Reloading systemd configuration"
|
||||
systemctl daemon-reload
|
||||
print_success "Systemd configuration reloaded"
|
||||
else
|
||||
print_warning "Service file not found"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Step 4: Ask about removing installation files
|
||||
print_section "Step 4: Installation Files"
|
||||
if [[ "$INSTALL_EXISTS" == true ]]; then
|
||||
print_warning "Installation directory found: $INSTALL_DIR"
|
||||
print_info "This contains all bot files, including:"
|
||||
echo " • Python scripts and modules"
|
||||
echo " • Configuration files"
|
||||
echo " • Virtual environment"
|
||||
echo " • Database files"
|
||||
echo " • Logs"
|
||||
echo ""
|
||||
|
||||
if ask_yes_no "Do you want to DELETE the installation directory and all its contents?"; then
|
||||
print_warning "This action cannot be undone!"
|
||||
if ask_yes_no "Are you SURE you want to delete $INSTALL_DIR?"; then
|
||||
print_info "Removing installation directory..."
|
||||
rm -rf "$INSTALL_DIR"
|
||||
print_success "Removed installation directory: $INSTALL_DIR"
|
||||
else
|
||||
print_info "Installation directory preserved: $INSTALL_DIR"
|
||||
fi
|
||||
else
|
||||
print_info "Installation directory preserved: $INSTALL_DIR"
|
||||
print_info "You can remove it manually later if needed"
|
||||
fi
|
||||
else
|
||||
print_warning "Installation directory not found: $INSTALL_DIR"
|
||||
print_info "Nothing to remove"
|
||||
fi
|
||||
|
||||
# Step 5: Remove log directory (optional)
|
||||
print_section "Step 5: Log Directory"
|
||||
if [ -d "$LOG_DIR" ]; then
|
||||
rm -rf "$LOG_DIR"
|
||||
echo -e "${GREEN}Removed log directory: $LOG_DIR${NC}"
|
||||
print_info "Log directory found: $LOG_DIR"
|
||||
if ask_yes_no "Do you want to remove the log directory?"; then
|
||||
rm -rf "$LOG_DIR"
|
||||
print_success "Removed log directory: $LOG_DIR"
|
||||
else
|
||||
print_info "Log directory preserved: $LOG_DIR"
|
||||
fi
|
||||
else
|
||||
echo -e "${YELLOW}Log directory not found${NC}"
|
||||
print_warning "Log directory not found: $LOG_DIR"
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}Step 5: Removing service user${NC}"
|
||||
# Remove service user
|
||||
if id "$SERVICE_USER" &>/dev/null; then
|
||||
userdel "$SERVICE_USER"
|
||||
echo -e "${GREEN}Removed user: $SERVICE_USER${NC}"
|
||||
# Step 6: Remove service user (Linux only)
|
||||
if [[ "$IS_LINUX" == true ]]; then
|
||||
print_section "Step 6: Service User"
|
||||
if id "$SERVICE_USER" &>/dev/null; then
|
||||
print_info "Service user found: $SERVICE_USER"
|
||||
if ask_yes_no "Do you want to remove the service user '$SERVICE_USER'?"; then
|
||||
userdel "$SERVICE_USER" 2>/dev/null || {
|
||||
print_warning "Could not remove user (may be in use or have dependencies)"
|
||||
}
|
||||
print_success "Removed service user: $SERVICE_USER"
|
||||
else
|
||||
print_info "Service user preserved: $SERVICE_USER"
|
||||
fi
|
||||
else
|
||||
print_warning "Service user not found: $SERVICE_USER"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Final summary
|
||||
print_section "Uninstallation Complete"
|
||||
echo ""
|
||||
print_success "Service uninstallation completed!"
|
||||
echo ""
|
||||
|
||||
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo -e "${BLUE}📋 Summary${NC}"
|
||||
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo ""
|
||||
|
||||
if [[ "$IS_MACOS" == true ]]; then
|
||||
echo -e " ${CYAN}Service:${NC} Removed from launchd"
|
||||
echo -e " ${CYAN}Service file:${NC} $LAUNCHD_DIR/$SERVICE_FILE (removed)"
|
||||
else
|
||||
echo -e "${YELLOW}User $SERVICE_USER not found${NC}"
|
||||
echo -e " ${CYAN}Service:${NC} Removed from systemd"
|
||||
echo -e " ${CYAN}Service file:${NC} $SYSTEMD_DIR/$SERVICE_NAME.service (removed)"
|
||||
fi
|
||||
|
||||
if [[ "$INSTALL_EXISTS" == true ]]; then
|
||||
if [ -d "$INSTALL_DIR" ]; then
|
||||
echo -e " ${CYAN}Installation:${NC} ${YELLOW}Preserved at $INSTALL_DIR${NC}"
|
||||
else
|
||||
echo -e " ${CYAN}Installation:${NC} ${GREEN}Removed${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e " ${CYAN}Installation:${NC} Not found (may have been removed already)"
|
||||
fi
|
||||
|
||||
if [ -d "$LOG_DIR" ]; then
|
||||
echo -e " ${CYAN}Logs:${NC} ${YELLOW}Preserved at $LOG_DIR${NC}"
|
||||
else
|
||||
echo -e " ${CYAN}Logs:${NC} ${GREEN}Removed${NC}"
|
||||
fi
|
||||
|
||||
if [[ "$IS_LINUX" == true ]]; then
|
||||
if id "$SERVICE_USER" &>/dev/null; then
|
||||
echo -e " ${CYAN}Service user:${NC} ${YELLOW}Preserved: $SERVICE_USER${NC}"
|
||||
else
|
||||
echo -e " ${CYAN}Service user:${NC} ${GREEN}Removed${NC}"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}Uninstallation completed successfully!${NC}"
|
||||
|
||||
# Check for backup files in common locations
|
||||
CONFIG_BACKUP_FOUND=$(find "$HOME_DIR" /tmp /home -name "meshcore-bot-config-backup-*.ini" -type f 2>/dev/null | head -1)
|
||||
DB_BACKUP_FOUND=$(find "$HOME_DIR" /tmp /home -name "meshcore-bot-db-backup-*.db" -type f 2>/dev/null | head -1)
|
||||
|
||||
if [ -n "$CONFIG_BACKUP_FOUND" ] || [ -n "$DB_BACKUP_FOUND" ]; then
|
||||
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo -e "${BLUE}💾 Backup Files${NC}"
|
||||
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo ""
|
||||
|
||||
if [ -n "$CONFIG_BACKUP_FOUND" ]; then
|
||||
print_success "Configuration backup saved to:"
|
||||
echo " ${YELLOW}$CONFIG_BACKUP_FOUND${NC}"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if [ -n "$DB_BACKUP_FOUND" ]; then
|
||||
print_success "Database backup saved to:"
|
||||
echo " ${YELLOW}$DB_BACKUP_FOUND${NC}"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
print_info "You can restore these backups when reinstalling"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo -e "${BLUE}ℹ️ Additional Notes${NC}"
|
||||
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo ""
|
||||
echo -e "${BLUE}What was removed:${NC}"
|
||||
echo " - Systemd service file"
|
||||
echo " - Installation directory: $INSTALL_DIR"
|
||||
echo " - Log directory: $LOG_DIR"
|
||||
echo " - Service user: $SERVICE_USER"
|
||||
print_info "Python packages installed via pip are not automatically removed"
|
||||
print_info "If you want to remove them, run:"
|
||||
echo " ${YELLOW}pip3 uninstall -r requirements.txt${NC}"
|
||||
echo ""
|
||||
|
||||
if [[ "$INSTALL_EXISTS" == true ]] && [ -d "$INSTALL_DIR" ]; then
|
||||
print_warning "Installation files are still present at: $INSTALL_DIR"
|
||||
print_info "You can remove them manually with:"
|
||||
echo " ${YELLOW}sudo rm -rf $INSTALL_DIR${NC}"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
print_success "Uninstallation process completed!"
|
||||
echo ""
|
||||
echo -e "${YELLOW}Note: Python packages installed via pip are not removed${NC}"
|
||||
echo -e "${YELLOW}If you want to remove them, run: pip3 uninstall -r requirements.txt${NC}"
|
||||
|
||||
Reference in New Issue
Block a user