Browse Source

fuck new years explosives

xenua 2 years ago
parent
commit
3efb2b8ec2
  1. 0
      .data-example/accounts
  2. 1
      .data-example/redirects
  3. 3
      .data-example/stats
  4. 6
      .data-example/users
  5. 1
      Cargo.lock
  6. 1
      Cargo.toml
  7. 157
      src/main.rs

0
.data-example/accounts

1
.data-example/redirects

@ -0,0 +1 @@ @@ -0,0 +1 @@
id: https://www.youtube.com/watch?v=dQw4w9WgXcQ

3
.data-example/stats

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
version: 1
id_collisions: 0
requests_served: 420691337

6
.data-example/users

@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
admin: hash
admin2: hash
---
user: hash
user2: hash
user3: hash

1
Cargo.lock generated

@ -1286,6 +1286,7 @@ dependencies = [ @@ -1286,6 +1286,7 @@ dependencies = [
"parking_lot",
"serde",
"tera",
"thiserror",
"tokio",
]

1
Cargo.toml

@ -14,4 +14,5 @@ nanoid = "0.4.0" @@ -14,4 +14,5 @@ nanoid = "0.4.0"
parking_lot = "0.12.1"
serde = { version = "1.0.152", features = ["derive", "serde_derive"] }
tera = "1.17.1"
thiserror = "1.0.38"
tokio = { version = "1.23.0", features = ["full"] }

157
src/main.rs

@ -1,8 +1,17 @@ @@ -1,8 +1,17 @@
use std::{collections::HashMap, net::SocketAddr, path::PathBuf};
use std::{
collections::HashMap,
ffi::OsString,
fs::{DirBuilder, File},
io::{self, BufRead},
net::SocketAddr,
path::PathBuf,
};
#[cfg(target_family = "unix")]
use std::os::unix::fs::DirBuilderExt;
use axum::{routing::get, Router};
use dashmap::DashMap;
use parking_lot::RwLock;
use serde::{Deserialize, Serialize};
use lazy_static::lazy_static;
@ -11,15 +20,31 @@ use tera::Tera; @@ -11,15 +20,31 @@ use tera::Tera;
mod down;
mod up;
const TEXT_DIR: String = "text".to_string();
const FILE_DIR: String = "files".to_string();
const REDIRECTS_FILE: String = "redirects".to_string();
const STATS_FILE: String = "stats".to_string();
const USERS_FILE: String = "users".to_string();
lazy_static! {
pub static ref TEMPLATES: Tera = {
let tera = Tera::new(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*.html"))
.expect("Parsing error(s):");
.expect("Parsing error(s)");
tera
};
}
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("io error")]
IO(#[from] std::io::Error),
#[error("metadata error")]
Metadata,
#[error("some shit missing: {0}")]
ShitMissing(String),
}
struct TextPaste {
pub text: String,
pub meta: HashMap<String, String>,
@ -29,22 +54,134 @@ struct FileMeta { @@ -29,22 +54,134 @@ struct FileMeta {
file_name: String,
}
struct UserData {
username: String,
pw_hash: String,
is_admin: bool,
}
struct DataStorage {
links: DashMap<String, String>,
base_dir: PathBuf,
redirects: DashMap<String, String>,
text: DashMap<String, TextPaste>,
files: DashMap<String, FileMeta>,
users: DashMap<String, UserData>,
}
impl DataStorage {
pub fn new(base_dir: PathBuf) -> Self {
let redirects = DashMap::new();
let text = DashMap::new();
let files = DashMap::new();
let users = DashMap::new();
DataStorage {
base_dir,
redirects,
text,
files,
users,
}
}
pub fn init(&mut self) -> Result<(), Error> {
self.ensure_folder_structure()?;
self.load_redirects()?;
self.load_text()?;
self.load_files()?;
self.load_users()?;
todo!()
}
fn ensure_folder_structure(&self) -> Result<(), Error> {
let dir_builder = DirBuilder::new().recursive(true);
if cfg!(target_family = "unix") {
dir_builder = dir_builder.mode(0o775);
}
dir_builder.create(self.base_dir)?;
dir_builder.create(self.base_dir.join(FILE_DIR))?;
dir_builder.create(self.base_dir.join(TEXT_DIR))?;
Ok(())
}
fn load_redirects(&mut self) -> Result<(), Error> {
let f = File::options()
.create(true)
.read(true)
.open(self.base_dir.join(REDIRECTS_FILE))?;
for line in io::BufReader::new(f).lines() {
line?;
let (id, url) = line?.split_once(": ").expect("invalid redirect format");
self.redirects
.insert(id.trim().to_string(), url.trim().to_string());
// if there's a better way to do this let me know
}
Ok(())
}
fn load_text(&mut self) -> Result<(), Error> {
for thing in std::fs::read_dir(self.base_dir.join(TEXT_DIR)).expect("fs error") {
let dir_entry = thing?; // i'm so good at naming things
let f = File::open(dir_entry.path())?;
let reader = io::BufReader::new(f);
}
Ok(())
}
fn load_files(&mut self) -> Result<(), Error> {
for thing in std::fs::read_dir(self.base_dir.join(FILE_DIR)).expect("fs error") {
let dir_entry = thing?; // i'm so good at naming things
let filename = dir_entry.file_name().into_string().expect("fucked up OS string");
if filename
.ends_with(".meta")
{
let id = filename.trim_end_matches(".meta").to_string();
let f = File::open(dir_entry.path())?;
let reader = io::BufReader::new(f);
let raw_metadata = HashMap::new();
for line in reader.lines() {
let (k, v) = line?.split_once(": ").expect("invalid metadata");
raw_metadata.insert(k.trim().to_string(), v.trim().to_string());
}
let metadata = Self::parse_file_meta(raw_metadata)?;
self.files.insert(id, metadata);
}
}
self.assert_all_files_present()?;
Ok(())
}
fn assert_all_files_present(&self) -> Result<(), Error> {
let files_folder = self.base_dir.join(FILE_DIR);
for (id, _) in self.files.into_iter() {
files_folder.join(id).try_exists().map_err(|_| Error::ShitMissing(id));
}
Ok(())
}
fn parse_file_meta(raw: HashMap<String, String>) -> Result<FileMeta, Error> {
let file_name = raw.get("file_name").ok_or(Error::Metadata)?.to_owned();
Ok(FileMeta { file_name })
}
fn load_users(&mut self) -> Result<(), Error> {
todo!()
}
}
struct AppState {
alphabet: Box<[char; 32]>,
alphabet: Vec<char>,
id_length: usize,
cache: DataStorage,
base_dir: PathBuf,
}
impl AppState {
}
impl AppState {}
fn routes() -> Router {
let up = up::routes();
@ -60,7 +197,7 @@ async fn main() -> anyhow::Result<()> { @@ -60,7 +197,7 @@ async fn main() -> anyhow::Result<()> {
let addr: SocketAddr = std::env::var("LISTEN_ADDR")
.unwrap_or("127.0.0.1:8080".to_string())
.parse()
.expect("parse error");
.expect("LISTEN_ADDR parse error");
let app = routes();

Loading…
Cancel
Save