this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Cleanup of existing scripts

+28 -437
+7
.claude/settings.local.json
··· 1 + { 2 + "permissions": { 3 + "allow": [ 4 + "WebFetch(domain:docs.rs)" 5 + ] 6 + } 7 + }
+1 -1
cidrcheck.rs
··· 5 5 edition = "2024" 6 6 [dependencies] 7 7 argh = "0.1" 8 - cidr = "0.2.1" 8 + cidr = "0.3.2" 9 9 --- 10 10 11 11 use std::net::IpAddr;
-280
emojidex.rs
··· 1 - #!/usr/bin/env -S cargo +nightly -Zscript 2 - 3 - --- 4 - [package] 5 - edition = "2024" 6 - [dependencies] 7 - argh = "0.1" 8 - reqwest = { version = "0.11.3", features = ["blocking", "json"] } 9 - serde = { version = "1.0", features = ["derive"] } 10 - viuer = "0.4.0" 11 - image = "0.23.14" 12 - --- 13 - 14 - use std::io::{BufReader, Cursor}; 15 - use std::str::FromStr; 16 - 17 - use argh::FromArgs; 18 - use image::io::Reader; 19 - use reqwest::blocking::Client; 20 - use serde::Deserialize; 21 - use viuer::Config; 22 - 23 - const BASE_API_URL: &str = "https://www.emojidex.com/api/v1"; 24 - const BASE_CDN_URL: &str = "https://cdn.emojidex.com/emoji"; 25 - 26 - #[derive(Copy, Clone, Eq, PartialEq)] 27 - enum Resolution { 28 - None, 29 - LDPI, 30 - MDPI, 31 - HDPI, 32 - XHDPI, 33 - XXHDPI, 34 - XXXHDPI, 35 - PX8, 36 - PX16, 37 - PX32, 38 - PX64, 39 - PX128, 40 - PX256, 41 - PX512, 42 - Hanko, 43 - Seal, 44 - } 45 - 46 - impl FromStr for Resolution { 47 - type Err = String; 48 - 49 - fn from_str(value: &str) -> Result<Resolution, String> { 50 - let resolution = match value.to_uppercase().as_str() { 51 - "NONE" | "OFF" => Resolution::None, 52 - "LDPI" => Resolution::LDPI, 53 - "MDPI" => Resolution::MDPI, 54 - "HDPI" => Resolution::HDPI, 55 - "XHDPI" => Resolution::XHDPI, 56 - "XXHDPI" => Resolution::XXHDPI, 57 - "XXXHDPI" => Resolution::XXXHDPI, 58 - "PX8" => Resolution::PX8, 59 - "PX16" => Resolution::PX16, 60 - "PX32" => Resolution::PX32, 61 - "PX64" => Resolution::PX64, 62 - "PX128" => Resolution::PX128, 63 - "PX256" => Resolution::PX256, 64 - "PX512" => Resolution::PX512, 65 - "HANKO" => Resolution::Hanko, 66 - "SEAL" => Resolution::Seal, 67 - _ => { 68 - let msg = "Unrecognized resolution, try one of: none, ldpi, mdpi, hdpi, xhdpi, xxhdpi, xxxdpi, px8, px16, px32, px64, px128, px256, px512, hanko, seal."; 69 - return Err(msg.to_string()); 70 - } 71 - }; 72 - 73 - Ok(resolution) 74 - } 75 - } 76 - 77 - impl Into<String> for Resolution { 78 - fn into(self) -> String { 79 - let resolution = match self { 80 - Resolution::LDPI => "ldpi", 81 - Resolution::MDPI => "mdpi", 82 - Resolution::HDPI => "hdpi", 83 - Resolution::XHDPI => "xhdpi", 84 - Resolution::XXHDPI => "xxhdpi", 85 - Resolution::XXXHDPI => "xxxhdpi", 86 - Resolution::PX8 => "px8", 87 - Resolution::PX16 => "px16", 88 - Resolution::PX32 => "px32", 89 - Resolution::PX64 => "px64", 90 - Resolution::PX128 => "px128", 91 - Resolution::PX256 => "px256", 92 - Resolution::PX512 => "px512", 93 - Resolution::Hanko => "hanko", 94 - Resolution::Seal => "seal", 95 - _ => panic!("unsupported resolution string"), 96 - }; 97 - 98 - resolution.to_string() 99 - } 100 - } 101 - 102 - #[derive(Deserialize, Debug)] 103 - struct SearchResponse { 104 - meta: SearchMeta, 105 - emoji: Vec<Emoji>, 106 - } 107 - 108 - #[derive(Deserialize, Debug)] 109 - struct SearchMeta { 110 - count: usize, 111 - total_count: usize, 112 - page: usize, 113 - } 114 - 115 - #[derive(Deserialize, Debug)] 116 - struct Emoji { 117 - code: String, 118 - moji: Option<String>, 119 - unicode: Option<String>, 120 - category: String, 121 - tags: Vec<String>, 122 - variants: Vec<String>, 123 - link: Option<String>, 124 - base: String, 125 - r18: bool, 126 - } 127 - 128 - #[derive(FromArgs)] 129 - #[argh(description = "Searches and displays emoji from emojidex.")] 130 - struct App { 131 - #[argh( 132 - option, 133 - description = "emoji preview resolution.", 134 - default = "Resolution::HDPI" 135 - )] 136 - resolution: Resolution, 137 - 138 - #[argh(option, description = "account auth token (required for r18 content).")] 139 - auth: Option<String>, 140 - 141 - #[argh(option, description = "limit the amount of results returned.")] 142 - limit: Option<usize>, 143 - 144 - #[argh(switch, description = "only displays images.")] 145 - images_only: bool, 146 - 147 - #[argh(switch, description = "filter out r18 emoji.")] 148 - sfw: bool, 149 - 150 - #[argh(option, description = "list of tags to search by.")] 151 - tag: Vec<String>, 152 - 153 - #[argh(option, description = "list of categories to search by.")] 154 - category: Vec<String>, 155 - 156 - #[argh(option, description = "code to search for.")] 157 - code: Option<String>, 158 - } 159 - 160 - fn main() { 161 - let App { 162 - sfw, 163 - tag, 164 - category, 165 - code, 166 - resolution, 167 - limit, 168 - auth, 169 - images_only, 170 - } = argh::from_env(); 171 - 172 - let tags = tag 173 - .into_iter() 174 - .map(|tag| ("tags[]", tag)) 175 - .collect::<Vec<_>>(); 176 - 177 - let category = category 178 - .into_iter() 179 - .map(|category| ("categories[]", category)) 180 - .collect::<Vec<_>>(); 181 - 182 - let code = if code.is_none() && tags.is_empty() && category.is_empty() { 183 - vec![("code_cont", "ferris".to_string())] 184 - } else { 185 - vec![( 186 - "code_cont", 187 - code.map(|code| code.replace(" ", "_")) 188 - .unwrap_or_else(|| "".to_string()), 189 - )] 190 - }; 191 - 192 - let auth_token = auth 193 - .map(|auth| vec![("auth_token", auth)]) 194 - .unwrap_or_else(|| vec![]); 195 - 196 - let terms = tags 197 - .into_iter() 198 - .chain(category) 199 - .chain(code) 200 - .chain(auth_token) 201 - .collect::<Vec<(&str, String)>>(); 202 - 203 - let client = Client::new(); 204 - let res = client 205 - .get(format!("{}/search/emoji", BASE_API_URL)) 206 - .form(&terms) 207 - .send() 208 - .expect("unexpected error while uploading file"); 209 - 210 - if res.status() != 200 { 211 - panic!("Unexpected status code {}", res.status()); 212 - } 213 - 214 - let SearchResponse { emoji, .. } = res.json().expect("should be able to deserialize body"); 215 - for emoji in emoji.into_iter().take(limit.unwrap_or(usize::MAX)) { 216 - if sfw && emoji.r18 { 217 - continue; 218 - } 219 - 220 - println!("\x1B[1m[{}]\x1B[0m\n", emoji.code.clone()); 221 - 222 - let encoded_code = emoji.code.replace(" ", "_"); 223 - let svg_url = format!("{}/{}.svg", BASE_CDN_URL, encoded_code.clone()); 224 - 225 - if !images_only { 226 - println!("\x1B[1mURL:\x1B[0m\n\t{}\n", svg_url.clone()); 227 - 228 - println!( 229 - "\x1B[1mHTML:\x1B[0m\n\t<img class=\"emojidex-emoji\" src=\"{}\" emoji-code=\"{}\" alt=\"{}\"{} />\n", 230 - svg_url.clone(), 231 - encoded_code.clone(), 232 - emoji.code.clone(), 233 - emoji 234 - .moji 235 - .as_ref() 236 - .map(|moji| format!(" emoji-moji=\"{}\"", moji)) 237 - .unwrap_or_else(|| "".to_string()), 238 - ); 239 - 240 - println!( 241 - "\x1B[1mMD:\x1B[0m\n\t![{}]({} \"{}\")\n", 242 - emoji.moji.unwrap_or(encoded_code.clone()), 243 - svg_url.clone(), 244 - emoji.code.clone(), 245 - ); 246 - } 247 - 248 - if resolution != Resolution::None { 249 - let res = client 250 - .get(format!( 251 - "{}/{}/{}.png", 252 - BASE_CDN_URL, 253 - <Resolution as Into<String>>::into(resolution), 254 - encoded_code, 255 - )) 256 - .send() 257 - .expect("should be able to get image"); 258 - 259 - let bytes = res.bytes().expect("should be able to get bytes"); 260 - let reader = Reader::new(BufReader::new(Cursor::new(bytes))) 261 - .with_guessed_format() 262 - .expect("should be able to guess format"); 263 - 264 - let image = reader 265 - .decode() 266 - .expect("should be able to interpret as image"); 267 - 268 - viuer::print( 269 - &image, 270 - &Config { 271 - absolute_offset: false, 272 - ..Default::default() 273 - }, 274 - ) 275 - .expect("Image printing failed."); 276 - } 277 - 278 - println!(); 279 - } 280 - }
-1
exiftool.rs
··· 1 - 2 1 #!/usr/bin/env -S cargo +nightly -Zscript 3 2 4 3 ---
-149
ghoshare.rs
··· 1 - #!/usr/bin/env -S cargo +nightly -Zscript 2 - 3 - --- 4 - [package] 5 - edition = "2024" 6 - [dependencies] 7 - argh = "0.1" 8 - reqwest = { version = "0.11.3", features = ["blocking"] } 9 - --- 10 - 11 - use std::fs::OpenOptions; 12 - use std::io::{BufReader, Read}; 13 - use std::path::PathBuf; 14 - use std::str::FromStr; 15 - 16 - use argh::FromArgs; 17 - use reqwest::blocking::Client; 18 - use reqwest::redirect::Policy; 19 - 20 - const BASE_URL: &str = "https://ghostbin.co"; 21 - 22 - #[derive(Debug)] 23 - enum ExpirationTime { 24 - Never, 25 - TenMinutes, 26 - OneHour, 27 - OneDay, 28 - Fortnight, 29 - } 30 - 31 - impl FromStr for ExpirationTime { 32 - type Err = String; 33 - 34 - fn from_str(value: &str) -> Result<ExpirationTime, String> { 35 - let expiration = match value { 36 - "never" => ExpirationTime::Never, 37 - "10m" | "10 m" | "10minutes" | "10 minutes" | "ten m" | "ten minutes" => { 38 - ExpirationTime::TenMinutes 39 - } 40 - "1h" | "1 h" | "1hour" | "1 hour" | "one h" | "one hour" => ExpirationTime::OneHour, 41 - "1d" | "1 d" | "1day" | "1 day" | "one d" | "one day" => ExpirationTime::OneDay, 42 - "14d" | "14 d" | "14days" | "14 days" | "fourteen d" | "fourteen days" 43 - | "fortnight" => ExpirationTime::Fortnight, 44 - _ => return Err("unrecoginized duration. try: never, 10m, 1h, 1d, or 14d.".to_string()), 45 - }; 46 - 47 - Ok(expiration) 48 - } 49 - } 50 - 51 - impl Into<String> for ExpirationTime { 52 - fn into(self) -> String { 53 - match self { 54 - ExpirationTime::Never => "-1".to_string(), 55 - ExpirationTime::TenMinutes => "10m".to_string(), 56 - ExpirationTime::OneHour => "1h".to_string(), 57 - ExpirationTime::OneDay => "1d".to_string(), 58 - ExpirationTime::Fortnight => "14d".to_string(), 59 - } 60 - } 61 - } 62 - 63 - #[derive(FromArgs)] 64 - #[argh(description = "Copies a local file onto ghostbin.co.")] 65 - struct App { 66 - #[argh( 67 - option, 68 - description = "language to apply syntax highlighting.", 69 - default = r#""text".to_string()"# 70 - )] 71 - language: String, 72 - 73 - #[argh(option, description = "how long to keep the file online.")] 74 - expiration: Option<ExpirationTime>, 75 - 76 - #[argh(option, description = "title of the uploaded file.")] 77 - title: Option<String>, 78 - 79 - #[argh( 80 - option, 81 - description = "password to access the file.", 82 - default = r#""".to_string()"# 83 - )] 84 - password: String, 85 - 86 - #[argh(positional, description = "file to share.")] 87 - file: PathBuf, 88 - } 89 - 90 - fn main() { 91 - let app: App = argh::from_env(); 92 - 93 - let file = OpenOptions::new() 94 - .read(true) 95 - .open(app.file.clone()) 96 - .expect("could not open file"); 97 - 98 - let mut reader = BufReader::new(file); 99 - 100 - let mut contents = String::new(); 101 - reader 102 - .read_to_string(&mut contents) 103 - .expect("should be able to read file contents"); 104 - 105 - let expiration: String = app.expiration.unwrap_or(ExpirationTime::TenMinutes).into(); 106 - 107 - let filename = app 108 - .file 109 - .file_name() 110 - .and_then(|name| name.to_str()) 111 - .map(|name| name.to_string()); 112 - 113 - let title = app 114 - .title 115 - .or_else(|| filename) 116 - .unwrap_or_else(|| "".to_string()); 117 - 118 - println!("Uploading file"); 119 - let client = Client::builder() 120 - .redirect(Policy::none()) 121 - .build() 122 - .expect("should be able to build client"); 123 - 124 - let res = client 125 - .post(format!("{}/paste/new", BASE_URL)) 126 - .header("User-Agent", "ghoshare") 127 - .form(&[ 128 - ("expire", expiration), 129 - ("password", app.password), 130 - ("lang", app.language), 131 - ("title", title), 132 - ("text", contents), 133 - ]) 134 - .send() 135 - .expect("unexpected error while uploading file"); 136 - 137 - if res.status() != 303 { 138 - panic!("Unexpected status code {}", res.status()); 139 - } 140 - 141 - let headers = res.headers(); 142 - let path = headers 143 - .get("location") 144 - .expect("we should be redirected!") 145 - .to_str() 146 - .expect("should be able to get location header value"); 147 - 148 - println!("URL: {}", format!("{}{}", BASE_URL, path)); 149 - }
+12 -3
stopwatch.rs
··· 31 31 32 32 #[argh(option, description = "how long to run the stopwatch.")] 33 33 duration: Option<humantime::Duration>, 34 + 35 + #[argh(switch, description = "disable terminal bell when stopped.")] 36 + no_ring: bool, 34 37 } 35 38 36 39 fn main() { ··· 42 45 .duration 43 46 .map(|d| d.into()) 44 47 .unwrap_or_else(|| Duration::new(u64::MAX, 0)); 48 + let no_ring = app.no_ring; 45 49 46 50 if let Some(delay) = delay { 47 51 println!("Waiting {:?}...", delay); 48 52 thread::sleep(delay); 49 53 } 50 54 55 + let bell = if no_ring { "" } else { "\x07" }; 56 + 51 57 let now = Instant::now(); 52 58 59 + print!("\x1B[?25l"); 53 60 let mut elapsed = now.elapsed(); 54 61 while elapsed < duration { 55 - print!("\x1B[2K\rElapsed: {}", humantime::format_duration(elapsed)); 62 + print!("\rElapsed: {}\x1B[K", humantime::format_duration(elapsed)); 56 63 thread::sleep(pause); 57 64 elapsed = now.elapsed(); 58 65 } 66 + print!("\x1B[?25h"); 59 67 60 68 print!( 61 - "\x1B[2K\rElapsed: {}\nStopped\x07", 62 - humantime::format_duration(elapsed) 69 + "\x1B[2K\rElapsed: {}\nStopped{}", 70 + humantime::format_duration(elapsed), 71 + bell 63 72 ); 64 73 }
+7 -2
strs.rs
··· 5 5 edition = "2024" 6 6 [dependencies] 7 7 argh = "0.1" 8 - object = "0.24.0" 8 + object = "0.38.0" 9 9 --- 10 10 11 11 use std::fs::OpenOptions; ··· 87 87 let object = File::parse(contents).expect("Could not parse object file"); 88 88 object 89 89 .sections() 90 - .filter(|section| all || section.kind() == SectionKind::Data) 90 + .filter(|section| { 91 + all || matches!( 92 + section.kind(), 93 + SectionKind::Data | SectionKind::ReadOnlyString | SectionKind::ReadOnlyData 94 + ) 95 + }) 91 96 .for_each(|section| { 92 97 let contents = section.data().expect("section should have data"); 93 98 print_strings(handle, contents, min_length);
+1 -1
tag_release.rs
··· 5 5 edition = "2024" 6 6 [dependencies] 7 7 argh = "0.1" 8 - crono = "0.4" 8 + chrono = "0.4" 9 9 --- 10 10 11 11 use argh::FromArgs;