add a work in progress cli and fix bugs

i'm making a cli that lets you add stuff to the names.json file and read
data from it and i moved stuff that can be shared between them like the
Site struct to a shared crate thats in workspace, like the cli crate. i
also switched to using typed json parsing which works well.
This commit is contained in:
Fries 2023-06-30 21:43:18 -07:00
parent 1667e14d64
commit c481999c55
13 changed files with 288 additions and 78 deletions

134
Cargo.lock generated
View file

@ -17,6 +17,55 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "anstream"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is-terminal",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd"
[[package]]
name = "anstyle-parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188"
dependencies = [
"anstyle",
"windows-sys",
]
[[package]] [[package]]
name = "askama" name = "askama"
version = "0.12.0" version = "0.12.0"
@ -172,6 +221,63 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "384e169cc618c613d5e3ca6404dda77a8685a63e08660dcc64abaf7da7cb0c7a"
dependencies = [
"clap_builder",
"clap_derive",
"once_cell",
]
[[package]]
name = "clap_builder"
version = "4.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef137bbe35aab78bdb468ccfba75a5f4d8321ae011d34063770780545176af2d"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
[[package]]
name = "cli"
version = "0.1.0"
dependencies = [
"clap",
"serde",
"serde_json",
"shared",
]
[[package]]
name = "colorchoice"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]] [[package]]
name = "cookie" name = "cookie"
version = "0.17.0" version = "0.17.0"
@ -439,6 +545,12 @@ version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.2.6" version = "0.2.6"
@ -663,7 +775,9 @@ dependencies = [
"askama_rocket", "askama_rocket",
"rocket", "rocket",
"rust-embed", "rust-embed",
"serde",
"serde_json", "serde_json",
"shared",
] ]
[[package]] [[package]]
@ -1207,6 +1321,14 @@ dependencies = [
"lazy_static", "lazy_static",
] ]
[[package]]
name = "shared"
version = "0.1.0"
dependencies = [
"serde",
"serde_json",
]
[[package]] [[package]]
name = "signal-hook-registry" name = "signal-hook-registry"
version = "1.4.1" version = "1.4.1"
@ -1265,6 +1387,12 @@ dependencies = [
"loom", "loom",
] ]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.22" version = "2.0.22"
@ -1534,6 +1662,12 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]] [[package]]
name = "valuable" name = "valuable"
version = "0.1.0" version = "0.1.0"

View file

@ -1,3 +1,6 @@
[workspace]
members = ["cli", "shared"]
[package] [package]
name = "meowy-webring" name = "meowy-webring"
version = "0.1.0" version = "0.1.0"
@ -11,9 +14,12 @@ default_features = false
features = ["json"] features = ["json"]
[dependencies.rust-embed] [dependencies.rust-embed]
version = "6.7.0" version = "6"
features = ["debug-embed"] features = ["debug-embed"]
[dependencies.serde]
version = "1.0"
[dependencies.serde_json] [dependencies.serde_json]
version = "1.0" version = "1.0"
@ -29,3 +35,6 @@ rev = "b9e51601560398766eac445517fb17c35090a952"
version = "0.12" version = "0.12"
default-features = true default-features = true
features = ["with-rocket", "mime", "mime_guess"] features = ["with-rocket", "mime", "mime_guess"]
[dependencies.shared]
path = "./shared"

19
cli/Cargo.toml Normal file
View file

@ -0,0 +1,19 @@
[package]
name = "cli"
version = "0.1.0"
edition = "2021"
[dependencies]
serde = "1.0"
serde_json = "1.0"
[dependencies.clap]
version = "4"
features = ["derive"]
[dependencies.shared]
path = "../shared"
[[bin]]
name = "meowy-cli"
path = "src/main.rs"

30
cli/src/arguments.rs Normal file
View file

@ -0,0 +1,30 @@
use clap::{Parser, command, Subcommand, arg, Args};
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
pub(crate) struct Arguments {
#[command(subcommand)]
pub(crate) command: Commands
}
#[derive(Subcommand, Debug)]
pub(crate) enum Commands {
#[command(about = "print the current webring sites and their names")]
Print {
#[arg(help = "the path to the names.json file")]
path: String,
#[command(flatten)]
group: Group
}
}
#[derive(Args, Debug)]
#[group(required = false)]
pub struct Group {
#[arg(long, short, action = clap::ArgAction::SetTrue, conflicts_with = "name", help = "print the url only")]
pub(crate) url: bool,
#[arg(long, short, action = clap::ArgAction::SetTrue, conflicts_with = "url", help = "print the name only")]
pub(crate) name: bool
}

18
cli/src/commands.rs Normal file
View file

@ -0,0 +1,18 @@
use crate::arguments::Group;
pub(crate) fn print(path: &String, group: &Group) {
let names = std::fs::read_to_string(path).unwrap();
let parsed_names = shared::names::load_names(names).unwrap();
for site in parsed_names {
if group.name {
println!("{}", site.name.unwrap_or_default());
continue;
}
if group.url {
println!("{}", site.url);
continue;
}
println!("{:?}", site);
}
}

14
cli/src/main.rs Normal file
View file

@ -0,0 +1,14 @@
use arguments::{Arguments, Commands};
use clap::Parser;
use commands::print;
mod arguments;
mod commands;
fn main() {
let args = Arguments::parse();
match &args.command {
Commands::Print { path, group } => print(path, group)
}
}

11
shared/Cargo.toml Normal file
View file

@ -0,0 +1,11 @@
[package]
name = "shared"
version = "0.1.0"
edition = "2021"
[dependencies]
serde_json = "1.0"
[dependencies.serde]
version = "1.0"
features = ["derive"]

1
shared/src/lib.rs Normal file
View file

@ -0,0 +1 @@
pub mod names;

20
shared/src/names.rs Normal file
View file

@ -0,0 +1,20 @@
use serde::Deserialize;
#[derive(Deserialize, Debug)]
pub struct Site {
pub url: String,
pub name: Option<String>,
}
#[derive(Debug)]
pub enum NamesError {
FileAccessError,
ParseError,
}
pub fn load_names(names: String) -> Result<Vec<Site>, NamesError> {
match serde_json::from_str::<Vec<Site>>(&names) {
Ok(content) => Ok(content),
Err(_) => Err(NamesError::ParseError)
}
}

View file

@ -1,18 +1,18 @@
use crate::names::Site; use shared::names::Site;
pub fn previous_url(source_url: &String, names: &Vec<Site>) -> Option<String> { pub fn previous_url(source_url: &String, names: &Vec<Site>) -> Option<String> {
match names.iter().position(|r| r.url() == source_url) { match names.iter().position(|r| &r.url == source_url) {
Some(index) if index == 0 => Some(names[names.len() - 1].url().to_string()), Some(index) if index == 0 => Some(names[names.len() - 1].url.to_string()),
Some(index) => Some(names[index - 1].url().to_string()), Some(index) => Some(names[index - 1].url.to_string()),
None => None, None => None,
} }
} }
pub fn next_url(source_url: &String, names: &Vec<Site>) -> Option<String> { pub fn next_url(source_url: &String, names: &Vec<Site>) -> Option<String> {
// this is gay // this is gay
match names.iter().position(|r| r.url() == source_url) { match names.iter().position(|r| &r.url == source_url) {
Some(index) if index == names.len() - 1 => Some(names[0].url().to_string()), Some(index) if index == names.len() - 1 => Some(names[0].url.to_string()),
Some(index) => Some(names[index + 1].url().to_string()), Some(index) => Some(names[index + 1].url.to_string()),
None => None, None => None,
} }
} }

View file

@ -6,12 +6,10 @@ mod links;
mod routes; mod routes;
mod names; mod names;
use names::Site;
#[launch] #[launch]
fn rocket() -> _ { fn rocket() -> _ {
let names_file = std::fs::File::open("names.json").unwrap(); let names_file = std::fs::read_to_string("names.json").unwrap();
let names = names::load_names(names_file).unwrap(); let names = shared::names::load_names(names_file).unwrap();
rocket::build() rocket::build()
.manage(names) .manage(names)
.mount( .mount(

View file

@ -1,69 +1,24 @@
use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
use std::fs::File; use std::fs::File;
use std::io::{BufReader, Read}; use std::io::{BufReader, Read};
use serde_json::{Map, Value};
#[derive(Debug)]
pub enum NamesError {
FileAccessError,
ParseError,
}
pub fn load_names(names_file: File) -> Result<Vec<Site>, NamesError> {
let mut buf_reader = BufReader::new(names_file);
let mut output: Vec<Site> = vec![];
let mut contents = String::new();
match buf_reader.read_to_string(&mut contents) {
Ok(_) => {},
Err(_) => {return Err(NamesError::FileAccessError)},
}
println!("{}", contents); // impl Site {
// pub fn new(url: &str, name: Option<&str>) -> Self {
match serde_json::from_str(&contents) { // Site {
Ok(Value::Array(sites_array)) => { // url: url.to_string(),
for i in sites_array { // name: name.map(str::to_string),
match i { // }
Value::Object(site) => { // }
let url = site.get("url"); // pub fn url(&self) -> &String {
let name = site.get("name"); // &self.url
match (url, name) { // }
(Some(Value::String(url)), Some(Value::String(name))) => { // pub fn name(&self) -> Option<&String> {
output.push(Site::new(url, Some(name))); // match &self.name {
}, // Some(name) => Some(&name),
(Some(Value::String(url)), None) => { // None => None,
output.push(Site::new(url, None)); // }
}, // }
_ => {return Err(NamesError::ParseError)}, // }
};
}
_ => {return Err(NamesError::ParseError)}
}
}
}
_ => {return Err(NamesError::ParseError)}
}
Ok(output)
}
pub struct Site {
url: String,
name: Option<String>,
}
impl Site {
pub fn new(url: &str, name: Option<&str>) -> Self {
Site {
url: url.to_string(),
name: name.map(str::to_string),
}
}
pub fn url(&self) -> &String {
&self.url
}
pub fn name(&self) -> Option<&String> {
match &self.name {
Some(name) => Some(&name),
None => None
}
}
}

View file

@ -1,4 +1,4 @@
use crate::{links::{next_url, previous_url}, assets::ErrorTemplate, names::Site}; use crate::{links::{next_url, previous_url}, assets::ErrorTemplate};
static NAMES: [&str; 3] = ["mossfet.xyz", "fries.gay", "ta-kev.digital"]; static NAMES: [&str; 3] = ["mossfet.xyz", "fries.gay", "ta-kev.digital"];
use rocket::{ use rocket::{
@ -7,6 +7,7 @@ use rocket::{
serde::{json::Json, Serialize}, serde::{json::Json, Serialize},
State, State,
}; };
use shared::names::Site;
const NOT_FOUND_ERROR: ErrorTemplate = ErrorTemplate { const NOT_FOUND_ERROR: ErrorTemplate = ErrorTemplate {
error: "Not Found", error: "Not Found",