mirror of
https://github.com/ergochat/ergo.git
synced 2024-12-23 03:02:48 +01:00
implement SAJOIN, allow channel founders to join unconditionally
This commit is contained in:
parent
13aba9e64c
commit
495705f538
@ -350,32 +350,36 @@ func (channel *Channel) IsEmpty() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Join joins the given client to this channel (if they can be joined).
|
// Join joins the given client to this channel (if they can be joined).
|
||||||
//TODO(dan): /SAJOIN and maybe a ForceJoin function?
|
func (channel *Channel) Join(client *Client, key string, isSajoin bool, rb *ResponseBuffer) {
|
||||||
func (channel *Channel) Join(client *Client, key string, rb *ResponseBuffer) {
|
|
||||||
if channel.hasClient(client) {
|
if channel.hasClient(client) {
|
||||||
// already joined, no message needs to be sent
|
// already joined, no message needs to be sent
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
chname := channel.Name()
|
channel.stateMutex.RLock()
|
||||||
|
chname := channel.name
|
||||||
|
founder := channel.registeredFounder
|
||||||
|
channel.stateMutex.RUnlock()
|
||||||
|
account := client.Account()
|
||||||
|
hasPrivs := isSajoin || (founder != "" && founder == account)
|
||||||
|
|
||||||
if channel.IsFull() {
|
if !hasPrivs && channel.IsFull() {
|
||||||
rb.Add(nil, client.server.name, ERR_CHANNELISFULL, chname, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "l"))
|
rb.Add(nil, client.server.name, ERR_CHANNELISFULL, chname, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "l"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !channel.CheckKey(key) {
|
if !hasPrivs && !channel.CheckKey(key) {
|
||||||
rb.Add(nil, client.server.name, ERR_BADCHANNELKEY, chname, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "k"))
|
rb.Add(nil, client.server.name, ERR_BADCHANNELKEY, chname, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "k"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
isInvited := channel.lists[modes.InviteMask].Match(client.nickMaskCasefolded)
|
isInvited := channel.lists[modes.InviteMask].Match(client.nickMaskCasefolded)
|
||||||
if channel.flags.HasMode(modes.InviteOnly) && !isInvited {
|
if !hasPrivs && channel.flags.HasMode(modes.InviteOnly) && !isInvited {
|
||||||
rb.Add(nil, client.server.name, ERR_INVITEONLYCHAN, chname, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "i"))
|
rb.Add(nil, client.server.name, ERR_INVITEONLYCHAN, chname, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "i"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if channel.lists[modes.BanMask].Match(client.nickMaskCasefolded) &&
|
if !hasPrivs && channel.lists[modes.BanMask].Match(client.nickMaskCasefolded) &&
|
||||||
!isInvited &&
|
!isInvited &&
|
||||||
!channel.lists[modes.ExceptMask].Match(client.nickMaskCasefolded) {
|
!channel.lists[modes.ExceptMask].Match(client.nickMaskCasefolded) {
|
||||||
rb.Add(nil, client.server.name, ERR_BANNEDFROMCHAN, chname, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "b"))
|
rb.Add(nil, client.server.name, ERR_BANNEDFROMCHAN, chname, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "b"))
|
||||||
@ -389,7 +393,6 @@ func (channel *Channel) Join(client *Client, key string, rb *ResponseBuffer) {
|
|||||||
defer channel.joinPartMutex.Unlock()
|
defer channel.joinPartMutex.Unlock()
|
||||||
|
|
||||||
func() {
|
func() {
|
||||||
account := client.Account()
|
|
||||||
channel.stateMutex.Lock()
|
channel.stateMutex.Lock()
|
||||||
defer channel.stateMutex.Unlock()
|
defer channel.stateMutex.Unlock()
|
||||||
|
|
||||||
@ -779,7 +782,7 @@ func (channel *Channel) Kick(client *Client, target *Client, comment string, rb
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !channel.ClientHasPrivsOver(client, target) {
|
if !channel.ClientHasPrivsOver(client, target) {
|
||||||
rb.Add(nil, client.server.name, ERR_CHANOPRIVSNEEDED, channel.name, client.t("You're not a channel operator"))
|
rb.Add(nil, client.server.name, ERR_CHANOPRIVSNEEDED, channel.name, client.t("You don't have enough channel privileges"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ func (cm *ChannelManager) Get(name string) *Channel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Join causes `client` to join the channel named `name`, creating it if necessary.
|
// Join causes `client` to join the channel named `name`, creating it if necessary.
|
||||||
func (cm *ChannelManager) Join(client *Client, name string, key string, rb *ResponseBuffer) error {
|
func (cm *ChannelManager) Join(client *Client, name string, key string, isSajoin bool, rb *ResponseBuffer) error {
|
||||||
server := client.server
|
server := client.server
|
||||||
casefoldedName, err := CasefoldChannel(name)
|
casefoldedName, err := CasefoldChannel(name)
|
||||||
if err != nil || len(casefoldedName) > server.Limits().ChannelLen {
|
if err != nil || len(casefoldedName) > server.Limits().ChannelLen {
|
||||||
@ -74,7 +74,7 @@ func (cm *ChannelManager) Join(client *Client, name string, key string, rb *Resp
|
|||||||
entry.pendingJoins += 1
|
entry.pendingJoins += 1
|
||||||
cm.Unlock()
|
cm.Unlock()
|
||||||
|
|
||||||
entry.channel.Join(client, key, rb)
|
entry.channel.Join(client, key, isSajoin, rb)
|
||||||
|
|
||||||
cm.maybeCleanup(entry.channel, true)
|
cm.maybeCleanup(entry.channel, true)
|
||||||
|
|
||||||
|
@ -229,6 +229,11 @@ func init() {
|
|||||||
usablePreReg: true,
|
usablePreReg: true,
|
||||||
minParams: 1,
|
minParams: 1,
|
||||||
},
|
},
|
||||||
|
"SAJOIN": {
|
||||||
|
handler: sajoinHandler,
|
||||||
|
minParams: 1,
|
||||||
|
capabs: []string{"sajoin"},
|
||||||
|
},
|
||||||
"SANICK": {
|
"SANICK": {
|
||||||
handler: sanickHandler,
|
handler: sanickHandler,
|
||||||
minParams: 2,
|
minParams: 2,
|
||||||
|
@ -889,7 +889,7 @@ func joinHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
|
|||||||
if len(keys) > i {
|
if len(keys) > i {
|
||||||
key = keys[i]
|
key = keys[i]
|
||||||
}
|
}
|
||||||
err := server.channels.Join(client, name, key, rb)
|
err := server.channels.Join(client, name, key, false, rb)
|
||||||
if err == errNoSuchChannel {
|
if err == errNoSuchChannel {
|
||||||
rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.Nick(), name, client.t("No such channel"))
|
rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.Nick(), name, client.t("No such channel"))
|
||||||
}
|
}
|
||||||
@ -897,6 +897,38 @@ func joinHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SAJOIN [nick] #channel{,#channel}
|
||||||
|
func sajoinHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
||||||
|
var target *Client
|
||||||
|
var channelString string
|
||||||
|
if strings.HasPrefix(msg.Params[0], "#") {
|
||||||
|
target = client
|
||||||
|
channelString = msg.Params[0]
|
||||||
|
} else {
|
||||||
|
if len(msg.Params) == 1 {
|
||||||
|
rb.Add(nil, server.name, ERR_NEEDMOREPARAMS, client.Nick(), "KICK", client.t("Not enough parameters"))
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
target = server.clients.Get(msg.Params[0])
|
||||||
|
if target == nil {
|
||||||
|
rb.Add(nil, server.name, ERR_NOSUCHNICK, client.Nick(), msg.Params[0], "No such nick")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
channelString = msg.Params[1]
|
||||||
|
rb = NewResponseBuffer(target)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
channels := strings.Split(channelString, ",")
|
||||||
|
for _, chname := range channels {
|
||||||
|
server.channels.Join(target, chname, "", true, rb)
|
||||||
|
}
|
||||||
|
if client != target {
|
||||||
|
rb.Send()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// KICK <channel>{,<channel>} <user>{,<user>} [<comment>]
|
// KICK <channel>{,<channel>} <user>{,<user>} [<comment>]
|
||||||
func kickHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
func kickHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
||||||
channels := strings.Split(msg.Params[0], ",")
|
channels := strings.Split(msg.Params[0], ",")
|
||||||
|
@ -400,6 +400,13 @@ Renames the given channel with the given reason, if possible.
|
|||||||
|
|
||||||
For example:
|
For example:
|
||||||
RENAME #ircv2 #ircv3 :Protocol upgrades!`,
|
RENAME #ircv2 #ircv3 :Protocol upgrades!`,
|
||||||
|
},
|
||||||
|
"sajoin": {
|
||||||
|
oper: true,
|
||||||
|
text: `SAJOIN [nick] #channel{,#channel}
|
||||||
|
|
||||||
|
Forcibly joins a user to a channel, ignoring restrictions like bans, user limits
|
||||||
|
and channel keys. If [nick] is omitted, it defaults to the operator.`,
|
||||||
},
|
},
|
||||||
"sanick": {
|
"sanick": {
|
||||||
oper: true,
|
oper: true,
|
||||||
|
@ -281,6 +281,7 @@ oper-classes:
|
|||||||
- "oper:rehash"
|
- "oper:rehash"
|
||||||
- "oper:die"
|
- "oper:die"
|
||||||
- "unregister"
|
- "unregister"
|
||||||
|
- "sajoin"
|
||||||
- "samode"
|
- "samode"
|
||||||
- "vhosts"
|
- "vhosts"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user