async-circe 0.2.3

IRC crate in Rust
Documentation
//! IRC commands
//! - commands that can be recived from a server
//! - commands that can be send to the server

#[doc(hidden)]
#[derive(Debug)]
pub enum CapMode {
    LS,
    END,
}

/// Commands that can be send or recived from an IRC server.
#[derive(Debug)]
pub enum Command {
    // TODO:
    // SERVICE <nickname> <reserved> <distribution> <type> <reserved> <info>
    // SQUIT <server> <comment>
    //
    /// Request information about the admin of a given server.
    /// ```run_fut
    /// # let config = Default::default();
    /// # let mut client = Client::new(config).await?;
    /// # client.identify().await?;
    /// client.admin("libera.chat").await?;
    /// # Ok(())
    /// ```
    /// # Errors
    /// Returns IO errors from the TcpStream.
    ADMIN(
        /// Target
        String,
    ),
    /// Set the status of the client.
    /// ```run_fut
    /// # let config = Default::default();
    /// # let mut client = Client::new(config).await?;
    /// # client.identify().await?;
    /// client.away("afk").await?;
    /// # Ok(())
    /// ```
    AWAY(
        /// Message
        String,
    ),
    #[doc(hidden)]
    CAP(CapMode),
    /// Invite someone to a channel.
    /// ```run_fut
    /// # let config = Default::default();
    /// # let mut client = Client::new(config).await?;
    /// # client.identify().await?;
    /// client.invite("liblemonirc", "#async-circe").await?;
    /// # Ok(())
    /// ```
    INVITE(
        /// User
        String,
        /// Channel
        String,
    ),
    /// Join a channel.
    /// ```run_fut
    /// # let config = Default::default();
    /// # let mut client = Client::new(config).await?;
    /// # client.identify().await?;
    /// client.join("#chaos").await?;
    /// # Ok(())
    /// ```
    JOIN(
        /// Channel
        String,
    ),
    /// List available channels on an IRC, or users in a channel.
    /// ```run_fut
    /// # let config = Default::default();
    /// # let mut client = Client::new(config).await?;
    /// # client.identify().await?;
    /// client.list(None, None).await?;
    /// # Ok(())
    /// ```
    LIST(
        /// Channel
        Option<String>,
        /// Server to foreward request to
        Option<String>,
    ),
    /// Set the mode for a user.
    /// ```run_fut
    /// # let config = Default::default();
    /// # let mut client = Client::new(config).await?;
    /// # client.identify().await?;
    /// client.mode("test", Some("+B")).await?;
    /// # Ok(())
    /// ```
    MODE(
        /// Channel
        String,
        /// Mode
        Option<String>,
    ),
    /// Get all the people online in channels.
    /// ```run_fut
    /// # let config = Default::default();
    /// # let mut client = Client::new(config).await?;
    /// # client.identify().await?;
    /// client.names("#chaos,#async-circe", None).await?;
    /// # Ok(())
    /// ```
    NAMES(
        /// Channel
        String,
        /// Server to foreward request to
        Option<String>,
    ),
    /// Change your nickname on a server.
    /// ```run_fut
    /// # let config = Default::default();
    /// # let mut client = Client::new(config).await?;
    /// # client.identify().await?;
    /// client.nick("Not async-circe").await?;
    /// # Ok(())
    /// ```
    NICK(
        /// Nickname
        String,
    ),
    /// Authentificate as an operator on a server.
    /// ```run_fut
    /// # let config = Default::default();
    /// # let mut client = Client::new(config).await?;
    /// # client.identify().await?;
    /// client.oper("username", "password").await?;
    /// # Ok(())
    /// ```
    OPER(
        /// Username
        String,
        /// Password
        String,
    ),
    /// Everything that is not a command
    OTHER(String),
    /// Leave a channel.
    /// ```run_fut
    /// # let config = Default::default();
    /// # let mut client = Client::new(config).await?;
    /// # client.identify().await?;
    /// client.part("#chaos").await?;
    /// # Ok(())
    /// ```
    PART(
        /// Target
        String,
    ),
    #[doc(hidden)]
    PASS(String),
    /// Tests the presence of a connection to a server.
    /// ```run_fut
    /// # let config = Default::default();
    /// # let mut client = Client::new(config).await?;
    /// # client.identify().await?;
    /// client.ping("libera.chat", None).await?;
    /// # Ok(())
    /// ```
    PING(String),
    #[doc(hidden)]
    PONG(String),
    /// Send a message to a channel.
    /// ```run_fut
    /// # let config = Default::default();
    /// # let mut client = Client::new(config).await?;
    /// # client.identify().await?;
    /// client.privmsg("#chaos", "Hello").await?;
    /// # Ok(())
    /// ```
    PRIVMSG(
        /// Source Nickname
        String,
        /// Channel
        String,
        /// Message
        String,
    ),
    /// Leave the IRC server you are connected to.
    /// ```run_fut
    /// # let config = Default::default();
    /// # let mut client = Client::new(config).await?;
    /// # client.identify().await?;
    /// client.quit(None).await?;
    /// # Ok(())
    /// ```
    QUIT(
        /// Leave message
        String,
    ),
    /// Get the topic of a channel.
    /// # Example
    /// ```run_fut
    /// # let config = Default::default();
    /// # let mut client = Client::new(config).await?;
    /// # client.identify().await?;
    /// client.topic("#chaos", None).await?;
    /// # Ok(())
    /// ```
    /// Set the topic of a channel.
    /// # Example
    /// ```run_fut
    /// # let config = Default::default();
    /// # let mut client = Client::new(config).await?;
    /// # client.identify().await?;
    /// client.topic("#chaos", Some("main channel")).await?;
    /// # Ok(())
    /// ```
    /// # Errors
    /// Returns IO errors from the TcpStream.
    TOPIC(
        /// Channel
        String,
        /// Topic
        Option<String>,
    ),
    #[doc(hidden)]
    USER(String, String, String, String),
}

impl Command {
    /// Creates a Command from a `&str`. Currently only `[PING]` and `[PRIVMSG]` are supported.
    ///
    /// # Panics
    /// This function will panic if the ``IRCd`` sends malformed messages. Please contact the
    /// maintainer of your ``IRCd`` if this happens.
    pub async fn command_from_str(s: &str) -> Self {
        let new = s.trim();
        tracing::trace!("{}", new);
        let parts: Vec<&str> = new.split_whitespace().collect();

        if parts.get(0) == Some(&"PING") {
            // We can assume that [1] exists because if it doesn't then something's gone very wrong
            // with the IRCD
            let command = parts[1].to_string();
            return Self::PING(command);
        } else if parts.get(1) == Some(&"PRIVMSG") {
            let nick_realname = parts[0];
            let nick: String;

            let index = nick_realname.chars().position(|c| c == '!');
            if let Some(index) = index {
                if index > 0 {
                    nick = String::from(&nick_realname[1..index]);
                } else {
                    nick = String::new();
                }
            } else {
                nick = String::new();
            }

            let target = parts[2];
            let msg = parts[3..].join(" ");

            return Self::PRIVMSG(nick, target.to_string(), (msg[1..]).to_string());
        }

        Self::OTHER(new.to_string())
    }
}