mirror of
https://github.com/vinezombie/vinezombie.git
synced 2026-01-25 07:26:18 +00:00
Restructure Register's nick and cap options
Moved capability options into Register. This was originally kept seperate due to being especially application-specific (where most of Register's other options aren't), but ultimately this way is tidier, and applications can always change caps before calling handler. nicks is now a struct containing nickgen (as "gen"). This should make things a bit tidier. Added an option to skip attempting to use the first nick. Useful for having the first nick exclusively as a fallback, or just jumping directly to generated nicks.
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
use std::collections::BTreeSet;
|
||||
use vinezombie::{
|
||||
client::{self, auth::Clear},
|
||||
ircmsg::ClientMsg,
|
||||
@@ -28,14 +27,10 @@ fn main() -> std::io::Result<()> {
|
||||
let mut sock = address.connect(tls_config)?;
|
||||
// The initial connection registration handshake needs to happen,
|
||||
// so let's build a handler for that.
|
||||
// The provided set is a set of capabilities to request.
|
||||
// We don't need anything, so this set is empty.
|
||||
// If we need SASL, that's added automatically.
|
||||
// `BotDefaults` provides default values for anything we didn't specify
|
||||
// in `options` above.
|
||||
// Passing the `queue` populates it with the initial message burst.
|
||||
let mut handler =
|
||||
options.handler(BTreeSet::new(), &client::register::BotDefaults, &mut queue)?;
|
||||
let mut handler = options.handler(&client::register::BotDefaults, &mut queue)?;
|
||||
// Let's do connection registration!
|
||||
let reg = vinezombie::client::run_handler(&mut sock, &mut queue, &mut handler)?;
|
||||
// Connection registration is done!
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use std::collections::BTreeSet;
|
||||
use vinezombie::{
|
||||
client::{self, auth::Clear},
|
||||
ircmsg::ClientMsg,
|
||||
@@ -23,8 +22,7 @@ async fn main() -> std::io::Result<()> {
|
||||
// but instead we run it using a run_handler_tokio function.
|
||||
// This function is actually more general than run_handler,
|
||||
// but we're not going to make use of its functionality in this example.
|
||||
let mut handler =
|
||||
options.handler(BTreeSet::new(), &client::register::BotDefaults, &mut queue)?;
|
||||
let mut handler = options.handler(&client::register::BotDefaults, &mut queue)?;
|
||||
let reg = vinezombie::client::run_handler_tokio(&mut sock, &mut queue, &mut handler).await?;
|
||||
tracing::info!("{} connected to Libera!", reg.nick);
|
||||
// As with the earlier example, let's just quit here.
|
||||
|
||||
@@ -3,6 +3,20 @@
|
||||
use crate::string::{Nick, NickBuilder};
|
||||
use std::{borrow::Cow, error::Error};
|
||||
|
||||
/// Standard nickname options.
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Nicks<N> {
|
||||
/// The list of nicknames to use.
|
||||
pub nicks: Vec<Nick<'static>>,
|
||||
/// Whether to skip attempting to use the first nickname,
|
||||
/// using it only for fallbacks.
|
||||
#[cfg_attr(feature = "serde", serde(default))]
|
||||
pub skip_first: bool,
|
||||
/// The [`NickTransformer`] for generating new nicknames from the first one.
|
||||
pub gen: std::sync::Arc<N>,
|
||||
}
|
||||
|
||||
/// Error indicating that a nickname generator cannot generate any more nicknames.
|
||||
#[derive(Clone, Copy, Default, Debug)]
|
||||
pub struct EndOfNicks;
|
||||
|
||||
@@ -5,12 +5,16 @@ mod handler;
|
||||
|
||||
pub use {fallbacks::*, handler::*};
|
||||
|
||||
use super::{auth::Sasl, nick::NickTransformer, ClientMsgSink};
|
||||
use super::{
|
||||
auth::Sasl,
|
||||
nick::{NickTransformer, Nicks},
|
||||
ClientMsgSink,
|
||||
};
|
||||
use crate::{
|
||||
client::auth::Secret,
|
||||
error::InvalidByte,
|
||||
ircmsg::ClientMsg,
|
||||
string::{Key, Line, Nick, User},
|
||||
string::{Key, Line, User},
|
||||
};
|
||||
use std::{
|
||||
collections::{BTreeMap, BTreeSet, VecDeque},
|
||||
@@ -21,15 +25,16 @@ use std::{
|
||||
///
|
||||
/// These are used to create the messages sent during the initial connection registration phase,
|
||||
/// such as USER and NICK.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(default))]
|
||||
pub struct Register<P, S, N> {
|
||||
/// The set of capabilities to request.
|
||||
pub caps: BTreeSet<Key<'static>>,
|
||||
/// The server password.
|
||||
pub pass: Option<P>,
|
||||
/// The list of nicknames to use.
|
||||
pub nicks: Vec<Nick<'static>>,
|
||||
/// A fallback nick transformer, for when all of the nicks in the list are unavailable.
|
||||
pub nickgen: Arc<N>,
|
||||
/// Options for nickname use and generation.
|
||||
pub nicks: Nicks<N>,
|
||||
/// The username, historically one's local account name.
|
||||
pub username: Option<User<'static>>,
|
||||
/// The realname, also sometimes known as the gecos.
|
||||
@@ -42,12 +47,26 @@ pub struct Register<P, S, N> {
|
||||
pub allow_sasl_fail: bool,
|
||||
}
|
||||
|
||||
impl<P, S, N: Default> Default for Register<P, S, N> {
|
||||
fn default() -> Self {
|
||||
Register {
|
||||
caps: BTreeSet::new(),
|
||||
pass: None,
|
||||
nicks: Nicks::default(),
|
||||
username: None,
|
||||
realname: None,
|
||||
sasl: Vec::new(),
|
||||
allow_sasl_fail: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new blank [`Register`] the provided choice of [`Secret`] implementation.
|
||||
pub fn new<S: Secret>() -> Register<S, crate::client::auth::AnySasl<S>, ()> {
|
||||
Register {
|
||||
caps: BTreeSet::new(),
|
||||
pass: None,
|
||||
nicks: Vec::new(),
|
||||
nickgen: Arc::new(()),
|
||||
nicks: Nicks::default(),
|
||||
username: None,
|
||||
realname: None,
|
||||
sasl: Vec::new(),
|
||||
@@ -64,9 +83,9 @@ impl<P, S, N> Register<P, S, N> {
|
||||
let pass = pass.try_into().map_err(|e| e.into())?.secret();
|
||||
let secret = P2::new(pass.into())?;
|
||||
Ok(Register {
|
||||
caps: self.caps,
|
||||
pass: Some(secret),
|
||||
nicks: self.nicks,
|
||||
nickgen: self.nickgen,
|
||||
username: self.username,
|
||||
realname: self.realname,
|
||||
sasl: self.sasl,
|
||||
@@ -76,9 +95,13 @@ impl<P, S, N> Register<P, S, N> {
|
||||
/// Uses the provided [`NickTransformer`] for fallback nicks.
|
||||
pub fn with_nickgen<N2: NickTransformer>(self, ng: N2) -> Register<P, S, N2> {
|
||||
Register {
|
||||
caps: self.caps,
|
||||
pass: self.pass,
|
||||
nicks: self.nicks,
|
||||
nickgen: Arc::new(ng),
|
||||
nicks: Nicks {
|
||||
nicks: self.nicks.nicks,
|
||||
skip_first: self.nicks.skip_first,
|
||||
gen: Arc::new(ng),
|
||||
},
|
||||
username: self.username,
|
||||
realname: self.realname,
|
||||
sasl: self.sasl,
|
||||
@@ -129,7 +152,7 @@ impl<P: Secret, S, N: NickTransformer> Register<P, S, N> {
|
||||
sink.send(msg)?;
|
||||
// NICK message.
|
||||
msg = ClientMsg::new_cmd(NICK);
|
||||
let (nick, fallbacks) = FallbackNicks::new(self, defaults);
|
||||
let (nick, fallbacks) = FallbackNicks::new(&self.nicks, defaults);
|
||||
msg.args.add(nick);
|
||||
sink.send(msg)?;
|
||||
Ok(fallbacks)
|
||||
@@ -143,11 +166,11 @@ impl<P: Secret, S: Sasl, N: NickTransformer> Register<P, S, N> {
|
||||
/// Errors only if `send_fn` errors.
|
||||
pub fn handler<N2: NickTransformer>(
|
||||
&self,
|
||||
mut caps: BTreeSet<Key<'static>>,
|
||||
defaults: &'static impl Defaults<NickGen = N2>,
|
||||
sink: impl ClientMsgSink<'static>,
|
||||
) -> std::io::Result<Handler<N, N2>> {
|
||||
let nicks = self.register_msgs(defaults, sink)?;
|
||||
let mut caps = self.caps.clone();
|
||||
let (auths, needs_auth) = if !self.sasl.is_empty() {
|
||||
caps.insert(Key::from_str("sasl"));
|
||||
let mut auths = Vec::with_capacity(self.sasl.len());
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
use super::Register;
|
||||
use crate::{
|
||||
client::nick::{NickSuffix, NickTransformer, SuffixRandom},
|
||||
client::nick::{NickSuffix, NickTransformer, Nicks, SuffixRandom},
|
||||
string::{Line, Nick, User},
|
||||
};
|
||||
use std::{collections::VecDeque, sync::Arc};
|
||||
|
||||
/// Source of fallback nicks from a [`Register`] and [`Defaults`].
|
||||
/// Source of fallback nicks from a [`Register`][super::Register] and [`Defaults`].
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct FallbackNicks<N1: NickTransformer, N2: NickTransformer + 'static> {
|
||||
state: FallbackNicksState<N1::State, N2::State>,
|
||||
@@ -13,20 +12,34 @@ pub struct FallbackNicks<N1: NickTransformer, N2: NickTransformer + 'static> {
|
||||
n2: &'static N2,
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn nicks_init<N1: NickTransformer, N2: NickTransformer + 'static>(
|
||||
reg: &Nicks<N1>,
|
||||
) -> Option<(Nick<'static>, FallbackNicksState<N1::State, N2::State>)> {
|
||||
let (first, rest) = reg.nicks.split_first()?;
|
||||
let nicks = if reg.skip_first { rest } else { ®.nicks };
|
||||
if let Some((nick, rest)) = nicks.split_first() {
|
||||
let rest: VecDeque<Nick<'static>> = rest.to_vec().into();
|
||||
Some((nick.clone(), FallbackNicksState::Select(first.clone(), rest)))
|
||||
} else if let Some((nick, state)) = reg.gen.init(first) {
|
||||
let state = state.map(FallbackNicksState::Gen1).unwrap_or(FallbackNicksState::Done);
|
||||
Some((nick, state))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<N1: NickTransformer, N2: NickTransformer> FallbackNicks<N1, N2> {
|
||||
/// Generate the first nickname and a `FallbackNicks` for more.
|
||||
pub fn new<P, S>(
|
||||
reg: &Register<P, S, N1>,
|
||||
pub fn new(
|
||||
reg: &Nicks<N1>,
|
||||
reg_def: &'static impl Defaults<NickGen = N2>,
|
||||
) -> (Nick<'static>, Self) {
|
||||
let (nick, state) = if let Some((nick, rest)) = reg.nicks.split_first() {
|
||||
let rest: VecDeque<Nick<'static>> = rest.to_vec().into();
|
||||
(nick.clone(), FallbackNicksState::Select(nick.clone(), rest))
|
||||
} else {
|
||||
let (nick, state) = nicks_init::<N1, N2>(reg).unwrap_or_else(|| {
|
||||
let (nick, state) = reg_def.nick();
|
||||
(nick, state.map(FallbackNicksState::Gen2).unwrap_or(FallbackNicksState::Done))
|
||||
};
|
||||
(nick, FallbackNicks { state, n1: reg.nickgen.clone(), n2: reg_def.nick_gen() })
|
||||
});
|
||||
(nick, Self { state, n1: reg.gen.clone(), n2: reg_def.nick_gen() })
|
||||
}
|
||||
/// Returns `true` if the next nickname yielded by `self` is a user-specified one.
|
||||
pub fn has_user_nicks(&self) -> bool {
|
||||
|
||||
Reference in New Issue
Block a user