ScuttleBot

scuttlebot / internal / registry / engagement.go
Blame History Raw 89 lines
1
package registry
2
3
import (
4
"fmt"
5
"strings"
6
)
7
8
// EngagementConfig is the rules-of-engagement configuration for a registered agent.
9
// Passed to Register() at registration time; signed into the payload returned to the agent.
10
type EngagementConfig struct {
11
// Channels is the list of IRC channels the agent should join.
12
Channels []string `json:"channels,omitempty"`
13
14
// OpsChannels is a subset of Channels where the agent is granted +o (operator).
15
// Only meaningful for orchestrator-type agents.
16
OpsChannels []string `json:"ops_channels,omitempty"`
17
18
// Permissions is the list of allowed action types (e.g. "task.create").
19
// Empty means no explicit restrictions.
20
Permissions []string `json:"permissions,omitempty"`
21
22
// RateLimit controls message throughput for this agent.
23
RateLimit RateLimitConfig `json:"rate_limit,omitempty"`
24
25
// Rules defines engagement behaviour rules for this agent.
26
Rules EngagementRules `json:"engagement,omitempty"`
27
}
28
29
// RateLimitConfig controls message throughput.
30
type RateLimitConfig struct {
31
// MessagesPerSecond is the sustained send rate allowed. 0 means no limit.
32
MessagesPerSecond float64 `json:"messages_per_second,omitempty"`
33
34
// Burst is the maximum burst above MessagesPerSecond. 0 means no burst.
35
Burst int `json:"burst,omitempty"`
36
}
37
38
// EngagementRules defines what message types and peers the agent should engage with.
39
type EngagementRules struct {
40
// RespondToTypes restricts which message types trigger handler callbacks.
41
// Empty means respond to all types.
42
RespondToTypes []string `json:"respond_to_types,omitempty"`
43
44
// IgnoreNicks is a list of IRC nicks whose messages are always ignored.
45
IgnoreNicks []string `json:"ignore_nicks,omitempty"`
46
}
47
48
// Validate checks the EngagementConfig for obvious errors.
49
// Returns a descriptive error for the first problem found.
50
func (c EngagementConfig) Validate() error {
51
for _, ch := range c.Channels {
52
if !strings.HasPrefix(ch, "#") {
53
return fmt.Errorf("engagement: channel %q must start with #", ch)
54
}
55
if strings.ContainsAny(ch, " \t\r\n,") {
56
return fmt.Errorf("engagement: channel %q contains invalid characters", ch)
57
}
58
if len(ch) < 2 {
59
return fmt.Errorf("engagement: channel %q is too short", ch)
60
}
61
}
62
63
// OpsChannels must be a subset of Channels.
64
joinSet := make(map[string]struct{}, len(c.Channels))
65
for _, ch := range c.Channels {
66
joinSet[ch] = struct{}{}
67
}
68
for _, ch := range c.OpsChannels {
69
if _, ok := joinSet[ch]; !ok {
70
return fmt.Errorf("engagement: ops_channel %q is not in channels list", ch)
71
}
72
}
73
74
if c.RateLimit.MessagesPerSecond < 0 {
75
return fmt.Errorf("engagement: rate_limit.messages_per_second must be >= 0")
76
}
77
if c.RateLimit.Burst < 0 {
78
return fmt.Errorf("engagement: rate_limit.burst must be >= 0")
79
}
80
81
for _, t := range c.Rules.RespondToTypes {
82
if t == "" {
83
return fmt.Errorf("engagement: respond_to_types contains empty string")
84
}
85
}
86
87
return nil
88
}
89

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button