mirror of
https://github.com/ergochat/ergo.git
synced 2024-12-28 13:42:35 +01:00
Merge pull request #271 from slingamn/sajoin.3
implement SAJOIN, allow channel founders to join unconditionally
This commit is contained in:
commit
4bfa5fc66e
@ -350,32 +350,36 @@ func (channel *Channel) IsEmpty() bool {
|
||||
}
|
||||
|
||||
// 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, rb *ResponseBuffer) {
|
||||
func (channel *Channel) Join(client *Client, key string, isSajoin bool, rb *ResponseBuffer) {
|
||||
if channel.hasClient(client) {
|
||||
// already joined, no message needs to be sent
|
||||
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"))
|
||||
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"))
|
||||
return
|
||||
}
|
||||
|
||||
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"))
|
||||
return
|
||||
}
|
||||
|
||||
if channel.lists[modes.BanMask].Match(client.nickMaskCasefolded) &&
|
||||
if !hasPrivs && channel.lists[modes.BanMask].Match(client.nickMaskCasefolded) &&
|
||||
!isInvited &&
|
||||
!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"))
|
||||
@ -389,7 +393,6 @@ func (channel *Channel) Join(client *Client, key string, rb *ResponseBuffer) {
|
||||
defer channel.joinPartMutex.Unlock()
|
||||
|
||||
func() {
|
||||
account := client.Account()
|
||||
channel.stateMutex.Lock()
|
||||
defer channel.stateMutex.Unlock()
|
||||
|
||||
@ -779,7 +782,7 @@ func (channel *Channel) Kick(client *Client, target *Client, comment string, rb
|
||||
return
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ func (cm *ChannelManager) Get(name string) *Channel {
|
||||
}
|
||||
|
||||
// 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
|
||||
casefoldedName, err := CasefoldChannel(name)
|
||||
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
|
||||
cm.Unlock()
|
||||
|
||||
entry.channel.Join(client, key, rb)
|
||||
entry.channel.Join(client, key, isSajoin, rb)
|
||||
|
||||
cm.maybeCleanup(entry.channel, true)
|
||||
|
||||
|
@ -229,6 +229,11 @@ func init() {
|
||||
usablePreReg: true,
|
||||
minParams: 1,
|
||||
},
|
||||
"SAJOIN": {
|
||||
handler: sajoinHandler,
|
||||
minParams: 1,
|
||||
capabs: []string{"sajoin"},
|
||||
},
|
||||
"SANICK": {
|
||||
handler: sanickHandler,
|
||||
minParams: 2,
|
||||
|
@ -889,7 +889,7 @@ func joinHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
|
||||
if len(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 {
|
||||
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
|
||||
}
|
||||
|
||||
// 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>]
|
||||
func kickHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
||||
channels := strings.Split(msg.Params[0], ",")
|
||||
|
@ -400,6 +400,13 @@ Renames the given channel with the given reason, if possible.
|
||||
|
||||
For example:
|
||||
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": {
|
||||
oper: true,
|
||||
|
@ -281,6 +281,7 @@ oper-classes:
|
||||
- "oper:rehash"
|
||||
- "oper:die"
|
||||
- "unregister"
|
||||
- "sajoin"
|
||||
- "samode"
|
||||
- "vhosts"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user