fix: parse negative session IDs and add debug logging
Amolith
created
The Mumble server can assign negative user session IDs (SIDs), e.g.,
`(-1)`. The regex patterns for parsing both move and disconnect events
have been updated to correctly handle negative session IDs.
Additionally, a new `log()` function provides granular debug output when
the `DEBUG` environment variable is set to a truthy value.
@@ -54,10 +54,10 @@ The script is designed to run as a systemd service under a dedicated user accoun
## Log Format Parsing
-The script parses specific Mumble server log formats:
+The script parses specific Mumble server log formats. The user session ID, shown as `(SID)` below, can be a negative number (e.g. `(-1)`).
-- Move events: `<W>YYYY-MM-DD HH:MM:SS.mmm N => <ID:Username(N)> Moved Username:ID(N) to ChannelName[ID:N]`-- Disconnect events: `<W>YYYY-MM-DD HH:MM:SS.mmm N => <ID:Username(N)> Connection closed: reason`
+- Move events: `<W>YYYY-MM-DD HH:MM:SS.mmm N => <UID:Username(SID)> Moved Username:UID(SID) to ChannelName[CID:N]`
+- Disconnect events: `<W>YYYY-MM-DD HH:MM:SS.mmm N => <UID:Username(SID)> Connection closed: reason`
## Message Templates
@@ -69,6 +69,21 @@ The herald's personality is expressed through varied message templates:
- **Format**: Messages use `{USERNAME}` and `{CHANNEL}` placeholders for substitution
- **Character actions**: Include physical actions like `*grumbles*`, `*adjusts spectacles*`, `*mutters*`
+## Debug Logging
+
+The script includes a `log()` function for debug output when the `DEBUG` environment variable is set to a truthy value (1, true, etc.):
+
+- **Function**: `log()` - Checks `if (($DEBUG))` and prints messages verbatim to stderr
+- **Usage**: Set `DEBUG=1` before running to see herald's internal thoughts
+- **Character**: Debug messages maintain the grumpy herald persona with observations like "_herald squints at parchment_" and "_mutters about modern technology_"
+- **Scope**: Added to helper functions (`is_monitored_channel`, `get_random_message`, `send_notification`, `parse_move_event`, `parse_disconnect_event`) but not main execution flow
+
+Example usage:
+
+```bash
+DEBUG=1 ./mumblingherald
+```
+
## Development Best Practices
- Use shellcheck after every edit.
@@ -19,14 +19,24 @@ MONITORED_CHANNELS=(
"Room 5"
)
+# Function to print debug messages if DEBUG is true
+log() {
+ if ((DEBUG)); then
+ echo "$1" >&2
+ fi
+}
+
# Function to check if a channel should be monitored
is_monitored_channel() {
local channel="$1"
+ log "*herald squints at parchment* Checking if '$channel' is worth my attention..."
for monitored in "${MONITORED_CHANNELS[@]}"; do
if [[ "$channel" == "$monitored" ]]; then
+ log "*herald nods approvingly* Ah yes, '$channel' is on my sacred list!"
return 0
fi
done
+ log "*herald waves dismissively* '$channel'? Not my concern, I'm afraid."
return 1
}
@@ -108,27 +118,34 @@ LEAVE_MESSAGES=(
# Function to get a random message from an array
get_random_message() {
local -n arr=$1
- echo "${arr[$RANDOM % ${#arr[@]}]}"
+ local selected_index=$((RANDOM % ${#arr[@]}))
+ log "*herald rummages through dusty scroll collection* Selecting message ${selected_index} from ${#arr[@]} possibilities..."
+ echo "${arr[$selected_index]}"
}
# Function to send XMPP notification
send_notification() {
local message="$1"
+ log "*herald clears throat and prepares speaking trumpet* Announcing: '$message'"
echo "$message" | go-sendxmpp -c -f "$XMPP_CONFIG_FILE" "$XMPP_RECIPIENTS"
+ log "*herald dusts off hands* Message dispatched to the digital realm!"
}
# Function to parse log line and extract user move information
parse_move_event() {
local log_line="$1"
+ log "*herald peers at ancient log scroll* Examining movement event..."
# Extract user and destination channel
# Format: <W>2025-07-01 14:07:32.352 1 => <28:Amolith(5)> Moved Amolith:28(5) to Room 5[53:20]
- if [[ "$log_line" =~ \<W\>[0-9-]+\ [0-9:.]+.*\>\ Moved\ ([^:]+):[0-9]+\([0-9]+\)\ to\ ([^\[]+)\[ ]]; then
+ if [[ "$log_line" =~ \<W\>[0-9-]+\ [0-9:.]+.*\>\ Moved\ ([^:]+):[0-9]+\(-?[0-9]+\)\ to\ ([^\[]+)\[ ]]; then
local username="${BASH_REMATCH[1]}"
local channel="${BASH_REMATCH[2]}"
+ log "*herald adjusts spectacles* Detected '$username' moving to '$channel'"
# Check if this channel should be monitored
if is_monitored_channel "$channel"; then
+ log "*herald perks up* This movement requires my attention!"
local join_msg
join_msg=$(get_random_message JOIN_MESSAGES)
local message="${join_msg//\{USERNAME\}/$username}"
@@ -136,23 +153,30 @@ parse_move_event() {
echo "*herald mumbles something about $username*"
send_notification "$message"
fi
+ else
+ log "*herald squints* Movement event format unrecognized. *mutters about modern technology* Line: $log_line"
fi
}
# Function to parse log line and extract user disconnect information
parse_disconnect_event() {
local log_line="$1"
+ log "*herald listens for departing footsteps* Examining disconnect event..."
# Extract user from disconnect event
# Format: <W>2025-07-01 14:19:46.484 1 => <28:Amolith(5)> Connection closed: The remote host closed the connection [1]
- if [[ "$log_line" =~ \<W\>[0-9-]+\ [0-9:.]+.*\<[0-9]+:([^\(]+)\([0-9]+\)\>\ Connection\ closed: ]]; then
+ # Format: <W>2025-07-01 23:24:47.986 1 => <199:DesertCr0w_Winblows(-1)> Connection closed: reason
+ if [[ "$log_line" =~ \<W\>[0-9-]+\ [0-9:.]+.*\<[0-9]+:([^\(]+)\(-?[0-9]+\)\>\ Connection\ closed: ]]; then
local username="${BASH_REMATCH[1]}"
+ log "*herald nods knowingly* '$username' has departed the realm entirely"
local leave_msg
leave_msg=$(get_random_message LEAVE_MESSAGES)
local message="${leave_msg//\{USERNAME\}/$username}"
echo "*herald notices someone's absence and sighs*"
send_notification "$message"
+ else
+ log "*herald frowns* Disconnect event format puzzling. *grumbles about log formats* Line: $log_line"
fi
}