update ui

This commit is contained in:
buchtioof 2026-02-10 15:52:33 +01:00
parent 9471892284
commit ddd114a8fe
3 changed files with 84 additions and 181 deletions

View File

@ -1,21 +1,18 @@
from typing import Optional
from datetime import datetime
from sqlmodel import Field, Session, SQLModel, create_engine, select # <--- Ajout de select
from sqlmodel import Field, Session, SQLModel, create_engine, select
# --- CONFIGURATION BASE DE DONNÉES ---
DB_FILE = "grabberman.db"
sqlite_url = f"sqlite:///{DB_FILE}"
engine = create_engine(sqlite_url, echo=False)
# --- MODÈLE DE DONNÉES (TABLE SQL) ---
class SystemLog(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
date_scan: datetime = Field(default_factory=datetime.now)
mac_address: str = Field(index=True) # On s'en sert pour la recherche
mac_address: str = Field(index=True)
hostname: str
# Champs Hardware
# Hardware
motherboard: Optional[str] = None
cpu_model: Optional[str] = None
cpu_id: Optional[str] = None
@ -25,9 +22,13 @@ class SystemLog(SQLModel, table=True):
cpu_frequency_cur: Optional[str] = None
cpu_frequency_max: Optional[str] = None
gpu_model: Optional[str] = None
ram_slots: Optional[str] = None
# Champs Software
# NOUVEAUX CHAMPS
ram_slots: Optional[str] = None
ram_total: Optional[str] = None
total_storage: Optional[str] = None
# Software
os: Optional[str] = None
arch: Optional[str] = None
desktop_env: Optional[str] = None
@ -37,7 +38,7 @@ class SystemLog(SQLModel, table=True):
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
# --- GESTION DE LA FLOTTE EN MÉMOIRE ---
# Flotte temporaire pour compatibilité, mais on utilise surtout la BDD
flotte = {}
class Grabber:
@ -47,7 +48,6 @@ class Grabber:
self.data_cache = {}
def update(self, json_data):
"""Met à jour les données et prépare l'objet SQLModel."""
hw = json_data.get("HARDWARE", {})
sw = json_data.get("SOFTWARE", {})
@ -67,6 +67,8 @@ class Grabber:
"cpu_frequency_max": hw.get("cpu_frequency_max", "N/A"),
"gpu_model": hw.get("gpu_model", "N/A"),
"ram_slots": hw.get("ram_slots", "N/A"),
"ram_total": hw.get("ram_total", "N/A"), # Ajouté
"total_storage": hw.get("total_storage", "N/A"), # Ajouté
"os": sw.get("os", "N/A"),
"arch": sw.get("arch", "N/A"),
"desktop_env": sw.get("desktop_env", "N/A"),
@ -75,37 +77,22 @@ class Grabber:
}
def save(self):
"""Enregistre ou met à jour les données dans la BDD."""
try:
with Session(engine) as session:
# 1. On cherche si une machine avec cette MAC existe déjà
statement = select(SystemLog).where(SystemLog.mac_address == self.mac_address)
existing_pc = session.exec(statement).first()
if existing_pc:
# --- MISE À JOUR (UPDATE) ---
print(f"Mise à jour de la BDD pour : {self.hostname} ({self.mac_address})")
# On met à jour chaque champ existant
# Update
for key, value in self.data_cache.items():
if hasattr(existing_pc, key):
setattr(existing_pc, key, value)
# On force la mise à jour de la date de scan
existing_pc.date_scan = datetime.now()
session.add(existing_pc)
else:
# --- CRÉATION (INSERT) ---
print(f"Création d'une nouvelle entrée BDD : {self.hostname}")
# Insert
log_entry = SystemLog(**self.data_cache)
session.add(log_entry)
session.commit()
except Exception as e:
print(f"Erreur critique BDD : {e}")
def __getattr__(self, name):
return self.data_cache.get(name, "N/A")
print(f"Erreur BDD : {e}")

View File

@ -4,20 +4,8 @@ export LC_ALL=C
export LANG=C
# ==============================================================================
# Script : grabber.sh
# Date : 2025-12-11
# Version: 0.2
#
# Description :
# Grabber is a bash program that fetch some informations
# of the computer like memory, storage or cpu for exemple.
#
# Usage :
# ./grabber.sh
#
# Dependancies :
# - dmidecode
# - inxi
# Script : grabber.sh
# Version: 0.4 (Full Display)
# ==============================================================================
##### Start process #####
@ -29,29 +17,18 @@ echo " \____| |_| \_\ /_/ \_\ |____/ |____/ |_____| |_| \_\ "
echo " _)(|_ // \ \_ \ \ \ \ _|| \ \_ _|| \ \_ << >> / / \ \ "
echo " (__)__) (__) (__)(__) (__)(__) (__)(__) (__)(__) (__) (__) (__) "
echo ""
echo "Welcome to grabber!"
#----- Verify sudo command -----
if [[ $EUID -ne 0 ]]; then
echo "Please run as root to be able to use superuser commands as dmidecode -> sudo ./grabber.sh"
exit 1
fi
echo ""
#----- Verify dependecies available -----
REQUIRED_CMDS_SIMPLE=(inxi dmidecode lscpu lsblk nproc numfmt)
REQUIRED_CMDS_FULL=(inxi dmidecode lscpu lsblk nproc numfmt python3 jq sqlite3)
#----- Verify dependecies -----
REQUIRED_CMDS=(inxi lscpu lsblk nproc numfmt python3 jq sqlite3)
requirements() {
echo -n "Checking dependencies... "
MISSING=()
for cmd in "${REQUIRED_CMDS_FULL[@]}"; do
for cmd in "${REQUIRED_CMDS[@]}"; do
command -v "$cmd" >/dev/null 2>&1 || MISSING+=("$cmd")
done
if (( ${#MISSING[@]} > 0 )); then
echo "Missing dependencies:"
printf ' - %s\n' "${MISSING[@]}"
echo "Missing dependencies: ${MISSING[*]}"
echo "Install with: sudo apt install ${MISSING[*]}"
exit 1
else
@ -59,109 +36,58 @@ requirements() {
fi
}
#----- Ask what user wants to do -----
echo "What you want grabber to do for you?"
echo "1: Launch grabber"
echo "2: Uninstall grabber"
read -p " 1 / 2 / Cancel(c):- " choice
if [ "$choice" = "1" ]; then
echo "Big work for today"
requirements
elif [ "$choice" = "2" ];then
echo "Uninstalling"
exit
elif [ "$choice" = "c" ];then
echo "Grabber canceled"
exit
else
echo "No choices detected!"
fi
echo "1: Launch grabber | 2: Uninstall | c: Cancel"
read -p ":- " choice
if [ "$choice" = "1" ]; then requirements;
elif [ "$choice" = "2" ]; then rm -rf gbvenv; exit;
elif [ "$choice" = "c" ]; then exit;
else echo "Invalid choice"; exit; fi
##### MAIN VARIABLES #####
DATE=$(date +'%Y-%m-%d_%H:%M:%S')
# Check who is behind sudo command then fetch his $HOME
REAL_USER="${SUDO_USER:-$USER}"
REAL_HOME="$(getent passwd "$REAL_USER" | cut -d: -f6)"
# Declare where to store grabber results
NAME_DIR="logs_$DATE"
WORKING_DIR="$REAL_HOME/grabber/$NAME_DIR"
mkdir $WORKING_DIR -p
# Declare the files to be written
SUM_FILE=$WORKING_DIR/summary.txt
SUCCESS_LOG=$WORKING_DIR/grabber-success.log
ERROR_LOG=$WORKING_DIR/grabber-error.log
############ HARDWARE FETCHER #################
#------------ CPU ----------------
CPU_MODEL=$(lscpu -eMODELNAME | tail -n1 | cut -d' ' -f1,2,3,4)
CPU_ID=$(dmidecode -t processor | grep ID | cut -d: -f2 | sed 's/^ *//' | xargs)
CPU_FREQUENCY_MIN=$(lscpu | grep MHz | cut -d: -f2 | sed -n '3p' | tr -s " " | sed 's/\ //' | cut -d, -f1)
CPU_FREQUENCY_CUR=$(dmidecode | grep "MHz" | cut -d: -f2 | sed -n '3p' | sed 's/\ //')
CPU_FREQUENCY_MAX=$(dmidecode | grep "MHz" | cut -d: -f2 | sed -n '2p' | sed 's/\ //')
CPU_CORES=$(inxi | grep core | cut -d' ' -f2 | sed 's/-core//')
# --- CPU ---
CPU_MODEL=$(lscpu | grep "Model name:" | cut -d: -f2 | sed 's/^ *//')
_VENDOR=$(lscpu | grep "Vendor ID:" | cut -d: -f2 | xargs)
_FAMILY=$(lscpu | grep "CPU family:" | cut -d: -f2 | xargs)
_MODEL=$(lscpu | grep "Model:" | cut -d: -f2 | xargs)
CPU_ID="${_VENDOR} Fam ${_FAMILY} Mod ${_MODEL}"
CPU_FREQUENCY_MIN=$(lscpu | grep "CPU min MHz" | cut -d: -f2 | xargs | cut -d. -f1)
CPU_FREQUENCY_MAX=$(lscpu | grep "CPU max MHz" | cut -d: -f2 | xargs | cut -d. -f1)
CPU_FREQUENCY_CUR=$(grep "cpu MHz" /proc/cpuinfo | head -n1 | cut -d: -f2 | cut -d. -f1 | xargs)
CPU_CORES=$(lscpu | grep "^CPU(s):" | cut -d: -f2 | xargs)
CPU_THREADS=$(nproc)
#---------------------------------
#------------ RAM ----------------
RAM_SIZE=$(lsmem | grep "Total online memory" | cut -d: -f2 | sed 's/\ *//')
RAM_NUMBER=$(dmidecode --type memory | grep 'Rank' | wc -l)
RAM_SLOTS=$(dmidecode --type memory | grep "Number Of Devices" | cut -d: -f2 | sed 's/\ //')
#---------------------------------
# --- RAM ---
# On récupère la RAM totale via free -h
RAM_TOTAL=$(free -h | awk '/^Mem:/ {print $2}')
# On récupère les slots via inxi
RAM_SLOTS=$(inxi -m -c 0 | grep "slots:" | head -n1 | sed -E 's/.*slots: ([0-9]+).*/\1/')
if [ -z "$RAM_SLOTS" ]; then RAM_SLOTS="N/A"; fi
#------------ COMPONENTS ---------
MB_SERIAL=$(dmidecode | grep -A 4 "Base Board" | tail -n1 | cut -d: -f2 | sed 's/\ //')
#------------ STORAGE ------------
disks_partitions(){
declare -a DEVICES
mapfile -t DEVICES < <(lsblk -dn -o NAME |grep -v loop)
declare -A PARTITIONS_BY_DISK
for disk in ${DEVICES[@]}; do
disk_path="/dev/$disk"
disk_parts=$(lsblk -nr -o PKNAME,PATH $disk_path |grep -vE "^\ " |cut -d\ -f 2)
PARTITIONS_BY_DISK[$disk]="${disk_parts[@]}"
done
echo "DISKS=${DEVICES[@]}" >> $SUM_FILE
echo "Partitions in each disks: " >> $SUM_FILE
for disk in ${!PARTITIONS_BY_DISK[@]}; do
echo "PARTS_$disk=$(printf '%s ' ${PARTITIONS_BY_DISK[$disk]})" >> $SUM_FILE
done
}
# --- MOTHERBOARD / GPU ---
MB_SERIAL=$(inxi -M -c 0 | grep "Mobo:" | sed -E 's/.*Mobo: (.*) model: (.*) serial: .*/\1 \2/' | xargs)
[ -z "$MB_SERIAL" ] && MB_SERIAL=$(inxi -M -c 0 | grep "Mobo:" | cut -d: -f2 | cut -d',' -f1 | xargs)
GPU_MODEL=$(inxi -G -c 0 | grep "Device-1:" | cut -d: -f2 | xargs)
# --- STORAGE ---
# Calcul du stockage total
SIZES=$(lsblk -dnb | grep -v loop | grep -v boot | tr -s " " | cut -d \ -f4)
TOTAL_STORAGE=0
for SIZE in ${SIZES[@]}; do
TOTAL_STORAGE+=$SIZE
done
for SIZE in ${SIZES[@]}; do TOTAL_STORAGE=$((TOTAL_STORAGE + SIZE)); done
TOTAL_STORAGE=$(numfmt --to iec $TOTAL_STORAGE)
#---------------------------------
################################################
######## SOFTWARE PART #########################
OS=$(lsb_release -a | grep Description | cut -f2)
ARCH=$(uname -a | cut -d' ' -f10)
# --- SOFTWARE ---
OS=$(lsb_release -d 2>/dev/null | cut -f2 || grep PRETTY_NAME /etc/os-release | cut -d= -f2 | tr -d '"')
ARCH=$(uname -m)
KERNEL=$(uname -r)
HOSTNAME=$(hostname)
MAC_ADDRESS=$(cat /sys/class/net/$(ls /sys/class/net | grep -vE '^(lo|docker|veth|br)' | head -n 1)/address)
DEFAULT_IFACE=$(ls /sys/class/net | grep -vE '^(lo|docker|veth|br)' | head -n 1)
MAC_ADDRESS=$(cat "/sys/class/net/$DEFAULT_IFACE/address" 2>/dev/null || echo "Unknown-MAC")
###############################################
##### JSON PART ###############################
##### JSON PART #####
json_file() {
json_data=$(jq -n \
--arg motherboard "$MB_SERIAL" \
@ -174,12 +100,14 @@ json_file() {
--arg cpu_frequency_max "$CPU_FREQUENCY_MAX" \
--arg gpu_model "$GPU_MODEL" \
--arg ram_slots "$RAM_SLOTS" \
--arg ram_total "$RAM_TOTAL" \
--arg total_storage "$TOTAL_STORAGE" \
--arg hostname "$HOSTNAME" \
--arg mac_address "$MAC_ADDRESS" \
--arg os "$OS" \
--arg arch "$ARCH" \
--arg desktop_env "$XDG_CURRENT_DESKTOP" \
--arg window_manager "$XDG_SESSION_TYPE" \
--arg desktop_env "${XDG_CURRENT_DESKTOP:-N/A}" \
--arg window_manager "${XDG_SESSION_TYPE:-N/A}" \
--arg kernel "$KERNEL" \
'{
HARDWARE: {
@ -192,7 +120,9 @@ json_file() {
cpu_frequency_cur: $cpu_frequency_cur,
cpu_frequency_max: $cpu_frequency_max,
gpu_model: $gpu_model,
ram_slots: $ram_slots
ram_slots: $ram_slots,
ram_total: $ram_total,
total_storage: $total_storage
},
SOFTWARE: {
hostname: $hostname,
@ -206,46 +136,27 @@ json_file() {
}'
)
# Envoi au serveur
curl -X POST http://localhost:8000/endpoint \
-H "Content-Type: application/json" \
-d "$json_data"
-d "$json_data" \
--connect-timeout 5 || echo "Erreur: Serveur injoignable."
}
python_venv() {
if [ ! -d "./gbvenv" ]; then
echo "Virtual environement doesn't exist, creating one..."
python3 -m venv gbvenv
fi
[ ! -d "./gbvenv" ] && python3 -m venv gbvenv
source gbvenv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
pip install -q --upgrade pip
pip install -q -r requirements.txt
uvicorn app:app --reload --host 0.0.0.0 --port 8000
}
if [ "$choice" = "2" ]; then
echo "Grabber has complete his mission! Find every logs saved in your home repository inside the /grabber folder."
echo "See you space cowboy..."
else
echo "It's grabbin time!"
echo "Opening a python virtual environement and starting server..."
# 1. On lance la fonction python_venv en arrière-plan avec '&'
if [ "$choice" = "1" ]; then
echo "Starting Python Server..."
python_venv &
# On récupère l'ID du processus du serveur pour pouvoir l'attendre plus tard
SERVER_PID=$!
echo "Waiting for server to initialize (10s)..."
# 2. On attend quelques secondes que uvicorn soit bien démarré
sleep 5
echo "Pushing fetch data into json file..."
# 3. Maintenant que le serveur tourne, on envoie le JSON
echo "Fetching data..."
json_file
echo "Grabber has complete his mission! Find every logs saved in your home repository inside the /grabber folder."
echo "Server is running on http://localhost:8000. Press Ctrl+C to stop."
# 4. On empêche le script de se fermer (ce qui tuerait le serveur si configuré ainsi)
echo "✅ Dashboard: http://localhost:8000"
wait $SERVER_PID
fi

View File

@ -207,9 +207,18 @@
<span class="label">Coeurs / Threads</span>
<span class="value">{{ ordi.cpu_cores }}C / {{ ordi.cpu_threads }}T</span>
</div>
<div class="data-row">
<span class="label">Fréquence Max</span>
<span class="value">{{ ordi.cpu_frequency_max }} MHz</span>
<span class="label">Mémoire RAM</span>
<span class="value badge badge-ram">{{ ordi.ram_total }}</span>
</div>
<div class="data-row">
<span class="label">Slots RAM</span>
<span class="value">{{ ordi.ram_slots }}</span>
</div>
<div class="data-row">
<span class="label">Stockage Total</span>
<span class="value" style="color: #fbbf24; font-weight:bold;">{{ ordi.total_storage }}</span>
</div>
<div class="data-row">
<span class="label">Carte Mère</span>
@ -219,10 +228,6 @@
<span class="label">GPU</span>
<span class="value">{{ ordi.gpu_model }}</span>
</div>
<div class="data-row">
<span class="label">Slots RAM</span>
<span class="value badge badge-ram">{{ ordi.ram_slots }}</span>
</div>
</div>
<div class="card">