Files
m5rcode-ubuntu/commands/cmd_fastfetch.py
2025-10-09 20:24:27 +02:00

122 lines
4.9 KiB
Python

import platform
import re
import datetime
from pathlib import Path
from colorama import Fore, Style
from pyfiglet import Figlet
try:
import psutil
_PSUTIL_AVAILABLE = True
except ImportError:
_PSUTIL_AVAILABLE = False
def strip_ansi(text):
return re.sub(r'\x1b\[[0-9;]*m', '', text)
class FastfetchCommand:
def _get_uptime(self):
if not _PSUTIL_AVAILABLE:
return "N/A (psutil not installed)"
try:
boot_time_timestamp = psutil.boot_time()
boot_datetime = datetime.datetime.fromtimestamp(boot_time_timestamp)
current_datetime = datetime.datetime.now()
uptime_seconds = (current_datetime - boot_datetime).total_seconds()
days = int(uptime_seconds // (24 * 3600))
uptime_seconds %= (24 * 3600)
hours = int(uptime_seconds // 3600)
uptime_seconds %= 3600
minutes = int(uptime_seconds // 60)
seconds = int(uptime_seconds % 60)
uptime_str = []
if days > 0:
uptime_str.append(f"{days}d")
if hours > 0:
uptime_str.append(f"{hours}h")
if minutes > 0:
uptime_str.append(f"{minutes}m")
if seconds > 0 or not uptime_str:
uptime_str.append(f"{seconds}s")
return " ".join(uptime_str)
except Exception:
return "Error calculating uptime"
def run(self):
m5rcode_version = "1.0.0"
try:
version_file = Path(__file__).parents[1] / "version.txt"
if version_file.exists():
m5rcode_version = version_file.read_text().strip()
except Exception:
pass
# ASCII "M" logo—27 chars wide
ascii_m = [
" _____ ",
" /\\ \\ ",
" /::\\____\\ ",
" /::::| | ",
" /:::::| | ",
" /::::::| | ",
" /:::/|::| | ",
" /:::/ |::| | ",
" /:::/ |::|___|______ ",
" /:::/ |::::::::\\ \\ ",
" /:::/ |:::::::::\\____\\",
" \\::/ / ~~~~~/:::/ / ",
" \\/____/ /:::/ / ",
" /:::/ / ",
" /:::/ / ",
" /:::/ / ",
" /:::/ / ",
" /:::/ / ",
" /:::/ / ",
" \\::/ / ",
" \\/____/ ",
" ",
]
uptime_info = self._get_uptime()
LABEL_PAD = 17
info_lines = [
f"{Fore.CYAN}{'m5rcode Version:':<{LABEL_PAD}}{Style.RESET_ALL} {Fore.LIGHTWHITE_EX}{m5rcode_version}{Style.RESET_ALL}",
f"{Fore.CYAN}{'Python Version:':<{LABEL_PAD}}{Style.RESET_ALL} {Fore.LIGHTWHITE_EX}{platform.python_version()}{Style.RESET_ALL}",
f"{Fore.CYAN}{'Platform:':<{LABEL_PAD}}{Style.RESET_ALL} {Fore.LIGHTWHITE_EX}{platform.system()} {platform.release()}{Style.RESET_ALL}",
f"{Fore.CYAN}{'Machine:':<{LABEL_PAD}}{Style.RESET_ALL} {Fore.LIGHTWHITE_EX}{platform.machine()}{Style.RESET_ALL}",
f"{Fore.CYAN}{'Processor:':<{LABEL_PAD}}{Style.RESET_ALL} {Fore.LIGHTWHITE_EX}{platform.processor()}{Style.RESET_ALL}",
f"{Fore.CYAN}{'Uptime:':<{LABEL_PAD}}{Style.RESET_ALL} {Fore.LIGHTWHITE_EX}{uptime_info}{Style.RESET_ALL}",
]
ascii_width = len(strip_ansi(ascii_m[0]))
content_width = max(len(strip_ansi(line)) for line in info_lines)
sep = " "
sep_width = len(sep)
total_content_width = ascii_width + sep_width + content_width
box_width = max(total_content_width, 48) + 2
# Pad info lines vertically to align with "M"
n_ascii = len(ascii_m)
n_info = len(info_lines)
info_lines_padded = [""] * ((n_ascii - n_info)//2) + info_lines + [""] * (n_ascii - n_info - (n_ascii - n_info)//2)
if len(info_lines_padded) < n_ascii:
info_lines_padded += [""] * (n_ascii - len(info_lines_padded))
# Header
print(Fore.MAGENTA + "" + "" * (box_width-2) + "")
title = f"m5rcode Fastfetch"
print(Fore.MAGENTA + "" + Fore.CYAN + title.center(box_width-2) + Fore.MAGENTA + "")
print(Fore.MAGENTA + "" + "" * (box_width-2) + "")
# Body
for mline, iline in zip(ascii_m, info_lines_padded):
line_content = (mline + sep + iline).rstrip()
pad = " " * (box_width - 2 - len(strip_ansi(line_content)))
print(Fore.MAGENTA + "" + line_content + pad + Fore.MAGENTA + "")
print(Fore.MAGENTA + "" + "" * (box_width-2) + "" + Style.RESET_ALL)