Repository: ergochat/ergo
Pull request #1728 (2021-07-02 23:51:49)

DISCONNECT Sno for always-on and/or multiclient
Everything _should_ be satisfactory and in tune  with the previous discussions we've had on my attempts at  #1720



Patch:
diff --git a/default.yaml b/default.yaml
index 96795214..289165d2 100644
--- a/default.yaml
+++ b/default.yaml
@@ -654,7 +654,7 @@ opers:
         # modes are modes to auto-set upon opering-up. uncomment this to automatically
         # enable snomasks ("server notification masks" that alert you to server events;
         # see `/quote help snomasks` while opered-up for more information):
-        #modes: +is acjknoqtuxv
+        #modes: +is acdjknoqtuxv
 
         # operators can be authenticated either by password (with the /OPER command),
         # or by certificate fingerprint, or both. if a password hash is set, then a
diff --git a/irc/client.go b/irc/client.go
index 3f406060..394f2a65 100644
--- a/irc/client.go
+++ b/irc/client.go
@@ -1310,6 +1310,9 @@ func (client *Client) destroy(session *Session) {
 			client.server.connectionLimiter.RemoveClient(flatip.FromNetIP(ip))
 			source = ip.String()
 		}
+		if !shouldDestroy {
+			client.server.snomasks.Send(sno.LocalDisconnects, fmt.Sprintf(ircfmt.Unescape("Client session disconnected for [a:%s] [h:%s] [ip:%s]"), details.accountName, session.rawHostname, source))
+		}
 		client.server.logger.Info("connect-ip", fmt.Sprintf("disconnecting session of %s from %s", details.nick, source))
 	}
 
diff --git a/irc/sno/constants.go b/irc/sno/constants.go
index 542ab57f..fe2f67fc 100644
--- a/irc/sno/constants.go
+++ b/irc/sno/constants.go
@@ -13,6 +13,7 @@ type Masks []Mask
 const (
 	LocalAnnouncements Mask = 'a'
 	LocalConnects      Mask = 'c'
+	LocalDisconnects   Mask = 'd'
 	LocalChannels      Mask = 'j'
 	LocalKills         Mask = 'k'
 	LocalNicks         Mask = 'n'
@@ -29,6 +30,7 @@ var (
 	NoticeMaskNames = map[Mask]string{
 		LocalAnnouncements: "ANNOUNCEMENT",
 		LocalConnects:      "CONNECT",
+		LocalDisconnects:   "DISCONNECT",
 		LocalChannels:      "CHANNEL",
 		LocalKills:         "KILL",
 		LocalNicks:         "NICK",
@@ -44,6 +46,7 @@ var (
 	ValidMasks = []Mask{
 		LocalAnnouncements,
 		LocalConnects,
+		LocalDisconnects,
 		LocalChannels,
 		LocalKills,
 		LocalNicks,
diff --git a/traditional.yaml b/traditional.yaml
index 349d7c5f..5d431c60 100644
--- a/traditional.yaml
+++ b/traditional.yaml
@@ -627,7 +627,7 @@ opers:
         # modes are modes to auto-set upon opering-up. uncomment this to automatically
         # enable snomasks ("server notification masks" that alert you to server events;
         # see `/quote help snomasks` while opered-up for more information):
-        #modes: +is acjknoqtuxv
+        #modes: +is acdjknoqtuxv
 
         # operators can be authenticated either by password (with the /OPER command),
         # or by certificate fingerprint, or both. if a password hash is set, then a


Test patch:
diff --git a/irc/sno/utils_test.go b/irc/sno/utils_test.go
index 46ce30bf..60ce3828 100644
--- a/irc/sno/utils_test.go
+++ b/irc/sno/utils_test.go
@@ -17,14 +17,14 @@ func assertEqual(supplied, expected interface{}, t *testing.T) {
 
 func TestEvaluateSnomaskChanges(t *testing.T) {
 	add, remove, newArg := EvaluateSnomaskChanges(true, "*", nil)
-	assertEqual(add, Masks{'a', 'c', 'j', 'k', 'n', 'o', 'q', 't', 'u', 'v', 'x'}, t)
+	assertEqual(add, Masks{'a', 'c', 'd', 'j', 'k', 'n', 'o', 'q', 't', 'u', 'v', 'x'}, t)
 	assertEqual(len(remove), 0, t)
-	assertEqual(newArg, "+acjknoqtuvx", t)
+	assertEqual(newArg, "+acdjknoqtuvx", t)
 
 	add, remove, newArg = EvaluateSnomaskChanges(true, "*", Masks{'a', 'u'})
-	assertEqual(add, Masks{'c', 'j', 'k', 'n', 'o', 'q', 't', 'v', 'x'}, t)
+	assertEqual(add, Masks{'c', 'd', 'j', 'k', 'n', 'o', 'q', 't', 'v', 'x'}, t)
 	assertEqual(len(remove), 0, t)
-	assertEqual(newArg, "+cjknoqtvx", t)
+	assertEqual(newArg, "+cdjknoqtvx", t)
 
 	add, remove, newArg = EvaluateSnomaskChanges(true, "-a", Masks{'a', 'u'})
 	assertEqual(len(add), 0, t)