Browse Source

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

tags/v0.6.0
Daniel Oaks 7 years ago
parent
commit
f6185fa336
4 changed files with 127 additions and 11 deletions
  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 View File

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
 func (channel *Channel) applyModeFlag(client *Client, mode ChannelMode,
454
 func (channel *Channel) applyModeFlag(client *Client, mode ChannelMode,
415
 	op ModeOp) bool {
455
 	op ModeOp) bool {
416
 	if !channel.ClientIsAtLeast(client, ChannelOperator) {
456
 	if !channel.ClientIsAtLeast(client, ChannelOperator) {

+ 15
- 3
irc/client.go View File

142
 		maxlenTags = 4096
142
 		maxlenTags = 4096
143
 	}
143
 	}
144
 	if client.capabilities[MaxLine] {
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
 	return maxlenTags, maxlenRest
150
 	return maxlenTags, maxlenRest
151
 }
151
 }
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
 // SendFromClient sends an IRC line coming from a specific client.
511
 // SendFromClient sends an IRC line coming from a specific client.
500
 // Adds account-tag to the line as well.
512
 // Adds account-tag to the line as well.
501
 func (client *Client) SendFromClient(from *Client, tags *map[string]ircmsg.TagValue, prefix string, command string, params ...string) error {
513
 func (client *Client) SendFromClient(from *Client, tags *map[string]ircmsg.TagValue, prefix string, command string, params ...string) error {

+ 0
- 3
irc/constants.go View File

16
 	// Ver is the full version of Oragono, used in responses to clients.
16
 	// Ver is the full version of Oragono, used in responses to clients.
17
 	Ver = fmt.Sprintf("oragono-%s", SemVer)
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
 	// maxLastArgLength is used to simply cap off the final argument when creating general messages where we need to select a limit.
19
 	// maxLastArgLength is used to simply cap off the final argument when creating general messages where we need to select a limit.
23
 	// for instance, in MONITOR lists, RPL_ISUPPORT lists, etc.
20
 	// for instance, in MONITOR lists, RPL_ISUPPORT lists, etc.
24
 	maxLastArgLength = 400
21
 	maxLastArgLength = 400

+ 72
- 5
irc/server.go View File

847
 	return false
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
 // PRIVMSG <target>{,<target>} <message>
911
 // PRIVMSG <target>{,<target>} <message>
851
 func privmsgHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
912
 func privmsgHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
852
 	clientOnlyTags := GetClientOnlyTags(msg.Tags)
913
 	clientOnlyTags := GetClientOnlyTags(msg.Tags)
853
 	targets := strings.Split(msg.Params[0], ",")
914
 	targets := strings.Split(msg.Params[0], ",")
854
 	message := msg.Params[1]
915
 	message := msg.Params[1]
855
 
916
 
917
+	// split privmsg
918
+	splitMsg := server.splitMessage(message)
919
+
856
 	for i, targetString := range targets {
920
 	for i, targetString := range targets {
857
 		// max of four targets per privmsg
921
 		// max of four targets per privmsg
858
 		if i > maxTargets-1 {
922
 		if i > maxTargets-1 {
873
 				client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, targetString, "No such channel")
937
 				client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, targetString, "No such channel")
874
 				continue
938
 				continue
875
 			}
939
 			}
876
-			channel.PrivMsg(lowestPrefix, clientOnlyTags, client, message)
940
+			channel.SplitPrivMsg(lowestPrefix, clientOnlyTags, client, splitMsg)
877
 		} else {
941
 		} else {
878
 			target, err = CasefoldName(targetString)
942
 			target, err = CasefoldName(targetString)
879
 			user := server.clients.Get(target)
943
 			user := server.clients.Get(target)
886
 			if !user.capabilities[MessageTags] {
950
 			if !user.capabilities[MessageTags] {
887
 				clientOnlyTags = nil
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
 			if client.capabilities[EchoMessage] {
954
 			if client.capabilities[EchoMessage] {
891
 				client.SendFromClient(client, clientOnlyTags, client.nickMaskString, "PRIVMSG", user.nick, message)
955
 				client.SendFromClient(client, clientOnlyTags, client.nickMaskString, "PRIVMSG", user.nick, message)
892
 			}
956
 			}
1116
 	}
1180
 	}
1117
 
1181
 
1118
 	// line lengths cannot be changed after launching the server
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
 		return fmt.Errorf("Maximum line length (linelen) cannot be changed after launching the server, rehash aborted")
1184
 		return fmt.Errorf("Maximum line length (linelen) cannot be changed after launching the server, rehash aborted")
1121
 	}
1185
 	}
1122
 
1186
 
1376
 	targets := strings.Split(msg.Params[0], ",")
1440
 	targets := strings.Split(msg.Params[0], ",")
1377
 	message := msg.Params[1]
1441
 	message := msg.Params[1]
1378
 
1442
 
1443
+	// split privmsg
1444
+	splitMsg := server.splitMessage(message)
1445
+
1379
 	for i, targetString := range targets {
1446
 	for i, targetString := range targets {
1380
 		// max of four targets per privmsg
1447
 		// max of four targets per privmsg
1381
 		if i > maxTargets-1 {
1448
 		if i > maxTargets-1 {
1391
 				// errors silently ignored with NOTICE as per RFC
1458
 				// errors silently ignored with NOTICE as per RFC
1392
 				continue
1459
 				continue
1393
 			}
1460
 			}
1394
-			channel.Notice(lowestPrefix, clientOnlyTags, client, message)
1461
+			channel.SplitNotice(lowestPrefix, clientOnlyTags, client, splitMsg)
1395
 		} else {
1462
 		} else {
1396
 			target, err := CasefoldName(targetString)
1463
 			target, err := CasefoldName(targetString)
1397
 			if err != nil {
1464
 			if err != nil {
1406
 			if !user.capabilities[MessageTags] {
1473
 			if !user.capabilities[MessageTags] {
1407
 				clientOnlyTags = nil
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
 			if client.capabilities[EchoMessage] {
1477
 			if client.capabilities[EchoMessage] {
1411
 				client.SendFromClient(client, clientOnlyTags, client.nickMaskString, "NOTICE", user.nick, message)
1478
 				client.SendFromClient(client, clientOnlyTags, client.nickMaskString, "NOTICE", user.nick, message)
1412
 			}
1479
 			}

Loading…
Cancel
Save