Skip to content

Commit

Permalink
Merge pull request #346 from andymandias/join-after-logged-in
Browse files Browse the repository at this point in the history
Handle `ERR_NEEDREGGEDNICK` (aka `ERR_NOCHANMODES`)
  • Loading branch information
casperstorm authored Apr 24, 2024
2 parents 2b0cdf2 + cc87a04 commit ccb79f0
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Changed:
- Simplified onboarding experience for users without a `config.toml` file
- MacOS will now also look in `$HOME/.config/halloy` for `config.toml`.
- Context menus can be dismissed by pressing Escape
- Join channels that report themselves as requiring registration after logging in

# 2024.6 (2024-04-05)

Expand Down
49 changes: 39 additions & 10 deletions data/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ pub struct Client {
supports_labels: bool,
supports_away_notify: bool,
highlight_blackout: HighlightBlackout,
registration_required_channels: Vec<String>,
}

impl fmt::Debug for Client {
Expand Down Expand Up @@ -135,6 +136,7 @@ impl Client {
supports_labels: false,
supports_away_notify: false,
highlight_blackout: HighlightBlackout::Blackout(Instant::now()),
registration_required_channels: vec![],
}
}

Expand Down Expand Up @@ -443,6 +445,17 @@ impl Client {
}
Command::Numeric(RPL_LOGGEDIN, _) => {
log::info!("[{}] logged in", self.server);

if !self.registration_required_channels.is_empty() {
for message in group_joins(
&self.registration_required_channels,
&self.config.channel_keys,
) {
let _ = self.handle.try_send(message);
}

self.registration_required_channels.clear();
}
}
Command::PRIVMSG(channel, text) | Command::NOTICE(channel, text) => {
if let Some(user) = message.user() {
Expand Down Expand Up @@ -606,7 +619,7 @@ impl Client {
}

// Send JOIN
for message in group_joins(&self.config) {
for message in group_joins(&self.config.channels, &self.config.channel_keys) {
let _ = self.handle.try_send(message);
}
}
Expand Down Expand Up @@ -816,6 +829,22 @@ impl Client {
#[cfg(feature = "dev")]
return None;
}
Command::Numeric(ERR_NOCHANMODES, args) => {
let channel = args.get(1)?;

// If the channel has not been joined but is in the configured channels,
// then interpret this numeric as ERR_NEEDREGGEDNICK (which has the
// same number as ERR_NOCHANMODES)
if self.chanmap.get(channel).is_none()
&& self
.config
.channels
.iter()
.any(|config_channel| config_channel == channel)
{
self.registration_required_channels.push(channel.clone());
}
}
_ => {}
}

Expand Down Expand Up @@ -1175,17 +1204,17 @@ pub enum WhoStatus {
}

/// Group channels together into as few JOIN messages as possible
fn group_joins(config: &config::Server) -> impl Iterator<Item = proto::Message> + '_ {
fn group_joins<'a>(
channels: &'a [String],
keys: &'a HashMap<String, String>,
) -> impl Iterator<Item = proto::Message> + 'a {
const MAX_LEN: usize = proto::format::BYTE_LIMIT - b"JOIN \r\n".len();

let (without_keys, with_keys): (Vec<_>, Vec<_>) =
config.channels.iter().partition_map(|channel| {
config
.channel_keys
.get(channel)
.map(|key| Either::Right((channel, key)))
.unwrap_or(Either::Left(channel))
});
let (without_keys, with_keys): (Vec<_>, Vec<_>) = channels.iter().partition_map(|channel| {
keys.get(channel)
.map(|key| Either::Right((channel, key)))
.unwrap_or(Either::Left(channel))
});

let joins_without_keys = without_keys
.into_iter()
Expand Down
2 changes: 2 additions & 0 deletions irc/proto/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@ pub enum Numeric {
ERR_BANNEDFROMCHAN = 474,
ERR_BADCHANNELKEY = 475,
ERR_BADCHANMASK = 476,
ERR_NOCHANMODES = 477,
ERR_NOPRIVILEGES = 481,
ERR_CHANOPRIVSNEEDED = 482,
ERR_CANTKILLSERVER = 483,
Expand Down Expand Up @@ -533,6 +534,7 @@ impl TryFrom<u16> for Numeric {
474 => ERR_BANNEDFROMCHAN,
475 => ERR_BADCHANNELKEY,
476 => ERR_BADCHANMASK,
477 => ERR_NOCHANMODES,
481 => ERR_NOPRIVILEGES,
482 => ERR_CHANOPRIVSNEEDED,
483 => ERR_CANTKILLSERVER,
Expand Down

0 comments on commit ccb79f0

Please sign in to comment.