146 lines
5.6 KiB
Bash
Executable File
146 lines
5.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
[ -f functions.sh ] && source functions.sh
|
|
|
|
who="${1%!*}"
|
|
who="${who//:}"
|
|
shift
|
|
# shellcheck disable=SC2034 # Used in action strings via execute_action
|
|
chan="$1"
|
|
shift
|
|
|
|
keywordsFile="triggers/keywords/keywords.cfg"
|
|
|
|
# Function to process random selection syntax: {random:opt1|opt2|opt3}
|
|
process_random() {
|
|
local text="$1"
|
|
while [[ "$text" =~ \{random:([^}]+)\} ]]; do
|
|
local options="${BASH_REMATCH[1]}"
|
|
IFS='|' read -ra optArray <<< "$options"
|
|
local selected="${optArray[$((RANDOM % ${#optArray[@]}))]}"
|
|
text="${text/\{random:$options\}/$selected}"
|
|
done
|
|
echo "$text"
|
|
}
|
|
|
|
# Safe execution function - only allows predefined IRC functions
|
|
execute_action() {
|
|
local action="$1"
|
|
|
|
# Parse the action to extract function name and arguments
|
|
if [[ "$action" =~ ^msg[[:space:]]+(\"[^\"]+\"|[^[:space:]]+)[[:space:]]+(.+)$ ]]; then
|
|
local target="${BASH_REMATCH[1]}"
|
|
local message="${BASH_REMATCH[2]}"
|
|
# Remove quotes from target and message if present
|
|
target="${target//\"/}"
|
|
# Safely expand only $chan and $who variables - NO EVAL
|
|
message="${message//\"\$chan\"/$chan}"
|
|
message="${message//\$chan/$chan}"
|
|
message="${message//\"\$who\"/$who}"
|
|
message="${message//\$who/$who}"
|
|
message="${message//\$\{chan\}/$chan}"
|
|
message="${message//\$\{who\}/$who}"
|
|
message="$(process_random "$message")"
|
|
msg "$target" "$message"
|
|
elif [[ "$action" =~ ^act[[:space:]]+(\"[^\"]+\"|[^[:space:]]+)[[:space:]]+(.+)$ ]]; then
|
|
local target="${BASH_REMATCH[1]}"
|
|
local message="${BASH_REMATCH[2]}"
|
|
# Remove quotes from target and message if present
|
|
target="${target//\"/}"
|
|
# Safely expand only $chan and $who variables - NO EVAL
|
|
message="${message//\"\$chan\"/$chan}"
|
|
message="${message//\$chan/$chan}"
|
|
message="${message//\"\$who\"/$who}"
|
|
message="${message//\$who/$who}"
|
|
message="${message//\$\{chan\}/$chan}"
|
|
message="${message//\$\{who\}/$who}"
|
|
message="$(process_random "$message")"
|
|
act "$target" "$message"
|
|
elif [[ "$action" =~ ^reply[[:space:]]+(\"[^\"]+\"|[^[:space:]]+)[[:space:]]+(.+)$ ]]; then
|
|
local target="${BASH_REMATCH[1]}"
|
|
local message="${BASH_REMATCH[2]}"
|
|
# Remove quotes from target and message if present
|
|
target="${target//\"/}"
|
|
# Safely expand only $chan and $who variables - NO EVAL
|
|
message="${message//\"\$chan\"/$chan}"
|
|
message="${message//\$chan/$chan}"
|
|
message="${message//\"\$who\"/$who}"
|
|
message="${message//\$who/$who}"
|
|
message="${message//\$\{chan\}/$chan}"
|
|
message="${message//\$\{who\}/$who}"
|
|
message="$(process_random "$message")"
|
|
reply "$target" "$message"
|
|
fi
|
|
}
|
|
|
|
# Load keywords from config file into associative array
|
|
declare -A keywords
|
|
if [[ -f "$keywordsFile" ]]; then
|
|
while IFS='|' read -r keyword action percentage || [[ -n "$keyword" ]]; do
|
|
# Skip comments and empty lines
|
|
[[ "$keyword" =~ ^[[:space:]]*# ]] && continue
|
|
[[ -z "$keyword" ]] && continue
|
|
|
|
# Trim whitespace
|
|
keyword="${keyword#"${keyword%%[![:space:]]*}"}"
|
|
keyword="${keyword%"${keyword##*[![:space:]]}"}"
|
|
action="${action#"${action%%[![:space:]]*}"}"
|
|
action="${action%"${action##*[![:space:]]}"}"
|
|
percentage="${percentage#"${percentage%%[![:space:]]*}"}"
|
|
percentage="${percentage%"${percentage##*[![:space:]]}"}"
|
|
|
|
# Store in array (key includes ~ prefix for multi-word triggers)
|
|
if [[ -n "$percentage" ]]; then
|
|
keywords["$keyword"]="$action $percentage"
|
|
else
|
|
keywords["$keyword"]="$action"
|
|
fi
|
|
done < "$keywordsFile"
|
|
fi
|
|
|
|
# Process single-word triggers
|
|
wordList="$(echo "${@,,}" | tr '[:space:]' $'\n' | sort -u)"
|
|
for w in ${wordList//[[:punct:]]/} ; do
|
|
if [[ -n "${keywords[${w,,}]}" && "$lastWordMatch" != "${keywords[${w,,}]}" ]]; then
|
|
keywordAction="${keywords[${w,,}]}"
|
|
# Check if the last element is a percentage
|
|
if [[ "$keywordAction" =~ (.*)\ ([0-9]+)%$ ]]; then
|
|
command="${BASH_REMATCH[1]}"
|
|
percentage="${BASH_REMATCH[2]}"
|
|
# Generate random number between 1-100 and only respond if within percentage
|
|
randomNum=$((RANDOM % 100 + 1))
|
|
if [[ $randomNum -le $percentage ]]; then
|
|
execute_action "$command"
|
|
fi
|
|
else
|
|
# No percentage specified, always respond
|
|
execute_action "$keywordAction"
|
|
fi
|
|
lastWordMatch="${keywords[${w,,}]}"
|
|
fi
|
|
done
|
|
|
|
# Process multi-word triggers (those starting with ~)
|
|
wordList="$(echo "${@,,}" | tr -d '[:space:]')"
|
|
for trigger in "${!keywords[@]}"; do
|
|
if [[ "$trigger" =~ ^~ ]]; then
|
|
# Remove the ~ prefix for matching
|
|
triggerPattern="${trigger#\~}"
|
|
if [[ "${wordList,,}" =~ .*${triggerPattern}.* ]]; then
|
|
keywordAction="${keywords[$trigger]}"
|
|
# Check if the last element is a percentage
|
|
if [[ "$keywordAction" =~ (.*)\ ([0-9]+)%$ ]]; then
|
|
command="${BASH_REMATCH[1]}"
|
|
percentage="${BASH_REMATCH[2]}"
|
|
# Generate random number between 1-100 and only respond if within percentage
|
|
randomNum=$((RANDOM % 100 + 1))
|
|
if [[ $randomNum -le $percentage ]]; then
|
|
execute_action "$command"
|
|
fi
|
|
else
|
|
# No percentage specified, always respond
|
|
execute_action "$keywordAction"
|
|
fi
|
|
fi
|
|
fi
|
|
done
|