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:
@@ -30,3 +30,9 @@ botCaller=",.!+?"
|
||||
# People who are allowed to private message the bot separate multiple names with |
|
||||
allowList=""
|
||||
ignoreList="storm_bot"
|
||||
# Interval in seconds to send PING to server for connection health check (default: 120)
|
||||
# Set to 0 to disable proactive ping checks (not recommended)
|
||||
pingInterval=120
|
||||
# Timeout in seconds to wait for PONG response before considering connection dead (default: 30)
|
||||
# If no PONG received within this time after sending PING, bot will reconnect
|
||||
pongTimeout=30
|
||||
|
||||
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"
|
||||
|
||||
@@ -3,8 +3,28 @@
|
||||
|
||||
farewellsFile="triggers/bye/farewells.txt"
|
||||
|
||||
# Time tracking to prevent spam from flaky connections
|
||||
# Track last bye time for each user (in seconds since epoch)
|
||||
declare -A lastByeTime
|
||||
|
||||
# Only say bye if user hasn't been farewelled in the last hour (3600 seconds)
|
||||
currentTime=$(date +%s)
|
||||
userName="${1,,}"
|
||||
cooldownPeriod=3600
|
||||
|
||||
if [[ -n "${lastByeTime[$userName]}" ]]; then
|
||||
timeSinceLastBye=$((currentTime - lastByeTime[$userName]))
|
||||
if [[ $timeSinceLastBye -lt $cooldownPeriod ]]; then
|
||||
# User was farewelled recently, skip bye message
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Update last bye time for this user
|
||||
lastByeTime[$userName]=$currentTime
|
||||
|
||||
# All names to match are completely lowercase.
|
||||
case "${1,,}" in
|
||||
case "$userName" in
|
||||
storm_dragon)
|
||||
msg "${2%% :*}" "NOOOOOOOOOO!!! $1: come back!!!"
|
||||
;;
|
||||
|
||||
@@ -3,8 +3,28 @@
|
||||
|
||||
greetingsFile="triggers/greet/greetings.txt"
|
||||
|
||||
# Time tracking to prevent spam from flaky connections
|
||||
# Track last greet time for each user (in seconds since epoch)
|
||||
declare -A lastGreetTime
|
||||
|
||||
# Only greet if user hasn't been greeted in the last hour (3600 seconds)
|
||||
currentTime=$(date +%s)
|
||||
userName="${1,,}"
|
||||
cooldownPeriod=3600
|
||||
|
||||
if [[ -n "${lastGreetTime[$userName]}" ]]; then
|
||||
timeSinceLastGreet=$((currentTime - lastGreetTime[$userName]))
|
||||
if [[ $timeSinceLastGreet -lt $cooldownPeriod ]]; then
|
||||
# User was greeted recently, skip greeting
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Update last greet time for this user
|
||||
lastGreetTime[$userName]=$currentTime
|
||||
|
||||
# All names to match are completely lowercase.
|
||||
case "${1,,}" in
|
||||
case "$userName" in
|
||||
storm_dragon)
|
||||
msg "$2" "my lord, $1: how may I serve you?"
|
||||
;;
|
||||
|
||||
Reference in New Issue
Block a user