summary refs log tree commit diff
diff options
context:
space:
mode:
authorNakidai <nakidai@disroot.org>2026-02-12 21:19:11 +0300
committerNakidai <nakidai@disroot.org>2026-02-12 21:19:11 +0300
commite76511e37e906c73d61aa65ec27efd9f060bf1a3 (patch)
treec5a4c38987c327f97ca386c81779d32a605ae0e9
parentec97c603288869efad52ed7235ae770f85a9d7e8 (diff)
downloadlibreircd-e76511e37e906c73d61aa65ec27efd9f060bf1a3.tar.gz
libreircd-e76511e37e906c73d61aa65ec27efd9f060bf1a3.zip
Add support for n channel flag
It's a flag that restricts a set of users able to write to a channel to
those who joined. If not, reply 442 is sent upon PRIVMSG
-rw-r--r--channel.c2
-rw-r--r--handle.c44
-rw-r--r--ircd.h1
3 files changed, 31 insertions, 16 deletions
diff --git a/channel.c b/channel.c
index d04f3cc..2717e5e 100644
--- a/channel.c
+++ b/channel.c
@@ -105,7 +105,7 @@ channel_modes_parse(const struct Message *msg)
 				return modes;
 			}
 			queue[queue_r++] = (set << 7) | *m;
-		break; case 's':
+		break; case 'n': case 's':
 			modes[modes_c].mode = *m;
 			modes[modes_c++].set = set;
 		break; default:
diff --git a/handle.c b/handle.c
index 2190bcf..d32714c 100644
--- a/handle.c
+++ b/handle.c
@@ -166,6 +166,12 @@ mode_channel(struct Message *msg, struct Peer *peer)
 			channel->peers[i].modes |= CHANNEL_OPER;
 		else
 			channel->peers[i].modes &= ~CHANNEL_OPER;
+	break; case 'n':
+		announce_change(1);
+		if (parsed->set)
+			channel->modes |= CHANNEL_NOFROMOUT;
+		else
+			channel->modes &= ~CHANNEL_NOFROMOUT;
 	break; case 's':
 		/* TODO: implement +s. For now it's just a some mode with no param */
 		announce_change(1);
@@ -418,25 +424,33 @@ privmsg(struct Message *msg, struct Peer *peer)
 	{
 	case '#':
 	{
+		struct Channel *ch;
+
 		for (i = 0; i < channels_c; ++i)
 			if (!strcmp(channels[i].name, msg->params[0]))
-			{
-				writechanf(
-					peer,
-					&channels[i],
-					":%s!%s@%s %s %s :%s",
-					peer->nick,
-					peer->user,
-					peer->host,
-					*msg->command == 'p'
-						? "PRIVMSG"
-						: "NOTICE",
-					msg->params[0],
-					msg->params[1]
-				);
 				break;
-			}
 		ensure(i != channels_c, reply(peer, 401, msg->params[0]), 0);
+		ch = &channels[i];
+
+		if (ch->modes & CHANNEL_NOFROMOUT)
+		{
+			for (i = 0; i < ch->peers_c; ++i)
+				if (!strcmp(ch->peers[i].p->nick, peer->nick))
+					break;
+			ensure(i != ch->peers_c, reply(peer, 442, ch->name), 0);
+		}
+
+		writechanf(
+			peer,
+			ch,
+			":%s!%s@%s %s %s :%s",
+			peer->nick,
+			peer->user,
+			peer->host,
+			*msg->command == 'p' ? "PRIVMSG" : "NOTICE",
+			msg->params[0],
+			msg->params[1]
+		);
 	} break;
 	default:
 	{
diff --git a/ircd.h b/ircd.h
index 931948b..d4ed678 100644
--- a/ircd.h
+++ b/ircd.h
@@ -83,6 +83,7 @@ struct Channel
 	enum ChannelMode
 	{
 		BIT(CHANNEL_SECRET),
+		BIT(CHANNEL_NOFROMOUT),
 	} modes;
 };