Merge pull request #119 from aatxe/develop

Finalize 0.13.3 release.
This commit is contained in:
Aaron Weiss 2018-02-14 14:51:50 +01:00 committed by GitHub
commit 2440a751d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 399 additions and 240 deletions

View file

@ -1,16 +1,13 @@
env:
global:
- secure: aGzqk53//ZQmZ/7Eb8XtlUG3bmwmR5p+RCSqUEz0xUazsYAO0/NRYgEkebXpggvjQCaJFsWWNxfSq5+3bVa43boIChKzshkrqIvF6sO5RxMslNQbb4rabo4GadJYMMFmoG/3h1EwFk3pEsAorNC/M6VVuH9XLKD5dWgvefMqclc=
language: rust language: rust
rust: stable rust: stable
sudo: false sudo: false
script: script:
- chmod +x mktestconfig.sh - chmod +x mktestconfig.sh
- ./mktestconfig.sh - ./mktestconfig.sh
- cargo build --verbose --features "toml yaml" - cargo build --verbose
- rustdoc --test README.md --extern irc=target/debug/libirc.rlib -L target/debug/deps
- cargo test --verbose --features "toml yaml" - cargo test --verbose --features "toml yaml"
- cargo test --doc - cargo test --doc
- cargo build --verbose --no-default-features
- cargo test --verbose --no-default-features - cargo test --verbose --no-default-features
notifications: notifications:
email: false email: false

46
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,46 @@
# How to contribute
Your contributions are essential for making the irc crate the best piece of software it could
possibly be! We welcome contributions from programmers of all skill levels, and are happy to provide
mentorship for new contributors working on bug fixes. To make the onboarding process as painless as
possible for everyone, there are a few guidelines that we need contributors to follow.
## Getting Started
* Make sure you have a [GitHub account](https://github.com/signup/free).
* Fork the repository on GitHub.
## Making Changes
* Create a topic branch from where you want to base your work.
* This is almost always the develop branch.
* Only target stable or a maintainer's feature branch if you are certain your fix must be on that
branch.
* To quickly create a topic branch based on develop, run `git checkout -b
fix/develop/my_contribution develop`. Please avoid working directly on the
`stable` branch, and keep direct work on `develop` minor.
* Make commits of logical and atomic units.
* Check for unnecessary whitespace with `git diff --check` before committing.
* Make sure you have added the necessary tests for your changes.
* Run _all_ the tests to assure nothing else was accidentally broken using `cargo test`. You can
also run `cargo test --no-default-features`, but this is generally not relevant and will be
handled by our continuous integration tools.
* Some tests related to configurations will fail if you don't run the `mktestconfig.sh` script.
## Submitting Changes
* Push your changes to a topic branch in your fork of the repository.
* Submit a pull request to the `aatxe/irc` repository.
* Await maintainer feedback and continuous integration results.
* We make an effort to triage quickly, but patience is appreciated!
## Additional Resources
* [Code of Conduct](https://github.com/aatxe/irc/blob/develop/CODE_OF_CONDUCT.md)
* [the irc crate docs](https://docs.rs/irc)
* #rust-irc IRC channel on irc.mozilla.org
## Credits
These contributing guidelines were inspired by the
[Puppet contributor guidelines](https://github.com/puppetlabs/puppet/blob/master/CONTRIBUTING.md).

View file

@ -1,6 +1,6 @@
[package] [package]
name = "irc" name = "irc"
version = "0.13.2" version = "0.13.3"
description = "A simple, thread-safe, and async-friendly library for IRC clients." description = "A simple, thread-safe, and async-friendly library for IRC clients."
authors = ["Aaron Weiss <awe@pdgn.co>"] authors = ["Aaron Weiss <awe@pdgn.co>"]
license = "MPL-2.0" license = "MPL-2.0"

160
README.md
View file

@ -1,4 +1,4 @@
# irc [![Build Status][ci-badge]][ci] [![Crates.io][cr-badge]][cr] [![Docs][doc-badge]][doc] [![Built with Spacemacs][bws]][sm] # the irc crate [![Build Status][ci-badge]][ci] [![Crates.io][cr-badge]][cr] [![Docs][doc-badge]][doc] [![Built with Spacemacs][bws]][sm]
[ci-badge]: https://travis-ci.org/aatxe/irc.svg?branch=stable [ci-badge]: https://travis-ci.org/aatxe/irc.svg?branch=stable
[ci]: https://travis-ci.org/aatxe/irc [ci]: https://travis-ci.org/aatxe/irc
@ -9,78 +9,123 @@
[bws]: https://cdn.rawgit.com/syl20bnr/spacemacs/442d025779da2f62fc86c2082703697714db6514/assets/spacemacs-badge.svg [bws]: https://cdn.rawgit.com/syl20bnr/spacemacs/442d025779da2f62fc86c2082703697714db6514/assets/spacemacs-badge.svg
[sm]: http://spacemacs.org [sm]: http://spacemacs.org
A robust, thread-safe and async-friendly library for IRC clients in Rust. It's compliant with [rfc2812]: http://tools.ietf.org/html/rfc2812
[RFC 2812](http://tools.ietf.org/html/rfc2812), [IRCv3.1](http://ircv3.net/irc/3.1.html), [ircv3.1]: http://ircv3.net/irc/3.1.html
[IRCv3.2](http://ircv3.net/irc/3.2.html), and includes some additional, common features. It also [ircv3.2]: http://ircv3.net/irc/3.2.html
includes a number of useful built-in features to faciliate rapid development of clients. You can
find up-to-date, ready-to-use documentation online [here](https://docs.rs/irc/). The "the irc crate" is a thread-safe and async-friendly IRC client library written in Rust. It's
documentation is generated with the default features. These are, however, strictly optional and compliant with [RFC 2812][rfc2812], [IRCv3.1][ircv3.1], [IRCv3.2][ircv3.2], and includes some
can be disabled accordingly. additional, common features from popular IRCds. You can find up-to-date, ready-to-use documentation
online [on docs.rs][doc].
## Built with the irc crate ##
the irc crate is being used to build new IRC software in Rust. Here are some of our favorite
projects:
- [alectro][alectro] — a terminal IRC client
- [spilo][spilo] — a minimalistic IRC bouncer
- [irc-bot.rs][ircbot] — a library for writing IRC bots
- [bunnybutt-rs][bunnybutt] — an IRC bot for the [Feed The Beast Wiki][ftb-wiki]
[alectro]: https://github.com/aatxe/alectro
[spilo]: https://github.com/aatxe/spilo
[ircbot]: https://github.com/8573/irc-bot.rs
[bunnybutt]: https://github.com/FTB-Gamepedia/bunnybutt-rs
[ftb-wiki]: https://ftb.gamepedia.com/FTB_Wiki
Making your own project? [Submit a pull request](https://github.com/aatxe/irc/pulls) to add it!
## Getting Started ## ## Getting Started ##
To start using this library with cargo, you can simply add `irc = "0.13"` to your dependencies in To start using the irc crate with cargo, you can simply add `irc = "0.13"` to your dependencies in
your Cargo.toml file. You'll likely want to take a look at some of the examples, as well as the your Cargo.toml file. The high-level API can be found `irc::client::prelude` linked to from the
documentation. You'll also be able to find below a small template to get a feel for the library. [doc root][doc]. You'll find a number of examples in `examples/`, throughout the documentation, and
below.
## Getting Started by Example ## ## A Tale of Two APIs ##
```rust ### Reactors (The "New" API) ###
The release of v0.13 brought with it a new API called `IrcReactor` that enables easier multiserver
support and more graceful error handling. The general model is that you use the reactor to create
new `IrcClients`, register message handler functions, and finally block the thread to run the
clients with their respective handlers. Here's an example:
```rust,no_run
extern crate irc;
use irc::client::prelude::*;
fn main() {
// We can also load the Config at runtime via Config::load("path/to/config.toml")
let config = Config {
nickname: Some("the-irc-crate".to_owned()),
server: Some("irc.pdgn.co".to_owned()),
channels: Some(vec!["#test".to_owned()]),
..Config::default()
};
let mut reactor = IrcReactor::new().unwrap();
let client = reactor.prepare_client_and_connect(&config).unwrap();
client.identify().unwrap();
reactor.register_client_with_handler(client, |client, message| {
print!("{}", message);
// And here we can do whatever we want with the messages.
Ok(())
});
reactor.run().unwrap();
}
```
### Direct Style (The "Old" API) ###
The old API for connecting to an IRC server is still supported through the `IrcClient` type. It's
simpler for the most basic use case, but will panic upon encountering any sort of connection issues.
In general, it's recommended that users switch to the new API if possible. Nevertheless, here is an
example:
```rust,no_run
extern crate irc; extern crate irc;
use std::default::Default; use std::default::Default;
use irc::client::prelude::*; use irc::client::prelude::*;
fn main() { fn main() {
// We can also load the Config at runtime via Config::load("path/to/config.toml")
let cfg = Config { let cfg = Config {
nickname: Some(format!("irc-rs")), nickname: Some(format!("the-irc-crate")),
client: Some(format!("irc.example.com")), server: Some(format!("irc.example.com")),
channels: Some(vec![format!("#test")]), channels: Some(vec![format!("#test")]),
.. Default::default() .. Default::default()
}; };
let client = IrcClient::from_config(cfg).unwrap(); let client = IrcClient::from_config(cfg).unwrap();
client.identify().unwrap(); client.identify().unwrap();
client.for_each_incoming(|message| { client.for_each_incoming(|message| {
// Do message processing. print!("{}", message);
// And here we can do whatever we want with the messages.
}).unwrap() }).unwrap()
} }
``` ```
It may not seem like much, but all it takes to get started with an IRC connection is the stub ## Configuring IRC Clients ##
above. In just a few lines, you can be connected to a server and processing IRC messages as you
wish. The library is built with flexibility in mind. If you need to work on multiple threads,
simply clone the server and have at it. We'll take care of the rest.
You'll probably find that programmatic configuration is a bit of a chore, and you'll often want to As seen above, there are two techniques for configuring the irc crate: runtime loading and
be able to change the configuration between runs of the program (for example, to change the server programmatic configuration. Runtime loading is done via the function `Config::load`, and is likely
that you're connecting to). Fortunately, runtime configuration loading is straightforward. sufficient for most IRC bots. Programmatic configuration is convenient for writing tests, but can
also be useful when defining your own custom configuration format that can be converted to `Config`.
The primary configuration format is TOML, but if you are so inclined, you can use JSON and/or YAML
via the optional `json` and `yaml` features respectively. At the minimum, a configuration requires
`nickname` and `server` to be defined, and all other fields are optional. You can find detailed
explanations of the various fields on
[docs.rs](https://docs.rs/irc/0.13.2/irc/client/data/config/struct.Config.html#fields).
```rust Alternatively, you can look at the example below of a TOML configuration with all the fields:
extern crate irc;
use irc::client::prelude::*;
fn main() {
let client = IrcClient::new("config.toml").unwrap();
client.identify().unwrap();
client.for_each_incoming(|message| {
// Do message processing.
}).unwrap()
}
```
## Configuration ##
Like the rest of the IRC crate, configuration is built with flexibility in mind. You can easily
create `Config` objects programmatically and choose your own methods for handling any saving or
loading of configuration required. However, for convenience, we've also included the option of
loading files with `serde` to write configurations. The default configuration format is TOML,
though there is optional support for JSON and YAML via the optional `json` and `yaml` features. All
the configuration fields are optional, and can thus be omitted, but a working configuration requires
at least a `server` and `nickname`. You can find detailed explanations of the configuration format
[here](https://docs.rs/irc/0.12.8/irc/client/data/config/struct.Config.html#fields).
Here's an example of a complete configuration in TOML:
```toml ```toml
owners = [] owners = []
@ -97,7 +142,7 @@ cert_path = "cert.der"
encoding = "UTF-8" encoding = "UTF-8"
channels = ["#rust", "#haskell", "#fake"] channels = ["#rust", "#haskell", "#fake"]
umodes = "+RB-x" umodes = "+RB-x"
user_info = "I'm a test user for the Rust IRC crate." user_info = "I'm a test user for the irc crate."
version = "irc:git:Rust" version = "irc:git:Rust"
source = "https://github.com/aatxe/irc" source = "https://github.com/aatxe/irc"
ping_time = 180 ping_time = 180
@ -118,7 +163,7 @@ key = "value"
You can convert between different configuration formats with `convertconf` like so: You can convert between different configuration formats with `convertconf` like so:
``` ```shell
cargo run --example convertconf -- -i client_config.json -o client_config.toml cargo run --example convertconf -- -i client_config.json -o client_config.toml
``` ```
@ -126,7 +171,12 @@ Note that the formats are automatically determined based on the selected file ex
tool should make it easy for users to migrate their old configurations to TOML. tool should make it easy for users to migrate their old configurations to TOML.
## Contributing ## ## Contributing ##
Contributions to this library would be immensely appreciated. Prior to version 0.12.0, this the irc crate is a free, open source library that relies on contributions from its maintainers,
library was public domain. As of 0.12.0, this library is offered under the Mozilla Public License Aaron Weiss ([@aatxe][awe]) and Peter Atashian ([@retep998][bun]), as well as the broader Rust
2.0 whose text can be found in `LICENSE.md`. Fostering an inclusive community around `irc` is community. It's licensed under the Mozilla Public License 2.0 whose text can be found in
important, and to that end, we've adopted an explicit Code of Conduct found in `CODE_OF_CONDUCT.md`. `LICENSE.md`. To foster an inclusive community around the irc crate, we have adopted a Code of
Conduct whose text can be found in `CODE_OF_CONDUCT.md`. You can find details about how to
contribute in `CONTRIBUTING.md`.
[awe]: https://github.com/aatxe/
[bun]: https://github.com/retep998/

View file

@ -398,7 +398,7 @@ impl ClientState {
let alt_nicks = self.config().alternate_nicknames(); let alt_nicks = self.config().alternate_nicknames();
let mut index = self.alt_nick_index.write().unwrap(); let mut index = self.alt_nick_index.write().unwrap();
if *index >= alt_nicks.len() { if *index >= alt_nicks.len() {
panic!("All specified nicknames were in use or disallowed.") return Err(error::IrcError::NoUsableNick);
} else { } else {
self.send(NICK(alt_nicks[*index].to_owned()))?; self.send(NICK(alt_nicks[*index].to_owned()))?;
*index += 1; *index += 1;
@ -861,6 +861,7 @@ mod test {
use std::time::Duration; use std::time::Duration;
use super::{IrcClient, Client}; use super::{IrcClient, Client};
use error::IrcError;
use client::data::Config; use client::data::Config;
#[cfg(not(feature = "nochanlists"))] #[cfg(not(feature = "nochanlists"))]
use client::data::User; use client::data::User;
@ -1044,7 +1045,6 @@ mod test {
} }
#[test] #[test]
#[should_panic(expected = "All specified nicknames were in use or disallowed.")]
fn ran_out_of_nicknames() { fn ran_out_of_nicknames() {
let value = ":irc.pdgn.co 433 * test :Nickname is already in use.\r\n\ let value = ":irc.pdgn.co 433 * test :Nickname is already in use.\r\n\
:irc.pdgn.co 433 * test2 :Nickname is already in use.\r\n"; :irc.pdgn.co 433 * test2 :Nickname is already in use.\r\n";
@ -1052,9 +1052,15 @@ mod test {
mock_initial_value: Some(value.to_owned()), mock_initial_value: Some(value.to_owned()),
..test_config() ..test_config()
}).unwrap(); }).unwrap();
client.for_each_incoming(|message| { let res = client.for_each_incoming(|message| {
println!("{:?}", message); println!("{:?}", message);
}).unwrap(); });
if let Err(IrcError::NoUsableNick) = res {
()
} else {
panic!("expected error when no valid nicks were specified")
}
} }
#[test] #[test]

View file

@ -108,13 +108,10 @@ where
} }
(Async::Ready(None), _) => Ok(Async::Ready(None)), (Async::Ready(None), _) => Ok(Async::Ready(None)),
(Async::Ready(Some(msg)), _) => { (Async::Ready(Some(msg)), _) => {
match timer_poll { if let Async::Ready(msg) = timer_poll {
Async::Ready(msg) => {
assert!(msg.is_some()); assert!(msg.is_some());
self.send_ping()?; self.send_ping()?;
} }
Async::NotReady => (),
}
match msg.command { match msg.command {
// Automatically respond to PINGs from the server. // Automatically respond to PINGs from the server.
@ -182,6 +179,13 @@ where
self.close()?; self.close()?;
Err(error::IrcError::PingTimeout) Err(error::IrcError::PingTimeout)
} else { } else {
// If it's time to send a ping, we should do it! This is necessary to ensure that the
// sink half will close even if the stream half closed without a ping timeout.
if let Async::Ready(msg) = self.ping_timer.poll()? {
assert!(msg.is_some());
self.send_ping()?;
}
Ok(self.inner.poll_complete()?) Ok(self.inner.poll_complete()?)
} }
} }

View file

@ -91,6 +91,10 @@ pub enum IrcError {
/// The data that failed to encode or decode. /// The data that failed to encode or decode.
data: String, data: String,
}, },
/// All specified nicknames were in use or unusable.
#[fail(display = "none of the specified nicknames were usable")]
NoUsableNick
} }
/// Errors that occur when parsing messages. /// Errors that occur when parsing messages.

View file

@ -3,14 +3,16 @@
use std::str::FromStr; use std::str::FromStr;
macro_rules! make_response { macro_rules! make_response {
($(#[$attr:meta] $variant:ident = $value:expr),+) => { ($($(#[$attr:meta])+ $variant:ident = $value:expr),+) => {
/// List of all server responses as defined in /// List of all server responses as defined in
/// [RFC 2812](http://tools.ietf.org/html/rfc2812). /// [RFC 2812](http://tools.ietf.org/html/rfc2812) and
/// All commands are documented with their expected form from the RFC. /// [Modern docs](https://modern.ircdocs.horse/#numerics) (henceforth referred to as
/// Modern). All commands are documented with their expected form from the RFC, and any
/// useful, additional information about the response code.
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
#[repr(u16)] #[repr(u16)]
pub enum Response { pub enum Response {
$(#[$attr] $variant = $value),+ $($(#[$attr])+ $variant = $value),+
} }
impl Response { impl Response {
@ -27,339 +29,389 @@ macro_rules! make_response {
make_response! { make_response! {
// Expected replies // Expected replies
/// `001 Welcome to the Internet Relay Network <nick>!<user>@<host>` /// `001 Welcome to the Internet Relay Network <nick>!<user>@<host>` (Source: RFC2812)
RPL_WELCOME = 1, RPL_WELCOME = 1,
/// `002 Your host is <servername>, running version <ver>` /// `002 Your host is <servername>, running version <ver>` (Source: RFC2812)
RPL_YOURHOST = 2, RPL_YOURHOST = 2,
/// `003 This server was created <date>` /// `003 This server was created <date>` (Source: RFC2812)
RPL_CREATED = 3, RPL_CREATED = 3,
/// `004 <servername> <version> <available user modes> available channel modes>` /// `004 <servername> <version> <available user modes> <available channel modes>` (Source:
/// RFC2812)
///
/// Various IRCds may choose to include additional arguments to `RPL_MYINFO`, and it's best to
/// check for certain what the servers you're targeting do. Typically, there are additional
/// parameters at the end for modes that have parameters, and server modes.
RPL_MYINFO = 4, RPL_MYINFO = 4,
/// `005 <servername> *(<feature>(=<value>)) :are supported by this server` /// `005 <servername> *(<feature>(=<value>)) :are supported by this server` (Source: Modern)
///
/// [RPL_ISUPPORT](https://modern.ircdocs.horse/#rplisupport-005) replaces RPL_BOUNCE from
/// RFC2812, but does so consistently in modern IRCd implementations. RPL_BOUNCE has been moved
/// to `010`.
RPL_ISUPPORT = 5, RPL_ISUPPORT = 5,
/// `010 Try server <server name>, port <port number>` /// `010 Try server <server name>, port <port number>` (Source: Modern)
RPL_BOUNCE = 10, RPL_BOUNCE = 10,
/// `302 :*1<reply> *( " " <reply> )` /// Undefined format. (Source: Modern)
///
/// RPL_NONE is a dummy numeric. It does not have a defined use nor format.
RPL_NONE = 300,
/// `302 :*1<reply> *( " " <reply> )` (Source: RFC2812)
RPL_USERHOST = 302, RPL_USERHOST = 302,
/// `303 :*1<nick> *( " " <nick> )` /// `303 :*1<nick> *( " " <nick> )` (Source: RFC2812)
RPL_ISON = 303, RPL_ISON = 303,
/// `301 <nick> :<away message>` /// `301 <nick> :<away message>` (Source: RFC2812)
RPL_AWAY = 301, RPL_AWAY = 301,
/// `305 :You are no longer marked as being away` /// `305 :You are no longer marked as being away` (Source: RFC2812)
RPL_UNAWAY = 305, RPL_UNAWAY = 305,
/// `306 :You have been marked as being away` /// `306 :You have been marked as being away` (Source: RFC2812)
RPL_NOWAWAY = 306, RPL_NOWAWAY = 306,
/// `311 <nick> <user> <host> * :<real name>` /// `311 <nick> <user> <host> * :<real name>` (Source: RFC2812)
RPL_WHOISUSER = 311, RPL_WHOISUSER = 311,
/// `312 <nick> <server> :<server info>` /// `312 <nick> <server> :<server info>` (Source: RFC2812)
RPL_WHOISSERVER = 312, RPL_WHOISSERVER = 312,
/// `313 <nick> :is an IRC operator` /// `313 <nick> :is an IRC operator` (Source: RFC2812)
RPL_WHOISOPERATOR = 313, RPL_WHOISOPERATOR = 313,
/// `317 <nick> <integer> :seconds idle` /// `317 <nick> <integer> :seconds idle` (Source: RFC2812)
RPL_WHOISIDLE = 317, RPL_WHOISIDLE = 317,
/// `318 <nick> :End of WHOIS list` /// `318 <nick> :End of WHOIS list` (Source: RFC2812)
RPL_ENDOFWHOIS = 318, RPL_ENDOFWHOIS = 318,
/// `319 <nick> :*( ( "@" / "+" ) <channel> " " )` /// `319 <nick> :*( ( "@" / "+" ) <channel> " " )` (Source: RFC2812)
RPL_WHOISCHANNELS = 319, RPL_WHOISCHANNELS = 319,
/// `314 <nick> <user> <host> * :<real name>` /// `314 <nick> <user> <host> * :<real name>` (Source: RFC2812)
RPL_WHOWASUSER = 314, RPL_WHOWASUSER = 314,
/// `369 <nick> :End of WHOWAS` /// `369 <nick> :End of WHOWAS` (Source: RFC2812)
RPL_ENDOFWHOWAS = 369, RPL_ENDOFWHOWAS = 369,
/// Obsolete. Not used. /// Obsolete. Not used. (Source: RFC2812)
RPL_LISTSTART = 321, RPL_LISTSTART = 321,
/// `322 <channel> <# visible> :<topic>` /// `322 <channel> <# visible> :<topic>` (Source: RFC2812)
RPL_LIST = 322, RPL_LIST = 322,
/// `323 :End of LIST /// `323 :End of LIST (Source: RFC2812)
RPL_LISTEND = 323, RPL_LISTEND = 323,
/// `325 <channel> <nickname>` /// `325 <channel> <nickname>` (Source: RFC2812)
RPL_UNIQOPIS = 325, RPL_UNIQOPIS = 325,
/// `324 <channel> <mode> <mode params>` /// `324 <channel> <mode> <mode params>` (Source: RFC2812)
RPL_CHANNELMODEIS = 324, RPL_CHANNELMODEIS = 324,
/// `331 <channel> :No topic is set` /// `331 <channel> :No topic is set` (Source: RFC2812)
RPL_NOTOPIC = 331, RPL_NOTOPIC = 331,
/// `332 <channel> :<topic>` /// `332 <channel> :<topic>` (Source: RFC2812)
RPL_TOPIC = 332, RPL_TOPIC = 332,
/// `333 <channel> <nick>!<user>@<host> <unix timestamp>` /// `333 <channel> <nick>!<user>@<host> <unix timestamp>` (Source: RFC2812)
RPL_TOPICWHOTIME = 333, RPL_TOPICWHOTIME = 333,
/// `341 <channel> <nick>` /// `341 <channel> <nick>` (Source: RFC2812)
RPL_INVITING = 341, RPL_INVITING = 341,
/// `342 <user> :Summoning user to IRC` /// `342 <user> :Summoning user to IRC` (Source: RFC2812)
///
/// According to Modern, this response is rarely implemented. In practice, people simply message
/// one another in a channel with their specified username in the message, rather than use the
/// `SUMMON` command.
RPL_SUMMONING = 342, RPL_SUMMONING = 342,
/// `346 <channel> <invitemask>` /// `346 <channel> <invitemask>` (Source: RFC2812)
RPL_INVITELIST = 346, RPL_INVITELIST = 346,
/// `347 <channel> :End of channel invite list` /// `347 <channel> :End of channel invite list` (Source: RFC2812)
///
/// According to Modern, `RPL_ENDOFEXCEPTLIST` (349) is frequently deployed for this same
/// purpose and the difference will be noted in channel mode and the statement in the suffix.
RPL_ENDOFINVITELIST = 347, RPL_ENDOFINVITELIST = 347,
/// `348 <channel> <exceptionmask>` /// `348 <channel> <exceptionmask>` (Source: RFC2812)
RPL_EXCEPTLIST = 348, RPL_EXCEPTLIST = 348,
/// `349 <channel> :End of channel exception list` /// `349 <channel> :End of channel exception list` (Source: RFC2812)
RPL_ENDOFEXCEPTLIST = 349, RPL_ENDOFEXCEPTLIST = 349,
/// `351 <version>.<debuglevel> <server> :<comments>` /// `351 <version> <server> :<comments>` (Source: RFC2812/Modern)
RPL_VERSION = 351, RPL_VERSION = 351,
/** `352 <channel> <user> <host> <server> <nick> ( "H" / "G" > ["*"] [ ( "@" / "+" ) ] /// `352 <channel> <user> <host> <server> <nick> ( "H" / "G" > ["*"] [ ( "@" / "+" ) ]
:<hopcount> <real name>` **/ /// :<hopcount> <real name>` (Source: RFC2812)
RPL_WHOREPLY = 352, RPL_WHOREPLY = 352,
/// `315 <name> :End of WHO list` /// `315 <name> :End of WHO list` (Source: RFC2812)
RPL_ENDOFWHO = 315, RPL_ENDOFWHO = 315,
/// `353 ( "=" / "*" / "@" ) <channel> :[ "@" / "+" ] <nick> *( " " [ "@" / "+" ] <nick> )` /// `353 ( "=" / "*" / "@" ) <channel> :[ "@" / "+" ] <nick> *( " " [ "@" / "+" ] <nick> )`
/// (Source: RFC2812)
RPL_NAMREPLY = 353, RPL_NAMREPLY = 353,
/// `366 <channel> :End of NAMES list` /// `366 <channel> :End of NAMES list` (Source: RFC2812)
RPL_ENDOFNAMES = 366, RPL_ENDOFNAMES = 366,
/// `364 <mask> <server> :<hopcount> <server info>` /// `364 <mask> <server> :<hopcount> <server info>` (Source: RFC2812)
RPL_LINKS = 364, RPL_LINKS = 364,
/// `365 <mask> :End of LINKS list` /// `365 <mask> :End of LINKS list` (Source: RFC2812)
RPL_ENDOFLINKS = 365, RPL_ENDOFLINKS = 365,
/// `367 <channel> <banmask>` /// `367 <channel> <banmask>` (Source: RFC2812)
RPL_BANLIST = 367, RPL_BANLIST = 367,
/// `368 <channel> :End of channel ban list` /// `368 <channel> :End of channel ban list` (Source: RFC2812)
RPL_ENDOFBANLIST = 368, RPL_ENDOFBANLIST = 368,
/// `371 :<string>` /// `371 :<string>` (Source: RFC2812)
RPL_INFO = 371, RPL_INFO = 371,
/// `374 :End of INFO list` /// `374 :End of INFO list` (Source: RFC2812)
RPL_ENDOFINFO = 374, RPL_ENDOFINFO = 374,
/// `375 :- <server> Message of the day -` /// `375 :- <server> Message of the day -` (Source: RFC2812)
RPL_MOTDSTART = 375, RPL_MOTDSTART = 375,
/// `372 :- <text>` /// `372 :- <text>` (Source: RFC2812)
RPL_MOTD = 372, RPL_MOTD = 372,
/// `376 :End of MOTD command` /// `376 :End of MOTD command` (Source: RFC2812)
RPL_ENDOFMOTD = 376, RPL_ENDOFMOTD = 376,
/// `381 :You are now an IRC operator` /// `381 :You are now an IRC operator` (Source: RFC2812)
RPL_YOUREOPER = 381, RPL_YOUREOPER = 381,
/// `382 <config file> :Rehashing` /// `382 <config file> :Rehashing` (Source: RFC2812)
RPL_REHASHING = 382, RPL_REHASHING = 382,
/// `383 You are service <servicename>` /// `383 You are service <servicename>` (Source: RFC2812)
RPL_YOURESERVICE = 383, RPL_YOURESERVICE = 383,
/// `391 <server> :<string showing server's local time>` /// `391 <server> :<string showing server's local time>` (Source: RFC2812)
RPL_TIME = 391, RPL_TIME = 391,
/// `392 :UserID Terminal Host` /// `392 :UserID Terminal Host` (Source: RFC2812)
RPL_USERSSTART = 392, RPL_USERSSTART = 392,
/// `393 :<username> <ttyline> <hostname>` /// `393 :<username> <ttyline> <hostname>` (Source: RFC2812)
RPL_USERS = 393, RPL_USERS = 393,
/// `394 :End of users` /// `394 :End of users` (Source: RFC2812)
RPL_ENDOFUSERS = 394, RPL_ENDOFUSERS = 394,
/// `395 :Nobody logged in` /// `395 :Nobody logged in` (Source: RFC2812)
RPL_NOUSERS = 395, RPL_NOUSERS = 395,
/** `200 Link <version & debug level> <destination> <next server> V<protocol version> /// `396 <nickname> <host> :is now your displayed host` (Source: InspIRCd)
<link uptime in seconds> <backstream sendq> <upstream sendq>` **/ ///
/// This response code is sent after a user enables the user mode +x (host masking), and it is
/// successfully enabled. The particular format described above is from InspIRCd, but the
/// response code should be common amongst servers that support host masks.
RPL_HOSTHIDDEN = 396,
/// `200 Link <version & debug level> <destination> <next server> V<protocol version>
/// <link uptime in seconds> <backstream sendq> <upstream sendq>` (Source: RFC2812)
RPL_TRACELINK = 200, RPL_TRACELINK = 200,
/// `201 Try. <class> <server>` /// `201 Try. <class> <server>` (Source: RFC2812)
RPL_TRACECONNECTING = 201, RPL_TRACECONNECTING = 201,
/// `202 H.S. <class> <server>` /// `202 H.S. <class> <server>` (Source: RFC2812)
RPL_TRACEHANDSHAKE = 202, RPL_TRACEHANDSHAKE = 202,
/// `203 ???? <class> [<client IP address in dot form>]` /// `203 ???? <class> [<client IP address in dot form>]` (Source: RFC2812)
RPL_TRACEUKNOWN = 203, RPL_TRACEUKNOWN = 203,
/// `204 Oper <class> <nick>` /// `204 Oper <class> <nick>` (Source: RFC2812)
RPL_TRACEOPERATOR = 204, RPL_TRACEOPERATOR = 204,
/// `205 User <class> <nick>` /// `205 User <class> <nick>` (Source: RFC2812)
RPL_TRACEUSER = 205, RPL_TRACEUSER = 205,
/// `206 Serv <class> <int>S <int>C <server> <nick!user|*!*>@<host|server> V<protocol version>` /// `206 Serv <class> <int>S <int>C <server> <nick!user|*!*>@<host|server> V<protocol version>`
/// (Source: RFC2812)
RPL_TRACESERVER = 206, RPL_TRACESERVER = 206,
/// `207 Service <class> <name> <type> <active type>` /// `207 Service <class> <name> <type> <active type>` (Source: RFC2812)
RPL_TRACESERVICE = 207, RPL_TRACESERVICE = 207,
/// `208 <newtype> 0 <client name>` /// `208 <newtype> 0 <client name>` (Source: RFC2812)
RPL_TRACENEWTYPE = 208, RPL_TRACENEWTYPE = 208,
/// `209 Class <class> <count>` /// `209 Class <class> <count>` (Source: RFC2812)
RPL_TRACECLASS = 209, RPL_TRACECLASS = 209,
/// Unused. /// Unused. (Source: RFC2812)
RPL_TRACERECONNECT = 210, RPL_TRACERECONNECT = 210,
/// `261 File <logfile> <debug level>` /// `261 File <logfile> <debug level>` (Source: RFC2812)
RPL_TRACELOG = 261, RPL_TRACELOG = 261,
/// `262 <server name> <version & debug level> :End of TRACE` /// `262 <server name> <version & debug level> :End of TRACE` (Source: RFC2812)
RPL_TRACEEND = 262, RPL_TRACEEND = 262,
/** `211 <linkname> <sendq> <sent messages> <sent Kbytes> <received messages> <received Kbytes> /// `211 <linkname> <sendq> <sent messages> <sent Kbytes> <received messages> <received Kbytes>
<time open>` **/ /// <time open>` (Source: RFC2812)
RPL_STATSLINKINFO = 211, RPL_STATSLINKINFO = 211,
/// `212 <command> <count> <byte count> <remote count>` /// `212 <command> <count> <byte count> <remote count>` (Source: RFC2812)
RPL_STATSCOMMANDS = 212, RPL_STATSCOMMANDS = 212,
/// `219 <stats letter> :End of STATS report` /// `219 <stats letter> :End of STATS report` (Source: RFC2812)
RPL_ENDOFSTATS = 219, RPL_ENDOFSTATS = 219,
/// `242 :Server Up %d days %d:%02d:%02d` /// `242 :Server Up %d days %d:%02d:%02d` (Source: RFC2812)
RPL_STATSUPTIME = 242, RPL_STATSUPTIME = 242,
/// `243 O <hostmask> * <name>` /// `243 O <hostmask> * <name>` (Source: RFC2812)
RPL_STATSOLINE = 243, RPL_STATSOLINE = 243,
/// `221 <user mode string>` /// `221 <user mode string>` (Source: RFC2812)
RPL_UMODEIS = 221, RPL_UMODEIS = 221,
/// `234 <name> <server> <mask> <type> <hopcount> <info>` /// `234 <name> <server> <mask> <type> <hopcount> <info>` (Source: RFC2812)
RPL_SERVLIST = 234, RPL_SERVLIST = 234,
/// `235 <mask> <type> :End of service listing` /// `235 <mask> <type> :End of service listing` (Source: RFC2812)
RPL_SERVLISTEND = 235, RPL_SERVLISTEND = 235,
/// `251 :There are <integer> users and <integer> services on <integer> servers` /// `251 :There are <int> users and <int> services on <int> servers` (Source: RFC2812)
RPL_LUSERCLIENT = 251, RPL_LUSERCLIENT = 251,
/// `252 <integer> :operator(s) online` /// `252 <integer> :operator(s) online` (Source: RFC2812)
RPL_LUSEROP = 252, RPL_LUSEROP = 252,
/// `253 <integer> :unknown connection(s)` /// `253 <integer> :unknown connection(s)` (Source: RFC2812)
RPL_LUSERUNKNOWN = 253, RPL_LUSERUNKNOWN = 253,
/// `254 <integer> :channels formed` /// `254 <integer> :channels formed` (Source: RFC2812)
RPL_LUSERCHANNELS = 254, RPL_LUSERCHANNELS = 254,
/// `255 :I have <integer> clients and <integer> servers` /// `255 :I have <integer> clients and <integer> servers` (Source: RFC2812)
RPL_LUSERME = 255, RPL_LUSERME = 255,
/// `256 <server> :Administrative info` /// `256 <server> :Administrative info` (Source: RFC2812)
RPL_ADMINME = 256, RPL_ADMINME = 256,
/// `257 :<admin info>` /// `257 :<admin info>` (Source: RFC2812)
RPL_ADMINLOC1 = 257, RPL_ADMINLOC1 = 257,
/// `258 :<admin info>` /// `258 :<admin info>` (Source: RFC2812)
RPL_ADMINLOC2 = 258, RPL_ADMINLOC2 = 258,
/// `259 :<admin info>` /// `259 :<admin info>` (Source: RFC2812)
RPL_ADMINEMAIL = 259, RPL_ADMINEMAIL = 259,
/// `263 <command> :Please wait a while and try again.` /// `263 <command> :Please wait a while and try again.` (Source: RFC2812)
RPL_TRYAGAIN = 263, RPL_TRYAGAIN = 263,
/// `730 <nick> :target[,target2]*` /// `265 <client> [<u> <m>] :Current local users <u>, max <m>` (Source: Modern)
RPL_LOCALUSERS = 265,
/// `266 <client> [<u> <m>] :Current local users <u>, max <m>` (Source: Modern)
RPL_GLOBALUSERS = 266,
/// `276 <client> <nick> :has client certificate fingerprint <fingerprint>` (Source: Modern)
RPL_WHOISCERTFP = 276,
/// `730 <nick> :target[,target2]*` (Source: RFC2812)
RPL_MONONLINE = 730, RPL_MONONLINE = 730,
/// `731 <nick> :target[,target2]*` /// `731 <nick> :target[,target2]*` (Source: RFC2812)
RPL_MONOFFLINE = 731, RPL_MONOFFLINE = 731,
/// `732 <nick> :target[,target2]*` /// `732 <nick> :target[,target2]*` (Source: RFC2812)
RPL_MONLIST = 732, RPL_MONLIST = 732,
/// `733 <nick> :End of MONITOR list` /// `733 <nick> :End of MONITOR list` (Source: RFC2812)
RPL_ENDOFMONLIST = 733, RPL_ENDOFMONLIST = 733,
/// `760 <target> <key> <visibility> :<value>` /// `760 <target> <key> <visibility> :<value>` (Source: RFC2812)
RPL_WHOISKEYVALUE = 760, RPL_WHOISKEYVALUE = 760,
/// `761 <target> <key> <visibility> :[<value>]` /// `761 <target> <key> <visibility> :[<value>]` (Source: RFC2812)
RPL_KEYVALUE = 761, RPL_KEYVALUE = 761,
/// `762 :end of metadata` /// `762 :end of metadata` (Source: RFC2812)
RPL_METADATAEND = 762, RPL_METADATAEND = 762,
/// `900 <nick> <nick>!<ident>@<host> <account> :You are now logged in as <user>` /// `900 <nick> <nick>!<ident>@<host> <account> :You are now logged in as <user>` (Source:
/// IRCv3)
RPL_LOGGEDIN = 900, RPL_LOGGEDIN = 900,
/// `901 <nick> <nick>!<ident>@<host> :You are now logged out` /// `901 <nick> <nick>!<ident>@<host> :You are now logged out` (Source: IRCv3)
RPL_LOGGEDOUT = 901, RPL_LOGGEDOUT = 901,
/// `903 <nick> :SASL authentication successful` /// `903 <nick> :SASL authentication successful` (Source: IRCv3)
RPL_SASLSUCCESS = 903, RPL_SASLSUCCESS = 903,
/// `908 <nick> <mechanisms> :are available SASL mechanisms` /// `908 <nick> <mechanisms> :are available SASL mechanisms` (Source: IRCv3)
RPL_SASLMECHS = 908, RPL_SASLMECHS = 908,
// Error replies // Error replies
/// `401 <nickname> :No such nick/channel` /// `400 <client> <command>{ <subcommand>} :<info>` (Source: Modern)
///
/// According to Modern, this error will be returned when the given command/subcommand could not
/// be processed. It's a very general error, and should only be used when more specific numerics
/// do not suffice.
ERR_UNKNOWNERROR = 400,
/// `401 <nickname> :No such nick/channel` (Source: RFC2812)
ERR_NOSUCHNICK = 401, ERR_NOSUCHNICK = 401,
/// `402 <server name> :No such server` /// `402 <server name> :No such server` (Source: RFC2812)
ERR_NOSUCHSERVER = 402, ERR_NOSUCHSERVER = 402,
/// `403 <channel name> :No such channel` /// `403 <channel name> :No such channel` (Source: RFC2812)
ERR_NOSUCHCHANNEL = 403, ERR_NOSUCHCHANNEL = 403,
/// `404 <channel name> :Cannot send to channel` /// `404 <channel name> :Cannot send to channel` (Source: RFC2812)
ERR_CANNOTSENDTOCHAN = 404, ERR_CANNOTSENDTOCHAN = 404,
/// `405 <channel name> :You have joined too many channels` /// `405 <channel name> :You have joined too many channels` (Source: RFC2812)
ERR_TOOMANYCHANNELS = 405, ERR_TOOMANYCHANNELS = 405,
/// `406 <nickname> :There was no such nickname` /// `406 <nickname> :There was no such nickname` (Source: RFC2812)
ERR_WASNOSUCHNICK = 406, ERR_WASNOSUCHNICK = 406,
/// `407 <target> :<error code> recipients. <abort message>` /// `407 <target> :<error code> recipients. <abort message>` (Source: RFC2812)
ERR_TOOMANYTARGETS = 407, ERR_TOOMANYTARGETS = 407,
/// `408 <service name> :No such service` /// `408 <service name> :No such service` (Source: RFC2812)
ERR_NOSUCHSERVICE = 408, ERR_NOSUCHSERVICE = 408,
/// `409 :No origin specified` /// `409 :No origin specified` (Source: RFC2812)
ERR_NOORIGIN = 409, ERR_NOORIGIN = 409,
/// `411 :No recipient given (<command>)` /// `411 :No recipient given (<command>)` (Source: RFC2812)
ERR_NORECIPIENT = 411, ERR_NORECIPIENT = 411,
/// `412 :No text to send` /// `412 :No text to send` (Source: RFC2812)
ERR_NOTEXTTOSEND = 412, ERR_NOTEXTTOSEND = 412,
/// `413 <mask> :No toplevel domain specified` /// `413 <mask> :No toplevel domain specified` (Source: RFC2812)
ERR_NOTOPLEVEL = 413, ERR_NOTOPLEVEL = 413,
/// `414 <mask> :Wildcard in toplevel domain` /// `414 <mask> :Wildcard in toplevel domain` (Source: RFC2812)
ERR_WILDTOPLEVEL = 414, ERR_WILDTOPLEVEL = 414,
/// `415 <mask> :Bad Server/host mask` /// `415 <mask> :Bad Server/host mask` (Source: RFC2812)
ERR_BADMASK = 415, ERR_BADMASK = 415,
/// `421 <command> :Unknown command` /// `421 <command> :Unknown command` (Source: RFC2812)
ERR_UNKNOWNCOMMAND = 421, ERR_UNKNOWNCOMMAND = 421,
/// `422 :MOTD File is missing` /// `422 :MOTD File is missing` (Source: RFC2812)
ERR_NOMOTD = 422, ERR_NOMOTD = 422,
/// `423 <server> :No administrative info available` /// `423 <server> :No administrative info available` (Source: RFC2812)
ERR_NOADMININFO = 423, ERR_NOADMININFO = 423,
/// `424 :File error doing <file op> on <file>` /// `424 :File error doing <file op> on <file>` (Source: RFC2812)
ERR_FILEERROR = 424, ERR_FILEERROR = 424,
/// `431 :No nickname given` /// `431 :No nickname given` (Source: RFC2812)
ERR_NONICKNAMEGIVEN = 431, ERR_NONICKNAMEGIVEN = 431,
/// `432 <nick> :Erroneous nickname"` /// `432 <nick> :Erroneous nickname"` (Source: RFC2812)
ERR_ERRONEOUSNICKNAME = 432, ERR_ERRONEOUSNICKNAME = 432,
/// `433 <nick> :Nickname is already in use` /// `433 <nick> :Nickname is already in use` (Source: RFC2812)
ERR_NICKNAMEINUSE = 433, ERR_NICKNAMEINUSE = 433,
/// `436 <nick> :Nickname collision KILL from <user>@<host>` /// `436 <nick> :Nickname collision KILL from <user>@<host>` (Source: RFC2812)
ERR_NICKCOLLISION = 436, ERR_NICKCOLLISION = 436,
/// `437 <nick/channel> :Nick/channel is temporarily unavailable` /// `437 <nick/channel> :Nick/channel is temporarily unavailable` (Source: RFC2812)
ERR_UNAVAILRESOURCE = 437, ERR_UNAVAILRESOURCE = 437,
/// `441 <nick> <channel> :They aren't on that channel` /// `441 <nick> <channel> :They aren't on that channel` (Source: RFC2812)
ERR_USERNOTINCHANNEL = 441, ERR_USERNOTINCHANNEL = 441,
/// `442 <channel> :You're not on that channel` /// `442 <channel> :You're not on that channel` (Source: RFC2812)
ERR_NOTONCHANNEL = 442, ERR_NOTONCHANNEL = 442,
/// `443 <user> <channel> :is already on channel` /// `443 <user> <channel> :is already on channel` (Source: RFC2812)
ERR_USERONCHANNEL = 443, ERR_USERONCHANNEL = 443,
/// `444 <user> :User not logged in` /// `444 <user> :User not logged in` (Source: RFC2812)
ERR_NOLOGIN = 444, ERR_NOLOGIN = 444,
/// `445 :SUMMON has been disabled` /// `445 :SUMMON has been disabled` (Source: RFC2812)
ERR_SUMMONDISABLED = 445, ERR_SUMMONDISABLED = 445,
/// `446 :USERS has been disabled` /// `446 :USERS has been disabled` (Source: RFC2812)
ERR_USERSDISABLED = 446, ERR_USERSDISABLED = 446,
/// `451 :You have not registered` /// `451 :You have not registered` (Source: RFC2812)
ERR_NOTREGISTERED = 451, ERR_NOTREGISTERED = 451,
/// `461 <command> :Not enough parameters` /// `461 <command> :Not enough parameters` (Source: RFC2812)
ERR_NEEDMOREPARAMS = 461, ERR_NEEDMOREPARAMS = 461,
/// `462 :Unauthorized command (already registered)` /// `462 :Unauthorized command (already registered)` (Source: RFC2812)
ERR_ALREADYREGISTRED = 462, ERR_ALREADYREGISTRED = 462,
/// `463 :Your host isn't among the privileged` /// `463 :Your host isn't among the privileged` (Source: RFC2812)
ERR_NOPERMFORHOST = 463, ERR_NOPERMFORHOST = 463,
/// `464 :Password incorrect` /// `464 :Password incorrect` (Source: RFC2812)
ERR_PASSWDMISMATCH = 464, ERR_PASSWDMISMATCH = 464,
/// `465 :You are banned from this server` /// `465 :You are banned from this server` (Source: RFC2812)
ERR_YOUREBANNEDCREEP = 465, ERR_YOUREBANNEDCREEP = 465,
/// `466` /// `466` (Source: RFC2812)
ERR_YOUWILLBEBANNED = 466, ERR_YOUWILLBEBANNED = 466,
/// `467 <channel> :Channel key already set` /// `467 <channel> :Channel key already set` (Source: RFC2812)
ERR_KEYSET = 467, ERR_KEYSET = 467,
/// `471 <channel> :Cannot join channel (+l)` /// `471 <channel> :Cannot join channel (+l)` (Source: RFC2812)
ERR_CHANNELISFULL = 471, ERR_CHANNELISFULL = 471,
/// `472 <char> :is unknown mode char to me for <channel>` /// `472 <char> :is unknown mode char to me for <channel>` (Source: RFC2812)
ERR_UNKNOWNMODE = 472, ERR_UNKNOWNMODE = 472,
/// `473 <channel> :Cannot join channel (+i)` /// `473 <channel> :Cannot join channel (+i)` (Source: RFC2812)
ERR_INVITEONLYCHAN = 473, ERR_INVITEONLYCHAN = 473,
/// `474 <channel> :Cannot join channel (+b)` /// `474 <channel> :Cannot join channel (+b)` (Source: RFC2812)
ERR_BANNEDFROMCHAN = 474, ERR_BANNEDFROMCHAN = 474,
/// `475 <channel> :Cannot join channel (+k)` /// `475 <channel> :Cannot join channel (+k)` (Source: RFC2812)
ERR_BADCHANNELKEY = 475, ERR_BADCHANNELKEY = 475,
/// `476 <channel> :Bad Channel Mask` /// `476 <channel> :Bad Channel Mask` (Source: RFC2812)
ERR_BADCHANMASK = 476, ERR_BADCHANMASK = 476,
/// `477 <channel> :Channel doesn't support modes` /// `477 <channel> :Channel doesn't support modes` (Source: RFC2812)
ERR_NOCHANMODES = 477, ERR_NOCHANMODES = 477,
/// `478 <channel> <char> :Channel list is full` /// `478 <channel> <char> :Channel list is full` (Source: RFC2812)
ERR_BANLISTFULL = 478, ERR_BANLISTFULL = 478,
/// `481 :Permission Denied- You're not an IRC operator` /// `481 :Permission Denied- You're not an IRC operator` (Source: RFC2812)
ERR_NOPRIVILEGES = 481, ERR_NOPRIVILEGES = 481,
/// `482 <channel> :You're not channel operator` /// `482 <channel> :You're not channel operator` (Source: RFC2812)
ERR_CHANOPRIVSNEEDED = 482, ERR_CHANOPRIVSNEEDED = 482,
/// `483 :You can't kill a server!` /// `483 :You can't kill a server!` (Source: RFC2812)
ERR_CANTKILLSERVER = 483, ERR_CANTKILLSERVER = 483,
/// `484 :Your connection is restricted!` /// `484 :Your connection is restricted!` (Source: RFC2812)
ERR_RESTRICTED = 484, ERR_RESTRICTED = 484,
/// `485 :You're not the original channel operator` /// `485 :You're not the original channel operator` (Source: RFC2812)
ERR_UNIQOPPRIVSNEEDED = 485, ERR_UNIQOPPRIVSNEEDED = 485,
/// `491 :No O-lines for your host` /// `491 :No O-lines for your host` (Source: RFC2812)
ERR_NOOPERHOST = 491, ERR_NOOPERHOST = 491,
/// `501 :Unknown MODE flag` /// `501 :Unknown MODE flag` (Source: RFC2812)
ERR_UMODEUNKNOWNFLAG = 501, ERR_UMODEUNKNOWNFLAG = 501,
/// `502 :Cannot change mode for other users` /// `502 :Cannot change mode for other users` (Source: RFC2812)
ERR_USERSDONTMATCH = 502, ERR_USERSDONTMATCH = 502,
/// `734 <nick> <limit> <targets> :Monitor list is full.` /// `723 <client> <priv> :Insufficient oper privileges.` (Source: Modern)
///
/// Sent to an operator to indicate that they don't have the specific privileges to perform the
/// desired action. The format and meaning of the privilege string is server-defined.
ERR_NOPRIVS = 723,
/// `734 <nick> <limit> <targets> :Monitor list is full.` (Source: RFC2812)
ERR_MONLISTFULL = 734, ERR_MONLISTFULL = 734,
/// `764 <target> :metadata limit reached` /// `764 <target> :metadata limit reached` (Source: RFC2812)
ERR_METADATALIMIT = 764, ERR_METADATALIMIT = 764,
/// `765 <target> :invalid metadata target` /// `765 <target> :invalid metadata target` (Source: RFC2812)
ERR_TARGETINVALID = 765, ERR_TARGETINVALID = 765,
/// `766 <key> :no matching key` /// `766 <key> :no matching key` (Source: RFC2812)
ERR_NOMATCHINGKEY = 766, ERR_NOMATCHINGKEY = 766,
/// `767 <key> :invalid metadata key` /// `767 <key> :invalid metadata key` (Source: RFC2812)
ERR_KEYINVALID = 767, ERR_KEYINVALID = 767,
/// `768 <target> <key> :key not set` /// `768 <target> <key> :key not set` (Source: RFC2812)
ERR_KEYNOTSET = 768, ERR_KEYNOTSET = 768,
/// `769 <target> <key> :permission denied` /// `769 <target> <key> :permission denied` (Source: RFC2812)
ERR_KEYNOPERMISSION = 769, ERR_KEYNOPERMISSION = 769,
/// `902 <nick> :You must use a nick assigned to you.` /// `902 <nick> :You must use a nick assigned to you.` (Source: IRCv3)
ERR_NICKLOCKED = 902, ERR_NICKLOCKED = 902,
/// `904 <nick> :SASL authentication failed` /// `904 <nick> :SASL authentication failed` (Source: IRCv3)
ERR_SASLFAIL = 904, ERR_SASLFAIL = 904,
/// `905 <nick> :SASL message too long` /// `905 <nick> :SASL message too long` (Source: IRCv3)
ERR_SASLTOOLONG = 905, ERR_SASLTOOLONG = 905,
/// `906 <nick> :SASL authentication aborted` /// `906 <nick> :SASL authentication aborted` (Source: IRCv3)
ERR_SASLABORT = 906, ERR_SASLABORT = 906,
/// `907 <nick> :You have already authenticated using SASL` /// `907 <nick> :You have already authenticated using SASL` (Source: IRCv3)
ERR_SASLALREADY = 907 ERR_SASLALREADY = 907
} }
impl Response { impl Response {
/// Determines whether or not this response is an error response. /// Determines whether or not this response is an error response.
///
/// This error consideration is according to RFC2812, but is rather simplistic. It considers all
/// response codes above 400 to be errors, which misclassifies some extensions (e.g. from IRCv3)
/// that add responses and errors both in the same range (typically 700s or 900s).
pub fn is_error(&self) -> bool { pub fn is_error(&self) -> bool {
*self as u16 >= 400 *self as u16 >= 400
} }