dotfiles/bin/rice-net
Sarthak 7f41cf7a82 replace the old dotfiles with the sakura line rice
The bare $HOME repo is gone. This is now the rice: install.sh, rice-*
scripts in bin/, configs in home/ linked into $HOME, theme templates, st
and the particle wallpaper. Clone to ~/rice and run install.sh.
2026-09-14 19:44:44 +05:30

152 lines
7.2 KiB
Bash
Executable file

#!/usr/bin/env bash
# rice-net - network state for the eww panel, and the actions it runs.
#
# rice-net list JSON: Wi-Fi radio, active connection, networks, VPNs
# rice-net radio on|off|toggle
# rice-net connect <id> id from the last list; asks for a password in rofi if needed
# rice-net disconnect
# rice-net rescan
# rice-net vpn <id> bring a VPN / WireGuard connection up or down
# rice-net share show the current Wi-Fi network as a QR code
#
# SSIDs are chosen by whoever broadcasts them, so the panel only ever passes
# the numeric id; the SSID is looked up again here from the cached list.
set -uo pipefail
run="${XDG_RUNTIME_DIR:-/tmp}/rice"
cache="$run/wifi.tsv"
vpncache="$run/vpn.tsv"
mkdir -p "$run"
say() { rice-notify send "$1" "${2:-}" -i network-wireless; }
poke() { date +%s%N > "$run/net.rev"; }
signal_glyph() {
local s=$1
if (( s >= 75 )); then echo 󰤨
elif (( s >= 50 )); then echo 󰤥
elif (( s >= 25 )); then echo 󰤢
else echo 󰤟; fi
}
list() {
local radio=false has_wifi=false active_type="" active_name="" active_dev=""
nmcli -g TYPE device 2>/dev/null | grep -qx wifi && has_wifi=true
[[ $has_wifi == true && $(nmcli -t radio wifi 2>/dev/null) == enabled ]] && radio=true
IFS=: read -r active_type active_name active_dev < <(nmcli -g TYPE,STATE,CONNECTION,DEVICE device status 2>/dev/null |
awk -F: '$2 == "connected" && ($1 == "wifi" || $1 == "ethernet") { print $1 ":" $3 ":" $4; exit }')
local known
known=$(nmcli -g NAME,TYPE connection show 2>/dev/null | awk -F: '$2 == "802-11-wireless" { print $1 }')
# IN-USE:SIGNAL:SECURITY:SSID, strongest first, one row per SSID, top 8.
: > "$cache"
local inuse signal security ssid id=0 seen=$'\n'
while IFS=: read -r inuse signal security ssid; do
ssid=${ssid//\\:/:}
[[ -z $ssid || $seen == *$'\n'"$ssid"$'\n'* ]] && continue
seen+="$ssid"$'\n'
printf '%s\t%s\t%s\t%s\t%s\t%s\n' "$id" "$ssid" "$signal" "${security:---}" \
"$([[ $inuse == '*' ]] && echo 1 || echo 0)" \
"$(grep -Fxq -- "$ssid" <<<"$known" && echo 1 || echo 0)" >> "$cache"
(( ++id >= 8 )) && break
done < <(nmcli -g IN-USE,SIGNAL,SECURITY,SSID device wifi list --rescan no 2>/dev/null | sort -t: -k2,2nr)
# VPN and WireGuard profiles known to NetworkManager.
: > "$vpncache"
local active_names name type vid=0
active_names=$(nmcli -g NAME connection show --active 2>/dev/null)
while IFS=: read -r name type; do
[[ $type == vpn || $type == wireguard ]] || continue
printf '%s\t%s\t%s\n' "$vid" "$name" "$(grep -Fxq -- "$name" <<<"$active_names" && echo 1 || echo 0)" >> "$vpncache"
(( vid++ ))
done < <(nmcli -g NAME,TYPE connection show 2>/dev/null)
jq -cn --argjson radio "$radio" --argjson haswifi "$has_wifi" \
--arg atype "$active_type" --arg aname "$active_name" \
--argjson wifi "$(while IFS=$'\t' read -r i s sig sec use kn; do
jq -cn --argjson id "$i" --arg ssid "$s" --argjson signal "$sig" --arg sec "$sec" \
--argjson active "$([[ $use == 1 ]] && echo true || echo false)" \
--argjson known "$([[ $kn == 1 ]] && echo true || echo false)" \
--arg glyph "$(signal_glyph "$sig")" \
'{id: $id, ssid: $ssid, signal: $signal, active: $active, known: $known, glyph: $glyph,
sub: ([(if $active then "connected" elif $known then "saved" else empty end),
(if $sec == "--" then "open" else "󰌾 " + $sec end)] | join(" · "))}'
done < "$cache" | jq -cs '.')" \
--argjson vpn "$(while IFS=$'\t' read -r i n a; do
jq -cn --argjson id "$i" --arg name "$n" --argjson active "$([[ $a == 1 ]] && echo true || echo false)" \
'{id: $id, name: $name, active: $active}'
done < "$vpncache" | jq -cs '.')" \
'{radio: $radio,
active: {type: $atype, name: $aname},
hasWifi: $haswifi,
wifi: $wifi, vpn: $vpn}'
}
field() { awk -F'\t' -v id="$1" -v col="$2" '$1 == id { print $col; exit }' "$3"; }
connect() {
[[ ${1:-} =~ ^[0-9]+$ ]] || { echo "rice-net: connect takes an id" >&2; exit 2; }
local ssid security known pass
ssid=$(field "$1" 2 "$cache"); security=$(field "$1" 4 "$cache"); known=$(field "$1" 6 "$cache")
[[ -n $ssid ]] || { say "Wi-Fi" "That network is gone; rescan and try again"; exit 1; }
if [[ $known == 1 ]]; then
nmcli connection up id "$ssid" >/dev/null 2>&1 && say "Connected" "$ssid" || say "Could not connect" "$ssid"
elif [[ $security == "--" ]]; then
nmcli device wifi connect "$ssid" >/dev/null 2>&1 && say "Connected" "$ssid" || say "Could not connect" "$ssid"
elif [[ $security == *802.1X* ]]; then
say "Enterprise network" "Opening the connection editor for $ssid"
setsid -f nm-connection-editor >/dev/null 2>&1
else
pass=$(rofi -dmenu -password -theme "$HOME/.config/rofi/prompt.rasi" -p "$ssid" -mesg "Wi-Fi password") || exit 0
[[ -n $pass ]] || exit 0
local mgmt=wpa-psk
[[ $security == *WPA3* && $security != *WPA2* ]] && mgmt=sae
# The password reaches nmcli through a file descriptor, not the command line.
nmcli connection add type wifi con-name "$ssid" ssid "$ssid" wifi-sec.key-mgmt "$mgmt" >/dev/null 2>&1
if nmcli connection up id "$ssid" passwd-file <(printf '802-11-wireless-security.psk:%s\n' "$pass") >/dev/null 2>&1; then
say "Connected" "$ssid"
else
nmcli connection delete id "$ssid" >/dev/null 2>&1
say "Could not connect" "Wrong password for $ssid?"
fi
fi
poke
}
case "${1:-}" in
list) list ;;
radio)
case "${2:-toggle}" in
on) nmcli radio wifi on ;;
off) nmcli radio wifi off ;;
*) [[ $(nmcli -t radio wifi) == enabled ]] && nmcli radio wifi off || nmcli radio wifi on ;;
esac
poke ;;
connect) connect "${2:-}" ;;
disconnect)
dev=$(nmcli -g TYPE,DEVICE,STATE device status | awk -F: '$1 == "wifi" && $3 == "connected" { print $2; exit }')
[[ -n $dev ]] && nmcli device disconnect "$dev" >/dev/null && say "Wi-Fi" "Disconnected"
poke ;;
rescan) nmcli device wifi rescan >/dev/null 2>&1; poke ;;
vpn)
[[ ${2:-} =~ ^[0-9]+$ ]] || { echo "rice-net: vpn takes an id" >&2; exit 2; }
name=$(field "$2" 2 "$vpncache"); active=$(field "$2" 3 "$vpncache")
[[ -n $name ]] || exit 1
if [[ $active == 1 ]]; then nmcli connection down id "$name" >/dev/null && say "VPN off" "$name"
else nmcli connection up id "$name" >/dev/null && say "VPN on" "$name" || say "VPN failed" "$name"; fi
poke ;;
share)
name=$(nmcli -g TYPE,STATE,CONNECTION device status | awk -F: '$1 == "wifi" && $2 == "connected" { print $3; exit }')
[[ -n $name ]] || { say "Wi-Fi" "Not connected to a Wi-Fi network"; exit 1; }
ssid=$(nmcli -g 802-11-wireless.ssid connection show id "$name")
psk=$(nmcli -s -g 802-11-wireless-security.psk connection show id "$name")
esc() { sed -e 's/[\\;,:"]/\\&/g' <<<"$1"; }
png="$run/wifi-qr.png"
printf 'WIFI:T:%s;S:%s;P:%s;;' "$([[ -n $psk ]] && echo WPA || echo nopass)" "$(esc "$ssid")" "$(esc "$psk")" |
qrencode -o "$png" -s 10 -m 2 --foreground="$(rice-theme get bg | tr -d '#')" --background="$(rice-theme get fg | tr -d '#')"
setsid -f feh --title "Wi-Fi: $ssid" --geometry 420x420 -Z "$png" >/dev/null 2>&1
;;
*) sed -n '2,11p' "$0" | sed 's/^# \{0,1\}//'; exit 2 ;;
esac