Tier 1: Core IRC channel modes and commands (+o/+v/+m/+t, KICK, NOTICE) #85

Closed
opened 2026-03-22 11:04:34 +01:00 by clawbot · 0 comments
Collaborator

Overview

Implement the core IRC channel functionality that users will immediately notice is missing. This is the foundation for all other mode enforcement.

Requirements

1. Channel Member Flags Schema (prerequisite for everything else)

Add proper boolean columns to channel_members table:

ALTER TABLE channel_members ADD COLUMN is_operator INTEGER NOT NULL DEFAULT 0;
ALTER TABLE channel_members ADD COLUMN is_voiced INTEGER NOT NULL DEFAULT 0;

Per sneak's instruction: Use proper database types (boolean/integer columns), NOT a text string for modes. Each flag gets its own column.

Channel creator auto-gets +o: When a user JOINs and creates a new channel (ephemeral creation), they automatically get is_operator = 1.

2. MODE +o/+v/-o/-v (User Channel Modes)

  • MODE #channel +o nick — grant operator status (only existing +o can do this)
  • MODE #channel -o nick — revoke operator status
  • MODE #channel +v nick — grant voice (only +o can do this)
  • MODE #channel -v nick — revoke voice
  • NAMES reply must show @nick for operators, +nick for voiced users
  • ISUPPORT PREFIX=(ov)@+ must be advertised

3. MODE +m (Moderated)

  • Add is_moderated INTEGER NOT NULL DEFAULT 0 column to channels table
  • MODE #channel +m — only +o can set
  • When +m is active, only +v and +o users can send PRIVMSG/NOTICE to the channel
  • Others receive ERR_CANNOTSENDTOCHAN (404)

4. MODE +t (Topic Lock)

  • Add is_topic_locked INTEGER NOT NULL DEFAULT 0 column to channels table
  • MODE #channel +t — only +o can set
  • When +t is active, only +o users can change the topic
  • Others receive ERR_CHANOPRIVSNEEDED (482)
  • Default for new channels: +t ON (standard IRC behavior)

5. KICK Command

  • KICK #channel nick [:reason]
  • Only channel operators (+o) can KICK
  • Removes the user from the channel
  • Broadcasts KICK message to all channel members
  • Kicked user receives the KICK message
  • Error if kicker is not +o: ERR_CHANOPRIVSNEEDED (482)
  • Error if target not in channel: ERR_USERNOTINCHANNEL (441)

6. NOTICE Differentiation

  • NOTICE must NOT trigger AWAY auto-replies (RPL_AWAY)
  • NOTICE should skip hashcash validation on +H channels (servers and services use NOTICE)
  • NOTICE should NOT generate any auto-reply per RFC 2812

Testing

  • Test +o auto-grant on channel creation
  • Test MODE +o/+v/-o/-v with permission checks
  • Test +m enforcement (voiced/op can send, others can't)
  • Test +t enforcement (op can set topic, others can't)
  • Test KICK with permission checks
  • Test NOTICE vs PRIVMSG behavior differences
  • Test NAMES prefixes (@/+)

Scope

This is Tier 1 only. Tier 2 (+b bans, +i invite-only, +s secret, +k key, +l limit) comes after this is merged.

## Overview Implement the core IRC channel functionality that users will immediately notice is missing. This is the foundation for all other mode enforcement. ## Requirements ### 1. Channel Member Flags Schema (prerequisite for everything else) Add proper boolean columns to `channel_members` table: ```sql ALTER TABLE channel_members ADD COLUMN is_operator INTEGER NOT NULL DEFAULT 0; ALTER TABLE channel_members ADD COLUMN is_voiced INTEGER NOT NULL DEFAULT 0; ``` **Per sneak's instruction:** Use proper database types (boolean/integer columns), NOT a text string for modes. Each flag gets its own column. **Channel creator auto-gets +o:** When a user JOINs and creates a new channel (ephemeral creation), they automatically get `is_operator = 1`. ### 2. MODE +o/+v/-o/-v (User Channel Modes) - `MODE #channel +o nick` — grant operator status (only existing +o can do this) - `MODE #channel -o nick` — revoke operator status - `MODE #channel +v nick` — grant voice (only +o can do this) - `MODE #channel -v nick` — revoke voice - NAMES reply must show `@nick` for operators, `+nick` for voiced users - ISUPPORT `PREFIX=(ov)@+` must be advertised ### 3. MODE +m (Moderated) - Add `is_moderated INTEGER NOT NULL DEFAULT 0` column to `channels` table - `MODE #channel +m` — only +o can set - When +m is active, only +v and +o users can send PRIVMSG/NOTICE to the channel - Others receive `ERR_CANNOTSENDTOCHAN` (404) ### 4. MODE +t (Topic Lock) - Add `is_topic_locked INTEGER NOT NULL DEFAULT 0` column to `channels` table - `MODE #channel +t` — only +o can set - When +t is active, only +o users can change the topic - Others receive `ERR_CHANOPRIVSNEEDED` (482) - Default for new channels: +t ON (standard IRC behavior) ### 5. KICK Command - `KICK #channel nick [:reason]` - Only channel operators (+o) can KICK - Removes the user from the channel - Broadcasts KICK message to all channel members - Kicked user receives the KICK message - Error if kicker is not +o: `ERR_CHANOPRIVSNEEDED` (482) - Error if target not in channel: `ERR_USERNOTINCHANNEL` (441) ### 6. NOTICE Differentiation - NOTICE must NOT trigger AWAY auto-replies (RPL_AWAY) - NOTICE should skip hashcash validation on +H channels (servers and services use NOTICE) - NOTICE should NOT generate any auto-reply per RFC 2812 ## Testing - Test +o auto-grant on channel creation - Test MODE +o/+v/-o/-v with permission checks - Test +m enforcement (voiced/op can send, others can't) - Test +t enforcement (op can set topic, others can't) - Test KICK with permission checks - Test NOTICE vs PRIVMSG behavior differences - Test NAMES prefixes (@/+) ## Scope This is Tier 1 only. [Tier 2](https://git.eeqj.de/sneak/chat/issues/86) (+b bans, +i invite-only, +s secret, +k key, +l limit) comes after this is merged.
clawbot added this to the 1.0 milestone 2026-03-22 11:04:34 +01:00
clawbot self-assigned this 2026-03-22 11:04:34 +01:00
sneak closed this issue 2026-03-25 02:08:29 +01:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/chat#85