<commit_before>//! Utilities and shortcuts for working with IRC servers.
use std::io::Result;
use std::borrow::ToOwned;
use client::data::{Capability, NegotiationVersion};
use client::data::Command::{CAP, INVITE, JOIN, KICK, KILL, MODE, NICK, NOTICE};
use client::data::Command::{OPER, PASS, PONG, PRIVMSG, QUIT, SAMODE, SANICK, TOPIC, USER};
use client::data::command::CapSubCommand::{END, LS, REQ};
use client::data::kinds::{IrcRead, IrcWrite};
#[cfg(feature = "ctcp")] use time::get_time;
use client::server::Server;

/// Extensions for Server capabilities that make it easier to work directly with the protocol.
pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
    /// Sends a request for a list of server capabilities for a specific IRCv3 version.
    fn send_cap_ls(&self, version: NegotiationVersion) -> Result<()> where Self: Sized {
        self.send(CAP(None, LS, match version {
            NegotiationVersion::V301 => None,
            NegotiationVersion::V302 => Some("302".to_owned()),
        }, None))
    }

    /// Sends an IRCv3 capabilities request for the specified extensions.
    fn send_cap_req(&self, extensions: &[Capability]) -> Result<()> where Self: Sized {
        let append = |mut s: String, c| { s.push_str(c); s.push(' '); s };
        let mut exts = extensions.iter().map(|c| c.as_ref()).fold(String::new(), append);
        let len = exts.len() - 1;
        exts.truncate(len);
        self.send(CAP(None, REQ, None, Some(exts)))
    }

    /// Sends a CAP END, NICK and USER to identify.
    fn identify(&self) -> Result<()> where Self: Sized {
        // Send a CAP END to signify that we're IRCv3-compliant (and to end negotiations!).
        try!(self.send(CAP(None, END, None, None)));
        if self.config().password() != "" {
            try!(self.send(PASS(self.config().password().to_owned())));
        }
        try!(self.send(NICK(self.config().nickname().to_owned())));
        try!(self.send(USER(self.config().username().to_owned(), "0".to_owned(),
                            self.config().real_name().to_owned())));
        Ok(())
    }

    /// Sends a PONG with the specified message.
    fn send_pong(&self, msg: &str) -> Result<()> where Self: Sized {
        self.send(PONG(msg.to_owned(), None))
    }

    /// Joins the specified channel or chanlist.
    fn send_join(&self, chanlist: &str) -> Result<()> where Self: Sized {
        self.send(JOIN(chanlist.to_owned(), None, None))
    }

    /// Attempts to oper up using the specified username and password.
    fn send_oper(&self, username: &str, password: &str) -> Result<()> where Self: Sized {
        self.send(OPER(username.to_owned(), password.to_owned()))
    }

    /// Sends a message to the specified target.
    fn send_privmsg(&self, target: &str, message: &str) -> Result<()> where Self: Sized {
        for line in message.split("\r\n") {
            try!(self.send(PRIVMSG(target.to_owned(), line.to_owned())))<commit_msg>Added utility functions to help with SASL.<commit_after>//! Utilities and shortcuts for working with IRC servers.
use std::io::Result;
use std::borrow::ToOwned;
use client::data::{Capability, NegotiationVersion};
use client::data::Command::{AUTHENTICATE, CAP, INVITE, JOIN, KICK, KILL, MODE, NICK, NOTICE};
use client::data::Command::{OPER, PASS, PONG, PRIVMSG, QUIT, SAMODE, SANICK, TOPIC, USER};
use client::data::command::CapSubCommand::{END, LS, REQ};
use client::data::kinds::{IrcRead, IrcWrite};
#[cfg(feature = "ctcp")] use time::get_time;
use client::server::Server;

/// Extensions for Server capabilities that make it easier to work directly with the protocol.
pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
    /// Sends a request for a list of server capabilities for a specific IRCv3 version.
    fn send_cap_ls(&self, version: NegotiationVersion) -> Result<()> where Self: Sized {
        self.send(CAP(None, LS, match version {
            NegotiationVersion::V301 => None,
            NegotiationVersion::V302 => Some("302".to_owned()),
        }, None))
    }

    /// Sends an IRCv3 capabilities request for the specified extensions.
    fn send_cap_req(&self, extensions: &[Capability]) -> Result<()> where Self: Sized {
        let append = |mut s: String, c| { s.push_str(c); s.push(' '); s };
        let mut exts = extensions.iter().map(|c| c.as_ref()).fold(String::new(), append);
        let len = exts.len() - 1;
        exts.truncate(len);
        self.send(CAP(None, REQ, None, Some(exts)))
    }

    /// Sends a CAP END, NICK and USER to identify.
    fn identify(&self) -> Result<()> where Self: Sized {
        // Send a CAP END to signify that we're IRCv3-compliant (and to end negotiations!).
        try!(self.send(CAP(None, END, None, None)));
        if self.config().password() != "" {
            try!(self.send(PASS(self.config().password().to_owned())));
        }
        try!(self.send(NICK(self.config().nickname().to_owned())));
        try!(self.send(USER(self.config().username().to_owned(), "0".to_owned(),
                            self.config().real_name().to_owned())));
        Ok(())
    }

    /// Sends a SASL AUTHENTICATE message with the specified data.
    fn send_sasl(&self, data: &str) -> Result<()> where Self: Sized {
        self.send(AUTHENTICATE(data.to_owned()))
    }

    /// Sends a SASL AUTHENTICATE request to use the PLAIN mechanism.
    fn send_sasl_plain(&self) -> Result<()> where Self: Sized {
        self.send_sasl("PLAIN")
    }


    /// Sends a SASL AUTHENTICATE request to use the EXTERNAL mechanism.
    fn send_sasl_external(&self) -> Result<()> where Self: Sized {
        self.send_sasl("EXTERNAL")
    }

    /// Sends a SASL AUTHENTICATE request to abort authentication.
    fn send_sasl_abort(&self) -> Result<()> where Self: Sized {
        self.send_sasl("*")
    }

    /// Sends a PONG with the specified message.
    fn send_pong(&self, msg: &str) -> Result<()> where Self: Sized {
        self.send(PONG(msg.to_owned(), None))
    }

    /// Joins the specified channel or chanlist.
    fn send_join(&self, chanlist: &str) -> Result<()> where Self: Sized {
        self.send(JOIN(chanlist.to_owned(), None, None))
    }

    /// Attempts to oper up using the specified username and password.
    fn send_oper(&self, username: &str, password: &str) -> Result<()> where Self: Sized {
        self.send(OPER(username.to_owned(), password.to_owned()))
    }

    /// Sends a message to the specified target.
    fn send_privmsg(&self, target: &str, message: &str) -> Result<()> where Self: Sized {
        for line in message.split("\r\n") {
            try!(self.send(PRIVMSG(target.to_owned(), line.to_owned())))
{'fraction_non_alphanumeric': 0.16281512605042017, 'fraction_numerical': 0.004201680672268907, 'mean_word_length': 3.139751552795031, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6481430', 'n_tokens_mistral': 2197, 'n_tokens_neox': 2134, 'n_words': 595}