summary refs log tree commit diff
path: root/handle.c
diff options
context:
space:
mode:
authorNakidai <nakidai@disroot.org>2026-02-10 03:38:15 +0300
committerNakidai <nakidai@disroot.org>2026-02-10 03:38:15 +0300
commitdb996c22cd51cd46dd9afee1085a8af04cc7b53b (patch)
tree3fdc59fc9f7d42a1e8f96d9ca615e2d8b19a60da /handle.c
parent15b0b805fe2e739c9d89b54e1bfb26beb79c3112 (diff)
downloadlibreircd-db996c22cd51cd46dd9afee1085a8af04cc7b53b.tar.gz
libreircd-db996c22cd51cd46dd9afee1085a8af04cc7b53b.zip
Add channel mode editing support
Well, an oper should have some way to manage their channel :)
Diffstat (limited to 'handle.c')
-rw-r--r--handle.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/handle.c b/handle.c
index ecbde08..d11b39a 100644
--- a/handle.c
+++ b/handle.c
@@ -76,8 +76,10 @@ join(struct Message *msg, struct Peer *peer)
 static int
 mode_channel(struct Message *msg, struct Peer *peer)
 {
+	const struct ChannelModeParam *parsed;
 	enum ChannelPeerMode modes;
 	struct Channel *channel;
+	char modebuf[2];
 	size_t i;
 
 	for (i = 0; i < channels_c; ++i)
@@ -96,6 +98,56 @@ mode_channel(struct Message *msg, struct Peer *peer)
 
 	ensure(modes & CHANNEL_OPER || peer->modes & OPER, reply(peer, 482, channel->name), 0);
 
+	parsed = channel_modes_parse(msg);
+	for (; parsed->param || parsed->mode; ++parsed) switch (parsed->mode)
+	{
+	break; case 'o':
+		ensure(parsed->param, reply(peer, 461, msg->command), 0);
+
+		for (i = 0; i < channel->peers_c; ++i)
+			if (!strcmp(channel->peers[i].p->nick, parsed->param))
+				break;
+		ensure(i != channel->peers_c, reply(peer, 441, parsed->param, channel->name), 0);
+
+		writechanf(
+			0,
+			channel,
+			"%s!%s@%s MODE %s %co %s",
+			getnick(peer),
+			peer->user,
+			peer->host,
+			channel->name,
+			parsed->set ? '+' : '-',
+			parsed->param
+		);
+
+		if (parsed->set)
+			channel->peers[i].modes |= CHANNEL_OPER;
+		else
+			channel->peers[i].modes &= ~CHANNEL_OPER;
+	break; case 's':
+		/* TODO: implement +s. For now it's just a some mode with no param */
+		writechanf(
+			0,
+			channel,
+			"%s!%s@%s MODE %s %cs",
+			getnick(peer),
+			peer->user,
+			peer->host,
+			channel->name,
+			parsed->set ? '+' : '-'
+		);
+		if (parsed->set)
+			channel->modes |= CHANNEL_SECRET;
+		else
+			channel->modes &= ~CHANNEL_SECRET;
+	break; default:
+		modebuf[0] = parsed->mode;
+		modebuf[1] = 0;
+		reply(peer, 472, modebuf, channel->name);
+		return 0;
+	}
+
 	return 0;
 }