Skip to content

Commit

Permalink
Save last 10 messages in channel
Browse files Browse the repository at this point in the history
  • Loading branch information
bkolobara committed Feb 6, 2021
1 parent 15ed829 commit b7a6b30
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 18 deletions.
10 changes: 10 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ telnet lunatic.chat
telnet eu.lunatic.chat
```

You should pick the one closer to you as all the rendering is done on the backend and lower latency
will mean better UX.

### Architecture

The server is written in Rust. The Rust code is then compiled to WebAssembly and runs on top of
Lunatic. Each connection runs in a separate (lightweight) process, has it's own state and sends
just a diff of esc-sequences back to the terminal to bring it up to date with the current render
buffer.

### Build & run instructions

TODO
Expand Down
20 changes: 16 additions & 4 deletions src/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ use crate::client::ClientMessage;
pub enum ChannelMessage {
Join(String, Sender<ChannelMessage>),
// channel name, sender, id_sender
Subscribe(String, Sender<ClientMessage>, Sender<u32>),
Subscribe(
String,
Sender<ClientMessage>,
Sender<(u32, Vec<(String, String, String)>)>,
),
// Channel name, username
Joined(String, String),
// Channel name, username, message
Message(String, String, String),
Message(String, String, String, String),
// Client with id left
Unsubscribe(u32),
// Assign id to client
Expand All @@ -23,12 +27,13 @@ pub enum ChannelMessage {
pub fn channel_process((channel_name, channel_receiver): (String, Receiver<ChannelMessage>)) {
let mut clients = HashMap::new();
let mut id_generator: u32 = 0;
let mut last_messages = Vec::new();
loop {
if let Ok(message) = channel_receiver.receive() {
match message {
ChannelMessage::Subscribe(name, client, id_sender) => {
clients.insert(id_generator, client.clone());
let _ = id_sender.send(id_generator);
let _ = id_sender.send((id_generator, last_messages.clone()));
id_generator += 1;

// Notify all participants about the new join
Expand All @@ -47,12 +52,19 @@ pub fn channel_process((channel_name, channel_receiver): (String, Receiver<Chann
}
}

ChannelMessage::Message(_, name, message) => {
ChannelMessage::Message(_, timestamp, name, message) => {
// Save
last_messages.push((timestamp.clone(), name.clone(), message.clone()));
// If too many last messages, drain
if last_messages.len() > 10 {
last_messages.drain(0..5);
}
// Broadcast
for (_id, client) in clients.iter() {
let _ =
client.send(ClientMessage::ChannelMessage(ChannelMessage::Message(
channel_name.clone(),
timestamp.clone(),
name.clone(),
message.clone(),
)));
Expand Down
32 changes: 22 additions & 10 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,12 @@ pub fn client_process((central_server, tcp_stream): (Sender<ServerMessage>, TcpS

let mut ui = Ui::new(tcp_stream, window_size.clone(), tabs.clone());
loop {
match interrupt_listener.receive().unwrap() {
let interrupt = if let Ok(interrupt) = interrupt_listener.receive() {
interrupt
} else {
break;
};
match interrupt {
// Handle commands coming from tcp
ClientMessage::Telnet(command) => match command {
CtrlC => {
Expand Down Expand Up @@ -161,7 +166,11 @@ pub fn client_process((central_server, tcp_stream): (Sender<ServerMessage>, TcpS
ui.render();
}
"/join" => {
let channel = split.next().unwrap();
let channel = if let Some(channel) = split.next() {
channel
} else {
continue;
};
if channel.starts_with("#") {
// Request channel from server
let (channel_lookup, channel_rcv) = bounded(1);
Expand All @@ -182,12 +191,12 @@ pub fn client_process((central_server, tcp_stream): (Sender<ServerMessage>, TcpS
))
.unwrap();
// Wait on channel to assign an id to client
let id = id_receiver.receive().unwrap();
let (id, last_messages) = id_receiver.receive().unwrap();
// Create new tab bound to channel
let tab = Tab::new(
channel.to_string(),
Some((id, channel_notify)),
TabType::Channel(Vec::new()),
TabType::Channel(last_messages),
);
tabs.add(tab);
ui.render();
Expand All @@ -202,9 +211,14 @@ pub fn client_process((central_server, tcp_stream): (Sender<ServerMessage>, TcpS
}
} else {
// Send to channel
if input.len() > 0 {
tabs.get_selected()
.message(username.clone(), input.to_string());
if input.len() > 0 && input.len() < 300 {
let now: DateTime<Local> = Local::now();
let timestamp = format!("[{}] ", now.format("%H:%M UTC"));
tabs.get_selected().message(
timestamp.clone(),
username.clone(),
input.to_string(),
);
}
}
ui.render();
Expand All @@ -218,9 +232,7 @@ pub fn client_process((central_server, tcp_stream): (Sender<ServerMessage>, TcpS

// Handle messages coming from channels
ClientMessage::ChannelMessage(message) => match message {
ChannelMessage::Message(channel, name, message) => {
let now: DateTime<Local> = Local::now();
let timestamp = format!("[{}] ", now.format("%H:%M UTC"));
ChannelMessage::Message(channel, timestamp, name, message) => {
tabs.add_message(channel, timestamp, name, message);
ui.render();
}
Expand Down
9 changes: 7 additions & 2 deletions src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,10 +309,15 @@ impl Tab {
self.input.push(ch);
}

pub fn message(&self, user: String, message: String) {
pub fn message(&self, timestamp: String, user: String, message: String) {
if let Some((_id, notifier)) = &self.notifier {
notifier
.send(ChannelMessage::Message("".to_string(), user, message))
.send(ChannelMessage::Message(
"".to_string(),
timestamp,
user,
message,
))
.unwrap();
}
}
Expand Down
5 changes: 3 additions & 2 deletions templates/instructions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

PRIVACY:

No data is stored on the server. Once the server shuts off all information
will be gone.
No data is stored on the server. Only the last 10 messages per channel
are kept in memory to bring new users up to date. Once the server shuts
off all information will be gone.

INSTRUCTIONS:

Expand Down

0 comments on commit b7a6b30

Please sign in to comment.