Compare commits

...

3 commits

Author SHA1 Message Date
famfo f336537670 Updated command parser 2022-01-11 18:50:44 +01:00
famfo 041922dae8 Improved command parser 2022-01-11 14:31:05 +01:00
famfo 9be9af0a8b Implemented some more commands 2022-01-11 11:16:06 +01:00
2 changed files with 56 additions and 67 deletions

View file

@ -109,8 +109,8 @@ pub enum Command {
NAMES(
/// Channel
String,
/// Server to foreward request to
Option<String>,
/// User
String,
),
/// Change your nickname on a server.
/// ```run_fut
@ -164,15 +164,8 @@ pub enum Command {
/// ```
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(())
/// ```
PONG(String, String),
/// Message send in a channel
PRIVMSG(
/// Source Nickname
String,
@ -219,59 +212,75 @@ pub enum Command {
/// Topic
String,
),
#[doc(hidden)]
TopicBy(String, String),
/// User the set the topic in a channel at a time
TOPIC_BY(String, String),
#[doc(hidden)]
USER(String, String, String, String),
}
impl Command {
/// Creates a Command from a `&str`. Currently only `[PING]` and `[PRIVMSG]` are supported.
/// Creates a Command from a `&str`. Currently `[PRIVMSG]` `[TOPIC]` `[NAMES]` and `[PONG]` 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 {
pub async fn command_from_str(s: String) -> 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]);
return Self::PING(command);
}
match 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();
}
} else {
nick = String::new();
let target = parts[2];
let msg = parts[3..].join(" ");
Self::PRIVMSG(nick, target.to_string(), (msg[1..]).to_string())
}
Some(&"331") | Some(&"332") => {
let channel = parts[3];
let topic = parts[4..].join(" ");
let target = parts[2];
let msg = parts[3..].join(" ");
Self::TOPIC(channel.to_string(), (topic[1..]).to_string())
}
Some(&"333") => {
let user = parts[4];
let time = parts[5];
return Self::PRIVMSG(nick, target.to_string(), (msg[1..]).to_string());
} else if parts.get(1) == Some(&"332") {
let channel = parts[3];
let topic = parts[4..].join(" ");
Self::TOPIC_BY(user.to_string(), time.to_string())
}
Some(&"353") => {
let channel = parts[4];
let user = parts[5..].join(" ");
return Self::TOPIC(channel.to_string(), topic.to_string());
} else if parts.get(1) == Some(&"333") {
let user = parts[4];
let time = parts[5];
Self::NAMES(channel.to_string(), (user[1..]).to_string())
}
Some(&"PONG") => {
let pong = parts[2];
let server = parts[3];
return Self::TopicBy(user.to_string(), time.to_string());
Self::PONG(pong.to_string(), (server[1..]).to_string())
}
_ => Self::OTHER(new.to_string()),
}
Self::OTHER(new.to_string())
}
}

View file

@ -24,7 +24,7 @@
//! is structured) see the [examples](https://git.karx.xyz/circe/async-circe/src/branch/master/examples) folder on our git.
#![warn(missing_docs)] // We want everything documented
#![allow(clippy::needless_return)] // Wants to remove a return statement, but when it's removed the code doesn't compile
#![allow(clippy::needless_return, non_camel_case_types)] // Wants to remove a return statement, but when it's removed the code doesn't compile
#![feature(doc_cfg)]
use tokio::io::BufReader;
@ -216,15 +216,14 @@ impl Client {
/// Returns IO errors from the TcpStream.
pub async fn read(&mut self) -> Result<Option<commands::Command>, tokio::io::Error> {
if let Some(string) = self.read_string().await? {
let command = commands::Command::command_from_str(&string).await;
let command = commands::Command::command_from_str(string).await;
if let commands::Command::PING(command) = command {
if let Err(_e) = self.pong(&command).await {
return Ok(None);
}
return Ok(Some(commands::Command::PONG("".to_string())));
return Ok(Some(commands::Command::PING("".to_string())));
}
return Ok(Some(command));
}
@ -474,7 +473,7 @@ impl Client {
/// # Errors
/// Returns IO errors from the TcpStream.
pub async fn privmsg(&mut self, channel: &str, message: &str) -> Result<(), Error> {
self.write(format!("PRIVMSG {} {}\r\n", channel, message))
self.write(format!("PRIVMSG {} :{}\r\n", channel, message))
.await?;
Ok(())
}
@ -527,34 +526,15 @@ impl Client {
/// ```
/// # Errors
/// Returns IO errors from the TcpStream.
pub async fn topic(
&mut self,
channel: &str,
topic: Option<&str>,
) -> Result<(String, String, String, String), Error> {
pub async fn topic(&mut self, channel: &str, topic: Option<&str>) -> Result<(), Error> {
if let Some(topic) = topic {
self.write(format!("TOPIC {} :{}\r\n", channel, topic))
.await?;
return Ok((String::new(), String::new(), String::new(), String::new()));
} else {
// Can we make this more efficient? Yes! But how?
self.write(format!("TOPIC {}\r\n", channel)).await?;
let mut channel_channel = String::new();
let mut channel_topic = String::new();
if let Some(command) = self.read().await? {
if let commands::Command::TOPIC(channel, topic) = command {
channel_channel = channel;
channel_topic = topic;
}
}
let mut topic_return = (String::new(), String::new(), String::new(), String::new());
if let Some(command) = self.read().await? {
if let commands::Command::TopicBy(user, time) = command {
topic_return = (channel_channel, channel_topic, user, time);
}
}
return Ok(topic_return);
}
Ok(())
}
#[doc(hidden)]