From 4b1e6b04c4c61d83de1517fefdcc4c67dbe5f90d Mon Sep 17 00:00:00 2001 From: Shivaram Lingamneni Date: Sun, 25 Oct 2020 22:16:19 -0400 Subject: [PATCH] add UNINVITE command (#1171) --- irc/channel.go | 16 ++++++++++++++++ irc/client.go | 6 ++++++ irc/commands.go | 4 ++++ irc/handlers.go | 9 ++++++++- irc/help.go | 5 +++++ 5 files changed, 39 insertions(+), 1 deletion(-) diff --git a/irc/channel.go b/irc/channel.go index 7304654d..59a80a04 100644 --- a/irc/channel.go +++ b/irc/channel.go @@ -1524,6 +1524,22 @@ func (channel *Channel) Invite(invitee *Client, inviter *Client, rb *ResponseBuf } } +// Uninvite rescinds a channel invitation, if the inviter can do so. +func (channel *Channel) Uninvite(invitee *Client, inviter *Client, rb *ResponseBuffer) { + if !channel.flags.HasMode(modes.InviteOnly) { + rb.Add(nil, channel.server.name, "FAIL", "UNINVITE", "NOT_INVITE_ONLY", channel.Name(), inviter.t("Channel is not invite-only")) + return + } + + if !channel.ClientIsAtLeast(inviter, modes.ChannelOperator) { + rb.Add(nil, channel.server.name, "FAIL", "UNINVITE", "NOT_PRIVED", channel.Name(), inviter.t("You're not a channel operator")) + return + } + + invitee.Uninvite(channel.NameCasefolded()) + rb.Add(nil, channel.server.name, "UNINVITE", invitee.Nick(), channel.Name()) +} + // returns who the client can "see" in the channel, respecting the auditorium mode func (channel *Channel) auditoriumFriends(client *Client) (friends []*Client) { channel.stateMutex.RLock() diff --git a/irc/client.go b/irc/client.go index 018918a5..693d14b8 100644 --- a/irc/client.go +++ b/irc/client.go @@ -1787,6 +1787,12 @@ func (client *Client) Invite(casefoldedChannel string, channelCreatedAt time.Tim return } +func (client *Client) Uninvite(casefoldedChannel string) { + client.stateMutex.Lock() + defer client.stateMutex.Unlock() + delete(client.invitedTo, casefoldedChannel) +} + // Checks that the client was invited to join a given channel func (client *Client) CheckInvited(casefoldedChannel string, createdTime time.Time) (invited bool) { config := client.server.Config() diff --git a/irc/commands.go b/irc/commands.go index c1ec6f41..cb81fd2f 100644 --- a/irc/commands.go +++ b/irc/commands.go @@ -324,6 +324,10 @@ func init() { minParams: 1, oper: true, }, + "UNINVITE": { + handler: inviteHandler, + minParams: 2, + }, "UNKLINE": { handler: unKLineHandler, minParams: 1, diff --git a/irc/handlers.go b/irc/handlers.go index 78f34b81..241bbefe 100644 --- a/irc/handlers.go +++ b/irc/handlers.go @@ -1113,7 +1113,9 @@ func infoHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp } // INVITE +// UNINVITE func inviteHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool { + invite := msg.Command == "INVITE" nickname := msg.Params[0] channelName := msg.Params[1] @@ -1129,7 +1131,12 @@ func inviteHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Re return false } - channel.Invite(target, client, rb) + if invite { + channel.Invite(target, client, rb) + } else { + channel.Uninvite(target, client, rb) + } + return false } diff --git a/irc/help.go b/irc/help.go index c867c31d..5fbd130b 100644 --- a/irc/help.go +++ b/irc/help.go @@ -541,6 +541,11 @@ For example: Used in connection registration, sets your username and realname to the given values (though your username may also be looked up with Ident).`, + }, + "uninvite": { + text: `UNINVITE + +UNINVITE rescinds a channel invitation sent for an invite-only channel.`, }, "users": { text: `USERS [parameters]