First chat implementation

This commit is contained in:
Julian Mutter 2023-05-07 16:08:07 +02:00
commit 0c0fc8e227
5 changed files with 120 additions and 0 deletions

20
.gitignore vendored Normal file
View File

@ -0,0 +1,20 @@
.DS_Store
.idea
*.log
tmp/
### Rust ###
# Generated by Cargo
# will have compiled files and executables
debug/
target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb

11
nats-client/Cargo.toml Normal file
View File

@ -0,0 +1,11 @@
[package]
name = "nats-client"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nats = "0.24.0"
serde = "1.0.162"
serde_json = "1.0.96"

86
nats-client/src/main.rs Normal file
View File

@ -0,0 +1,86 @@
use std::{
fmt::{self, Display},
io::{self, BufRead},
};
use nats::Connection;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct Message {
author: String,
message: String,
}
impl Display for Message {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Message from {}: {}", self.author, self.message)
}
}
const SUBJECT_MESSAGES: &str = "here.happens.messaging";
fn main() -> io::Result<()> {
let nc = nats::connect("127.0.0.1")?;
let username = ask_user_name();
println!(
"Hello {}, please write your message. Use q to quit:",
username
);
let my_username = username.clone();
let sub = nc.subscribe(SUBJECT_MESSAGES)?.with_handler(move |msg| {
// This runs in a separate Thread
let message: Message = serde_json::from_str(&String::from_utf8(msg.data).unwrap()).unwrap();
// Do not show messages from me
if message.author != my_username {
println!("Received {}", message);
}
Ok(())
});
let stdin = io::stdin();
for line in stdin.lock().lines() {
let line = line.unwrap();
let line = line.trim();
if line.is_empty() {
continue;
}
if line == "q" || line == "Q" {
break;
}
publish_message(
&Message {
author: username.clone(),
message: line.to_string(),
},
&nc,
)?;
}
sub.unsubscribe()?;
Ok(())
}
fn publish_message(message: &Message, nc: &Connection) -> io::Result<()> {
let json_string_utf8 = serde_json::to_string(message).expect("Cannot serialize message");
nc.publish(SUBJECT_MESSAGES, json_string_utf8)?;
Ok(())
}
fn ask_user_name() -> String {
println!("Please enter your username: ");
let mut input_text = String::new();
io::stdin()
.read_line(&mut input_text)
.expect("Failed reading from stdin");
input_text = input_text.trim().to_string();
if input_text.is_empty() {
println!("Your input was empty. Please try again.");
return ask_user_name();
}
input_text
}

View File

3
nats-server/run.sh Executable file
View File

@ -0,0 +1,3 @@
#!/usr/bin/env sh
docker run -p 4222:4222 -t nats:latest