514 lines
12 KiB
Go

/*
Package babble is the active record implementation for global chat messages in the game.
Babble represents the global chat system where players can communicate with each other in real-time. The package provides comprehensive chat message management with features like mentions, search, time-based queries, and moderation utilities.
# Basic Usage
To retrieve a babble message by ID:
message, err := babble.Find(db, 1)
if err != nil {
log.Fatal(err)
}
fmt.Printf("<%s> %s\n", message.Author, message.Babble)
To get all babble messages:
allMessages, err := babble.All(db)
if err != nil {
log.Fatal(err)
}
for _, message := range allMessages {
fmt.Printf("[%s] <%s> %s\n",
message.PostedTime().Format("15:04"),
message.Author,
message.Babble)
}
To get recent chat messages:
recentChat, err := babble.Recent(db, 50)
if err != nil {
log.Fatal(err)
}
To filter messages by author:
userMessages, err := babble.ByAuthor(db, "PlayerName")
if err != nil {
log.Fatal(err)
}
# Creating Messages with Builder Pattern
The package provides a fluent builder interface for creating new chat messages:
message, err := babble.NewBuilder(db).
WithAuthor("PlayerName").
WithBabble("Hello everyone! Ready for some adventure?").
WithPostedTime(time.Now()).
Create()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Posted message with ID: %d\n", message.ID)
The builder automatically sets the current time if no posted time is specified:
message, err := babble.NewBuilder(db).
WithAuthor("Admin").
WithMessage("Server restart in 5 minutes!").
Create() // Uses current timestamp
You can use either `WithBabble()` or `WithMessage()` - they are aliases for the same functionality.
# Updating Messages
Chat messages can be modified and saved back to the database:
message, _ := babble.Find(db, 1)
message.Babble = "[EDITED] Original message was inappropriate"
err := message.Save()
if err != nil {
log.Fatal(err)
}
# Deleting Messages
Messages can be removed from the database (for moderation):
message, _ := babble.Find(db, 1)
err := message.Delete()
if err != nil {
log.Fatal(err)
}
# Database Schema
The babble table has the following structure:
CREATE TABLE babble (
id INTEGER PRIMARY KEY AUTOINCREMENT,
posted INTEGER NOT NULL DEFAULT (unixepoch()),
author TEXT NOT NULL DEFAULT '',
babble TEXT NOT NULL DEFAULT ''
)
Where:
- id: Unique identifier for the chat message
- posted: Unix timestamp when the message was posted
- author: Username of the player who posted the message
- babble: The text content of the chat message
# Time-Based Queries
## Recent Messages
Get the most recent chat messages:
// Get 100 most recent messages for chat display
chatHistory, err := babble.Recent(db, 100)
if err != nil {
log.Fatal(err)
}
fmt.Println("=== Recent Chat ===")
for _, msg := range chatHistory {
age := msg.Age()
timeStr := ""
if age < time.Minute {
timeStr = "just now"
} else if age < time.Hour {
timeStr = fmt.Sprintf("%dm ago", int(age.Minutes()))
} else {
timeStr = msg.PostedTime().Format("15:04")
}
fmt.Printf("[%s] <%s> %s\n", timeStr, msg.Author, msg.Babble)
}
## Messages Since Timestamp
Get messages posted since a specific time:
// Get messages since user's last login
lastLogin := getUserLastLogin(userID)
newMessages, err := babble.Since(db, lastLogin)
if err != nil {
log.Fatal(err)
}
if len(newMessages) > 0 {
fmt.Printf("You missed %d messages while you were away\n", len(newMessages))
}
## Messages Between Timestamps
Get messages within a time range:
// Get today's chat history
startOfDay := time.Now().Truncate(24 * time.Hour).Unix()
endOfDay := time.Now().Unix()
todaysChat, err := babble.Between(db, startOfDay, endOfDay)
if err != nil {
log.Fatal(err)
}
# Search and Filtering
## Text Search
Search for messages containing specific terms:
// Search for messages about "boss fight"
bossMessages, err := babble.Search(db, "boss fight")
if err != nil {
log.Fatal(err)
}
for _, msg := range bossMessages {
fmt.Printf("<%s> %s\n", msg.Author, msg.Preview(60))
}
Search is case-insensitive and matches partial words.
## Author-Based Queries
Get messages from specific players:
// Get recent messages from a player
playerRecent, err := babble.RecentByAuthor(db, "PlayerName", 10)
if err != nil {
log.Fatal(err)
}
// Get all messages from a player (for moderation)
allPlayerMessages, err := babble.ByAuthor(db, "ReportedPlayer")
if err != nil {
log.Fatal(err)
}
All author searches are case-insensitive.
# Mention System
## Finding Mentions
The package includes a comprehensive mention system using @username syntax:
message, _ := babble.Find(db, someID)
// Get all mentioned usernames
mentions := message.GetMentions()
for _, username := range mentions {
fmt.Printf("Message mentions: @%s\n", username)
}
// Check if specific user is mentioned
if message.HasMention("PlayerName") {
fmt.Println("You were mentioned in this message!")
}
## Mention Parsing
The mention system handles various formats:
- `@username` - Basic mention
- `@username!` - With punctuation
- `@username,` - In lists
- `@username?` - In questions
Mentions are extracted without the punctuation and are case-insensitive.
## Notification Integration
Use mentions for player notifications:
// Process new messages for mentions
recentMessages, _ := babble.Recent(db, 50)
for _, msg := range recentMessages {
mentions := msg.GetMentions()
for _, mentionedUser := range mentions {
// Send notification to mentioned user
notifyUser(mentionedUser, fmt.Sprintf("%s mentioned you: %s",
msg.Author, msg.Preview(50)))
}
}
# Message Analysis
## Content Analysis
Analyze message content for moderation or statistics:
message, _ := babble.Find(db, someID)
// Basic content metrics
fmt.Printf("Length: %d characters\n", message.Length())
fmt.Printf("Words: %d\n", message.WordCount())
// Content checks
if message.IsEmpty() {
fmt.Println("Empty message detected")
}
if message.IsLongMessage(200) {
fmt.Println("Very long message - possible spam")
}
// Search within message
if message.Contains("inappropriate_term") {
fmt.Println("Message flagged for review")
}
## Time Analysis
Analyze posting patterns:
message, _ := babble.Find(db, someID)
age := message.Age()
fmt.Printf("Message posted %v ago\n", age)
if message.IsRecent() {
fmt.Println("This is a recent message (within 1 hour)")
}
// Format for display
postedTime := message.PostedTime()
if age < 24*time.Hour {
fmt.Printf("Posted at %s\n", postedTime.Format("15:04"))
} else {
fmt.Printf("Posted on %s\n", postedTime.Format("Jan 2 15:04"))
}
# Chat Display Patterns
## Live Chat Feed
Display real-time chat messages:
func displayChatFeed(db *database.DB) {
messages, _ := babble.Recent(db, 50)
fmt.Println("=== Global Chat ===")
for i := len(messages) - 1; i >= 0; i-- { // Reverse for chronological order
msg := messages[i]
// Format timestamp
age := msg.Age()
var timeStr string
if age < time.Minute {
timeStr = "now"
} else if age < time.Hour {
timeStr = fmt.Sprintf("%dm", int(age.Minutes()))
} else {
timeStr = msg.PostedTime().Format("15:04")
}
// Handle mentions highlighting
content := msg.Babble
if msg.HasMention(currentUser) {
content = fmt.Sprintf("🔔 %s", content) // Highlight mentions
}
fmt.Printf("[%s] <%s> %s\n", timeStr, msg.Author, content)
}
}
## Chat History Browser
Browse historical messages:
func browseChatHistory(db *database.DB, page int, pageSize int) {
offset := page * pageSize
// Get paginated results (implement with LIMIT/OFFSET)
allMessages, _ := babble.All(db)
start := offset
end := offset + pageSize
if end > len(allMessages) {
end = len(allMessages)
}
if start >= len(allMessages) {
fmt.Println("No more messages")
return
}
pageMessages := allMessages[start:end]
fmt.Printf("=== Chat History (Page %d) ===\n", page+1)
for _, msg := range pageMessages {
fmt.Printf("%s <%s> %s\n",
msg.PostedTime().Format("Jan 2 15:04"),
msg.Author,
msg.Babble)
}
}
# Moderation Features
## Content Moderation
Tools for chat moderation:
// Flag inappropriate messages
func moderateMessage(db *database.DB, messageID int) {
msg, err := babble.Find(db, messageID)
if err != nil {
return
}
// Check for spam (very short or very long)
if msg.WordCount() < 2 {
fmt.Printf("Possible spam: %s\n", msg.Preview(30))
}
if msg.IsLongMessage(500) {
fmt.Printf("Very long message from %s\n", msg.Author)
}
// Check for excessive mentions
mentions := msg.GetMentions()
if len(mentions) > 5 {
fmt.Printf("Message with %d mentions from %s\n", len(mentions), msg.Author)
}
}
## User Activity Analysis
Analyze user posting patterns:
// Check user activity
func analyzeUserActivity(db *database.DB, username string) {
// Recent activity
recentMessages, _ := babble.RecentByAuthor(db, username, 10)
fmt.Printf("User %s recent activity:\n", username)
fmt.Printf("- Recent messages: %d\n", len(recentMessages))
if len(recentMessages) > 0 {
totalWords := 0
for _, msg := range recentMessages {
totalWords += msg.WordCount()
}
avgWords := totalWords / len(recentMessages)
fmt.Printf("- Average words per message: %d\n", avgWords)
latest := recentMessages[0]
fmt.Printf("- Last message: %s (%s ago)\n",
latest.Preview(40), latest.Age())
}
// Check for mention patterns
allUserMessages, _ := babble.ByAuthor(db, username)
mentionCount := 0
for _, msg := range allUserMessages {
mentionCount += len(msg.GetMentions())
}
if len(allUserMessages) > 0 {
avgMentions := float64(mentionCount) / float64(len(allUserMessages))
fmt.Printf("- Average mentions per message: %.2f\n", avgMentions)
}
}
# Performance Considerations
## Efficient Queries
All time-based queries are optimized:
// Recent messages are efficiently ordered
recent, _ := babble.Recent(db, 100) // Uses LIMIT for efficiency
// Time-based queries use indexed timestamp
since, _ := babble.Since(db, timestamp) // Efficient with proper index
// Author queries support case-insensitive search
authorMessages, _ := babble.ByAuthor(db, "username") // Uses LOWER() function
## Memory Management
For large chat histories, process in batches:
// Process messages in batches
func processAllMessages(db *database.DB, batchSize int) {
allMessages, _ := babble.All(db)
for i := 0; i < len(allMessages); i += batchSize {
end := i + batchSize
if end > len(allMessages) {
end = len(allMessages)
}
batch := allMessages[i:end]
processBatch(batch)
}
}
# Integration Examples
## Real-Time Chat
Implement live chat updates:
func pollForNewMessages(db *database.DB, lastMessageID int) []*babble.Babble {
// Get messages newer than last seen
allMessages, _ := babble.All(db)
newMessages := make([]*babble.Babble, 0)
for _, msg := range allMessages {
if msg.ID > lastMessageID {
newMessages = append(newMessages, msg)
}
}
return newMessages
}
## Chat Commands
Process special chat commands:
func processMessage(db *database.DB, author, content string) {
// Check for commands
if strings.HasPrefix(content, "/") {
handleCommand(author, content)
return
}
// Regular chat message
msg, err := babble.NewBuilder(db).
WithAuthor(author).
WithBabble(content).
Create()
if err != nil {
log.Printf("Failed to save message: %v", err)
return
}
// Process mentions for notifications
mentions := msg.GetMentions()
for _, username := range mentions {
sendMentionNotification(username, msg)
}
}
# Error Handling
All functions return appropriate errors for common failure cases:
- Message not found (Find returns error for non-existent IDs)
- Database connection issues
- Invalid operations (e.g., saving/deleting messages without IDs)
- Search query errors
- Time range validation errors
*/
package babble