[WIP] A (somewhat barebones) atproto app for creating custom sites without hosting!

upload: add the utility rkey <=> url functions

vielle.dev deae99f7 7a1053cf

verified
Changed files
+65
upload
+1
upload/src/main.rs
··· 2 2 use std::path::PathBuf; 3 3 4 4 mod sitemap; 5 + mod utils; 5 6 6 7 #[derive(Parser, Debug)] 7 8 #[command(version, about, long_about = None)]
+64
upload/src/utils.rs
··· 1 + use regex::Regex; 2 + 3 + pub fn rkey_to_url(rkey: String) -> Option<String> { 4 + let regex = Regex::new( 5 + // symbols A-Za-z0-9 -._~: are all valid rkey characters 6 + // however we use a subset of record keys where : is an escape character 7 + // allow any rkey character except colons 8 + // or any of the valid escape sequences 9 + // from start of string to end between 0 and unlimited times 10 + r"^(?:[A-Za-z0-9.\-_~]|(?:::)|(?::~)|(?::21)|(?::24)|(?::26)|(?::27)|(?::28)|(?::29)|(?::2A)|(?::2B)|(?::2C)|(?::3A)|(?::3B)|(?::3D)|(?::40))*$", 11 + ) 12 + .expect("Regex failed to generate"); 13 + 14 + if !regex.is_match(&rkey) { 15 + return None; 16 + }; 17 + 18 + let res = rkey 19 + .replace("::", "/") 20 + .replace(":~", "%") 21 + .replace(":21", "!") 22 + .replace(":24", "$") 23 + .replace(":26", "&") 24 + .replace(":27", "'") 25 + .replace(":28", "(") 26 + .replace(":29", ")") 27 + .replace(":2A", "*") 28 + .replace(":2B", "+") 29 + .replace(":2C", ",") 30 + .replace(":3A", ":") 31 + .replace(":3B", ";") 32 + .replace(":3D", "=") 33 + .replace(":40", "@"); 34 + 35 + return Some(res); 36 + } 37 + 38 + pub fn url_to_rkey(url: String) -> Option<String> { 39 + let regex = Regex::new(r"^(?:[a-zA-Z0-9/\-._~!$&'()*+,;=:@]|(?:%[0-9a-fA-F]{2}))*$") 40 + .expect("Regex failed to generate"); 41 + if !regex.is_match(&url) { 42 + return None; 43 + } 44 + 45 + let res = url 46 + // : replace is hoisted so it doesnt replace colons from elsewhere 47 + .replace(":", ":3A") 48 + .replace("/", "::") 49 + .replace("%", ":~") 50 + .replace("!", ":21") 51 + .replace("$", ":24") 52 + .replace("&", ":26") 53 + .replace("'", ":27") 54 + .replace("(", ":28") 55 + .replace(")", ":29") 56 + .replace("*", ":2A") 57 + .replace("+", ":2B") 58 + .replace(",", ":2C") 59 + .replace(";", ":3B") 60 + .replace("=", ":3D") 61 + .replace("@", ":40"); 62 + 63 + return Some(res); 64 + }