Files
mattermore/server/engagement.go
T

84 lines
2.2 KiB
Go

package main
import (
"sync"
"time"
)
// EngagementState tracks whether a user is in an active conversation.
type EngagementState int
const (
Sleeping EngagementState = 0
Active EngagementState = 1
)
// engagementSession tracks a single user's active conversation.
type engagementSession struct {
userID string
channelID string
state EngagementState
lastActive time.Time
}
// EngagementEngine manages active conversations per user+channel.
// When a user @mentions the bot, they enter an Active session.
// Their subsequent non-@mention messages in the same channel
// are treated as continuations until a stop word or timeout.
type EngagementEngine struct {
mu sync.Mutex
sessions map[string]*engagementSession
timeout time.Duration
}
// NewEngagementEngine creates a new engine with the given inactivity timeout.
func NewEngagementEngine() *EngagementEngine {
return &EngagementEngine{
sessions: make(map[string]*engagementSession),
timeout: 5 * time.Minute,
}
}
// sessionKey builds a unique key per user+channel.
func (e *EngagementEngine) sessionKey(userID, channelID string) string {
return userID + ":" + channelID
}
// Wake marks a user+channel as actively engaged with the bot.
func (e *EngagementEngine) Wake(userID, channelID string) {
e.mu.Lock()
defer e.mu.Unlock()
key := e.sessionKey(userID, channelID)
e.sessions[key] = &engagementSession{
userID: userID,
channelID: channelID,
state: Active,
lastActive: time.Now(),
}
}
// IsActive returns true if the user+channel is in an active conversation.
func (e *EngagementEngine) IsActive(userID, channelID string) bool {
e.mu.Lock()
defer e.mu.Unlock()
key := e.sessionKey(userID, channelID)
s, exists := e.sessions[key]
if !exists {
return false
}
if time.Since(s.lastActive) > e.timeout {
delete(e.sessions, key)
return false
}
s.lastActive = time.Now()
return true
}
// Sleep ends the active conversation for a user+channel.
func (e *EngagementEngine) Sleep(userID, channelID string) {
e.mu.Lock()
defer e.mu.Unlock()
key := e.sessionKey(userID, channelID)
delete(e.sessions, key)
}