added support for use of a custom names file
This commit is contained in:
parent
7d5c70ddd6
commit
7abb3c5d11
10 changed files with 120 additions and 69 deletions
|
@ -3,6 +3,7 @@ use lazy_static::lazy_static;
|
|||
use std::convert::Infallible;
|
||||
use std::fmt;
|
||||
use std::net::IpAddr;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
|
||||
lazy_static! {
|
||||
|
@ -124,6 +125,11 @@ pub struct Args {
|
|||
#[clap(long, env = "MICROBIN_CUSTOM_CSS")]
|
||||
pub custom_css: Option<String>,
|
||||
|
||||
/// Replace built-in animal names file with custom names file for pasta links.
|
||||
/// The file must be newline seperated.
|
||||
#[clap(long, env = "MICROBIN_CUSTOM_NAMES")]
|
||||
pub custom_names: Option<PathBuf>,
|
||||
|
||||
/// Enable the use of Hash IDs for shorter URLs instead of animal names.
|
||||
#[clap(long, env = "MICROBIN_HASH_IDS")]
|
||||
pub hash_ids: bool,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use crate::dbio::save_to_file;
|
||||
use crate::pasta::PastaFile;
|
||||
use crate::util::animalnumbers::to_animal_names;
|
||||
use crate::util::hashids::to_hashids;
|
||||
use crate::util::misc::is_valid_url;
|
||||
use crate::util::pasta_id_converter::CONVERTER;
|
||||
use crate::{AppState, Pasta, ARGS};
|
||||
use actix_multipart::Multipart;
|
||||
use actix_web::{get, web, Error, HttpResponse, Responder};
|
||||
|
@ -194,7 +194,7 @@ pub async fn create(
|
|||
let slug = if ARGS.hash_ids {
|
||||
to_hashids(id)
|
||||
} else {
|
||||
to_animal_names(id)
|
||||
CONVERTER.to_names(id)
|
||||
};
|
||||
Ok(HttpResponse::Found()
|
||||
.append_header(("Location", format!("{}/pasta/{}", ARGS.public_path, slug)))
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use crate::args::Args;
|
||||
use crate::dbio::save_to_file;
|
||||
use crate::endpoints::errors::ErrorTemplate;
|
||||
use crate::util::animalnumbers::to_u64;
|
||||
use crate::util::hashids::to_u64 as hashid_to_u64;
|
||||
use crate::util::misc::remove_expired;
|
||||
use crate::util::pasta_id_converter::CONVERTER;
|
||||
use crate::{AppState, Pasta, ARGS};
|
||||
use actix_multipart::Multipart;
|
||||
use actix_web::{get, post, web, Error, HttpResponse};
|
||||
|
@ -24,7 +24,7 @@ pub async fn get_edit(data: web::Data<AppState>, id: web::Path<String>) -> HttpR
|
|||
let id = if ARGS.hash_ids {
|
||||
hashid_to_u64(&id).unwrap_or(0)
|
||||
} else {
|
||||
to_u64(&id.into_inner()).unwrap_or(0)
|
||||
CONVERTER.to_u64(&id.into_inner()).unwrap_or(0)
|
||||
};
|
||||
|
||||
remove_expired(&mut pastas);
|
||||
|
@ -62,7 +62,7 @@ pub async fn post_edit(
|
|||
let id = if ARGS.hash_ids {
|
||||
hashid_to_u64(&id).unwrap_or(0)
|
||||
} else {
|
||||
to_u64(&id.into_inner()).unwrap_or(0)
|
||||
CONVERTER.to_u64(&id.into_inner()).unwrap_or(0)
|
||||
};
|
||||
|
||||
let mut pastas = data.pastas.lock().await;
|
||||
|
|
|
@ -2,10 +2,10 @@ use crate::args::{Args, ARGS};
|
|||
use crate::dbio::save_to_file;
|
||||
use crate::endpoints::errors::ErrorTemplate;
|
||||
use crate::pasta::Pasta;
|
||||
use crate::util::animalnumbers::to_u64;
|
||||
use crate::util::hashids::to_u64 as hashid_to_u64;
|
||||
use crate::util::misc::remove_expired;
|
||||
use crate::AppState;
|
||||
use crate::util::pasta_id_converter::CONVERTER;
|
||||
|
||||
use actix_web::{get, web, HttpResponse};
|
||||
use askama::Template;
|
||||
|
@ -27,7 +27,7 @@ pub async fn getpasta(data: web::Data<AppState>, id: web::Path<String>) -> HttpR
|
|||
let id = if ARGS.hash_ids {
|
||||
hashid_to_u64(&id).unwrap_or(0)
|
||||
} else {
|
||||
to_u64(&id.into_inner()).unwrap_or(0)
|
||||
CONVERTER.to_u64(&id.into_inner()).unwrap_or(0)
|
||||
};
|
||||
|
||||
// remove expired pastas (including this one if needed)
|
||||
|
@ -92,7 +92,7 @@ pub async fn redirecturl(data: web::Data<AppState>, id: web::Path<String>) -> Ht
|
|||
let id = if ARGS.hash_ids {
|
||||
hashid_to_u64(&id).unwrap_or(0)
|
||||
} else {
|
||||
to_u64(&id.into_inner()).unwrap_or(0)
|
||||
CONVERTER.to_u64(&id.into_inner()).unwrap_or(0)
|
||||
};
|
||||
|
||||
// remove expired pastas (including this one if needed)
|
||||
|
@ -160,7 +160,7 @@ pub async fn getrawpasta(data: web::Data<AppState>, id: web::Path<String>) -> St
|
|||
let id = if ARGS.hash_ids {
|
||||
hashid_to_u64(&id).unwrap_or(0)
|
||||
} else {
|
||||
to_u64(&id.into_inner()).unwrap_or(0)
|
||||
CONVERTER.to_u64(&id.into_inner()).unwrap_or(0)
|
||||
};
|
||||
|
||||
// remove expired pastas (including this one if needed)
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use crate::args::{Args, ARGS};
|
||||
use crate::endpoints::errors::ErrorTemplate;
|
||||
use crate::pasta::Pasta;
|
||||
use crate::util::animalnumbers::to_u64;
|
||||
use crate::util::hashids::to_u64 as hashid_to_u64;
|
||||
use crate::util::misc::{self, remove_expired};
|
||||
use crate::AppState;
|
||||
use crate::util::pasta_id_converter::CONVERTER;
|
||||
use actix_web::{get, web, HttpResponse};
|
||||
use askama::Template;
|
||||
|
||||
|
@ -25,7 +25,7 @@ pub async fn getqr(data: web::Data<AppState>, id: web::Path<String>) -> HttpResp
|
|||
let u64_id = if ARGS.hash_ids {
|
||||
hashid_to_u64(&id).unwrap_or(0)
|
||||
} else {
|
||||
to_u64(&id).unwrap_or(0)
|
||||
CONVERTER.to_u64(&id).unwrap_or(0)
|
||||
};
|
||||
|
||||
// remove expired pastas (including this one if needed)
|
||||
|
|
|
@ -3,10 +3,10 @@ use actix_web::{get, web, HttpResponse};
|
|||
use crate::args::ARGS;
|
||||
use crate::endpoints::errors::ErrorTemplate;
|
||||
use crate::pasta::PastaFile;
|
||||
use crate::util::animalnumbers::to_u64;
|
||||
use crate::util::hashids::to_u64 as hashid_to_u64;
|
||||
use crate::util::misc::remove_expired;
|
||||
use crate::AppState;
|
||||
use crate::util::pasta_id_converter::CONVERTER;
|
||||
use askama::Template;
|
||||
use std::fs;
|
||||
|
||||
|
@ -24,7 +24,7 @@ pub async fn remove(data: web::Data<AppState>, id: web::Path<String>) -> HttpRes
|
|||
let id = if ARGS.hash_ids {
|
||||
hashid_to_u64(&id).unwrap_or(0)
|
||||
} else {
|
||||
to_u64(&id.into_inner()).unwrap_or(0)
|
||||
CONVERTER.to_u64(&id.into_inner()).unwrap_or(0)
|
||||
};
|
||||
|
||||
for (i, pasta) in pastas.iter().enumerate() {
|
||||
|
|
|
@ -20,7 +20,7 @@ pub mod args;
|
|||
pub mod pasta;
|
||||
|
||||
pub mod util {
|
||||
pub mod animalnumbers;
|
||||
pub mod pasta_id_converter;
|
||||
pub mod auth;
|
||||
pub mod dbio;
|
||||
pub mod hashids;
|
||||
|
|
|
@ -6,8 +6,8 @@ use std::path::Path;
|
|||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
use crate::args::ARGS;
|
||||
use crate::util::animalnumbers::to_animal_names;
|
||||
use crate::util::hashids::to_hashids;
|
||||
use crate::util::pasta_id_converter::CONVERTER;
|
||||
use crate::util::syntaxhighlighter::html_highlight;
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Eq)]
|
||||
|
@ -55,7 +55,7 @@ impl Pasta {
|
|||
if ARGS.hash_ids {
|
||||
to_hashids(self.id)
|
||||
} else {
|
||||
to_animal_names(self.id)
|
||||
CONVERTER.to_names(self.id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
const ANIMAL_NAMES: &[&str] = &[
|
||||
"ant", "eel", "mole", "sloth", "ape", "emu", "monkey", "snail", "bat", "falcon", "mouse",
|
||||
"snake", "bear", "fish", "otter", "spider", "bee", "fly", "parrot", "squid", "bird", "fox",
|
||||
"panda", "swan", "bison", "frog", "pig", "tiger", "camel", "gecko", "pigeon", "toad", "cat",
|
||||
"goat", "pony", "turkey", "cobra", "goose", "pug", "turtle", "crow", "hawk", "rabbit", "viper",
|
||||
"deer", "horse", "rat", "wasp", "dog", "jaguar", "raven", "whale", "dove", "koala", "seal",
|
||||
"wolf", "duck", "lion", "shark", "worm", "eagle", "lizard", "sheep", "zebra",
|
||||
];
|
||||
|
||||
pub fn to_animal_names(mut number: u64) -> String {
|
||||
let mut result: Vec<&str> = Vec::new();
|
||||
|
||||
if number == 0 {
|
||||
return ANIMAL_NAMES[0].parse().unwrap();
|
||||
}
|
||||
|
||||
let mut power = 6;
|
||||
|
||||
loop {
|
||||
let digit = number / ANIMAL_NAMES.len().pow(power) as u64;
|
||||
if !(result.is_empty() && digit == 0) {
|
||||
result.push(ANIMAL_NAMES[digit as usize]);
|
||||
}
|
||||
number -= digit * ANIMAL_NAMES.len().pow(power) as u64;
|
||||
if power > 0 {
|
||||
power -= 1;
|
||||
} else if power == 0 || number == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result.join("-")
|
||||
}
|
||||
|
||||
pub fn to_u64(animal_names: &str) -> Result<u64, &str> {
|
||||
let mut result: u64 = 0;
|
||||
|
||||
let animals: Vec<&str> = animal_names.split('-').collect();
|
||||
|
||||
let mut pow = animals.len();
|
||||
for animal in animals {
|
||||
pow -= 1;
|
||||
let animal_index = ANIMAL_NAMES.iter().position(|&r| r == animal);
|
||||
match animal_index {
|
||||
None => return Err("Failed to convert animal name to u64!"),
|
||||
Some(_) => {
|
||||
result += (animal_index.unwrap() * ANIMAL_NAMES.len().pow(pow as u32)) as u64
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
98
src/util/pasta_id_converter.rs
Normal file
98
src/util/pasta_id_converter.rs
Normal file
|
@ -0,0 +1,98 @@
|
|||
use std::fs;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use crate::args::ARGS;
|
||||
|
||||
const ANIMAL_NAMES: &[&str] = &[
|
||||
"ant", "eel", "mole", "sloth", "ape", "emu", "monkey", "snail", "bat", "falcon", "mouse",
|
||||
"snake", "bear", "fish", "otter", "spider", "bee", "fly", "parrot", "squid", "bird", "fox",
|
||||
"panda", "swan", "bison", "frog", "pig", "tiger", "camel", "gecko", "pigeon", "toad", "cat",
|
||||
"goat", "pony", "turkey", "cobra", "goose", "pug", "turtle", "crow", "hawk", "rabbit", "viper",
|
||||
"deer", "horse", "rat", "wasp", "dog", "jaguar", "raven", "whale", "dove", "koala", "seal",
|
||||
"wolf", "duck", "lion", "shark", "worm", "eagle", "lizard", "sheep", "zebra",
|
||||
];
|
||||
|
||||
lazy_static!{
|
||||
pub static ref CONVERTER: PastaIdConverter = PastaIdConverter::new();
|
||||
}
|
||||
|
||||
/// Convert pasta IDs to names and vice versa
|
||||
pub struct PastaIdConverter {
|
||||
names: Vec<String>
|
||||
}
|
||||
|
||||
impl PastaIdConverter {
|
||||
pub fn new() -> Self {
|
||||
let names;
|
||||
if let Some(names_path) = &ARGS.custom_names {
|
||||
let names_data = fs::read_to_string(names_path)
|
||||
.expect("path for the names file should contain a names file");
|
||||
names = names_data
|
||||
.split('\n')
|
||||
.map(ToOwned::to_owned)
|
||||
.collect::<Vec<String>>();
|
||||
} else {
|
||||
names = ANIMAL_NAMES
|
||||
.iter()
|
||||
.copied()
|
||||
.map(ToOwned::to_owned)
|
||||
.collect();
|
||||
}
|
||||
|
||||
Self { names }
|
||||
}
|
||||
|
||||
pub fn to_names(&self, mut number: u64) -> String {
|
||||
let mut result: Vec<&str> = Vec::new();
|
||||
|
||||
if number == 0 {
|
||||
return self.names[0].parse().unwrap();
|
||||
}
|
||||
|
||||
let mut power = 6;
|
||||
|
||||
loop {
|
||||
let digit = number / self.names.len().pow(power) as u64;
|
||||
if !(result.is_empty() && digit == 0) {
|
||||
result.push(&self.names[digit as usize]);
|
||||
}
|
||||
number -= digit * self.names.len().pow(power) as u64;
|
||||
if power > 0 {
|
||||
power -= 1;
|
||||
} else if power == 0 || number == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result.join("-")
|
||||
}
|
||||
|
||||
pub fn to_u64(&self, pasta_id: &str) -> Result<u64, &str> {
|
||||
let mut result: u64 = 0;
|
||||
|
||||
let names: Vec<&str> = pasta_id.split('-').collect();
|
||||
|
||||
let mut pow = names.len();
|
||||
for name in names {
|
||||
pow -= 1;
|
||||
let name_index = self.names.iter().position(|r| r == name);
|
||||
match name_index {
|
||||
None => return Err("Failed to convert animal name to u64!"),
|
||||
Some(_) => {
|
||||
result += (name_index.unwrap() * self.names.len().pow(pow as u32)) as u64
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PastaIdConverter {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in a new issue