Attempt to cut down on spam from greet and bye triggers. Add ping/pong to help deal with flakey connections.?
This commit is contained in:
95
bot.sh
95
bot.sh
@@ -78,6 +78,10 @@ export nick
|
||||
export quitMessage
|
||||
export intentionalExit
|
||||
|
||||
# Set default values for ping/pong monitoring if not configured
|
||||
pingInterval="${pingInterval:-120}"
|
||||
pongTimeout="${pongTimeout:-30}"
|
||||
|
||||
# Check for critical dependencies needed by the bot core
|
||||
coreDependencies=("socat" "tail" "shuf" "grep" "sed" "tr" "cut" "date")
|
||||
missingCore=()
|
||||
@@ -105,6 +109,74 @@ rm_input() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to stop ping monitor process
|
||||
stop_ping_monitor() {
|
||||
if [[ -n "$pingMonitorPid" ]] && kill -0 "$pingMonitorPid" 2>/dev/null; then
|
||||
kill "$pingMonitorPid" 2>/dev/null
|
||||
wait "$pingMonitorPid" 2>/dev/null
|
||||
fi
|
||||
# Clean up ping/pong tracking files
|
||||
rm -f "${input}.lastping" "${input}.lastpong" 2>/dev/null
|
||||
}
|
||||
|
||||
# Start background ping monitor process
|
||||
# Sends PING at regular intervals and monitors for PONG responses
|
||||
start_ping_monitor() {
|
||||
# Only start if ping interval is greater than 0
|
||||
if [[ "$pingInterval" -le 0 ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
# Stop any existing monitor
|
||||
stop_ping_monitor
|
||||
|
||||
# Capture variables for the background process
|
||||
local monitorInput="$input"
|
||||
local monitorLog="$log"
|
||||
local monitorServer="$server"
|
||||
local monitorPort="$port"
|
||||
local monitorDateFormat="$dateFormat"
|
||||
local monitorPingInterval="$pingInterval"
|
||||
local monitorPongTimeout="$pongTimeout"
|
||||
|
||||
# Start ping monitor in background
|
||||
(
|
||||
while true; do
|
||||
sleep "$monitorPingInterval"
|
||||
# Send PING with timestamp
|
||||
currentTime=$(date +%s)
|
||||
echo "PING :healthcheck_${currentTime}" >> "$monitorInput"
|
||||
echo "$currentTime" > "${monitorInput}.lastping"
|
||||
|
||||
# Wait for pong timeout period and check if we got a response
|
||||
sleep "$monitorPongTimeout"
|
||||
|
||||
# Check if we received a PONG
|
||||
if [[ -f "${monitorInput}.lastpong" ]]; then
|
||||
lastPongTime=$(cat "${monitorInput}.lastpong")
|
||||
# If last pong is newer than last ping, we're good
|
||||
if [[ "$lastPongTime" -ge "$currentTime" ]]; then
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
# No PONG received within timeout - connection is likely dead
|
||||
echo "No PONG received within ${monitorPongTimeout}s. Connection appears dead. [$(date "+$monitorDateFormat")]" >> "$monitorLog"
|
||||
# Kill the socat process to trigger reconnection
|
||||
# Escape regex metacharacters in server and port to prevent injection
|
||||
safeServer="${monitorServer//./\\.}"
|
||||
safeServer="${safeServer//[/\\[}"
|
||||
safeServer="${safeServer//]/\\]}"
|
||||
safeServer="${safeServer//\*/\\*}"
|
||||
safePort="${monitorPort//[^0-9]/}"
|
||||
# Find and kill the socat process for this bot
|
||||
pkill -f "socat.*${safeServer}:${safePort}" 2>/dev/null
|
||||
exit 0
|
||||
done
|
||||
) &
|
||||
pingMonitorPid=$!
|
||||
}
|
||||
|
||||
# Function to trim log file to prevent unbounded growth
|
||||
# Keeps log between 800-1000 lines by trimming oldest entries when limit reached
|
||||
trim_log() {
|
||||
@@ -127,8 +199,12 @@ trim_log() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Trap exiting ffrom the program to remove the temporary input file.
|
||||
trap rm_input EXIT
|
||||
# Trap exiting from the program to remove the temporary input file and stop ping monitor
|
||||
cleanup_on_exit() {
|
||||
stop_ping_monitor
|
||||
rm_input
|
||||
}
|
||||
trap cleanup_on_exit EXIT
|
||||
|
||||
# Flag to track intentional shutdown (set by exit module)
|
||||
intentionalExit=false
|
||||
@@ -159,6 +235,9 @@ while true; do
|
||||
# Counter for log trimming (check every 50 messages)
|
||||
logTrimCounter=0
|
||||
|
||||
# Start ping monitor for this connection
|
||||
start_ping_monitor
|
||||
|
||||
tail -f "$input" | socat -,ignoreeof "$socatAddress" | while read -r result ; do
|
||||
# Strip carriage return from IRC protocol (CRLF line endings)
|
||||
result="${result%$'\r'}"
|
||||
@@ -190,6 +269,15 @@ while true; do
|
||||
PING*)
|
||||
echo "${result/I/O}" >> "$input"
|
||||
;;
|
||||
# track pong responses for connection health monitoring
|
||||
# Match PONG as IRC command, not user messages containing "pong"
|
||||
*" PONG "*|PONG*)
|
||||
# Only process if NOT a user PRIVMSG (prevents spoofing)
|
||||
if [[ ! "$result" =~ PRIVMSG ]]; then
|
||||
# Update last pong timestamp
|
||||
date +%s > "${input}.lastpong"
|
||||
fi
|
||||
;;
|
||||
# for pings on nick/user
|
||||
*"You have not"*)
|
||||
for channelName in "${channels[@]}"; do
|
||||
@@ -338,6 +426,9 @@ while true; do
|
||||
done
|
||||
|
||||
# If we reach here, the connection was dropped
|
||||
# Stop the ping monitor for this connection
|
||||
stop_ping_monitor
|
||||
|
||||
# Check if this was an intentional exit
|
||||
if [[ "$intentionalExit" == "true" ]]; then
|
||||
echo "Bot shutdown requested. Exiting. [$(date "+$dateFormat")]" | tee -a "$log"
|
||||
|
||||
Reference in New Issue
Block a user