|
@@ -4,10 +4,11 @@
|
4
|
4
|
package irc
|
5
|
5
|
|
6
|
6
|
import (
|
7
|
|
- "fmt"
|
|
7
|
+ "bytes"
|
8
|
8
|
|
9
|
|
- "github.com/oragono/oragono/irc/caps"
|
|
9
|
+ "github.com/oragono/oragono/irc/history"
|
10
|
10
|
"github.com/oragono/oragono/irc/modes"
|
|
11
|
+ "github.com/oragono/oragono/irc/utils"
|
11
|
12
|
)
|
12
|
13
|
|
13
|
14
|
const (
|
|
@@ -15,18 +16,40 @@ const (
|
15
|
16
|
sceneNickMask = "=Scene=!%s@npc.fakeuser.invalid"
|
16
|
17
|
)
|
17
|
18
|
|
18
|
|
-func sendRoleplayMessage(server *Server, client *Client, source string, targetString string, isAction bool, message string, rb *ResponseBuffer) {
|
|
19
|
+func sendRoleplayMessage(server *Server, client *Client, source string, targetString string, isAction bool, messageParts []string, rb *ResponseBuffer) {
|
|
20
|
+ config := server.Config()
|
|
21
|
+ if !config.Roleplay.enabled {
|
|
22
|
+ rb.Add(nil, client.server.name, ERR_CANNOTSENDRP, targetString, client.t("Roleplaying has been disabled by the server administrators"))
|
|
23
|
+ return
|
|
24
|
+ }
|
|
25
|
+ if config.Roleplay.RequireOper && !client.HasRoleCapabs("roleplay") {
|
|
26
|
+ rb.Add(nil, client.server.name, ERR_CANNOTSENDRP, targetString, client.t("Insufficient privileges"))
|
|
27
|
+ return
|
|
28
|
+ }
|
|
29
|
+
|
|
30
|
+ // block attempts to send CTCP messages to Tor clients
|
|
31
|
+ if len(messageParts) > 0 && len(messageParts[0]) > 0 && messageParts[0][0] == '\x01' {
|
|
32
|
+ return
|
|
33
|
+ }
|
|
34
|
+
|
|
35
|
+ var buf bytes.Buffer
|
19
|
36
|
if isAction {
|
20
|
|
- message = fmt.Sprintf("\x01ACTION %s (%s)\x01", message, client.nick)
|
21
|
|
- } else {
|
22
|
|
- // block attempts to send CTCP messages to Tor clients
|
23
|
|
- // TODO(#395) clean this up
|
24
|
|
- if len(message) != 0 && message[0] == '\x01' {
|
25
|
|
- return
|
|
37
|
+ buf.WriteString("\x01ACTION ")
|
|
38
|
+ }
|
|
39
|
+ for i, part := range messageParts {
|
|
40
|
+ buf.WriteString(part)
|
|
41
|
+ if i != len(messageParts)-1 {
|
|
42
|
+ buf.WriteByte(' ')
|
26
|
43
|
}
|
27
|
|
- message = fmt.Sprintf("%s (%s)", message, client.nick)
|
|
44
|
+ }
|
|
45
|
+ if config.Roleplay.addSuffix {
|
|
46
|
+ buf.WriteString(" (")
|
|
47
|
+ buf.WriteString(client.Nick())
|
|
48
|
+ buf.WriteString(")")
|
28
|
49
|
}
|
29
|
50
|
|
|
51
|
+ splitMessage := utils.MakeMessage(buf.String())
|
|
52
|
+
|
30
|
53
|
target, cerr := CasefoldChannel(targetString)
|
31
|
54
|
if cerr == nil {
|
32
|
55
|
channel := server.channels.Get(target)
|
|
@@ -35,27 +58,40 @@ func sendRoleplayMessage(server *Server, client *Client, source string, targetSt
|
35
|
58
|
return
|
36
|
59
|
}
|
37
|
60
|
|
|
61
|
+ targetString = channel.Name()
|
38
|
62
|
if !channel.CanSpeak(client) {
|
39
|
|
- rb.Add(nil, client.server.name, ERR_CANNOTSENDTOCHAN, channel.name, client.t("Cannot send to channel"))
|
|
63
|
+ rb.Add(nil, client.server.name, ERR_CANNOTSENDTOCHAN, targetString, client.t("Cannot send to channel"))
|
40
|
64
|
return
|
41
|
65
|
}
|
42
|
66
|
|
43
|
67
|
if !channel.flags.HasMode(modes.ChanRoleplaying) {
|
44
|
|
- rb.Add(nil, client.server.name, ERR_CANNOTSENDRP, channel.name, client.t("Channel doesn't have roleplaying mode available"))
|
|
68
|
+ rb.Add(nil, client.server.name, ERR_CANNOTSENDRP, targetString, client.t("Channel doesn't have roleplaying mode available"))
|
|
69
|
+ return
|
|
70
|
+ }
|
|
71
|
+
|
|
72
|
+ if config.Roleplay.RequireChanops && !channel.ClientIsAtLeast(client, modes.ChannelOperator) {
|
|
73
|
+ rb.Add(nil, client.server.name, ERR_CANNOTSENDRP, targetString, client.t("Insufficient privileges"))
|
45
|
74
|
return
|
46
|
75
|
}
|
47
|
76
|
|
48
|
77
|
for _, member := range channel.Members() {
|
49
|
78
|
for _, session := range member.Sessions() {
|
50
|
|
- if member == client && !session.capabilities.Has(caps.EchoMessage) {
|
51
|
|
- continue
|
52
|
|
- } else if rb.session == session {
|
53
|
|
- rb.Add(nil, source, "PRIVMSG", channel.name, message)
|
54
|
|
- } else if member == client || session.capabilities.Has(caps.EchoMessage) {
|
55
|
|
- session.Send(nil, source, "PRIVMSG", channel.name, message)
|
|
79
|
+ // see discussion on #865: clients do not understand how to do local echo
|
|
80
|
+ // of roleplay commands, so send them a copy whether they have echo-message
|
|
81
|
+ // or not
|
|
82
|
+ if rb.session == session {
|
|
83
|
+ rb.AddSplitMessageFromClient(source, "", nil, "PRIVMSG", targetString, splitMessage)
|
|
84
|
+ } else {
|
|
85
|
+ session.sendSplitMsgFromClientInternal(false, source, "", nil, "PRIVMSG", targetString, splitMessage)
|
56
|
86
|
}
|
57
|
87
|
}
|
58
|
88
|
}
|
|
89
|
+
|
|
90
|
+ channel.AddHistoryItem(history.Item{
|
|
91
|
+ Type: history.Privmsg,
|
|
92
|
+ Message: splitMessage,
|
|
93
|
+ Nick: source,
|
|
94
|
+ })
|
59
|
95
|
} else {
|
60
|
96
|
target, err := CasefoldName(targetString)
|
61
|
97
|
user := server.clients.Get(target)
|
|
@@ -71,9 +107,8 @@ func sendRoleplayMessage(server *Server, client *Client, source string, targetSt
|
71
|
107
|
|
72
|
108
|
cnick := client.Nick()
|
73
|
109
|
tnick := user.Nick()
|
74
|
|
- user.Send(nil, source, "PRIVMSG", tnick, message)
|
75
|
|
- if rb.session.capabilities.Has(caps.EchoMessage) {
|
76
|
|
- rb.Add(nil, source, "PRIVMSG", tnick, message)
|
|
110
|
+ for _, session := range user.Sessions() {
|
|
111
|
+ session.sendSplitMsgFromClientInternal(false, source, "", nil, "PRIVMSG", tnick, splitMessage)
|
77
|
112
|
}
|
78
|
113
|
if user.Away() {
|
79
|
114
|
//TODO(dan): possibly implement cooldown of away notifications to users
|