Use current nickname instead of hardcoded value
This commit is contained in:
parent
8065fdd8ff
commit
63b04208d0
3 changed files with 97 additions and 83 deletions
|
@ -1,12 +1,15 @@
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
|
use irc::proto::Capability;
|
||||||
use tokio::{
|
use tokio::{
|
||||||
select,
|
select,
|
||||||
sync::mpsc::{UnboundedReceiver, UnboundedSender},
|
sync::mpsc::{UnboundedReceiver, UnboundedSender},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub async fn connect() -> Result<irc::client::Client> {
|
pub async fn connect() -> Result<irc::client::Client> {
|
||||||
Ok(irc::client::Client::new("config.toml").await?)
|
let client = irc::client::Client::new("config.toml").await?;
|
||||||
|
client.send_cap_req(&[Capability::EchoMessage, Capability::ServerTime])?;
|
||||||
|
Ok(client)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn message_loop(
|
pub async fn message_loop(
|
||||||
|
@ -21,13 +24,13 @@ pub async fn message_loop(
|
||||||
select! {
|
select! {
|
||||||
val = irc_stream.next() => {
|
val = irc_stream.next() => {
|
||||||
if let Some(message) = val.transpose()? {
|
if let Some(message) = val.transpose()? {
|
||||||
print!("[Rx] {message}");
|
println!("[Rx] {} {:?}", message.to_string().trim(), message.tags);
|
||||||
message_tx.send(message)?;
|
message_tx.send(message)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val = input_rx.recv() => {
|
val = input_rx.recv() => {
|
||||||
let message = val.unwrap();
|
let message = val.unwrap();
|
||||||
print!("[Tx] {message}");
|
println!("[Tx] {} {:?}", message.to_string().trim(), message.tags);
|
||||||
client.send(message)?;
|
client.send(message)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
152
src/main.rs
152
src/main.rs
|
@ -11,7 +11,7 @@ use iced::{
|
||||||
widget::{column, container, mouse_area, row, text, text_input},
|
widget::{column, container, mouse_area, row, text, text_input},
|
||||||
Application, Background, Color, Element, Length, Settings,
|
Application, Background, Color, Element, Length, Settings,
|
||||||
};
|
};
|
||||||
use irc::proto::Command as IrcCommand;
|
use irc::proto::{Command as IrcCommand, Response};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
|
use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
|
||||||
|
@ -56,6 +56,7 @@ struct Cri {
|
||||||
input_tx: RefCell<UnboundedSender<irc::proto::Message>>,
|
input_tx: RefCell<UnboundedSender<irc::proto::Message>>,
|
||||||
message_log: MessageLog,
|
message_log: MessageLog,
|
||||||
input_value: String,
|
input_value: String,
|
||||||
|
nickname: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cri {
|
impl Cri {
|
||||||
|
@ -63,15 +64,6 @@ impl Cri {
|
||||||
if let Some(active_channel) = &self.message_log.active_channel {
|
if let Some(active_channel) = &self.message_log.active_channel {
|
||||||
let command = IrcCommand::PRIVMSG(active_channel.to_string(), input_value.to_string());
|
let command = IrcCommand::PRIVMSG(active_channel.to_string(), input_value.to_string());
|
||||||
let message: irc::proto::Message = command.into();
|
let message: irc::proto::Message = command.into();
|
||||||
|
|
||||||
self.message_log
|
|
||||||
.get_mut(self.message_log.active_channel.clone())
|
|
||||||
.messages
|
|
||||||
.push(IrcMessage::Privmsg {
|
|
||||||
nickname: String::from("cri"),
|
|
||||||
message: input_value.to_string(),
|
|
||||||
});
|
|
||||||
|
|
||||||
self.input_tx.borrow().send(message.clone()).unwrap();
|
self.input_tx.borrow().send(message.clone()).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,66 +73,69 @@ impl Cri {
|
||||||
|
|
||||||
let command = tokens.next().unwrap();
|
let command = tokens.next().unwrap();
|
||||||
match command {
|
match command {
|
||||||
"/join" => {
|
"/join" => self.handle_join_command(&mut tokens),
|
||||||
let channel = tokens
|
"/part" => self.handle_part_command(&mut tokens),
|
||||||
.next()
|
"/query" => self.handle_query_command(tokens),
|
||||||
.map(str::to_string)
|
|
||||||
.or_else(|| self.message_log.active_channel.clone());
|
|
||||||
if channel.is_none() {
|
|
||||||
// TODO error message
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let channel = channel.unwrap();
|
|
||||||
if !channel.starts_with('#') {
|
|
||||||
// TODO error message
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.input_tx
|
|
||||||
.borrow()
|
|
||||||
.send(
|
|
||||||
IrcCommand::JOIN(channel.clone(), tokens.next().map(str::to_string), None)
|
|
||||||
.into(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
self.message_log.set_active(Some(channel));
|
|
||||||
}
|
|
||||||
"/part" => {
|
|
||||||
let channel = tokens
|
|
||||||
.next()
|
|
||||||
.map(str::to_string)
|
|
||||||
.or_else(|| self.message_log.active_channel.clone());
|
|
||||||
if channel.is_none() {
|
|
||||||
// TODO error message
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let channel = channel.unwrap();
|
|
||||||
if !channel.starts_with('#') {
|
|
||||||
// TODO error message
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let reason = tokens.collect::<Vec<_>>().join(" ");
|
|
||||||
let reason = if reason.is_empty() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(reason)
|
|
||||||
};
|
|
||||||
|
|
||||||
self.input_tx
|
|
||||||
.borrow()
|
|
||||||
.send(IrcCommand::PART(channel, reason).into())
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
"/query" => self
|
|
||||||
.message_log
|
|
||||||
.set_active(Some(tokens.next().unwrap().to_string())),
|
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_part_command(&mut self, tokens: &mut std::str::SplitWhitespace<'_>) {
|
||||||
|
let channel = tokens
|
||||||
|
.next()
|
||||||
|
.map(str::to_string)
|
||||||
|
.or_else(|| self.message_log.active_channel.clone());
|
||||||
|
if channel.is_none() {
|
||||||
|
// TODO error message
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let channel = channel.unwrap();
|
||||||
|
if !channel.starts_with('#') {
|
||||||
|
// TODO error message
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let reason = tokens.collect::<Vec<_>>().join(" ");
|
||||||
|
let reason = if reason.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(reason)
|
||||||
|
};
|
||||||
|
|
||||||
|
self.input_tx
|
||||||
|
.borrow()
|
||||||
|
.send(IrcCommand::PART(channel, reason).into())
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_join_command(&mut self, tokens: &mut std::str::SplitWhitespace<'_>) {
|
||||||
|
let channel = tokens
|
||||||
|
.next()
|
||||||
|
.map(str::to_string)
|
||||||
|
.or_else(|| self.message_log.active_channel.clone());
|
||||||
|
if channel.is_none() {
|
||||||
|
// TODO error message
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let channel = channel.unwrap();
|
||||||
|
if !channel.starts_with('#') {
|
||||||
|
// TODO error message
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.input_tx
|
||||||
|
.borrow()
|
||||||
|
.send(IrcCommand::JOIN(channel.clone(), tokens.next().map(str::to_string), None).into())
|
||||||
|
.unwrap();
|
||||||
|
self.message_log.set_active(Some(channel));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_query_command(&mut self, mut tokens: std::str::SplitWhitespace<'_>) {
|
||||||
|
self.message_log
|
||||||
|
.set_active(Some(tokens.next().unwrap().to_string()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for Cri {
|
impl Application for Cri {
|
||||||
|
@ -156,6 +151,7 @@ impl Application for Cri {
|
||||||
input_tx: RefCell::new(flags.input_tx),
|
input_tx: RefCell::new(flags.input_tx),
|
||||||
message_log: MessageLog::new(),
|
message_log: MessageLog::new(),
|
||||||
input_value: String::new(),
|
input_value: String::new(),
|
||||||
|
nickname: "cri".to_string(), // TODO take default value from config
|
||||||
},
|
},
|
||||||
iced::Command::none(),
|
iced::Command::none(),
|
||||||
)
|
)
|
||||||
|
@ -169,7 +165,10 @@ impl Application for Cri {
|
||||||
match message {
|
match message {
|
||||||
UiMessage::IrcMessageReceived(message) => {
|
UiMessage::IrcMessageReceived(message) => {
|
||||||
// TODO use actual nickname
|
// TODO use actual nickname
|
||||||
let source_nickname = message.source_nickname().unwrap_or("cri").to_string();
|
let source_nickname = message
|
||||||
|
.source_nickname()
|
||||||
|
.unwrap_or(&self.nickname)
|
||||||
|
.to_string();
|
||||||
|
|
||||||
match &message.command {
|
match &message.command {
|
||||||
IrcCommand::JOIN(chanlist, _, _) => {
|
IrcCommand::JOIN(chanlist, _, _) => {
|
||||||
|
@ -190,12 +189,19 @@ impl Application for Cri {
|
||||||
.on_quit(&source_nickname, comment.as_deref());
|
.on_quit(&source_nickname, comment.as_deref());
|
||||||
}
|
}
|
||||||
|
|
||||||
IrcCommand::PRIVMSG(msgtarget, content) | IrcCommand::NOTICE(msgtarget, content) => {
|
IrcCommand::PRIVMSG(msgtarget, content)
|
||||||
|
| IrcCommand::NOTICE(msgtarget, content) => {
|
||||||
let channel = message.response_target().unwrap_or(msgtarget).to_string();
|
let channel = message.response_target().unwrap_or(msgtarget).to_string();
|
||||||
self.message_log
|
self.message_log.on_privmsg(
|
||||||
.on_privmsg(&channel, &source_nickname, content);
|
&self.nickname,
|
||||||
|
&channel,
|
||||||
|
&source_nickname,
|
||||||
|
content,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
IrcCommand::Response(Response::RPL_WELCOME, args) => {
|
||||||
|
self.nickname = args[0].clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => self.message_log.on_other(&message.to_string()),
|
_ => self.message_log.on_other(&message.to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,7 +238,7 @@ impl Application for Cri {
|
||||||
let light_blue = Color::new(0.26, 0.62, 0.85, 1.0);
|
let light_blue = Color::new(0.26, 0.62, 0.85, 1.0);
|
||||||
let light_red = Color::new(0.99, 0.36, 0.40, 1.0);
|
let light_red = Color::new(0.99, 0.36, 0.40, 1.0);
|
||||||
|
|
||||||
let log = self.message_log.view(&self.message_log.active_channel);
|
let log = self.message_log.view(&self.nickname);
|
||||||
|
|
||||||
let message_box = text_input("your magnum opus", &self.input_value)
|
let message_box = text_input("your magnum opus", &self.input_value)
|
||||||
.id(INPUT_ID.clone())
|
.id(INPUT_ID.clone())
|
||||||
|
|
|
@ -94,7 +94,13 @@ impl<'a> MessageLog {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_privmsg(&mut self, channel_name: &str, nickname: &str, message: &str) {
|
pub fn on_privmsg(
|
||||||
|
&mut self,
|
||||||
|
current_nickname: &str,
|
||||||
|
channel_name: &str,
|
||||||
|
nickname: &str,
|
||||||
|
message: &str,
|
||||||
|
) {
|
||||||
let is_active = self.active_channel.as_deref() == Some(channel_name);
|
let is_active = self.active_channel.as_deref() == Some(channel_name);
|
||||||
|
|
||||||
let channel = self.get_mut(Some(channel_name.to_string()));
|
let channel = self.get_mut(Some(channel_name.to_string()));
|
||||||
|
@ -104,8 +110,8 @@ impl<'a> MessageLog {
|
||||||
});
|
});
|
||||||
|
|
||||||
if !is_active {
|
if !is_active {
|
||||||
// TODO Configurable nickname
|
let highlight_regex =
|
||||||
let highlight_regex = Regex::new(r"\bcri\b").unwrap();
|
Regex::new(&format!(r"\b{}\b", regex::escape(current_nickname))).unwrap();
|
||||||
if highlight_regex.is_match(message) {
|
if highlight_regex.is_match(message) {
|
||||||
channel.unread_highlights += 1;
|
channel.unread_highlights += 1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -128,7 +134,7 @@ impl<'a> MessageLog {
|
||||||
channel.unread_highlights = 0;
|
channel.unread_highlights = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view(&self, active_channel: &Option<String>) -> Container<'_, crate::UiMessage> {
|
pub fn view(&self, current_nickname: &str) -> Container<'_, crate::UiMessage> {
|
||||||
let lighter_grey = Color::new(0.93, 0.94, 0.95, 1.0);
|
let lighter_grey = Color::new(0.93, 0.94, 0.95, 1.0);
|
||||||
let dark_grey = Color::new(0.58, 0.65, 0.65, 1.0);
|
let dark_grey = Color::new(0.58, 0.65, 0.65, 1.0);
|
||||||
let lighter_green = Color::new(0.94, 0.99, 0.87, 1.0);
|
let lighter_green = Color::new(0.94, 0.99, 0.87, 1.0);
|
||||||
|
@ -154,7 +160,7 @@ impl<'a> MessageLog {
|
||||||
};
|
};
|
||||||
|
|
||||||
let messages = self
|
let messages = self
|
||||||
.get(active_channel)
|
.get(&self.active_channel)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.messages
|
.messages
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -218,8 +224,7 @@ impl<'a> MessageLog {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
IrcMessage::Privmsg { nickname, message } => {
|
IrcMessage::Privmsg { nickname, message } => {
|
||||||
// TODO don't hardcode nickname lol
|
let is_self = nickname == current_nickname;
|
||||||
let is_self = nickname == "cri";
|
|
||||||
|
|
||||||
let mut elements = Vec::new();
|
let mut elements = Vec::new();
|
||||||
if !is_self {
|
if !is_self {
|
||||||
|
|
Loading…
Reference in a new issue