This commit is contained in:
Storm Dragon
2025-10-24 21:35:41 -04:00
parent 3669e07a9a
commit a0afefadfd
20 changed files with 533 additions and 223 deletions

View File

@@ -0,0 +1,103 @@
# Wordtrack Trigger
Automatically tracks word usage by users and awards level-ups based on configurable thresholds.
## How It Works
The wordtrack trigger monitors all channel messages and counts occurrences of tracked words across different categories. Users automatically level up when they reach configured thresholds.
## Files
- `wordtrack.sh` - Main trigger script (called automatically on messages)
- `categories.sh` - Configuration file defining categories, words, and levels
- `data/<channel>/<nick>.dat` - Per-user tracking data
## Modules
Users can interact with wordtrack using these command modules:
### `.wordtrack-stats [nick]`
Shows word tracking statistics for yourself or another user.
Example:
```
.wordtrack-stats
.wordtrack-stats alice
```
Output: `alice's word tracking stats: coffee: Coffee Lover (50/100, 50 to next) | tea: Tea Sipper (12/25, 13 to next)`
### `.wordtrack-leaders <category>`
Shows top 5 users in a category.
Example:
```
.wordtrack-leaders coffee
.wordtrack-leaders
```
Output: `Top coffee users: 1. alice: Coffee Lover (50 words) | 2. bob: Coffee Drinker (30 words) | 3. charlie: Coffee Newbie (15 words)`
If no category is provided, lists available categories.
## Configuration
Edit `categories.sh` to add new categories or modify existing ones.
### Adding a New Category
1. Create a word array: `categoryWords=("word1" "word2" "word3")`
2. Create a levels array: `declare -A categoryLevels=([threshold1]="Level Name" [threshold2]="Level Name")`
3. Add category to the categories list: `categories=("coffee" "tea" "yournewcategory")`
Example:
```bash
# Category: programming
programmingWords=("code" "coding" "python" "javascript" "rust" "git" "debug")
declare -A programmingLevels=(
[10]="Code Newbie"
[25]="Junior Dev"
[50]="Developer"
[100]="Senior Dev"
[200]="Code Wizard"
)
# Add to categories list
categories=("coffee" "tea" "gaming" "programming")
```
### Array Structure
- **Word arrays**: Simple indexed arrays containing words to track
- Words are matched case-insensitively
- Multiple word matches in one message count separately
- **Level arrays**: Associative arrays with threshold as key, level name as value
- Keys must be integers representing word counts
- Users advance when their count meets or exceeds the threshold
- Thresholds can be any positive integer
## Data Format
User data files (`data/<channel>/<nick>.dat`) use simple key=value format:
```
coffee=45
tea=12
gaming=78
```
## Integration with bot.sh
The wordtrack trigger is called automatically for all channel messages from users not in the ignoreList (bot.sh:254-262). It processes messages after the keywords trigger.
Level-up announcements are sent to the channel automatically when thresholds are crossed.
## Notes
- Users in the `ignoreList` are not tracked
- Word matching is case-insensitive
- Multiple occurrences of tracked words in a single message all count
- Data persists across bot restarts (stored in flat files)
- Each channel has independent tracking data

View File

@@ -0,0 +1,61 @@
#!/usr/bin/env bash
# Word tracking categories configuration
# Add your own categories by following the pattern below
# Category: coffee
# Words that trigger tracking for coffee category
coffeeWords=("coffee" "espresso" "latte" "mocha" "cappuccino" "americano" "frappuccino" "macchiato" "cortado" "affogato")
# Level thresholds and reward names for coffee category
# Array key is the threshold (word count needed), value is the level name
declare -A coffeeLevels=(
[10]="Coffee Newbie"
[25]="Coffee Drinker"
[50]="Coffee Lover"
[100]="Coffee Addict"
[200]="Coffee Fiend"
[500]="Coffee God"
)
# Category: tea
teaWords=("tea" "matcha" "chai" "oolong" "earl" "green tea" "black tea" "herbal" "chamomile" "rooibos")
declare -A teaLevels=(
[10]="Tea Sipper"
[25]="Tea Enthusiast"
[50]="Tea Connoisseur"
[100]="Tea Master"
[200]="Tea Guru"
)
# Category: gaming
gamingWords=("game" "gaming" "play" "played" "console" "steam" "xbox" "playstation" "nintendo" "pc gaming")
declare -A gamingLevels=(
[10]="Casual Gamer"
[25]="Regular Player"
[50]="Dedicated Gamer"
[100]="Hardcore Gamer"
[200]="Gaming Enthusiast"
[500]="Gaming Legend"
)
# Words that trigger tracking for drugs category
drugsWords=("kratom" "gummy" "hemp" "nicotine")
# Level thresholds and reward names for drugs category
# Array key is the threshold (word count needed), value is the level name
declare -A drugsLevels=(
[10]="Adict"
[20]="Junky"
[40]="Burnout"
[80]="Dope Fiend"
[160]="Intervention Candidate"
[320]="Drug Lord"
[640]="Pickled"
)
# List all active categories (must match the prefix of your arrays above)
# This is used by the trigger to know which categories to track
categories=("coffee" "tea" "gaming" "drugs")

View File

@@ -0,0 +1,46 @@
#!/usr/bin/env bash
# Word tracking categories configuration
# Add your own categories by following the pattern below
# Category: coffee
# Words that trigger tracking for coffee category
coffeeWords=("coffee" "espresso" "latte" "mocha" "cappuccino" "americano" "frappuccino" "macchiato" "cortado" "affogato")
# Level thresholds and reward names for coffee category
# Array key is the threshold (word count needed), value is the level name
declare -A coffeeLevels=(
[10]="Coffee Newbie"
[25]="Coffee Drinker"
[50]="Coffee Lover"
[100]="Coffee Addict"
[200]="Coffee Fiend"
[500]="Coffee God"
)
# Category: tea
teaWords=("tea" "matcha" "chai" "oolong" "earl" "green tea" "black tea" "herbal" "chamomile" "rooibos")
declare -A teaLevels=(
[10]="Tea Sipper"
[25]="Tea Enthusiast"
[50]="Tea Connoisseur"
[100]="Tea Master"
[200]="Tea Guru"
)
# Category: gaming
gamingWords=("game" "gaming" "play" "played" "console" "steam" "xbox" "playstation" "nintendo" "pc gaming")
declare -A gamingLevels=(
[10]="Casual Gamer"
[25]="Regular Player"
[50]="Dedicated Gamer"
[100]="Hardcore Gamer"
[200]="Gaming Enthusiast"
[500]="Gaming Legend"
)
# List all active categories (must match the prefix of your arrays above)
# This is used by the trigger to know which categories to track
categories=("coffee" "tea" "gaming")

View File

@@ -0,0 +1 @@
gaming=30

116
triggers/wordtrack/wordtrack.sh Executable file
View File

@@ -0,0 +1,116 @@
#!/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 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