diff options
| author | Nakidai <nakidai@disroot.org> | 2026-02-14 00:05:36 +0300 |
|---|---|---|
| committer | Nakidai <nakidai@disroot.org> | 2026-02-14 00:20:38 +0300 |
| commit | 834c85d80914007e31657d12d2f22a9cb2cd8624 (patch) | |
| tree | 283ed0dacb635b97f93c21c8b0b94b6116ca29a3 | |
| parent | 15151c88a7eb381fb5b46daaf521fc609d40539c (diff) | |
| download | libreircd-834c85d80914007e31657d12d2f22a9cb2cd8624.tar.gz libreircd-834c85d80914007e31657d12d2f22a9cb2cd8624.zip | |
Add support for voice and +m channel mode
So now voices in code are not that useless. Also, code was fixed for their printing as it is valid for a user to be both an oper and voiced
| -rw-r--r-- | channel.c | 4 | ||||
| -rw-r--r-- | handle.c | 52 | ||||
| -rw-r--r-- | ircd.h | 1 | ||||
| -rw-r--r-- | reply.c | 6 |
4 files changed, 47 insertions, 16 deletions
diff --git a/channel.c b/channel.c index f2da302..1b3024b 100644 --- a/channel.c +++ b/channel.c @@ -96,7 +96,7 @@ channel_modes_parse(const struct Message *msg) { for (m = msg->params[i]+1; *m; ++m) switch (*m) { - break; case 'o': + break; case 'o': case 'v': /* since all flags are ASCII (< 128) bit 7 * can be and is abused for the set flag */ if (queue_r == lengthof(queue)) @@ -105,7 +105,7 @@ channel_modes_parse(const struct Message *msg) return modes; } queue[queue_r++] = (set << 7) | *m; - break; case 'n': case 's': case 't': + break; case 'm': case 'n': case 's': case 't': modes[modes_c].mode = *m; modes[modes_c++].set = set; break; default: diff --git a/handle.c b/handle.c index 684c2ee..1253cdf 100644 --- a/handle.c +++ b/handle.c @@ -182,6 +182,18 @@ mode_channel(struct Message *msg, struct Peer *peer) parsed = channel_modes_parse(msg); for (; parsed->param || parsed->mode; ++parsed) switch (parsed->mode) { + break; case 'm': + announce_change(1); + if (parsed->set) + channel->modes |= CHANNEL_MODERATED; + else + channel->modes &= ~CHANNEL_MODERATED; + break; case 'n': + announce_change(1); + if (parsed->set) + channel->modes |= CHANNEL_NOFROMOUT; + else + channel->modes &= ~CHANNEL_NOFROMOUT; break; case 'o': ensure(parsed->param, reply(peer, 461, msg->command), 0); @@ -195,12 +207,6 @@ 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); @@ -214,6 +220,19 @@ mode_channel(struct Message *msg, struct Peer *peer) channel->modes |= CHANNEL_TOPIC; else channel->modes &= ~CHANNEL_TOPIC; + break; case 'v': + 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); + + announce_change(0); + if (parsed->set) + channel->peers[i].modes |= CHANNEL_VOICE; + else + channel->peers[i].modes &= ~CHANNEL_VOICE; break; default: modebuf[0] = parsed->mode; modebuf[1] = 0; @@ -295,7 +314,7 @@ names(struct Message *msg, struct Peer *peer) chpp = &peer->channels[i]->peers[j]; if (chpp->modes & CHANNEL_OPER) strlcat(buf, "@", sizeof(buf)); - else if (chpp->modes & CHANNEL_VOICE) + if (chpp->modes & CHANNEL_VOICE) strlcat(buf, "+", sizeof(buf)); strlcat(buf, peer->channels[i]->peers[j].p->nick, sizeof(buf)); if (strlen(buf) >= MESSAGE_MAX - 4*PEER_NICK_MAX @@ -466,13 +485,18 @@ privmsg(struct Message *msg, struct Peer *peer) 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); - } + for (i = 0; i < ch->peers_c; ++i) + if (ch->peers[i].p == peer) + break; + + ensure( + (!(ch->modes & CHANNEL_NOFROMOUT) || i != ch->peers_c) + && (!(ch->modes & CHANNEL_MODERATED) + || ch->peers[i].modes & (CHANNEL_OPER | CHANNEL_VOICE) + ), + reply(peer, 404, ch->name), + 0 + ); writechanf( peer, diff --git a/ircd.h b/ircd.h index 3012783..fecfe60 100644 --- a/ircd.h +++ b/ircd.h @@ -83,6 +83,7 @@ struct Channel size_t peers_c; enum ChannelMode { + BIT(CHANNEL_MODERATED), BIT(CHANNEL_NOFROMOUT), BIT(CHANNEL_SECRET), BIT(CHANNEL_TOPIC), diff --git a/reply.c b/reply.c index 41fcb4a..e7f899b 100644 --- a/reply.c +++ b/reply.c @@ -196,6 +196,12 @@ vreply(const struct Peer *peer, int number, va_list ap) getnick(peer), channel ), channel, _); + REPLY(404, WRITE( + ":%s 404 %s %s :Cannot send to channel", + hostname, + getnick(peer), + channel + ), channel, _); REPLY(405, WRITE( ":%s 405 %s %s :You have joined too many channels", hostname, |