Add media directory commands

This commit is contained in:
2026-05-30 22:06:59 -07:00
parent 1154f9d3c8
commit b1f31a0de8
4 changed files with 52 additions and 13 deletions
Generated
+1 -1
View File
@@ -397,7 +397,6 @@ dependencies = [
[[package]] [[package]]
name = "fedichat" name = "fedichat"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.firechicken.net/fedichat/fedichat-lib#53398bf4ea611fb8bdff973e348d8bf9d37708ea"
dependencies = [ dependencies = [
"serde", "serde",
"serde_bytes", "serde_bytes",
@@ -424,6 +423,7 @@ dependencies = [
"toml", "toml",
"tracing", "tracing",
"tracing-subscriber", "tracing-subscriber",
"uuid",
] ]
[[package]] [[package]]
+3 -2
View File
@@ -5,8 +5,8 @@ edition = "2024"
[dependencies] [dependencies]
quinn = "0.11.9" quinn = "0.11.9"
fedichat = {git = "https://git.firechicken.net/fedichat/fedichat-lib"} #fedichat = {git = "https://git.firechicken.net/fedichat/fedichat-lib"}
#fedichat = {path = "../fedichat-lib"} fedichat = {path = "../fedichat-lib"}
tracing = "0.1.44" tracing = "0.1.44"
tracing-subscriber = "0.3.23" tracing-subscriber = "0.3.23"
clap = { version = "4.6.1", features = ["derive"] } clap = { version = "4.6.1", features = ["derive"] }
@@ -20,3 +20,4 @@ dotenv = "0.15.0"
time = { version = "0.3.47", features = ["serde"] } time = { version = "0.3.47", features = ["serde"] }
hickory-resolver = "0.26.1" hickory-resolver = "0.26.1"
expanduser = "1.2.2" expanduser = "1.2.2"
uuid = { version = "1.23.2", features = ["v4"] }
+35 -10
View File
@@ -2,8 +2,12 @@ use clap::{Parser,Subcommand,ArgAction};
use fedichat::client::{ClientMessage,SignedClientMessage,AuthMethod}; use fedichat::client::{ClientMessage,SignedClientMessage,AuthMethod};
use fedichat::ServerAddr; use fedichat::ServerAddr;
use fedichat::state::StatePath; use fedichat::state::StatePath;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;
use time::OffsetDateTime; use time::OffsetDateTime;
use thiserror::Error; use thiserror::Error;
use uuid::Uuid;
// Everything except server, user, and password lives in these // Everything except server, user, and password lives in these
@@ -61,6 +65,15 @@ pub enum Command {
#[clap(short, long, value_parser=Room::from_str)] #[clap(short, long, value_parser=Room::from_str)]
room: Room, room: Room,
}, },
Upload {
file: PathBuf,
},
Fetch {
#[clap(short, long)]
id: String,
#[clap(short, long)]
file: PathBuf
},
GetState { GetState {
#[clap(short, long, value_parser=Room::from_str)] #[clap(short, long, value_parser=Room::from_str)]
room: Room, room: Room,
@@ -90,9 +103,9 @@ pub enum Command {
} }
impl Command { impl Command {
// Returns clientmessage and target server // Returns clientmessage and target server
fn into_client_message(self,username: String) -> (ClientMessage,Option<ServerAddr>) { fn into_client_message(self,username: String) -> Result<(ClientMessage,Option<ServerAddr>),MessageError> {
use Command::*; use Command::*;
match self { Ok(match self {
CreateUser { CreateUser {
password, password,
} => (ClientMessage::UserCreate {username, password},None), } => (ClientMessage::UserCreate {username, password},None),
@@ -118,6 +131,14 @@ impl Command {
Create { Create {
room, room,
} => (ClientMessage::RoomCreate{room_id: room.get_coord()},room.get_server()), } => (ClientMessage::RoomCreate{room_id: room.get_coord()},room.get_server()),
Upload {file} => {
let mut buf = Vec::with_capacity(4096);
let mut file = File::open(file)?;
file.read_to_end(&mut buf)?;
(ClientMessage::MediaUpload{bytes: buf},None)
},
Fetch {file: _, id} => (ClientMessage::MediaFetch{id: Uuid::parse_str(&id)?},None),
GetState { GetState {
room, room,
path, path,
@@ -137,20 +158,19 @@ impl Command {
body, body,
user, user,
} => (ClientMessage::MessagePost{body, user: user.clone()},Some(ServerAddr(user.server))), } => (ClientMessage::MessagePost{body, user: user.clone()},Some(ServerAddr(user.server))),
})
}
} }
pub fn into_signed_message(self, username: String) -> SignedClientMessage { pub fn into_signed_message(self, username: String) -> Result<SignedClientMessage,MessageError> {
let (message,target) = self.into_client_message(username); let (message,target) = self.into_client_message(username)?;
SignedClientMessage { Ok(SignedClientMessage {
message, message,
target, target,
timestamp: OffsetDateTime::now_utc(), timestamp: OffsetDateTime::now_utc(),
// TODO: actually implement signatures // TODO: actually implement signatures
signature: Box::new([0]) signature: Box::new([0])
} })
} }
pub fn needs_auth(&self) -> bool { pub fn needs_auth(&self) -> bool {
@@ -180,7 +200,7 @@ impl Command {
signature: Box::new([0]) signature: Box::new([0])
}) })
} }
messages.push(self.into_signed_message(username)); messages.push(self.into_signed_message(username)?);
// If this message is authenticating us then we should be generating // If this message is authenticating us then we should be generating
// a new token and saving it for future commands // a new token and saving it for future commands
if !needs_auth { if !needs_auth {
@@ -198,7 +218,12 @@ impl Command {
#[derive(Error,Debug)] #[derive(Error,Debug)]
pub enum MessageError { pub enum MessageError {
#[error("Command needs a token. Login or create an account first.")] #[error("Command needs a token. Login or create an account first.")]
NoToken NoToken,
#[error("Error while parsing uuid: {0}")]
UuidError(#[from] uuid::Error),
#[error("Error during file IO: {0}")]
IoError(#[from] std::io::Error),
} }
+13
View File
@@ -9,6 +9,8 @@ use clap::Parser;
use fedichat::client::ServerMessage; use fedichat::client::ServerMessage;
use hickory_resolver::Resolver; use hickory_resolver::Resolver;
use std::net::{IpAddr,SocketAddr}; use std::net::{IpAddr,SocketAddr};
use std::fs::File;
use std::io::Write;
use quinn::Endpoint; use quinn::Endpoint;
use rmp_serde::encode::Serializer; use rmp_serde::encode::Serializer;
use serde::Serialize; use serde::Serialize;
@@ -76,11 +78,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
SocketAddr::new(response,PORT), SocketAddr::new(response,PORT),
&target_server)?.await?; &target_server)?.await?;
// Dumb pattern
let mut file_to_write = None;
if let Command::Fetch{file, ..} = &cli.command {
file_to_write = Some(file.clone());
}
// send messages, each time waiting for a response // send messages, each time waiting for a response
let messages = cli.command.generate_messages(cli.username.clone(),token)?; let messages = cli.command.generate_messages(cli.username.clone(),token)?;
debug!("Sending commands"); debug!("Sending commands");
for message in messages { for message in messages {
let mut buf = Vec::new(); let mut buf = Vec::new();
@@ -101,6 +110,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
ServerMessage::Token(ref token) => { ServerMessage::Token(ref token) => {
config.insert_token(&target_server,cli.username.clone(),token.clone())?; config.insert_token(&target_server,cli.username.clone(),token.clone())?;
}, },
ServerMessage::Media(ref bytes) => {
let mut file = File::create(file_to_write.clone().expect("File path not specified"))?;
file.write_all(bytes)?;
},
_ => {} _ => {}
} }