+ User* u;
+ if (IS_LOCAL(user))
+ u = ServerInstance->FindNickOnly(parameters[0]);
+ else
+ u = ServerInstance->FindNick(parameters[0]);
+
+ Channel* c = ServerInstance->FindChan(parameters[1]);
+
+ if ((!c) || (!u) || (u->registered != REG_ALL))
+ {
+ if (!c)
+ {
+ user->WriteNumeric(Numerics::NoSuchChannel(parameters[1]));
+ }
+ else
+ {
+ user->WriteNumeric(Numerics::NoSuchNick(parameters[0]));
+ }
+
+ return CMD_FAILURE;
+ }
+
+ if (IS_LOCAL(user))
+ {
+ if (c->GetPrefixValue(user) < HALFOP_VALUE)
+ {
+ user->WriteNumeric(ERR_CHANOPRIVSNEEDED, c->name, InspIRCd::Format("You must be a channel %soperator", c->GetPrefixValue(u) == HALFOP_VALUE ? "" : "half-"));
+ return CMD_FAILURE;
+ }
+ }
+
+ /* Servers remember invites only for their local users, so act
+ * only if the target is local. Otherwise the command will be
+ * passed to the target users server.
+ */
+ LocalUser* lu = IS_LOCAL(u);
+ if (lu)
+ {
+ // XXX: The source of the numeric we send must be the server of the user doing the /UNINVITE,
+ // so they don't see where the target user is connected to
+ if (!invapi->Remove(lu, c))
+ {
+ Numeric::Numeric n(505);
+ n.SetServer(user->server);
+ n.push(u->nick).push(c->name).push(InspIRCd::Format("Is not invited to channel %s", c->name.c_str()));
+ user->WriteRemoteNumeric(n);
+ return CMD_FAILURE;
+ }
+
+ Numeric::Numeric n(494);
+ n.SetServer(user->server);
+ n.push(c->name).push(u->nick).push("Uninvited");
+ user->WriteRemoteNumeric(n);
+
+ lu->WriteNumeric(RPL_UNINVITED, InspIRCd::Format("You were uninvited from %s by %s", c->name.c_str(), user->nick.c_str()));
+
+ std::string msg = "*** " + user->nick + " uninvited " + u->nick + ".";
+ c->WriteNotice(msg);
+ ServerInstance->PI->SendChannelNotice(c, 0, msg);
+ }
+
+ return CMD_SUCCESS;