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.
152 lines
7.2 KiB
Bash
Executable file
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
|