3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-25 21:39:25 +01:00

Initial RELAYMSG implementation

This commit is contained in:
Daniel Oaks 2020-06-08 10:19:28 +10:00
parent 2801018150
commit 4ee49f8450
9 changed files with 91 additions and 1 deletions

View File

@ -583,6 +583,7 @@ oper-classes:
- "vhosts" - "vhosts"
- "chanreg" - "chanreg"
- "history" - "history"
- "relaymsg-anywhere"
# ircd operators # ircd operators
opers: opers:

View File

@ -93,6 +93,12 @@ CAPDEFS = [
url="https://ircv3.net/specs/extensions/multi-prefix-3.1.html", url="https://ircv3.net/specs/extensions/multi-prefix-3.1.html",
standard="IRCv3", standard="IRCv3",
), ),
CapDef(
identifier="Relaymsg",
name="draft/relaymsg",
url="https://github.com/ircv3/ircv3-specifications/pull/417",
standard="proposed IRCv3",
),
CapDef( CapDef(
identifier="Rename", identifier="Rename",
name="draft/rename", name="draft/rename",

View File

@ -7,7 +7,7 @@ package caps
const ( const (
// number of recognized capabilities: // number of recognized capabilities:
numCapabs = 26 numCapabs = 27
// length of the uint64 array that represents the bitset: // length of the uint64 array that represents the bitset:
bitsetLen = 1 bitsetLen = 1
) )
@ -53,6 +53,10 @@ const (
// https://github.com/ircv3/ircv3-specifications/pull/398 // https://github.com/ircv3/ircv3-specifications/pull/398
Multiline Capability = iota Multiline Capability = iota
// Relaymsg is the proposed IRCv3 capability named "draft/relaymsg":
// https://github.com/ircv3/ircv3-specifications/pull/417
Relaymsg Capability = iota
// Rename is the proposed IRCv3 capability named "draft/rename": // Rename is the proposed IRCv3 capability named "draft/rename":
// https://github.com/SaberUK/ircv3-specifications/blob/rename/extensions/rename.md // https://github.com/SaberUK/ircv3-specifications/blob/rename/extensions/rename.md
Rename Capability = iota Rename Capability = iota
@ -131,6 +135,7 @@ var (
"draft/event-playback", "draft/event-playback",
"draft/languages", "draft/languages",
"draft/multiline", "draft/multiline",
"draft/relaymsg",
"draft/rename", "draft/rename",
"draft/resume-0.5", "draft/resume-0.5",
"echo-message", "echo-message",

View File

@ -173,6 +173,10 @@ func (clients *ClientManager) SetNick(client *Client, session *Session, newNick
return "", errNicknameInvalid, false return "", errNicknameInvalid, false
} }
if strings.Contains(newCfNick, "/") {
return "", errNicknameInvalid, false
}
if restrictedCasefoldedNicks[newCfNick] || restrictedSkeletons[newSkeleton] { if restrictedCasefoldedNicks[newCfNick] || restrictedSkeletons[newSkeleton] {
return "", errNicknameInvalid, false return "", errNicknameInvalid, false
} }

View File

@ -250,6 +250,10 @@ func init() {
minParams: 2, minParams: 2,
allowedInBatch: true, allowedInBatch: true,
}, },
"RELAYMSG": {
handler: relaymsgHandler,
minParams: 3,
},
"RENAME": { "RENAME": {
handler: renameHandler, handler: renameHandler,
minParams: 2, minParams: 2,

View File

@ -1068,6 +1068,9 @@ func LoadConfig(filename string) (config *Config, err error) {
} }
config.Server.capValues[caps.Languages] = config.languageManager.CapValue() config.Server.capValues[caps.Languages] = config.languageManager.CapValue()
// intentionally not configurable
config.Server.capValues[caps.Relaymsg] = "/"
config.Debug.recoverFromErrors = utils.BoolDefaultTrue(config.Debug.RecoverFromErrors) config.Debug.recoverFromErrors = utils.BoolDefaultTrue(config.Debug.RecoverFromErrors)
// process operator definitions, store them to config.operators // process operator definitions, store them to config.operators

View File

@ -1887,6 +1887,15 @@ func messageHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *R
if i == maxTargets { if i == maxTargets {
break break
} }
if strings.Contains(targetString, "/") {
if histType == history.Privmsg {
rb.Add(nil, server.name, ERR_NOSUCHNICK, client.Nick(), targetString, client.t("Relayed users cannot be sent private messages"))
}
// TAGMSG/NOTICEs are intentionally silently dropped
continue
}
// each target gets distinct msgids // each target gets distinct msgids
splitMsg := utils.MakeMessage(message) splitMsg := utils.MakeMessage(message)
dispatchMessageToTarget(client, clientOnlyTags, histType, msg.Command, targetString, splitMsg, rb) dispatchMessageToTarget(client, clientOnlyTags, histType, msg.Command, targetString, splitMsg, rb)
@ -2270,6 +2279,53 @@ func rehashHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Re
return false return false
} }
// RELAYMSG <channel> <spoofed nick> :<message>
func relaymsgHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) (result bool) {
channel := server.channels.Get(msg.Params[0])
if channel == nil {
rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.Nick(), utils.SafeErrorParam(msg.Params[0]), client.t("No such channel"))
return false
}
if !(channel.ClientIsAtLeast(client, modes.ChannelOperator) || client.HasRoleCapabs("relaymsg-anywhere")) {
rb.Add(nil, server.name, "FAIL", "RELAYMSG", "NOT_PRIVED", client.t("Only channel operators or ircops with the 'relaymsg-anywhere' role can relay messages"))
return false
}
rawMessage := msg.Params[2]
if strings.TrimSpace(rawMessage) == "" {
rb.Add(nil, server.name, "FAIL", "RELAYMSG", "BLANK_MSG", client.t("The message must not be blank"))
return false
}
message := utils.MakeMessage(rawMessage)
nick := msg.Params[1]
_, err := CasefoldName(nick)
if err != nil {
rb.Add(nil, server.name, "FAIL", "RELAYMSG", "INVALID_NICK", client.t("Invalid nickname"))
return false
}
if !strings.Contains(nick, "/") {
rb.Add(nil, server.name, "FAIL", "RELAYMSG", "INVALID_NICK", fmt.Sprintf(client.t("Relayed nicknames MUST contain the relaymsg separator %s"), "/"))
return false
}
//TODO: add to history here??
// send msg
for _, member := range channel.Members() {
for _, session := range member.Sessions() {
tagsToUse := make(map[string]string)
if session.capabilities.Has(caps.Relaymsg) {
tagsToUse["relaymsg"] = client.Nick()
}
session.sendSplitMsgFromClientInternal(false, nick, "", tagsToUse, "PRIVMSG", channel.Name(), message)
}
}
return false
}
// RENAME <oldchan> <newchan> [<reason>] // RENAME <oldchan> <newchan> [<reason>]
func renameHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) (result bool) { func renameHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) (result bool) {
result = false result = false

View File

@ -393,6 +393,16 @@ Replies to a PING. Used to check link connectivity.`,
text: `PRIVMSG <target>{,<target>} <text to be sent> text: `PRIVMSG <target>{,<target>} <text to be sent>
Sends the text to the given targets as a PRIVMSG.`, Sends the text to the given targets as a PRIVMSG.`,
},
"relaymsg": {
text: `RELAYMSG <channel> <spoofed nick> :<message>
This command lets channel operators relay messages to their
channel from other messaging systems using relay bots. The
spoofed nickname MUST contain a forwardslash.
For example:
RELAYMSG #ircv3 Mallory/D :Welp, we linked Discord...`,
}, },
"rename": { "rename": {
text: `RENAME <channel> <newname> [<reason>] text: `RENAME <channel> <newname> [<reason>]

View File

@ -609,6 +609,7 @@ oper-classes:
- "vhosts" - "vhosts"
- "chanreg" - "chanreg"
- "history" - "history"
- "relaymsg-anywhere"
# ircd operators # ircd operators
opers: opers: