Basics working.
This commit is contained in:
parent
686d1d74fe
commit
65086a3b3c
1 changed files with 146 additions and 19 deletions
165
src/main.rs
165
src/main.rs
|
@ -1,13 +1,13 @@
|
||||||
#![feature(random)]
|
#![feature(random)]
|
||||||
#![feature(inline_const_pat)]
|
#![feature(inline_const_pat)]
|
||||||
|
|
||||||
use std::io::prelude::*;
|
use std::io::{ErrorKind, prelude::*};
|
||||||
use std::net::{TcpListener, TcpStream};
|
use std::net::{TcpListener, TcpStream};
|
||||||
use std::random;
|
use std::random;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::thread::{self, sleep};
|
use std::thread::{self, JoinHandle, sleep};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, PartialEq, Eq)]
|
||||||
enum UserStatus {
|
enum UserStatus {
|
||||||
ONLINE,
|
ONLINE,
|
||||||
DISCONNECTED,
|
DISCONNECTED,
|
||||||
|
@ -18,10 +18,10 @@ enum UserStatus {
|
||||||
impl UserStatus {
|
impl UserStatus {
|
||||||
fn get_status_string(&self) -> String {
|
fn get_status_string(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
UserStatus::ONLINE => "\x1b[0m\x1b[32mOnline\x1b[0m".to_string(),
|
UserStatus::ONLINE => "\x1b[0m\x1b[32monline\x1b[0m".to_string(),
|
||||||
UserStatus::IDLE => "\x1b[0m\x1b[33mIdle\x1b[0m".to_string(),
|
UserStatus::IDLE => "\x1b[0m\x1b[33midle\x1b[0m".to_string(),
|
||||||
UserStatus::DISCONNECTED => "\x1b[0m\x1b[31mDisconnected\x1b[0m".to_string(),
|
UserStatus::DISCONNECTED => "\x1b[0m\x1b[31mdisconnected\x1b[0m".to_string(),
|
||||||
UserStatus::CUSTOM(val) => format!("\x1b[0m\x1b[34m{}\x1b[0m", val)
|
UserStatus::CUSTOM(val) => format!("\x1b[0m\x1b[34m{}\x1b[0m", val),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ fn handle_client(mut stream: TcpStream, channel: Channel) {
|
||||||
let mut buf = [0u8; 30];
|
let mut buf = [0u8; 30];
|
||||||
let mut i = 0usize;
|
let mut i = 0usize;
|
||||||
let mut buf1 = [0u8];
|
let mut buf1 = [0u8];
|
||||||
while buf1[0] != b'\n' || i == 0 {
|
'bufreadloop: while buf1[0] != b'\n' || i == 0 {
|
||||||
stream.read_exact(&mut buf1).unwrap();
|
stream.read_exact(&mut buf1).unwrap();
|
||||||
if buf1[0] == b'\n' && i == 0 {
|
if buf1[0] == b'\n' && i == 0 {
|
||||||
stream.write_all(
|
stream.write_all(
|
||||||
|
@ -73,6 +73,19 @@ fn handle_client(mut stream: TcpStream, channel: Channel) {
|
||||||
i = 0;
|
i = 0;
|
||||||
continue;
|
continue;
|
||||||
} else if buf1[0] == b'\n' {
|
} else if buf1[0] == b'\n' {
|
||||||
|
for user in &channel.lock().unwrap().online_users {
|
||||||
|
if user.name == String::from_utf8_lossy(&(buf[..i])).to_string()
|
||||||
|
&& user.status != UserStatus::DISCONNECTED
|
||||||
|
{
|
||||||
|
stream.write_all(
|
||||||
|
b"\x1b[0m\x1b[31;1mSorry, but that nickname is taken.\n\x1b[0m\x1b[33mEnter your chosen nickname(up to 30 characters):\x1b[0m\x1b[4m\n"
|
||||||
|
).unwrap();
|
||||||
|
buf = [0u8; 30];
|
||||||
|
buf1[0] = b'\0';
|
||||||
|
i = 0;
|
||||||
|
continue 'bufreadloop;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if i < 30 {
|
if i < 30 {
|
||||||
|
@ -89,22 +102,34 @@ fn handle_client(mut stream: TcpStream, channel: Channel) {
|
||||||
))
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let user = User {
|
let mut user = User {
|
||||||
name: String::from_utf8_lossy(&(buf[..i])).to_string(),
|
name: String::from_utf8_lossy(&(buf[..i])).to_string(),
|
||||||
status: UserStatus::ONLINE,
|
status: UserStatus::ONLINE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let netbot = User {
|
||||||
|
name: "Netbot".to_owned(),
|
||||||
|
status: UserStatus::ONLINE,
|
||||||
|
};
|
||||||
|
|
||||||
channel.lock().unwrap().online_users.push(user.clone());
|
channel.lock().unwrap().online_users.push(user.clone());
|
||||||
|
|
||||||
|
let (recieve_terminate_send, recieve_terminate_recv) = std::sync::mpsc::channel::<()>();
|
||||||
|
let recieve_thread: JoinHandle<_>;
|
||||||
|
|
||||||
{
|
{
|
||||||
let channel = channel.clone();
|
let channel = channel.clone();
|
||||||
let mut stream = stream.try_clone().unwrap();
|
let mut stream = stream.try_clone().unwrap();
|
||||||
|
|
||||||
let time_format = time::format_description::well_known::Rfc2822;
|
let time_format = time::format_description::well_known::Rfc2822;
|
||||||
|
|
||||||
thread::spawn(move || {
|
recieve_thread = thread::spawn(move || {
|
||||||
let mut current_message_count = channel.lock().unwrap().messages.len();
|
let mut current_message_count = channel.lock().unwrap().messages.len();
|
||||||
loop {
|
loop {
|
||||||
|
if let Ok(_) = recieve_terminate_recv.try_recv() {
|
||||||
|
stream.shutdown(std::net::Shutdown::Both).unwrap();
|
||||||
|
panic!("recieve thread exiting");
|
||||||
|
}
|
||||||
let new_message_count = channel.lock().unwrap().messages.len();
|
let new_message_count = channel.lock().unwrap().messages.len();
|
||||||
if current_message_count != new_message_count {
|
if current_message_count != new_message_count {
|
||||||
let new_messages = &channel.lock().unwrap().messages[current_message_count..];
|
let new_messages = &channel.lock().unwrap().messages[current_message_count..];
|
||||||
|
@ -133,7 +158,27 @@ fn handle_client(mut stream: TcpStream, channel: Channel) {
|
||||||
let mut buf1 = [0u8];
|
let mut buf1 = [0u8];
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
stream.read_exact(&mut buf1).unwrap();
|
if let Err(err) = stream.read_exact(&mut buf1) {
|
||||||
|
if err.kind() == ErrorKind::UnexpectedEof {
|
||||||
|
user.status = UserStatus::DISCONNECTED;
|
||||||
|
for usr in &mut channel.lock().unwrap().online_users {
|
||||||
|
if usr.name == user.name {
|
||||||
|
usr.status = user.status.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
channel.lock().unwrap().messages.push(Message {
|
||||||
|
sender: netbot.clone(),
|
||||||
|
contents: format!("User {} has left.", user.name),
|
||||||
|
timestamp: time::OffsetDateTime::now_local().unwrap(),
|
||||||
|
});
|
||||||
|
|
||||||
|
recieve_terminate_send.send(()).unwrap();
|
||||||
|
let _ = recieve_thread.join();
|
||||||
|
stream.shutdown(std::net::Shutdown::Both).unwrap();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if buf1[0] == b'\x08' {
|
if buf1[0] == b'\x08' {
|
||||||
buf.pop();
|
buf.pop();
|
||||||
|
@ -148,25 +193,107 @@ fn handle_client(mut stream: TcpStream, channel: Channel) {
|
||||||
timestamp: time::OffsetDateTime::now_local().unwrap(),
|
timestamp: time::OffsetDateTime::now_local().unwrap(),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if contents.starts_with("/help") || contents.starts_with("/?") {
|
if contents.split(" ").collect::<Vec<&str>>()[0] == "/help" || contents.split(" ").collect::<Vec<&str>>()[0] == "/?" {
|
||||||
stream
|
stream
|
||||||
.write_all(
|
.write_all(
|
||||||
b"\x1b[0m\x1b[32mValid commands:\n \
|
b"\x1b[0m\x1b[32mValid commands:\n \
|
||||||
/help, /?: Print this help.\n \
|
/help, /?: Print this help.\n \
|
||||||
/status online|idle|disconnected|(any value): Set your status.\n \
|
/status [online|idle|disconnected|(any value)]: Set your status.\n \
|
||||||
/user nick: Get information about a user.\x1b[0m",
|
/user [nick]: Get information about a user.\n \
|
||||||
|
/server [new name]: Get or set the server name.\n \
|
||||||
|
/users: List users.\x1b[0m\n",
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
} else if contents.starts_with("/status") {
|
} else if contents.split(" ").collect::<Vec<&str>>()[0] == "/status" || contents == "/user" {
|
||||||
let contents = contents.split(" ").collect::<Vec<&str>>();
|
let contents = contents.split(" ").collect::<Vec<&str>>();
|
||||||
if contents.len() == 1 {
|
if contents.len() == 1 {
|
||||||
stream
|
stream
|
||||||
.write_fmt(
|
.write_fmt(format_args!(
|
||||||
format_args!("\x1b[0m\x1b[32mYou are currently marked as {}\n\x1b[0m"),
|
"\x1b[0m\x1b[32mYou are currently marked as {}\n\x1b[0m",
|
||||||
|
user.clone().status.get_status_string()
|
||||||
)
|
))
|
||||||
|
.unwrap();
|
||||||
|
} else {
|
||||||
|
match contents[1] {
|
||||||
|
"online" => {
|
||||||
|
user.status = UserStatus::ONLINE;
|
||||||
|
}
|
||||||
|
"idle" => {
|
||||||
|
user.status = UserStatus::IDLE;
|
||||||
|
}
|
||||||
|
"disconnected" => {
|
||||||
|
user.status = UserStatus::DISCONNECTED;
|
||||||
|
}
|
||||||
|
other => {
|
||||||
|
user.status = UserStatus::CUSTOM(other.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for usr in &mut channel.lock().unwrap().online_users {
|
||||||
|
if usr.name == user.name {
|
||||||
|
usr.status = user.status.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stream
|
||||||
|
.write_fmt(format_args!(
|
||||||
|
"\x1b[0m\x1b[32mYou are now marked as {}\n\x1b[0m",
|
||||||
|
user.status.get_status_string()
|
||||||
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
} else if contents.split(" ").collect::<Vec<&str>>()[0] == "/server" {
|
||||||
|
let contents = contents.split(" ").collect::<Vec<&str>>();
|
||||||
|
if contents.len() == 1 {
|
||||||
|
stream
|
||||||
|
.write_fmt(format_args!(
|
||||||
|
"\x1b[0m\x1b[32mCurrent server name: {}.\n\x1b[0m",
|
||||||
|
channel.lock().unwrap().name
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
} else {
|
||||||
|
channel.lock().unwrap().name = contents[1].to_owned();
|
||||||
|
stream
|
||||||
|
.write_fmt(format_args!(
|
||||||
|
"\x1b[0m\x1b[32mNew server name: {}.\n\x1b[0m",
|
||||||
|
channel.lock().unwrap().name
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
} else if contents.split(" ").collect::<Vec<&str>>()[0] == "/user" {
|
||||||
|
let contents = contents.split(" ").collect::<Vec<&str>>();
|
||||||
|
let mut found_user = false;
|
||||||
|
for usr in &mut channel.lock().unwrap().online_users {
|
||||||
|
if usr.name == contents[1] {
|
||||||
|
stream
|
||||||
|
.write_fmt(format_args!(
|
||||||
|
"\x1b[0m\x1b[32mUser {} is currently {}.\n\x1b[0m",
|
||||||
|
usr.name,
|
||||||
|
usr.status.get_status_string()
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
found_user = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found_user {
|
||||||
|
stream
|
||||||
|
.write_fmt(format_args!(
|
||||||
|
"\x1b[0m\x1b[32mUnknown user \"{}\".\n\x1b[0m",
|
||||||
|
contents[1]
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
} else if contents.starts_with("/users") {
|
||||||
|
stream.write_all(b"\x1b[0m\x1b[32mUsers:\x1b[0m").unwrap();
|
||||||
|
for usr in &channel.lock().unwrap().online_users {
|
||||||
|
stream
|
||||||
|
.write_fmt(format_args!(
|
||||||
|
"\n{} (currently {})",
|
||||||
|
usr.name,
|
||||||
|
usr.status.get_status_string()
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
stream.write_all(b"\n\x1b[0m").unwrap();
|
||||||
} else {
|
} else {
|
||||||
stream
|
stream
|
||||||
.write_all(b"\x1b[0m\x1b[31;1mThat's an invalid command!\n\x1b[0m")
|
.write_all(b"\x1b[0m\x1b[31;1mThat's an invalid command!\n\x1b[0m")
|
||||||
|
|
Loading…
Add table
Reference in a new issue