#!/usr/bin/env bash # Word tracking trigger - monitors messages and tracks word usage # shellcheck disable=SC1091 [ -f functions.sh ] && source functions.sh # shellcheck disable=SC1091 [ -f triggers/wordtrack/categories.sh ] && source triggers/wordtrack/categories.sh name="$1" channelName="$2" shift 2 message="$*" # Sanitize username (extract just the nickname, max 30 chars per IRC RFC) # Remove any IRC protocol remnants, hostmask info, etc. name="${name%%!*}" # Remove hostmask if present name="${name%%[[:space:]]*}" # Remove any trailing data name="${name//[^a-zA-Z0-9_\[\]\{\}\\|\^-]/}" # Only allow valid IRC nick chars name="${name:0:30}" # Limit to max IRC nickname length # If name is empty or invalid after sanitization, skip if [[ -z "$name" ]]; then exit 0 fi # Sanitize channel name (remove any IRC protocol remnants) channelName="${channelName%%[[:space:]]*}" channelName="${channelName//[^a-zA-Z0-9#_-]/}" # Only process if we have a valid channel name starting with # if [[ ! "$channelName" =~ ^#[a-zA-Z0-9_-]+$ ]]; then exit 0 fi # Convert message to lowercase for case-insensitive matching messageLower="${message,,}" # Create data directory for this channel if it doesn't exist dataDir="triggers/wordtrack/data/${channelName}" mkdir -p "$dataDir" # User data file userDataFile="${dataDir}/${name}.dat" # Load existing user data declare -A userCounts if [[ -f "$userDataFile" ]]; then while IFS='=' read -r category count; do userCounts["$category"]="$count" done < "$userDataFile" fi # Track which categories had level-ups declare -a levelUps # Process each category # shellcheck disable=SC2154 for category in "${categories[@]}"; do # Get the word array and levels array for this category levelsArrayName="${category}Levels" # Check if message contains any words from this category wordCount=0 wordsArrayNameClean="${category}Words" declare -n wordsRef="$wordsArrayNameClean" for word in "${wordsRef[@]}"; do # Count all occurrences of this word in the message wordLower="${word,,}" tempMessage="$messageLower" while [[ "$tempMessage" =~ $wordLower ]]; do ((wordCount++)) # Remove the matched word to find more occurrences tempMessage="${tempMessage/$wordLower/}" done done unset -n wordsRef # If words were found, update the counter if ((wordCount > 0)); then oldCount="${userCounts[$category]:-0}" newCount=$((oldCount + wordCount)) userCounts["$category"]="$newCount" # Check for level-up oldLevel="" newLevel="" # Get the thresholds for this category using nameref declare -n levelsRef="$levelsArrayName" # Get old level for threshold in $(printf '%s\n' "${!levelsRef[@]}" | sort -n); do if ((oldCount >= threshold)); then oldLevel="${levelsRef[$threshold]}" fi done # Get new level for threshold in $(printf '%s\n' "${!levelsRef[@]}" | sort -n); do if ((newCount >= threshold)); then newLevel="${levelsRef[$threshold]}" fi done # If level changed, record the level-up if [[ -n "$newLevel" && "$newLevel" != "$oldLevel" ]]; then levelUps+=("$category:$newLevel:$newCount") fi # Clean up nameref unset -n levelsRef fi done # Save updated user data : > "$userDataFile" for category in "${!userCounts[@]}"; do echo "${category}=${userCounts[$category]}" >> "$userDataFile" done # Announce level-ups for levelUp in "${levelUps[@]}"; do IFS=':' read -r category level count <<< "$levelUp" msg "$channelName" "$name just leveled up in ${category}! You are now a ${level} with ${count} words!" done