ScuttleBot

fix: delay SAMODE 30s so bots connect before modes are applied SAMODE only works on nicks already in the channel. Bots connect after provisioning, so SAMODE fired before they joined. Now AMODE (persistent) fires immediately, and SAMODE (immediate) fires after a 30s delay to catch bots that connected post-provisioning. This ensures shepherd and all other bots get their modes.

lmata 2026-04-05 22:54 trunk
Commit 1ff6cfa7edabfb7094169508a0117489a7be82b3fd3c974c278e196883ea9220
1 file changed +12 -4
--- internal/topology/topology.go
+++ internal/topology/topology.go
@@ -217,20 +217,28 @@
217217
for _, mode := range ch.Modes {
218218
m.client.Cmd.Mode(ch.Name, mode)
219219
}
220220
221221
// Fire mode grants asynchronously — don't block provisioning.
222
+ // ChanServ AMODE persists and auto-applies on join.
223
+ // SAMODE is immediate but only works for nicks already in the channel,
224
+ // so we delay it to give bots time to connect first.
222225
go func(name string, ops, voice []string) {
226
+ // Set persistent AMODE first (works regardless of presence).
223227
for _, nick := range ops {
224228
m.chanserv("AMODE %s +o %s", name, nick)
225
- if m.operPass != "" && m.client != nil {
226
- m.client.Cmd.SendRawf("SAMODE %s +o %s", name, nick)
227
- }
228229
}
229230
for _, nick := range voice {
230231
m.chanserv("AMODE %s +v %s", name, nick)
231
- if m.operPass != "" && m.client != nil {
232
+ }
233
+ // Delay SAMODE to apply modes to bots that connected after provisioning.
234
+ if m.operPass != "" && m.client != nil {
235
+ time.Sleep(30 * time.Second)
236
+ for _, nick := range ops {
237
+ m.client.Cmd.SendRawf("SAMODE %s +o %s", name, nick)
238
+ }
239
+ for _, nick := range voice {
232240
m.client.Cmd.SendRawf("SAMODE %s +v %s", name, nick)
233241
}
234242
}
235243
}(ch.Name, ch.Ops, ch.Voice)
236244
237245
--- internal/topology/topology.go
+++ internal/topology/topology.go
@@ -217,20 +217,28 @@
217 for _, mode := range ch.Modes {
218 m.client.Cmd.Mode(ch.Name, mode)
219 }
220
221 // Fire mode grants asynchronously — don't block provisioning.
 
 
 
222 go func(name string, ops, voice []string) {
 
223 for _, nick := range ops {
224 m.chanserv("AMODE %s +o %s", name, nick)
225 if m.operPass != "" && m.client != nil {
226 m.client.Cmd.SendRawf("SAMODE %s +o %s", name, nick)
227 }
228 }
229 for _, nick := range voice {
230 m.chanserv("AMODE %s +v %s", name, nick)
231 if m.operPass != "" && m.client != nil {
 
 
 
 
 
 
 
232 m.client.Cmd.SendRawf("SAMODE %s +v %s", name, nick)
233 }
234 }
235 }(ch.Name, ch.Ops, ch.Voice)
236
237
--- internal/topology/topology.go
+++ internal/topology/topology.go
@@ -217,20 +217,28 @@
217 for _, mode := range ch.Modes {
218 m.client.Cmd.Mode(ch.Name, mode)
219 }
220
221 // Fire mode grants asynchronously — don't block provisioning.
222 // ChanServ AMODE persists and auto-applies on join.
223 // SAMODE is immediate but only works for nicks already in the channel,
224 // so we delay it to give bots time to connect first.
225 go func(name string, ops, voice []string) {
226 // Set persistent AMODE first (works regardless of presence).
227 for _, nick := range ops {
228 m.chanserv("AMODE %s +o %s", name, nick)
 
 
 
229 }
230 for _, nick := range voice {
231 m.chanserv("AMODE %s +v %s", name, nick)
232 }
233 // Delay SAMODE to apply modes to bots that connected after provisioning.
234 if m.operPass != "" && m.client != nil {
235 time.Sleep(30 * time.Second)
236 for _, nick := range ops {
237 m.client.Cmd.SendRawf("SAMODE %s +o %s", name, nick)
238 }
239 for _, nick := range voice {
240 m.client.Cmd.SendRawf("SAMODE %s +v %s", name, nick)
241 }
242 }
243 }(ch.Name, ch.Ops, ch.Voice)
244
245

Keyboard Shortcuts

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