Просмотр исходного кода

Get it working, using not-great and very initial splitting code

tags/v0.6.0
Daniel Oaks 7 лет назад
Родитель
Сommit
f6185fa336
4 измененных файлов: 127 добавлений и 11 удалений
  1. 40
    0
      irc/channel.go
  2. 15
    3
      irc/client.go
  3. 0
    3
      irc/constants.go
  4. 72
    5
      irc/server.go

+ 40
- 0
irc/channel.go Просмотреть файл

@@ -411,6 +411,46 @@ func (channel *Channel) sendMessage(cmd string, minPrefix *ChannelMode, clientOn
411 411
 	}
412 412
 }
413 413
 
414
+// SplitPrivMsg sends a private message to everyone in this channel.
415
+func (channel *Channel) SplitPrivMsg(minPrefix *ChannelMode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message SplitMessage) {
416
+	channel.sendSplitMessage("PRIVMSG", minPrefix, clientOnlyTags, client, message)
417
+}
418
+
419
+// SplitNotice sends a private message to everyone in this channel.
420
+func (channel *Channel) SplitNotice(minPrefix *ChannelMode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message SplitMessage) {
421
+	channel.sendSplitMessage("NOTICE", minPrefix, clientOnlyTags, client, message)
422
+}
423
+
424
+func (channel *Channel) sendSplitMessage(cmd string, minPrefix *ChannelMode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message SplitMessage) {
425
+	if !channel.CanSpeak(client) {
426
+		client.Send(nil, client.server.name, ERR_CANNOTSENDTOCHAN, channel.name, "Cannot send to channel")
427
+		return
428
+	}
429
+
430
+	channel.membersMutex.RLock()
431
+	defer channel.membersMutex.RUnlock()
432
+
433
+	// for STATUSMSG
434
+	var minPrefixMode ChannelMode
435
+	if minPrefix != nil {
436
+		minPrefixMode = *minPrefix
437
+	}
438
+	for member := range channel.members {
439
+		if minPrefix != nil && !channel.ClientIsAtLeast(member, minPrefixMode) {
440
+			// STATUSMSG
441
+			continue
442
+		}
443
+		if member == client && !client.capabilities[EchoMessage] {
444
+			continue
445
+		}
446
+		if member.capabilities[MessageTags] {
447
+			member.SendSplitMsgFromClient(client, clientOnlyTags, cmd, channel.name, message)
448
+		} else {
449
+			member.SendSplitMsgFromClient(client, nil, cmd, channel.name, message)
450
+		}
451
+	}
452
+}
453
+
414 454
 func (channel *Channel) applyModeFlag(client *Client, mode ChannelMode,
415 455
 	op ModeOp) bool {
416 456
 	if !channel.ClientIsAtLeast(client, ChannelOperator) {

+ 15
- 3
irc/client.go Просмотреть файл

@@ -142,10 +142,10 @@ func (client *Client) maxlens() (int, int) {
142 142
 		maxlenTags = 4096
143 143
 	}
144 144
 	if client.capabilities[MaxLine] {
145
-		if maxLineTagsLength > maxlenTags {
146
-			maxlenTags = maxLineTagsLength
145
+		if client.server.limits.LineLen.Tags > maxlenTags {
146
+			maxlenTags = client.server.limits.LineLen.Tags
147 147
 		}
148
-		maxlenRest = maxLineRestLength
148
+		maxlenRest = client.server.limits.LineLen.Rest
149 149
 	}
150 150
 	return maxlenTags, maxlenRest
151 151
 }
@@ -496,6 +496,18 @@ func (client *Client) destroy() {
496 496
 	}
497 497
 }
498 498
 
499
+// SendSplitMsgFromClient sends an IRC PRIVMSG/NOTICE coming from a specific client.
500
+// Adds account-tag to the line as well.
501
+func (client *Client) SendSplitMsgFromClient(from *Client, tags *map[string]ircmsg.TagValue, command, target string, message SplitMessage) {
502
+	if client.capabilities[MaxLine] {
503
+		client.SendFromClient(from, tags, from.nickMaskString, command, target, message.ForMaxLine)
504
+	} else {
505
+		for _, str := range message.For512 {
506
+			client.SendFromClient(from, tags, from.nickMaskString, command, target, str)
507
+		}
508
+	}
509
+}
510
+
499 511
 // SendFromClient sends an IRC line coming from a specific client.
500 512
 // Adds account-tag to the line as well.
501 513
 func (client *Client) SendFromClient(from *Client, tags *map[string]ircmsg.TagValue, prefix string, command string, params ...string) error {

+ 0
- 3
irc/constants.go Просмотреть файл

@@ -16,9 +16,6 @@ var (
16 16
 	// Ver is the full version of Oragono, used in responses to clients.
17 17
 	Ver = fmt.Sprintf("oragono-%s", SemVer)
18 18
 
19
-	// Used as the standard maximum line length unless overridden at runtime.
20
-	maxLineTagsLength = 512
21
-	maxLineRestLength = 512
22 19
 	// maxLastArgLength is used to simply cap off the final argument when creating general messages where we need to select a limit.
23 20
 	// for instance, in MONITOR lists, RPL_ISUPPORT lists, etc.
24 21
 	maxLastArgLength = 400

+ 72
- 5
irc/server.go Просмотреть файл

@@ -847,12 +847,76 @@ func topicHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
847 847
 	return false
848 848
 }
849 849
 
850
+// func wordWrap(text string, lineWidth int) []string {
851
+// 	var split []string
852
+// 	var cache, cacheLastWord string
853
+
854
+// 	for _, char := range text {
855
+// 		if char == " " {
856
+// 			cache += cacheLastWord + char
857
+// 			continue
858
+// 		}
859
+
860
+// 		cacheLastWord += char
861
+// 		if cache + cacheLastWord ==
862
+
863
+// 		if len(cacheLastWord) >= lineWidth
864
+// 	}
865
+// }
866
+
867
+// taken from https://gist.github.com/kennwhite/306317d81ab4a885a965e25aa835b8ef
868
+func wordWrap(text string, lineWidth int) []string {
869
+	var split []string
870
+	words := strings.Fields(text)
871
+	if len(words) == 0 {
872
+		return split
873
+	}
874
+	cache := words[0]
875
+	spaceLeft := lineWidth - len(cache)
876
+	for _, word := range words[1:] {
877
+		if len(word)+1 > spaceLeft {
878
+			split = append(split, cache)
879
+			cache = word
880
+			spaceLeft = lineWidth - len(word)
881
+		} else {
882
+			cache += " " + word
883
+			spaceLeft -= 1 + len(word)
884
+		}
885
+	}
886
+	split = append(split, cache)
887
+
888
+	return split
889
+}
890
+
891
+// SplitMessage represents a message that's been split for sending.
892
+type SplitMessage struct {
893
+	For512     []string
894
+	ForMaxLine string
895
+}
896
+
897
+func (server *Server) splitMessage(original string) SplitMessage {
898
+	var newSplit SplitMessage
899
+
900
+	newSplit.ForMaxLine = original
901
+
902
+	if len(original) > 400 {
903
+		newSplit.For512 = wordWrap(original, 400)
904
+	} else {
905
+		newSplit.For512 = []string{original}
906
+	}
907
+
908
+	return newSplit
909
+}
910
+
850 911
 // PRIVMSG <target>{,<target>} <message>
851 912
 func privmsgHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
852 913
 	clientOnlyTags := GetClientOnlyTags(msg.Tags)
853 914
 	targets := strings.Split(msg.Params[0], ",")
854 915
 	message := msg.Params[1]
855 916
 
917
+	// split privmsg
918
+	splitMsg := server.splitMessage(message)
919
+
856 920
 	for i, targetString := range targets {
857 921
 		// max of four targets per privmsg
858 922
 		if i > maxTargets-1 {
@@ -873,7 +937,7 @@ func privmsgHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool
873 937
 				client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, targetString, "No such channel")
874 938
 				continue
875 939
 			}
876
-			channel.PrivMsg(lowestPrefix, clientOnlyTags, client, message)
940
+			channel.SplitPrivMsg(lowestPrefix, clientOnlyTags, client, splitMsg)
877 941
 		} else {
878 942
 			target, err = CasefoldName(targetString)
879 943
 			user := server.clients.Get(target)
@@ -886,7 +950,7 @@ func privmsgHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool
886 950
 			if !user.capabilities[MessageTags] {
887 951
 				clientOnlyTags = nil
888 952
 			}
889
-			user.SendFromClient(client, clientOnlyTags, client.nickMaskString, "PRIVMSG", user.nick, message)
953
+			user.SendSplitMsgFromClient(client, clientOnlyTags, "PRIVMSG", user.nick, splitMsg)
890 954
 			if client.capabilities[EchoMessage] {
891 955
 				client.SendFromClient(client, clientOnlyTags, client.nickMaskString, "PRIVMSG", user.nick, message)
892 956
 			}
@@ -1116,7 +1180,7 @@ func (server *Server) rehash() error {
1116 1180
 	}
1117 1181
 
1118 1182
 	// line lengths cannot be changed after launching the server
1119
-	if maxLineTagsLength != config.Limits.LineLen.Tags || maxLineRestLength != config.Limits.LineLen.Rest {
1183
+	if server.limits.LineLen.Tags != config.Limits.LineLen.Tags || server.limits.LineLen.Rest != config.Limits.LineLen.Rest {
1120 1184
 		return fmt.Errorf("Maximum line length (linelen) cannot be changed after launching the server, rehash aborted")
1121 1185
 	}
1122 1186
 
@@ -1376,6 +1440,9 @@ func noticeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
1376 1440
 	targets := strings.Split(msg.Params[0], ",")
1377 1441
 	message := msg.Params[1]
1378 1442
 
1443
+	// split privmsg
1444
+	splitMsg := server.splitMessage(message)
1445
+
1379 1446
 	for i, targetString := range targets {
1380 1447
 		// max of four targets per privmsg
1381 1448
 		if i > maxTargets-1 {
@@ -1391,7 +1458,7 @@ func noticeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
1391 1458
 				// errors silently ignored with NOTICE as per RFC
1392 1459
 				continue
1393 1460
 			}
1394
-			channel.Notice(lowestPrefix, clientOnlyTags, client, message)
1461
+			channel.SplitNotice(lowestPrefix, clientOnlyTags, client, splitMsg)
1395 1462
 		} else {
1396 1463
 			target, err := CasefoldName(targetString)
1397 1464
 			if err != nil {
@@ -1406,7 +1473,7 @@ func noticeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
1406 1473
 			if !user.capabilities[MessageTags] {
1407 1474
 				clientOnlyTags = nil
1408 1475
 			}
1409
-			user.SendFromClient(client, clientOnlyTags, client.nickMaskString, "NOTICE", user.nick, message)
1476
+			user.SendSplitMsgFromClient(client, clientOnlyTags, "NOTICE", user.nick, splitMsg)
1410 1477
 			if client.capabilities[EchoMessage] {
1411 1478
 				client.SendFromClient(client, clientOnlyTags, client.nickMaskString, "NOTICE", user.nick, message)
1412 1479
 			}

Загрузка…
Отмена
Сохранить