# nzk-scripts

# nzk-app-add

```
#!/bin/bash
#nzk-app-add
#i use kali linux
# Check for at least one argument
if [ "$#" -lt 1 ]; then
    echo "Usage: nzk-app-add <executable> [--icon <iconpath>]"
    exit 1
fi

EXECUTABLE=$(realpath "$1")
APP_NAME=$(basename "$EXECUTABLE")
ICON_PATH=""

# Check for optional icon argument
if [ "$2" == "--icon" ] && [ -n "$3" ]; then
    ICON_PATH=$(realpath "$3")
fi

# Create .desktop file
DESKTOP_ENTRY="$HOME/.local/share/applications/$APP_NAME.desktop"
echo "[Desktop Entry]" > "$DESKTOP_ENTRY"
echo "Type=Application" >> "$DESKTOP_ENTRY"
echo "Name=$APP_NAME" >> "$DESKTOP_ENTRY"
echo "Exec=$EXECUTABLE" >> "$DESKTOP_ENTRY"
echo "Icon=$ICON_PATH" >> "$DESKTOP_ENTRY"
echo "Terminal=false" >> "$DESKTOP_ENTRY"

# Make the .desktop file executable
chmod +x "$DESKTOP_ENTRY"

echo "$APP_NAME added to applications menu."
      
```

# install log fail

┌──(kali㉿kali)-\[~\]  
└─$ cd nzk-apps   
   
┌──(kali㉿kali)-\[~/nzk-apps\]  
└─$ ls  
bash install-NZK-Scripts.sh LICENSE nzk-code README.md  
   
┌──(kali㉿kali)-\[~/nzk-apps\]  
└─$ bash ./install-NZK-Scripts.sh  
Are you NaruZKurai? (y/n)  
If you aren't and you say yes, things will break.  
So if you are you NaruZKurai, v1 will be installed and uses /home/kali as default user path  
Please enter your answer: n  
Cool, let's get started.  
nzk-code3 copied successfully.  
cp: cannot create regular file '/usr/local/bin/nzk-nature': Permission denied  
Failed to copy nzk-nature. Ensure the file exists and try again.  
Installation complete.  
   
┌──(kali㉿kali)-\[~/nzk-apps\]  
└─$ cat ./bash/ nzk-nature  
cat: ./bash/: Is a directory  
cat: nzk-nature: No such file or directory  
   
┌──(kali㉿kali)-\[~/nzk-apps\]  
└─$ cat ./bash/nzk-nature   
\#!/bin/bash  
\#nzk-nature  
\# Define associative arrays for natures and their properties  
CONFIG\_FILE="~/.config/nzk-apps/settings.conf"  
declare -A nature\_stats=(  
 \[0\]="— —" \[1\]="Attack Defense" \[2\]="Attack Speed" \[3\]="Attack Sp. Attack" \[4\]="Attack Sp. Defense"   
 \[5\]="Defense Attack" \[6\]="— —" \[7\]="Defense Speed" \[8\]="Defense Sp. Attack" \[9\]="Defense Sp. Defense"   
 \[10\]="Speed Attack" \[11\]="Speed Defense" \[12\]="— —" \[13\]="Speed Sp. Attack" \[14\]="Speed Sp. Defense"   
 \[15\]="Sp. Attack Attack" \[16\]="Sp. Attack Defense" \[17\]="Sp. Attack Speed" \[18\]="— —" \[19\]="Sp. Attack Sp. Defense"   
 \[20\]="Sp. Defense Attack" \[21\]="Sp. Defense Defense" \[22\]="Sp. Defense Speed" \[23\]="Sp. Defense Sp. Attack" \[24\]="— —"  
)  
declare -A nature\_flavors\_english=(  
 \[0\]="— —" \[1\]="Spicy Sour" \[2\]="Spicy Sweet" \[3\]="Spicy Dry" \[4\]="Spicy Bitter"   
 \[5\]="Sour Spicy" \[6\]="— —" \[7\]="Sour Sweet" \[8\]="Sour Dry" \[9\]="Sour Bitter"   
 \[10\]="Sweet Spicy" \[11\]="Sweet Sour" \[12\]="— —" \[13\]="Sweet Dry" \[14\]="Sweet Bitter"   
 \[15\]="Dry Spicy" \[16\]="Dry Sour" \[17\]="Dry Sweet" \[18\]="— —" \[19\]="Dry Bitter"   
 \[20\]="Bitter Spicy" \[21\]="Bitter Sour" \[22\]="Bitter Sweet" \[23\]="Bitter Dry" \[24\]="— —"  
)  
declare -A nature\_flavors\_japanese=(  
 \[0\]="— —" \[1\]="からい すっぱい" \[2\]="からい あまい" \[3\]="からい のま" \[4\]="からい にがい"   
 \[5\]="すっぱい からい" \[6\]="— —" \[7\]="すっぱい あまい" \[8\]="すっぱい のま" \[9\]="すっぱい にがい"   
 \[10\]="あまい からい" \[11\]="あまい すっぱい" \[12\]="— —" \[13\]="あまい のま" \[14\]="あまい にがい"   
 \[15\]="のま からい" \[16\]="のま すっぱい" \[17\]="のま あまい" \[18\]="— —" \[19\]="のま にがい"   
 \[20\]="にがい からい" \[21\]="にがい すっぱい" \[22\]="にがい あまい" \[23\]="にがい のま" \[24\]="— —"  
)  
declare -A nature\_flavors\_romanji=(  
 \[0\]="— —" \[1\]="Karaī Suppai" \[2\]="Karaī Amai" \[3\]="Karaī Noma" \[4\]="Karaī Nigai"   
 \[5\]="Suppai Karaī" \[6\]="— —" \[7\]="Suppai Amai" \[8\]="Suppai Noma" \[9\]="Suppai Nigai"   
 \[10\]="Amai Karaī" \[11\]="Amai Suppai" \[12\]="— —" \[13\]="Amai Noma" \[14\]="Amai Nigai"   
 \[15\]="Noma Karaī" \[16\]="Noma Suppai" \[17\]="Noma Amai" \[18\]="— —" \[19\]="Noma Nigai"   
 \[20\]="Nigai Karaī" \[21\]="Nigai Suppai" \[22\]="Nigai Amai" \[23\]="Nigai Noma" \[24\]="— —"  
)  
\# Define associative arrays for English, Japanese, and Romanji nature names  
declare -A english\_natures=(   
 \[0\]="Hardy" \[1\]="Lonely" \[2\]="Brave" \[3\]="Adamant" \[4\]="Naughty"   
 \[5\]="Bold" \[6\]="Docile" \[7\]="Relaxed" \[8\]="Impish" \[9\]="Lax"   
 \[10\]="Timid" \[11\]="Hasty" \[12\]="Serious" \[13\]="Jolly" \[14\]="Naive"   
 \[15\]="Modest" \[16\]="Mild" \[17\]="Quiet" \[18\]="Bashful" \[19\]="Rash"   
 \[20\]="Calm" \[21\]="Gentle" \[22\]="Sassy" \[23\]="Careful" \[24\]="Quirky"   
)  
declare -A japanese\_natures=(   
 \[0\]="がんばりや" \[1\]="さみしがり" \[2\]="ゆうかん" \[3\]="いじっぱり" \[4\]="やんちゃ"   
 \[5\]="ずぶとい" \[6\]="すなお" \[7\]="のんき" \[8\]="わんぱく" \[9\]="のうてんき"   
 \[10\]="おくびょう" \[11\]="せっかち" \[12\]="まじめ" \[13\]="ようき" \[14\]="むじゃき"   
 \[15\]="ひかえめ" \[16\]="おっとり" \[17\]="れいせい" \[18\]="てれや" \[19\]="うっかりや"   
 \[20\]="おだやか" \[21\]="おとなしい" \[22\]="なまいき" \[23\]="しんちょう" \[24\]="きまぐれ"   
)  
declare -A romanji\_natures=(  
 \[0\]="Gannbariya" \[1\]="Samishigari" \[2\]="Yuukan" \[3\]="Ijippari" \[4\]="Yancha"   
 \[5\]="Zubutoi" \[6\]="Sunao" \[7\]="Nonnki" \[8\]="Wanpaku" \[9\]="Noutennki"   
 \[10\]="Okubiyou" \[11\]="Sekkachi" \[12\]="Majime" \[13\]="Youki" \[14\]="Mujyaki"   
 \[15\]="Hikaeme" \[16\]="Ottori" \[17\]="Reisei" \[18\]="Tereya" \[19\]="Ukkariya"   
 \[20\]="Odayaka" \[21\]="Otonashii" \[22\]="Namaiki" \[23\]="Shinnchyou" \[24\]="Kimagure"  
)  
\# Function to find the index of a nature name, case-insensitive  
find\_nature\_index() {  
 local nature\_name\_lower=$(echo "$1" | tr '\[:upper:\]' '\[:lower:\]')  
 local -n arr=$2  
 for i in "${!arr\[@\]}"; do  
 if \[\[ "$(echo "${arr\[$i\]}" | tr '\[:upper:\]' '\[:lower:\]')" == "$nature\_name\_lower" \]\]; then  
 echo $i  
 return  
 fi  
 done  
 echo "-1"  
}

\# Check for correct number of arguments  
if \[ $# -ne 2 \]; then  
 echo "Usage: $0 &lt;nature\_name&gt; \[-e|-j|-r\]"  
 exit 1  
fi

\# Get the nature name and flag  
nature\_name="$1"  
flag="$2"

\# Main logic to get nature information based on flag and nature name  
case $flag in  
 -e)  
 index=$(find\_nature\_index "$nature\_name" english\_natures)  
 if \[\[ $index -ne -1 \]\]; then  
 echo "${japanese\_natures\[$index\]}"  
 else  
 echo "Error: Nature '$nature\_name' not found in English natures."  
 fi  
 ;;  
 -j)  
 index=$(find\_nature\_index "$nature\_name" japanese\_natures)  
 if \[\[ $index -ne -1 \]\]; then  
 echo "${english\_natures\[$index\]}"  
 else  
 echo "Error: Nature '$nature\_name' not found in Japanese natures."  
 fi  
 ;;  
 -r)  
 index=$(find\_nature\_index "$nature\_name" romanji\_natures)  
 if \[\[ $index -ne -1 \]\]; then  
 echo "${english\_natures\[$index\]}"  
 else  
 echo "Error: Nature '$nature\_name' not found in Romanji natures."  
 fi  
 ;;  
 \*)  
 echo "Invalid flag: $flag. Use -e for English to Japanese, -j for Japanese to English, -r for Romanji to English."  
 echo "correct usage would be something like:"  
 echo "nzk-nature "jolly" -e"  
 exit 1  
 ;;  
esac  
   
┌──(kali㉿kali)-\[~/nzk-apps\]  
└─$

# py scripts from other repo's that i use (need to add to my repo)

[https://github.com/Crypto-Cat/CTF/blob/main/pentesting/gen\_nmap.py](https://github.com/Crypto-Cat/CTF/blob/main/pentesting/gen_nmap.py)

```python
#!/bin/python
#
# can be found on crypto cat's repo, 
# https://github.com/Crypto-Cat/CTF/blob/main/pentesting/gen_nmap.py
#
# sudo apt-get install python3 masscan nmap
#
# This script will take in Masscan results and produce an output which can be fed into NMap

# Save your Masscan result as mscan.txt then run this script to produce nmap.txt then you can run:
# while read item; do sudo nmap -sV -sC -sS -sU $item; done < nmap.txt; rm mscan.txt nmap.txt

# If you want to export to .xml file you can use the following command and then later use this script to merge files: https://github.com/sidaf/scripts/blob/master/nmap_merge.py
# while read item; do filename=$(echo $item | grep -o "^\S*"); sudo nmap -O -sV -sC -sS -sU $item -oX $filename.xml; done < nmap.txt

import re
from socket import inet_aton
from os import path

regex = re.compile(r"Discovered open port (\d+)\/(udp|tcp) on (\d+\.\d+\.\d+\.\d+)", re.I)

ip_list = {}

with open(path.abspath('mscan.txt')) as f:
    lines = f.readlines()
    for line in lines:
        port = regex.match(line).group(1)
        protocol = regex.match(line).group(2)
        ip = regex.match(line).group(3)

        # Add the IP to dictionary if it's not already
        try:
            ip_list[ip]
        except KeyError:
            ip_list[ip] = {}

        # Add protocol to dictionary if it's not already
        try:
            ip_list[ip][protocol]
        except KeyError:
            ip_list[ip][protocol] = []

        # Append the port to the list
        ip_list[ip][protocol].append(port)

with open(path.abspath('nmap.txt'), 'a') as f:
    sorted_ips = sorted(ip_list.items(), key=lambda item: inet_aton(item[0]))
    for ip, protocols in sorted_ips:
        udp_ports = ""
        tcp_ports = ""

        # Check to see if any UDP ports were found
        try:
            for port in protocols['udp']:
                udp_ports += port + ','
        except KeyError:
            pass

        # Check to see if any TCP ports were found
        try:
            for port in protocols['tcp']:
                tcp_ports += port + ','
        except KeyError:
            pass

        # Print IP and ports to file ready for NMap scan
        if udp_ports and tcp_ports:
            line = ip + ' -p U:' + udp_ports + 'T:' + tcp_ports
        elif udp_ports:
            line = ip + ' -p U:' + udp_ports
        elif tcp_ports:
            line = ip + ' -p T:' + tcp_ports
        f.write(line + '\n')
```

# new ubuntu script

```
sudo apt update && sudo apt install -y firefox ubuntu-restricted-extras build-essential curl wget software-properties-common kde-plasma-desktop inkscape gimp openscad meshlab librecad python3 python3-tk python3-pip flatpak gnome-software-plugin-flatpak && \
[ -f /tmp/chrome.deb ] || wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb -O /tmp/chrome.deb && sudo apt install -y /tmp/chrome.deb || sudo apt --fix-broken install -y && \
sudo ubuntu-drivers install && \
sudo dpkg --add-architecture i386 && sudo apt update && sudo apt install -y wine64 wine32 winetricks lutris && \
[ -f /tmp/obsidian.deb ] || wget "$(curl -s https://api.github.com/repos/obsidianmd/obsidian-releases/releases/latest | grep browser_download_url | grep amd64.deb | cut -d '"' -f 4)" -O /tmp/obsidian.deb && sudo apt install -y /tmp/obsidian.deb && \
wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo tee /usr/share/keyrings/vscode.gpg > /dev/null && \
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/vscode.gpg] https://packages.microsoft.com/repos/vscode stable main" | sudo tee /etc/apt/sources.list.d/vscode.list > /dev/null && \
sudo apt update && sudo apt install -y code && \
flatpak remote-add -y --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo && \
flatpak install -y flathub com.ultimaker.cura org.freecadweb.FreeCAD org.kicad.KiCad org.blender.Blender com.github.tchx84.Flatseal com.prusa3d.PrusaSlicer && \
sudo pip3 install bCNC && \
[ -f /usr/local/bin/OpenBuildsCONTROL.AppImage ] || wget https://github.com/OpenBuilds/OpenBuilds-Control/releases/latest/download/OpenBuildsCONTROL.AppImage -O /usr/local/bin/OpenBuildsCONTROL.AppImage && chmod +x /usr/local/bin/OpenBuildsCONTROL.AppImage && \
[ -f /tmp/ugs.tar.gz ] || wget https://github.com/winder/Universal-G-Code-Sender/releases/latest/download/ugsplatform-linux.tar.gz -O /tmp/ugs.tar.gz && mkdir -p /opt/UGS && tar -xzf /tmp/ugs.tar.gz -C /opt/UGS && \
WINEPREFIX=~/.wine-sparkmax winecfg && \
[ -f ~/sparkmax-client-latest.msi ] || wget https://www.revrobotics.com/content/sw/max/sparkmax-client-latest.msi -O ~/sparkmax-client-latest.msi && \
WINEPREFIX=~/.wine-sparkmax wine msiexec /i ~/sparkmax-client-latest.msi && \
sudo mkdir -p /etc/skel/Desktop && cd /etc/skel/Desktop && \
for app in firefox code obsidian prusa-slicer cura freecad kicad blender gimp inkscape bCNC wine OpenBuildsCONTROL.AppImage; do \
  echo "[Desktop Entry]\nName=$app\nExec=$(command -v $app || echo $app)\nIcon=utilities-terminal\nType=Application\nTerminal=false" | sudo tee "$app.desktop" > /dev/null; \
  chmod +x "$app.desktop"; \
done && \
[ -x /usr/local/bin/OpenBuildsCONTROL.AppImage ] || /usr/local/bin/OpenBuildsCONTROL.AppImage && \
[ -d /opt/UGS ] || xdg-open https://github.com/winder/Universal-G-Code-Sender/releases

```

orignial@Robotronix-cad-orignial:~$ sudo apt update &amp;&amp; sudo apt install -y firefox ubuntu-restricted-extras build-essential curl wget software-properties-common kde-plasma-desktop inkscape gimp openscad meshlab librecad python3 python3-tk python3-pip flatpak gnome-software-plugin-flatpak &amp;&amp; \\  
\[ -f /tmp/chrome.deb \] || wget https://dl.google.com/linux/direct/google-chrome-stable\_current\_amd64.deb -O /tmp/chrome.deb &amp;&amp; sudo apt install -y /tmp/chrome.deb || sudo apt --fix-broken install -y &amp;&amp; \\  
sudo ubuntu-drivers install &amp;&amp; \\  
sudo dpkg --add-architecture i386 &amp;&amp; sudo apt update &amp;&amp; sudo apt install -y wine64 wine32 winetricks lutris &amp;&amp; \\  
\[ -f /tmp/obsidian.deb \] || wget "$(curl -s https://api.github.com/repos/obsidianmd/obsidian-releases/releases/latest | grep browser\_download\_url | grep amd64.deb | cut -d '"' -f 4)" -O /tmp/obsidian.deb &amp;&amp; sudo apt install -y /tmp/obsidian.deb &amp;&amp; \\  
wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo tee /usr/share/keyrings/vscode.gpg &gt; /dev/null &amp;&amp; \\  
echo "deb \[arch=amd64 signed-by=/usr/share/keyrings/vscode.gpg\] https://packages.microsoft.com/repos/vscode stable main" | sudo tee /etc/apt/sources.list.d/vscode.list &gt; /dev/null &amp;&amp; \\  
sudo apt update &amp;&amp; sudo apt install -y code &amp;&amp; \\  
flatpak remote-add -y --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo &amp;&amp; \\  
flatpak install -y flathub com.ultimaker.cura org.freecadweb.FreeCAD org.kicad.KiCad org.blender.Blender com.github.tchx84.Flatseal com.prusa3d.PrusaSlicer &amp;&amp; \\leasesopt/UGS \] || xdg-open https://github.com/winder/Universal-G-Code-Sender/re  
Hit:1 http://ca.archive.ubuntu.com/ubuntu plucky InRelease  
Hit:2 http://security.ubuntu.com/ubuntu plucky-security InRelease   
Hit:3 http://ca.archive.ubuntu.com/ubuntu plucky-updates InRelease   
Hit:4 http://ca.archive.ubuntu.com/ubuntu plucky-backports InRelease   
Hit:5 https://dl.google.com/linux/chrome/deb stable InRelease   
All packages are up to date.   
Notice: Some sources can be modernized. Run 'apt modernize-sources' to do so.  
firefox is already the newest version (1:1snap1-0ubuntu7).  
ubuntu-restricted-extras is already the newest version (67).  
build-essential is already the newest version (12.10ubuntu1).  
curl is already the newest version (8.12.1-3ubuntu1).  
wget is already the newest version (1.24.5-2ubuntu1).  
software-properties-common is already the newest version (0.109).  
kde-plasma-desktop is already the newest version (5:159ubuntu1).  
inkscape is already the newest version (1.2.2-8build1).  
gimp is already the newest version (3.0.0-2).  
openscad is already the newest version (2021.01-8build1).  
meshlab is already the newest version (2022.02+dfsg1-1).  
librecad is already the newest version (2.2.0.2-1build3).  
python3 is already the newest version (3.13.2-2).  
python3-tk is already the newest version (3.13.2-1).  
python3-pip is already the newest version (25.0+dfsg-1).  
flatpak is already the newest version (1.16.0-2).  
gnome-software-plugin-flatpak is already the newest version (48.0-1).  
The following package was automatically installed and is no longer required:  
 grub-pc-bin  
Use 'sudo apt autoremove' to remove it.

Summary:  
 Upgrading: 0, Installing: 0, Removing: 0, Not Upgrading: 0  
Note, selecting 'google-chrome-stable' instead of '/tmp/chrome.deb'  
google-chrome-stable is already the newest version (134.0.6998.165-1).  
The following package was automatically installed and is no longer required:  
 grub-pc-bin  
Use 'sudo apt autoremove' to remove it.

Summary:  
 Upgrading: 0, Installing: 0, Removing: 0, Not Upgrading: 0

All the available drivers are already installed.  
Get:1 http://ca.archive.ubuntu.com/ubuntu plucky InRelease \[265 kB\]  
Hit:2 http://security.ubuntu.com/ubuntu plucky-security InRelease   
Hit:3 https://dl.google.com/linux/chrome/deb stable InRelease   
Hit:4 http://ca.archive.ubuntu.com/ubuntu plucky-updates InRelease   
Hit:5 http://ca.archive.ubuntu.com/ubuntu plucky-backports InRelease  
Get:6 http://ca.archive.ubuntu.com/ubuntu plucky/main amd64 Packages \[1,437 kB\]  
Get:7 http://ca.archive.ubuntu.com/ubuntu plucky/main i386 Packages \[1,072 kB\]  
Get:8 http://ca.archive.ubuntu.com/ubuntu plucky/main Translation-en \[521 kB\]  
Get:9 http://ca.archive.ubuntu.com/ubuntu plucky/main amd64 c-n-f Metadata \[31.7 kB\]  
Get:10 http://ca.archive.ubuntu.com/ubuntu plucky/universe i386 Packages \[8,852 kB\]  
Get:11 http://ca.archive.ubuntu.com/ubuntu plucky/universe amd64 Packages \[15.9 MB\]  
Get:12 http://ca.archive.ubuntu.com/ubuntu plucky/universe Translation-en \[6,266 kB\]  
Get:13 http://ca.archive.ubuntu.com/ubuntu plucky/universe amd64 c-n-f Metadata \[309 kB\]  
Fetched 34.6 MB in 12s (2,909 kB/s)   
All packages are up to date.   
Notice: Some sources can be modernized. Run 'apt modernize-sources' to do so.  
wine64 is already the newest version (9.0~repack-4build3).  
wine32:i386 is already the newest version (9.0~repack-4build3).  
winetricks is already the newest version (20250102-1).  
lutris is already the newest version (0.5.17-2).  
The following package was automatically installed and is no longer required:  
 grub-pc-bin  
Use 'sudo apt autoremove' to remove it.

Summary:  
 Upgrading: 0, Installing: 0, Removing: 0, Not Upgrading: 0  
Reading package lists... Error!  
Error: read, still have 8 to read but none left  
Error: Internal error, could not locate member control.tar{.zst,.lz4,.gz,.xz,.bz2,.lzma,}  
Error: Could not read meta data from /tmp/obsidian.deb  
Error: The package lists or status file could not be parsed or opened.  
/usr/local/bin/OpenBuildsCONTROL.AppImage: Permission denied  
\--2025-03-22 04:22:47-- https://github.com/winder/Universal-G-Code-Sender/releases/latest/download/ugsplatform-linux.tar.gz  
Resolving github.com (github.com)... 140.82.114.4  
Connecting to github.com (github.com)|140.82.114.4|:443... connected.  
HTTP request sent, awaiting response... 302 Found  
Location: https://github.com/winder/Universal-G-Code-Sender/releases/download/v2.1.12/ugsplatform-linux.tar.gz \[following\]  
\--2025-03-22 04:22:47-- https://github.com/winder/Universal-G-Code-Sender/releases/download/v2.1.12/ugsplatform-linux.tar.gz  
Reusing existing connection to github.com:443.  
HTTP request sent, awaiting response... 404 Not Found  
2025-03-22 04:22:47 ERROR 404: Not Found.

\--2025-03-22 04:22:47-- https://www.revrobotics.com/content/sw/max/sparkmax-client-latest.msi  
Resolving www.revrobotics.com (www.revrobotics.com)... 192.200.160.248  
Connecting to www.revrobotics.com (www.revrobotics.com)|192.200.160.248|:443... connected.  
HTTP request sent, awaiting response... 404 Not Found  
2025-03-22 04:22:48 ERROR 404: Not Found.

bash: /usr/local/bin/OpenBuildsCONTROL.AppImage: No such file or directory  
orignial@Robotronix-cad-orignial:~$ Gtk-Message: 04:22:48.965: Not loading module "atk-bridge": The functionality is provided by GTK natively. Please try to not load it.

```
install_if_missing() { pkgs=""; for p in "$@"; do dpkg -s "$p" &>/dev/null || pkgs="$pkgs $p"; done; [ -n "$pkgs" ] && sudo apt install -y $pkgs; } && \
sudo apt update && \
install_if_missing firefox ubuntu-restricted-extras build-essential curl wget software-properties-common kde-plasma-desktop inkscape gimp openscad meshlab librecad python3 python3-tk python3-pip flatpak gnome-software-plugin-flatpak && \
([ -f /tmp/chrome.deb ] || wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb -O /tmp/chrome.deb) && sudo apt install -y /tmp/chrome.deb || sudo apt --fix-broken install -y && \
sudo ubuntu-drivers install && \
sudo dpkg --add-architecture i386 && sudo apt update && \
install_if_missing wine64 wine32 winetricks lutris && \
[ -f /tmp/obsidian.deb ] || wget "$(curl -s https://api.github.com/repos/obsidianmd/obsidian-releases/releases/latest | grep browser_download_url | grep amd64.deb | cut -d '"' -f 4)" -O /tmp/obsidian.deb && sudo apt install -y /tmp/obsidian.deb && \
wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo tee /usr/share/keyrings/vscode.gpg > /dev/null && \
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/vscode.gpg] https://packages.microsoft.com/repos/vscode stable main" | sudo tee /etc/apt/sources.list.d/vscode.list > /dev/null && \
sudo apt update && install_if_missing code && \
flatpak remote-add -y --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo && \
flatpak install -y flathub com.ultimaker.cura org.freecadweb.FreeCAD org.kicad.KiCad org.blender.Blender com.github.tchx84.Flatseal com.prusa3d.PrusaSlicer && \
sudo pip3 install bCNC && \
[ -f /usr/local/bin/OpenBuildsCONTROL.AppImage ] || { sudo wget https://github.com/OpenBuilds/OpenBuilds-Control/releases/latest/download/OpenBuildsCONTROL.AppImage -O /usr/local/bin/OpenBuildsCONTROL.AppImage && sudo chmod +x /usr/local/bin/OpenBuildsCONTROL.AppImage; } && \
UGS_URL="$(curl -s https://api.github.com/repos/winder/Universal-G-Code-Sender/releases/latest | grep browser_download_url | grep 'ugsplatform-linux.tar.gz' | cut -d '\"' -f 4)" && \
[ -f /tmp/ugs.tar.gz ] || wget "$UGS_URL" -O /tmp/ugs.tar.gz && mkdir -p /opt/UGS && tar -xzf /tmp/ugs.tar.gz -C /opt/UGS && \
WINEPREFIX=~/.wine-sparkmax winecfg && \
[ -f ~/REV-Hardware-Client.exe ] || wget "$(curl -s https://api.github.com/repos/REVrobotics/REV-Software-Binaries/releases/latest | grep browser_download_url | grep 'REV-Hardware-Client-Setup' | grep exe | cut -d '"' -f 4)" -O ~/REV-Hardware-Client.exe && \
WINEPREFIX=~/.wine-sparkmax wine ~/REV-Hardware-Client.exe && \
sudo mkdir -p /etc/skel/Desktop && cd /etc/skel/Desktop && \
for app in firefox code obsidian prusa-slicer cura freecad kicad blender gimp inkscape bCNC wine OpenBuildsCONTROL.AppImage; do \
  echo "[Desktop Entry]\nName=$app\nExec=$(command -v $app || echo $app)\nIcon=utilities-terminal\nType=Application\nTerminal=false" | sudo tee "$app.desktop" > /dev/null; \
  chmod +x "$app.desktop"; \
done && \
[ -x /usr/local/bin/OpenBuildsCONTROL.AppImage ] || /usr/local/bin/OpenBuildsCONTROL.AppImage && \
[ -d /opt/UGS ] || xdg-open https://github.com/winder/Universal-G-Code-Sender/releases

```

# recharjme

# ubuntu kiosk with phidgethub using touch screen

```powershell
#!/bin/bash
set -eu
# Enable pipefail if supported
if set -o | grep -q pipefail; then
    set -o pipefail
fi

# Function definitions for each section
section_1() {
    #read "Press [Enter] key to continue... stopping screen blanking (best effort for GNOME; harmless on Plasma)"
    ##############################################
    # SECTION 1: POWER MANAGEMENT AND SCREEN BLANKING for current user
    ##############################################
    echo "=== SECTION 1: POWER MANAGEMENT AND SCREEN BLANKING ==="
    # Stop screen blanking/suspend for kiosk session (no-op if schema absent)
    current_user=$(logname 2>/dev/null || echo "$SUDO_USER" || echo "$USER")
    sudo -u "$current_user" dbus-run-session gsettings set org.gnome.desktop.session idle-delay 0 || true
    sudo -u "$current_user" dbus-run-session gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-type 'nothing' || true
    sudo -u "$current_user" dbus-run-session gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-battery-type 'nothing' || true
}

section_2() {
    ##############################################
    # SECTION 2: INITIAL SYSTEM SETUP
    ##############################################
    echo "=== SECTION 2: INITIAL SYSTEM SETUP ==="
    apt-get update -yq
    apt-get upgrade -yq
    apt-get update -yq
    apt install -yq kde-plasma-desktop chromium-browser xdotool unclutter sed curl libinput-tools net-tools ssh

    #wait for user input 
    #read "Press [Enter] key to continue... try gdm3, ssdm has issues with my app"
}

section_3() {
    #######################################################
    # SECTION 3: DESKTOP ENVIRONMENT INSTALLATION
    #######################################################
    echo "=== SECTION 3: DESKTOP ENVIRONMENT INSTALLATION ==="
    systemctl enable ssh

    #wait for user input 
    #read "Press [Enter] key to continue... plasma installed. installing other stuff for phidget and enabling ssh  "
}

section_4() {
    ##############################################
    # SECTION 4: PHIDGET SETUP AND DEPENDENCIES
    ##############################################
    echo "=== SECTION 4: PHIDGET SETUP AND DEPENDENCIES ==="
    apt install -y chromium-browser sed xdotool unclutter
    curl -fsSL https://www.phidgets.com/downloads/setup_linux | bash -
    apt install -y libphidget22 phidget22networkserver
    apt install -y libphidget22* phidget22*
    apt install -y python3 npm nodejs 
    ifconfig
}

section_5() {
    ##############################################
    # SECTION 5: TOUCHSCREEN CONFIGURATION
    ##############################################
    echo "=== SECTION 5: TOUCHSCREEN CONFIGURATION ==="
    #setup touchscreen
    echo -e "usbtouchscreen\nusbhid" |  tee /etc/modules-load.d/touchscreen.conf
    modprobe usbtouchscreen
    modprobe usbhid
    lsmod | grep usb
    lsmod | grep hid
    lsmod | grep usb
    lsmod | grep hid
    dmesg | grep -i touch
}

section_6() {
    ##############################################
    # SECTION 6: PHIDGET NETWORK SERVER SETUP
    ##############################################
    echo "=== SECTION 6: PHIDGET NETWORK SERVER SETUP ==="
    #setup phidget22networkserver 
    DEFAULT_PHIDGET_PORT_VAR=""
    DEFAULT_WEB_PORT_VAR=""
    SERVICE_NAME="phidget22networkserver"
    INIT_PATH="/etc/init.d/$SERVICE_NAME"
    #v1 (works???)
    if [[ "$(id -u)" -ne 0 ]]; then
      echo "Run this as root."
      exit 1
    fi

    cat > "$INIT_PATH" <<'EOF'
#!/bin/sh
### BEGIN INIT INFO
# Provides:          phidget22networkserver
# Required-Start:    $network $remote_fs
# Required-Stop:     $network $remote_fs
# Should-Start:      avahi avahi-daemon
# Should-Stop:       avahi avahi-daemon
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Phidget Network Server
# Description:       Phidget network server for accessing Phidgets over the network.
### END INIT INFO

sudo phidget22networkserver -c /etc/phidgets/phidget22networkserver.pc -D

EOF

    #add ipv6 to phidget config??? { port: 8080 }   

    chmod +x "$INIT_PATH"
    sudo sed -i "s#docroot: '/var/phidgets/www'#docroot: '/home/recharjme/Desktop/APP'#" /etc/phidgets/phidget22networkserver.pc
    update-rc.d "$SERVICE_NAME" defaults
    service "$SERVICE_NAME" start
    systemctl daemon-reload
    systemctl enable "$SERVICE_NAME"
    systemctl restart "$SERVICE_NAME"
    #systemctl status "$SERVICE_NAME"

    #wait for user input 
   # read "Press [Enter] key to continue... this is usuially where shit breaks"
}

section_7() {
    ##############################################
    # SECTION 7: KIOSK USER SETUP
    ##############################################
    echo "=== SECTION 7: KIOSK USER SETUP ==="
    # 1) Ensure kiosk exists
    if ! id kiosk &>/dev/null; then adduser --disabled-password --gecos "" kiosk; fi
    passwd -d kiosk || true
    usermod -aG sudo kiosk

    install -d -m 0755 /home/kiosk/.config/autostart
    chown -R kiosk:kiosk /home/kiosk

    #read "Press [Enter] key to continue... touch works now, configuring GDM for Plasma Wayland"

    # Force Wayland in GDM for admin acct
    sed -i 's/^#\?WaylandEnable=.*/WaylandEnable=true/' /etc/gdm3/custom.conf
    grep WaylandEnable /etc/gdm3/custom.conf || true

    #read "Press [Enter] key to continue... setting autologin for GDM3 (Plasma Wayland)"

    sudo -u kiosk kwriteconfig6 --file startkderc --group General --key desktopSession empty
    sudo -u kiosk kwriteconfig6 --file ksmserverrc --group General --key loginMode emptySession

}

section_8() {
    ##############################################
    # SECTION 8: GDM3 AUTOLOGIN CONFIGURATION
    ##############################################
    echo "=== SECTION 8: GDM3 AUTOLOGIN CONFIGURATION ==="
    # GDM3 Autologin to Plasma Wayland
    if [ -f /etc/gdm3/custom.conf ]; then
      awk '
        BEGIN{inDaemon=0; hasALE=0; hasAL=0; hasDS=0}
        /^\[daemon\]/{inDaemon=1; print; next}
        /^\[/{ if(inDaemon && !(hasALE&&hasAL&&hasDS)){print "AutomaticLoginEnable=true\nAutomaticLogin=kiosk\nDefaultSession=plasma"}; inDaemon=0; print; next}
        {
          if(inDaemon){
            if($0 ~ /^AutomaticLoginEnable=/){$0="AutomaticLoginEnable=true"; hasALE=1}
            if($0 ~ /^AutomaticLogin=/){$0="AutomaticLogin=kiosk"; hasAL=1}
            if($0 ~ /^DefaultSession=/){$0="DefaultSession=plasma"; hasDS=1}
          }
          print
        }
        END{
          if(inDaemon && !(hasALE&&hasAL&&hasDS)){
            print "AutomaticLoginEnable=true"
            print "AutomaticLogin=kiosk"
            print "DefaultSession=plasma"
          }
        }
      ' /etc/gdm3/custom.conf > /tmp/custom.conf && mv /tmp/custom.conf /etc/gdm3/custom.conf

      # Make sure AccountsService maps kiosk -> plasma
      install -d -m 0755 /var/lib/AccountsService/users
      cat >/var/lib/AccountsService/users/kiosk <<'EOF'
[User]
XSession=plasma
SystemAccount=false
EOF
      chmod 0644 /var/lib/AccountsService/users/kiosk
      #systemctl restart gdm3
    fi
}

section_9() {
    ##############################################
    # SECTION 9: SDDM CONFIGURATION (ALTERNATIVE)
    ##############################################
    echo "=== SECTION 9: SDDM CONFIGURATION (ALTERNATIVE) ==="

    # Make sure /etc/sddm.conf exists
    [ -f /etc/sddm.conf ] || touch /etc/sddm.conf

    # Ensure autologin block exists and points to kiosk + plasma
    if grep -q '^\[Autologin\]' /etc/sddm.conf; then
        sed -i '/^\[Autologin\]/,/^\[/{s/^User.*/User=kiosk/;s/^Session.*/Session=plasma/}' /etc/sddm.conf
    else
        tee -a /etc/sddm.conf >/dev/null <<'EOF'
[Autologin]
User=kiosk
Session=plasma
EOF
    fi

    # Switch DM to SDDM
    echo "sddm shared/default-x-display-manager select sddm" | sudo debconf-set-selections
    sudo dpkg-reconfigure -fnoninteractive sddm
    systemctl disable gdm3 || true
    systemctl enable sddm
    systemctl set-default graphical.target
    #systemctl restart sddm

    # Show resulting configs
    [ -f /etc/gdm3/custom.conf ] && cat /etc/gdm3/custom.conf || true
    [ -f /etc/sddm.conf ] && cat /etc/sddm.conf || true

    #read "Press [Enter] key to continue... creating Chromium autostart"
}

section_10() {
    ##############################################
    # SECTION 10: CHROMIUM KIOSK AUTOSTART SETUP
    ##############################################
    echo "=== SECTION 10: CHROMIUM KIOSK AUTOSTART SETUP ==="
    # Create Chromium kiosk autostart for Plasma session
    APP_URL="http://localhost:8080"
    cat >/home/kiosk/.config/autostart/chromium-kiosk.desktop <<EOF
[Desktop Entry]
Type=Application
Name=Chromium Kiosk
Exec=/usr/bin/chromium-browser --ozone-platform=wayland --enable-features=UseOzonePlatform,WaylandWindowDecorations --no-first-run --no-default-browser-check --disable-session-crashed-bubble --disable-infobars --start-maximized --noerrdialogs --incognito --kiosk "$APP_URL"
X-GNOME-Autostart-enabled=true
X-KDE-AutostartScript=true
EOF
    chown kiosk:kiosk /home/kiosk/.config/autostart/chromium-kiosk.desktop
    chmod 0644 /home/kiosk/.config/autostart/chromium-kiosk.desktop
}

section_11() {
    #read "Press [Enter] key to continue... verifying Wayland toggles and kiosk autostart path"
    ##############################################
    # SECTION 11: WAYLAND AND KIOSK VERIFICATION
    ##############################################
    echo "=== SECTION 11: WAYLAND AND KIOSK VERIFICATION ==="
    # Ensure WaylandEnable=false is commented if present
    if grep -q '^WaylandEnable=false' /etc/gdm3/custom.conf; then
      sed -i 's/^WaylandEnable=false/#WaylandEnable=false/' /etc/gdm3/custom.conf
    fi

    # Make sure APP_URL uses http (Phidget web piece typically)
    sed -i 's#https://localhost:8080#http://localhost:8080#g' /home/kiosk/.config/autostart/chromium-kiosk.desktop
    chown kiosk:kiosk /home/kiosk/.config/autostart/chromium-kiosk.desktop

}

section_12() {
    #read "Press [Enter] key to continue... disabling touch gestures (GNOME keys; ignored on Plasma)"
    ##############################################
    # SECTION 12: TOUCH GESTURE CONFIGURATION
    ##############################################
    echo "=== SECTION 12: TOUCH GESTURE CONFIGURATION ==="
    # Remove Wayland touch shortcuts (GNOME dconf; harmless if schema missing)
    gsettings set org.gnome.desktop.peripherals.touchpad three-finger-swipe-enabled false || true
    gsettings set org.gnome.desktop.peripherals.touchpad pinch-to-zoom false || true
}

section_13() {
    #read "Press [Enter] key to continue... applying KWin tweaks"
    echo "=== SECTION 13: KWIN TWEAKS AND FINAL SETUP ==="

    kwriteconfig6 --file kwinrc --group "Global Shortcuts" --key _k_friendly_name "" || true

    mkdir -p ~/.config/autostart-scripts
    cat > ~/.config/autostart-scripts/reload-kwin.sh <<'EOF'
#!/bin/sh
(qdbus6 org.kde.KWin /KWin reconfigure || qdbus6 org.kde.KWin.Wayland /KWin reconfigure) || true
EOF
    chmod +x ~/.config/autostart-scripts/reload-kwin.sh
}

section_14() {
    #read "Press [Enter] key to continue... stopping screen blanking for kiosk user (best effort for GNOME; harmless on Plasma)"
    ##############################################
    # SECTION 14: POWER MANAGEMENT AND SCREEN BLANKING for current user
    ##############################################
    echo "=== SECTION 1: POWER MANAGEMENT AND SCREEN BLANKING ==="
    # Stop screen blanking/suspend for kiosk session (no-op if schema absent)
    sudo -u kiosk dbus-run-session gsettings set org.gnome.desktop.session idle-delay 0 || true
    sudo -u kiosk dbus-run-session gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-type 'nothing' || true
    sudo -u kiosk dbus-run-session gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-battery-type 'nothing' || true

}
section_15() {
    ##############################################
    # SECTION 15: FINAL SYSTEM RESTART
    ##############################################
    echo "=== SECTION 15: FINAL SYSTEM RESTART ==="
    systemctl enable chromium-kiosk || true
    systemctl disable gdm3 || true
    systemctl enable sddm
    systemctl set-default graphical.target
    im-config -n none
    sudo tee /etc/environment >/dev/null <<'EOF'
GTK_IM_MODULE=none
QT_IM_MODULE=none
XMODIFIERS=@im=none
EOF

}

section_16() {
    echo "=== SECTION 16: remove notifs and enable auto updater  ==="
    # Placeholder for future sections
    sudo snap remove snapd-desktop-integration
    sudo snap remove snapd-desktop-integration-test
    sudo -u kiosk im-config -n none || true



}
section_17() {
    ##############################################
    # SECTION 17: DISABLE ERROR POPUPS (Apport, notifications)
    ##############################################
    echo "=== SECTION 17: Disable error popups for kiosk user ==="

    # Disable Apport (Ubuntu crash reporter)
    sed -i 's/^enabled=1/enabled=0/' /etc/default/apport || true
    systemctl disable apport.service || true
    systemctl mask apport.service || true
    systemctl stop apport.service || true

    # Disable update-notifier crash reports
    rm -f /var/crash/* || true

    # For kiosk user: suppress all desktop notifications
    sudo -u kiosk dbus-launch gsettings set org.gnome.desktop.notifications show-banners false || true
    sudo -u kiosk dbus-launch gsettings set org.gnome.desktop.notifications show-in-lock-screen false || true

    # Divert stderr of systemd services to logs only (no journal popups)
    mkdir -p /etc/systemd/system.conf.d
    cat >/etc/systemd/system.conf.d/no-notify.conf <<'EOF'
[Manager]
DefaultStandardError=journal
DefaultStandardOutput=journal
EOF

    systemctl daemon-reexec || true
}


# Automatically detect the number of sections
get_max_section() {
    declare -F | grep -o 'section_[0-9]\+' | grep -o '[0-9]\+' | sort -n | tail -1
}

MAX_SECTIONS=$(get_max_section)

# Main script execution logic
show_usage() {
    echo "Usage: $0 [-s SECTION_NUMBER]"
    echo ""
    echo "Options:"
    echo "  -s SECTION_NUMBER  Run only the specified section (1-$MAX_SECTIONS)"
    echo "  -h, --help        Show this help message"
    echo ""
    echo "If no options are provided, all sections will be run in order."
    echo ""
    echo "Available sections:"
    echo "  1  - Power Management and Screen Blanking for current user"
    echo "  2  - Initial System Setup"
    echo "  3  - Desktop Environment Installation"
    echo "  4  - Phidget Setup and Dependencies"
    echo "  5  - Touchscreen Configuration"
    echo "  6  - Phidget Network Server Setup"
    echo "  7  - Kiosk User Setup"
    echo "  8  - GDM3 Autologin Configuration"
    echo "  9  - SDDM Configuration (Alternative)"
    echo "  10 - Chromium Kiosk Autostart Setup"
    echo "  11 - Wayland and Kiosk Verification"
    echo "  12 - Touch Gesture Configuration"
    echo "  13 - KWin Tweaks and Final Setup"
    echo "  14 - Power Management and Screen Blanking for kiosk user"
    echo "  15 - Final System Restart"
    echo "  16 - Remove notifications and enable auto updater"
    echo "  17 - Disable error popups for kiosk user"
    #echo "  18 - USB Auto-Update Service and eventual reboot"
}

run_all_sections() {
    echo "Running all sections in order..."
    for i in $(seq 1 $MAX_SECTIONS); do
        echo ""
        echo "========================================="
        echo "Starting Section $i"
        echo "========================================="
        section_$i
        echo "Section $i completed."
    done
    echo ""
    echo "All sections completed successfully!"
}

run_specific_section() {
    local section_num=$1
    if [[ $section_num -lt 1 || $section_num -gt $MAX_SECTIONS ]]; then
        echo "Error: Section number must be between 1 and $MAX_SECTIONS"
        exit 1
    fi
    
    echo "Running section $section_num only..."
    echo "========================================="
    echo "Starting Section $section_num"
    echo "========================================="
    section_$section_num
    echo "Section $section_num completed successfully!"
}
SECTION_NUM=""
# Parse command line arguments
while [[ $# -gt 0 ]]; do
    case $1 in
        -s|--section)
            if [[ -z "$2" ]] || [[ "$2" =~ ^-.*$ ]]; then
                echo "Error: Option -s requires a section number"
                show_usage
                exit 1
            fi
            SECTION_NUM="$2"
            shift 2
            ;;
        -h|--help)
            show_usage
            exit 0
            ;;       
        -a|--all)
            run_all_sections
            reboot
            exit 0
            ;;
            
        *)
            echo "Error: Unknown option: $1"
            show_usage
            exit 1
            ;;
    esac
done

# Execute based on arguments
if [[ -n "$SECTION_NUM" ]]; then
    # Validate that section number is numeric
    if ! [[ "$SECTION_NUM" =~ ^[0-9]+$ ]]; then
        echo "Error: Section number must be a valid integer"
        exit 1
    fi
    run_specific_section "$SECTION_NUM"
else
    run_all_sections
fi

```

```


rm -rf /home/kiosk/.config/chromium/Default/Preferences
rm -rf /home/kiosk/.config/chromium/Singleton*


kwriteconfig6 --file startkderc --group General --key desktopSession empty
kwriteconfig6 --file ksmserverrc --group General --key loginMode emptySession

```

# restart chromium demon

```
#!/bin/bash
set -euo pipefail

# CONFIGURATION
APP_URL="http://localhost:8080"
INACTIVITY_MINUTES=10
CHROMIUM_BIN="/usr/bin/chromium-browser"
WATCHDOG_SCRIPT="/usr/bin/chromium-idle-restart.sh"
SERVICE_FILE="/etc/systemd/system/chromium-idle-restart.service"
USER_NAME="kiosk"

echo "=== Installing Wayland-Compatible Chromium Idle Watchdog ==="

# 1. Write the Chromium Watchdog Script
cat >"$WATCHDOG_SCRIPT" <<EOF
#!/bin/bash
set -euo pipefail

APP_URL="$APP_URL"
INACTIVITY_MINUTES=$INACTIVITY_MINUTES
CHROMIUM_BIN="$CHROMIUM_BIN"
USER_NAME="$USER_NAME"
PARAMS="--ozone-platform=wayland --enable-features=UseOzonePlatform,WaylandWindowDecorations \
 --no-first-run --no-default-browser-check --disable-session-crashed-bubble --disable-infobars \
 --start-maximized --noerrdialogs --incognito --kiosk \$APP_URL"

while true; do
    idle_ns=\$(loginctl show-user "\$USER_NAME" -p IdleSinceHint | cut -d= -f2)
    now_ns=\$(date +%s%N)

    if [[ "\$idle_ns" =~ ^[0-9]+$ ]]; then
        idle_ms=\$(( (now_ns - idle_ns) / 1000000 ))

        if [ "\$idle_ms" -ge \$((INACTIVITY_MINUTES*60*1000)) ]; then
            echo "\$(date) - Wayland Idle Detected. Restarting Chromium..."
            pkill -9 -f "\$CHROMIUM_BIN" || true
            sleep 2
            eval "\$CHROMIUM_BIN \$PARAMS &"
            sleep \$((INACTIVITY_MINUTES*60))
        fi
    fi

    sleep 30
done
EOF

chmod +x "$WATCHDOG_SCRIPT"

# 2. Create the systemd service
cat >"$SERVICE_FILE" <<EOF
[Unit]
Description=Wayland Chromium Idle Restart Watchdog
After=graphical.target

[Service]
ExecStart=$WATCHDOG_SCRIPT
Restart=always
User=$USER_NAME

[Install]
WantedBy=graphical.target
EOF

# 3. Activate the service
systemctl daemon-reload
systemctl enable --now chromium-idle-restart.service

echo "=== Chromium Idle Watchdog Installed and Running ==="

```

# Installer Demon Template

```
#!/bin/bash
set -euo pipefail

# CONFIG
MEDIA_BASE="/media"
USB_LABEL="recharjme"                      
MONITOR_BIN="/usr/bin/NZK_System_Updater.sh"
SERVICE_FILE="/etc/systemd/system/NZK_System_Updater.service"

echo "=== Installing USB Update Monitor daemon ==="

# 1) Write daemon script
rm -f "$MONITOR_BIN"
cat >"$MONITOR_BIN" <<'EOF'
#!/bin/bash
set -euo pipefail

#!/bin/bash
set -euo pipefail

MEDIA_BASE="/media"
USB_LABEL="recharjme"
UPDATE_FLAG="/tmp/_updating"
TEMP_UPDATE_SCRIPT="/tmp/update.sh"
USB_MOUNT_PATH=""  # Global variable to track current USB path

log(){ printf '%s - %s\n' "$(date '+%F %T')" "$*"; }

find_recharjme_usb(){
  # Find any USB mount with label matching "recharjme" (case-insensitive)
  for user_dir in "$MEDIA_BASE"/*; do
    [ -d "$user_dir" ] || continue
    for mount_dir in "$user_dir"/*; do
      [ -d "$mount_dir" ] || continue
      mount_name=$(basename "$mount_dir")
      # Case-insensitive comparison
      if [[ "${mount_name,,}" == "${USB_LABEL,,}" ]] && mountpoint -q "$mount_dir"; then
        echo "$mount_dir"
        return 0
      fi
    done
  done
  return 1
}

check_usb_connected(){
  USB_MOUNT_PATH=$(find_recharjme_usb)
  if [ -n "$USB_MOUNT_PATH" ]; then
    return 0
  else
    USB_MOUNT_PATH=""
    return 1
  fi
}

restart_display_managers(){
  log "Restarting display managers..."
  systemctl restart gdm3 2>/dev/null || true
  systemctl restart sddm 2>/dev/null || true
}

process_update(){
  local update_file="$1"
  log "Found update: $update_file"
  : > "$UPDATE_FLAG"
  log "Created update flag: $UPDATE_FLAG"
  cp -f "$update_file" "$TEMP_UPDATE_SCRIPT"
  chmod +x "$TEMP_UPDATE_SCRIPT"
  log "Executing: $TEMP_UPDATE_SCRIPT"
  bash "$TEMP_UPDATE_SCRIPT"
  log "Update finished; cleaning"
  rm -f "$TEMP_UPDATE_SCRIPT"
  rm -f "$UPDATE_FLAG"
  restart_display_managers
}

log "=== USB Update Monitor started ==="
shopt -s nullglob

while true; do
  if check_usb_connected; then
    log "Found RECHARJME USB at: $USB_MOUNT_PATH"
    
    # Check if update is already in progress
    if [ -f "$UPDATE_FLAG" ]; then
      log "Update already in progress, waiting..."
      sleep 3
      continue
    fi
    
    # Look for update scripts
    candidates=( "$USB_MOUNT_PATH"/update*.sh )
    if [ ${#candidates[@]} -gt 0 ]; then
      process_update "${candidates[0]}"
      # Wait for USB disconnect with proper state checking
      log "Waiting for USB disconnect..."
      while check_usb_connected; do 
        sleep 2
      done
      log "USB disconnected; rebooting in 3 seconds..."
      sleep 3
      systemctl reboot
    else
      sleep 3
    fi
  else
    # No USB connected, remove updating flag if it exists
    if [ -f "$UPDATE_FLAG" ]; then
      log "No USB connected, removing stale update flag"
      rm -f "$UPDATE_FLAG"
    fi
    sleep 3
  fi
done
EOF
chmod +x "$MONITOR_BIN"

# 2) Write systemd unit
rm -f "$SERVICE_FILE"
cat >"$SERVICE_FILE" <<EOF
[Unit]
Description=USB Update Monitor
After=local-fs.target
Wants=local-fs.target

[Service]
Type=simple
ExecStart=$MONITOR_BIN
Restart=always
RestartSec=2

[Install]
WantedBy=multi-user.target
EOF

# 3) Activate
systemctl daemon-reload
systemctl enable --now usb-update-monitor.service
systemctl restart usb-update-monitor.service || true
echo "=== Installed and running: usb-update-monitor.service ==="
systemctl --no-pager status usb-update-monitor.service || true

```