Build the project on stable rust
This commit is contained in:
		
					parent
					
						
							
								5bc6dfa667
							
						
					
				
			
			
				commit
				
					
						8d3c26b036
					
				
			
		
					 11 changed files with 126 additions and 178 deletions
				
			
		
							
								
								
									
										31
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										31
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							|  | @ -173,9 +173,9 @@ dependencies = [ | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "async-trait" | name = "async-trait" | ||||||
| version = "0.1.82" | version = "0.1.86" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" | checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "proc-macro2", |  "proc-macro2", | ||||||
|  "quote", |  "quote", | ||||||
|  | @ -219,14 +219,14 @@ dependencies = [ | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "axum" | name = "axum" | ||||||
| version = "0.7.6" | version = "0.8.1" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "8f43644eed690f5374f1af436ecd6aea01cd201f6fbdf0178adaf6907afb2cec" | checksum = "6d6fd624c75e18b3b4c6b9caf42b1afe24437daaee904069137d8bab077be8b8" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "async-trait", |  | ||||||
|  "axum-core", |  "axum-core", | ||||||
|  "axum-macros", |  "axum-macros", | ||||||
|  "bytes", |  "bytes", | ||||||
|  |  "form_urlencoded", | ||||||
|  "futures-util", |  "futures-util", | ||||||
|  "http 1.1.0", |  "http 1.1.0", | ||||||
|  "http-body 1.0.1", |  "http-body 1.0.1", | ||||||
|  | @ -246,7 +246,7 @@ dependencies = [ | ||||||
|  "serde_urlencoded", |  "serde_urlencoded", | ||||||
|  "sync_wrapper 1.0.1", |  "sync_wrapper 1.0.1", | ||||||
|  "tokio", |  "tokio", | ||||||
|  "tower 0.5.1", |  "tower 0.5.2", | ||||||
|  "tower-layer", |  "tower-layer", | ||||||
|  "tower-service", |  "tower-service", | ||||||
|  "tracing", |  "tracing", | ||||||
|  | @ -254,11 +254,10 @@ dependencies = [ | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "axum-core" | name = "axum-core" | ||||||
| version = "0.4.4" | version = "0.5.0" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "5e6b8ba012a258d63c9adfa28b9ddcf66149da6f986c5b5452e629d5ee64bf00" | checksum = "df1362f362fd16024ae199c1970ce98f9661bf5ef94b9808fee734bc3698b733" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "async-trait", |  | ||||||
|  "bytes", |  "bytes", | ||||||
|  "futures-util", |  "futures-util", | ||||||
|  "http 1.1.0", |  "http 1.1.0", | ||||||
|  | @ -275,9 +274,9 @@ dependencies = [ | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "axum-macros" | name = "axum-macros" | ||||||
| version = "0.4.2" | version = "0.5.0" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" | checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "proc-macro2", |  "proc-macro2", | ||||||
|  "quote", |  "quote", | ||||||
|  | @ -2002,9 +2001,9 @@ dependencies = [ | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "matchit" | name = "matchit" | ||||||
| version = "0.7.3" | version = "0.8.4" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" | checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "matrixcompare" | name = "matrixcompare" | ||||||
|  | @ -3924,14 +3923,14 @@ dependencies = [ | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "tower" | name = "tower" | ||||||
| version = "0.5.1" | version = "0.5.2" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" | checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "futures-core", |  "futures-core", | ||||||
|  "futures-util", |  "futures-util", | ||||||
|  "pin-project-lite", |  "pin-project-lite", | ||||||
|  "sync_wrapper 0.1.2", |  "sync_wrapper 1.0.1", | ||||||
|  "tokio", |  "tokio", | ||||||
|  "tower-layer", |  "tower-layer", | ||||||
|  "tower-service", |  "tower-service", | ||||||
|  |  | ||||||
|  | @ -46,7 +46,7 @@ postcard = { version = "1.0.10", features = ["use-std"], default-features = fals | ||||||
| anyhow = "1.0.87" | anyhow = "1.0.87" | ||||||
| sha2 = "0.10.8" | sha2 = "0.10.8" | ||||||
| base16ct = { version = "0.2.0", features = ["alloc"] } | base16ct = { version = "0.2.0", features = ["alloc"] } | ||||||
| axum = { version = "0.7.6", features = ["macros"] } | axum = { version = "0.8.1", features = ["macros"] } | ||||||
| paste = "1.0.15" | paste = "1.0.15" | ||||||
| discord-rich-presence = "0.2.4" | discord-rich-presence = "0.2.4" | ||||||
| reqwest = { version = "0.12.7", features = ["json"] } | reqwest = { version = "0.12.7", features = ["json"] } | ||||||
|  |  | ||||||
|  | @ -24,6 +24,8 @@ No neural-networks/machine-learning is used by this project. All image analysis | ||||||
| 
 | 
 | ||||||
| ## Running locally | ## Running locally | ||||||
| 
 | 
 | ||||||
|  | > WARNING: the instructions in this file are a bit outdated. | ||||||
|  | 
 | ||||||
| The programs need (sometimes a subset of) the following environment variables in order to run: | The programs need (sometimes a subset of) the following environment variables in order to run: | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
							
								
								
									
										39
									
								
								flake.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										39
									
								
								flake.lock
									
										
									
										generated
									
									
									
								
							|  | @ -1,26 +1,5 @@ | ||||||
| { | { | ||||||
|   "nodes": { |   "nodes": { | ||||||
|     "fenix": { |  | ||||||
|       "inputs": { |  | ||||||
|         "nixpkgs": [ |  | ||||||
|           "nixpkgs" |  | ||||||
|         ], |  | ||||||
|         "rust-analyzer-src": "rust-analyzer-src" |  | ||||||
|       }, |  | ||||||
|       "locked": { |  | ||||||
|         "lastModified": 1739169164, |  | ||||||
|         "narHash": "sha256-2+/6/2rHsMjlrulkrjZbwthCQiQpeW2pukRFaaUMLy8=", |  | ||||||
|         "owner": "nix-community", |  | ||||||
|         "repo": "fenix", |  | ||||||
|         "rev": "d7616af878cd0cb7f940b470440347920395be0c", |  | ||||||
|         "type": "github" |  | ||||||
|       }, |  | ||||||
|       "original": { |  | ||||||
|         "owner": "nix-community", |  | ||||||
|         "repo": "fenix", |  | ||||||
|         "type": "github" |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "flake-utils": { |     "flake-utils": { | ||||||
|       "inputs": { |       "inputs": { | ||||||
|         "systems": "systems" |         "systems": "systems" | ||||||
|  | @ -57,29 +36,11 @@ | ||||||
|     }, |     }, | ||||||
|     "root": { |     "root": { | ||||||
|       "inputs": { |       "inputs": { | ||||||
|         "fenix": "fenix", |  | ||||||
|         "flake-utils": "flake-utils", |         "flake-utils": "flake-utils", | ||||||
|         "nixpkgs": "nixpkgs", |         "nixpkgs": "nixpkgs", | ||||||
|         "shimmeringdarkness": "shimmeringdarkness" |         "shimmeringdarkness": "shimmeringdarkness" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "rust-analyzer-src": { |  | ||||||
|       "flake": false, |  | ||||||
|       "locked": { |  | ||||||
|         "lastModified": 1739099919, |  | ||||||
|         "narHash": "sha256-YUdM2yZzQIbakgc2LdVmkgJMYTqeTu3YdWGgFfiZiTg=", |  | ||||||
|         "owner": "rust-lang", |  | ||||||
|         "repo": "rust-analyzer", |  | ||||||
|         "rev": "35181e167efb94d5090df588e6af9f93250421f3", |  | ||||||
|         "type": "github" |  | ||||||
|       }, |  | ||||||
|       "original": { |  | ||||||
|         "owner": "rust-lang", |  | ||||||
|         "ref": "nightly", |  | ||||||
|         "repo": "rust-analyzer", |  | ||||||
|         "type": "github" |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "shimmeringdarkness": { |     "shimmeringdarkness": { | ||||||
|       "flake": false, |       "flake": false, | ||||||
|       "locked": { |       "locked": { | ||||||
|  |  | ||||||
							
								
								
									
										19
									
								
								flake.nix
									
										
									
									
									
								
							
							
						
						
									
										19
									
								
								flake.nix
									
										
									
									
									
								
							|  | @ -2,8 +2,6 @@ | ||||||
|   inputs = { |   inputs = { | ||||||
|     nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; |     nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; | ||||||
|     flake-utils.url = "github:numtide/flake-utils"; |     flake-utils.url = "github:numtide/flake-utils"; | ||||||
|     fenix.url = "github:nix-community/fenix"; |  | ||||||
|     fenix.inputs.nixpkgs.follows = "nixpkgs"; |  | ||||||
|     shimmeringdarkness.url = "git+ssh://forgejo@ssh.git.moonythm.dev/prescientmoon/shimmeringdarkness.git"; |     shimmeringdarkness.url = "git+ssh://forgejo@ssh.git.moonythm.dev/prescientmoon/shimmeringdarkness.git"; | ||||||
|     shimmeringdarkness.flake = false; |     shimmeringdarkness.flake = false; | ||||||
|   }; |   }; | ||||||
|  | @ -13,15 +11,12 @@ | ||||||
|     inputs.flake-utils.lib.eachSystem (with inputs.flake-utils.lib.system; [ x86_64-linux ]) ( |     inputs.flake-utils.lib.eachSystem (with inputs.flake-utils.lib.system; [ x86_64-linux ]) ( | ||||||
|       system: |       system: | ||||||
|       let |       let | ||||||
|         pkgs = inputs.nixpkgs.legacyPackages.${system}.extend inputs.fenix.overlays.default; |         pkgs = inputs.nixpkgs.legacyPackages.${system}; | ||||||
|         rust-toolchain = pkgs.fenix.complete.toolchain; |  | ||||||
|         spkgs = inputs.self.packages.${system}; |         spkgs = inputs.self.packages.${system}; | ||||||
|         inherit (pkgs) lib; |         inherit (pkgs) lib; | ||||||
|       in |       in | ||||||
|       { |       { | ||||||
|         packages = { |         packages = { | ||||||
|           inherit rust-toolchain; |  | ||||||
| 
 |  | ||||||
|           # {{{ Private config |           # {{{ Private config | ||||||
|           shimmeringdarkness = inputs.shimmeringdarkness.outPath; |           shimmeringdarkness = inputs.shimmeringdarkness.outPath; | ||||||
|           glass-bundler = pkgs.callPackage ./nix/glass-bundler.nix { }; |           glass-bundler = pkgs.callPackage ./nix/glass-bundler.nix { }; | ||||||
|  | @ -43,23 +38,27 @@ | ||||||
|             inherit (spkgs) exo kazesawa geosans-light; |             inherit (spkgs) exo kazesawa geosans-light; | ||||||
|           }; |           }; | ||||||
|           # }}} |           # }}} | ||||||
| 
 |           # {{{ Shimmeringmoon | ||||||
|           cc-data = pkgs.callPackage ./nix/cc-data.nix { }; |           cc-data = pkgs.callPackage ./nix/cc-data.nix { }; | ||||||
|           default = spkgs.shimmeringmoon; |           default = spkgs.shimmeringmoon; | ||||||
|           shimmeringmoon = pkgs.callPackage ./nix/shimmeringmoon.nix { |           shimmeringmoon = pkgs.callPackage ./nix/shimmeringmoon.nix { | ||||||
|             inherit (spkgs) |             inherit (spkgs) | ||||||
|               shimmering-fonts |               shimmering-fonts | ||||||
|               rust-toolchain |  | ||||||
|               cc-data |               cc-data | ||||||
|               private-config |               private-config | ||||||
|               ; |               ; | ||||||
|           }; |           }; | ||||||
|  |           # }}} | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         #  {{{ Devshell |         #  {{{ Devshell | ||||||
|         devShell = pkgs.mkShell rec { |         devShell = pkgs.mkShell rec { | ||||||
|           nativeBuildInputs = with pkgs; [ |           nativeBuildInputs = [ | ||||||
|             spkgs.rust-toolchain |             pkgs.rustc | ||||||
|  |             pkgs.cargo | ||||||
|  |             pkgs.rustfmt | ||||||
|  |             pkgs.clippy | ||||||
|  |             pkgs.rust-analyzer | ||||||
| 
 | 
 | ||||||
|             pkgs.ruff |             pkgs.ruff | ||||||
|             pkgs.imagemagick |             pkgs.imagemagick | ||||||
|  |  | ||||||
|  | @ -1,5 +1,4 @@ | ||||||
| { | { | ||||||
|   lib, |  | ||||||
|   pkg-config, |   pkg-config, | ||||||
|   makeWrapper, |   makeWrapper, | ||||||
| 
 | 
 | ||||||
|  | @ -7,19 +6,12 @@ | ||||||
|   fontconfig, |   fontconfig, | ||||||
|   openssl, |   openssl, | ||||||
|   sqlite, |   sqlite, | ||||||
|   makeRustPlatform, |   rustPlatform, | ||||||
|   rust-toolchain, |  | ||||||
| 
 | 
 | ||||||
|   shimmering-fonts, |   shimmering-fonts, | ||||||
|   cc-data, |   cc-data, | ||||||
|   private-config, |   private-config, | ||||||
| }: | }: | ||||||
| let |  | ||||||
|   rustPlatform = makeRustPlatform { |  | ||||||
|     cargo = rust-toolchain; |  | ||||||
|     rustc = rust-toolchain; |  | ||||||
|   }; |  | ||||||
| in |  | ||||||
| rustPlatform.buildRustPackage rec { | rustPlatform.buildRustPackage rec { | ||||||
|   pname = "shimmeringmoon"; |   pname = "shimmeringmoon"; | ||||||
|   version = "unstable-2025-02-11"; |   version = "unstable-2025-02-11"; | ||||||
|  |  | ||||||
|  | @ -32,8 +32,8 @@ async fn main() -> anyhow::Result<()> { | ||||||
| 						return Ok(None); | 						return Ok(None); | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					if let (Ok(global_prefix)) = global_prefix { | 					if let Ok(global_prefix) = global_prefix { | ||||||
| 						if message.content.starts_with(global_prefix) { | 						if message.content.starts_with(&global_prefix) { | ||||||
| 							return Ok(Some(message.content.split_at(global_prefix.len()))); | 							return Ok(Some(message.content.split_at(global_prefix.len()))); | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
|  | @ -46,7 +46,7 @@ async fn main() -> anyhow::Result<()> { | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					return Ok(None); | 					Ok(None) | ||||||
| 				}) | 				}) | ||||||
| 			}), | 			}), | ||||||
| 			edit_tracker: Some(Arc::new(poise::EditTracker::for_timespan( | 			edit_tracker: Some(Arc::new(poise::EditTracker::for_timespan( | ||||||
|  |  | ||||||
|  | @ -4,9 +4,10 @@ use crate::arcaea::score::Score; | ||||||
| use crate::context::{Error, ErrorKind, PoiseContext, TagError, TaggedError}; | use crate::context::{Error, ErrorKind, PoiseContext, TagError, TaggedError}; | ||||||
| use crate::recognition::recognize::{ImageAnalyzer, ScoreKind}; | use crate::recognition::recognize::{ImageAnalyzer, ScoreKind}; | ||||||
| use crate::user::User; | use crate::user::User; | ||||||
| use crate::{async_try_block, get_user_error, timed}; | use crate::{get_user_error, timed}; | ||||||
| use anyhow::anyhow; | use anyhow::anyhow; | ||||||
| use image::DynamicImage; | use image::DynamicImage; | ||||||
|  | use poise::serenity_prelude::{CreateAttachment, CreateEmbed}; | ||||||
| use poise::{serenity_prelude as serenity, CreateReply}; | use poise::{serenity_prelude as serenity, CreateReply}; | ||||||
| 
 | 
 | ||||||
| use super::discord::{CreateReplyExtra, MessageContext}; | use super::discord::{CreateReplyExtra, MessageContext}; | ||||||
|  | @ -26,62 +27,49 @@ pub async fn score(_ctx: PoiseContext<'_>) -> Result<(), Error> { | ||||||
| // }}}
 | // }}}
 | ||||||
| // {{{ Score magic
 | // {{{ Score magic
 | ||||||
| // {{{ Implementation
 | // {{{ Implementation
 | ||||||
| pub async fn magic_impl<C: MessageContext>( | #[allow(clippy::too_many_arguments)] | ||||||
|  | async fn magic_detect_one<C: MessageContext>( | ||||||
| 	ctx: &mut C, | 	ctx: &mut C, | ||||||
| 	files: &[C::Attachment], | 	user: &User, | ||||||
| ) -> Result<Vec<Play>, TaggedError> { | 	embeds: &mut Vec<CreateEmbed>, | ||||||
| 	let user = User::from_context(ctx)?; | 	attachments: &mut Vec<CreateAttachment>, | ||||||
| 	let files = ctx.download_images(files).await?; | 	plays: &mut Vec<Play>, | ||||||
| 
 | 	analyzer: &mut ImageAnalyzer, | ||||||
| 	if files.is_empty() { | 	attachment: &C::Attachment, | ||||||
| 		return Err(anyhow!("No images found attached to message").tag(ErrorKind::User)); | 	index: usize, | ||||||
| 	} | 	image: &mut DynamicImage, | ||||||
| 
 | 	grayscale_image: &mut DynamicImage, | ||||||
| 	let mut embeds = Vec::with_capacity(files.len()); | ) -> Result<(), TaggedError> { | ||||||
| 	let mut attachments = Vec::with_capacity(files.len()); |  | ||||||
| 	let mut plays = Vec::with_capacity(files.len()); |  | ||||||
| 	let mut analyzer = ImageAnalyzer::default(); |  | ||||||
| 
 |  | ||||||
| 	for (i, (attachment, bytes)) in files.into_iter().enumerate() { |  | ||||||
| 		// {{{ Preapare image
 |  | ||||||
| 		let mut image = image::load_from_memory(&bytes)?; |  | ||||||
| 		let mut grayscale_image = DynamicImage::ImageLuma8(image.to_luma8()); |  | ||||||
| 		// }}}
 |  | ||||||
| 
 |  | ||||||
| 		let result: Result<(), TaggedError> = async_try_block!({ |  | ||||||
| 	// {{{ Detection
 | 	// {{{ Detection
 | ||||||
| 
 |  | ||||||
| 	let kind = timed!("read_score_kind", { | 	let kind = timed!("read_score_kind", { | ||||||
| 				analyzer.read_score_kind(ctx.data(), &grayscale_image)? | 		analyzer.read_score_kind(ctx.data(), grayscale_image)? | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
| 	let difficulty = timed!("read_difficulty", { | 	let difficulty = timed!("read_difficulty", { | ||||||
| 				analyzer.read_difficulty(ctx.data(), &image, &grayscale_image, kind)? | 		analyzer.read_difficulty(ctx.data(), image, grayscale_image, kind)? | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
| 	let (song, chart) = timed!("read_jacket", { | 	let (song, chart) = timed!("read_jacket", { | ||||||
| 				analyzer.read_jacket(ctx.data(), &mut image, kind, difficulty)? | 		analyzer.read_jacket(ctx.data(), image, kind, difficulty)? | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
| 	let max_recall = match kind { | 	let max_recall = match kind { | ||||||
| 		ScoreKind::ScoreScreen => { | 		ScoreKind::ScoreScreen => { | ||||||
| 			// NOTE: are we ok with discarding errors like that?
 | 			// NOTE: are we ok with discarding errors like that?
 | ||||||
| 					analyzer.read_max_recall(ctx.data(), &grayscale_image).ok() | 			analyzer.read_max_recall(ctx.data(), grayscale_image).ok() | ||||||
| 		} | 		} | ||||||
| 		ScoreKind::SongSelect => None, | 		ScoreKind::SongSelect => None, | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	grayscale_image.invert(); | 	grayscale_image.invert(); | ||||||
| 	let note_distribution = match kind { | 	let note_distribution = match kind { | ||||||
| 				ScoreKind::ScoreScreen => { | 		ScoreKind::ScoreScreen => Some(analyzer.read_distribution(ctx.data(), grayscale_image)?), | ||||||
| 					Some(analyzer.read_distribution(ctx.data(), &grayscale_image)?) |  | ||||||
| 				} |  | ||||||
| 		ScoreKind::SongSelect => None, | 		ScoreKind::SongSelect => None, | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	let score = timed!("read_score", { | 	let score = timed!("read_score", { | ||||||
| 		analyzer | 		analyzer | ||||||
| 					.read_score(ctx.data(), Some(chart.note_count), &grayscale_image, kind) | 			.read_score(ctx.data(), Some(chart.note_count), grayscale_image, kind) | ||||||
| 			.map_err(|err| { | 			.map_err(|err| { | ||||||
| 				anyhow!( | 				anyhow!( | ||||||
| 					"Could not read score for chart {} [{:?}]: {err}", | 					"Could not read score for chart {} [{:?}]: {err}", | ||||||
|  | @ -99,20 +87,57 @@ pub async fn magic_impl<C: MessageContext>( | ||||||
| 		.with_attachment(C::attachment_id(attachment)) | 		.with_attachment(C::attachment_id(attachment)) | ||||||
| 		.with_fars(maybe_fars) | 		.with_fars(maybe_fars) | ||||||
| 		.with_max_recall(max_recall) | 		.with_max_recall(max_recall) | ||||||
| 				.save(ctx.data(), &user, chart) | 		.save(ctx.data(), user, chart) | ||||||
| 		.await?; | 		.await?; | ||||||
| 	// }}}
 | 	// }}}
 | ||||||
| 	// }}}
 | 	// }}}
 | ||||||
| 	// {{{ Deliver embed
 | 	// {{{ Deliver embed
 | ||||||
| 	let (embed, attachment) = timed!("to embed", { | 	let (embed, attachment) = timed!("to embed", { | ||||||
| 				play.to_embed(ctx.data(), &user, song, chart, i, None)? | 		play.to_embed(ctx.data(), user, song, chart, index, None)? | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
| 	plays.push(play); | 	plays.push(play); | ||||||
| 	embeds.push(embed); | 	embeds.push(embed); | ||||||
| 	attachments.extend(attachment); | 	attachments.extend(attachment); | ||||||
| 	// }}}
 | 	// }}}
 | ||||||
| 		}); | 
 | ||||||
|  | 	Ok(()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub async fn magic_impl<C: MessageContext>( | ||||||
|  | 	ctx: &mut C, | ||||||
|  | 	files: &[C::Attachment], | ||||||
|  | ) -> Result<Vec<Play>, TaggedError> { | ||||||
|  | 	let user = User::from_context(ctx)?; | ||||||
|  | 	let files = ctx.download_images(files).await?; | ||||||
|  | 
 | ||||||
|  | 	if files.is_empty() { | ||||||
|  | 		return Err(anyhow!("No images found attached to message").tag(ErrorKind::User)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	let mut embeds = Vec::with_capacity(files.len()); | ||||||
|  | 	let mut attachments = Vec::with_capacity(files.len()); | ||||||
|  | 	let mut plays = Vec::with_capacity(files.len()); | ||||||
|  | 	let mut analyzer = ImageAnalyzer::default(); | ||||||
|  | 
 | ||||||
|  | 	for (i, (attachment, bytes)) in files.into_iter().enumerate() { | ||||||
|  | 		// {{{ Process attachment
 | ||||||
|  | 		let mut image = image::load_from_memory(&bytes)?; | ||||||
|  | 		let mut grayscale_image = DynamicImage::ImageLuma8(image.to_luma8()); | ||||||
|  | 
 | ||||||
|  | 		let result = magic_detect_one( | ||||||
|  | 			ctx, | ||||||
|  | 			&user, | ||||||
|  | 			&mut embeds, | ||||||
|  | 			&mut attachments, | ||||||
|  | 			&mut plays, | ||||||
|  | 			&mut analyzer, | ||||||
|  | 			attachment, | ||||||
|  | 			i, | ||||||
|  | 			&mut image, | ||||||
|  | 			&mut grayscale_image, | ||||||
|  | 		) | ||||||
|  | 		.await; | ||||||
| 
 | 
 | ||||||
| 		if let Err(err) = result { | 		if let Err(err) = result { | ||||||
| 			let user_err = get_user_error!(err); | 			let user_err = get_user_error!(err); | ||||||
|  | @ -120,6 +145,7 @@ pub async fn magic_impl<C: MessageContext>( | ||||||
| 				.send_discord_error(ctx, &image, C::filename(attachment), user_err) | 				.send_discord_error(ctx, &image, C::filename(attachment), user_err) | ||||||
| 				.await?; | 				.await?; | ||||||
| 		} | 		} | ||||||
|  | 		// }}}
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if !embeds.is_empty() { | 	if !embeds.is_empty() { | ||||||
|  |  | ||||||
|  | @ -27,6 +27,5 @@ pub fn hash_bytes(bytes: &[u8]) -> String { | ||||||
| 	let mut hasher = Sha256::default(); | 	let mut hasher = Sha256::default(); | ||||||
| 	hasher.update(bytes); | 	hasher.update(bytes); | ||||||
| 	let res = hasher.finalize(); | 	let res = hasher.finalize(); | ||||||
| 	let string = base16ct::lower::encode_string(&res); | 	base16ct::lower::encode_string(&res) | ||||||
| 	string |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -17,4 +17,3 @@ pub mod recognition; | ||||||
| pub mod time; | pub mod time; | ||||||
| pub mod transform; | pub mod transform; | ||||||
| pub mod user; | pub mod user; | ||||||
| mod utils; |  | ||||||
|  |  | ||||||
							
								
								
									
										29
									
								
								src/utils.rs
									
										
									
									
									
								
							
							
						
						
									
										29
									
								
								src/utils.rs
									
										
									
									
									
								
							|  | @ -1,29 +0,0 @@ | ||||||
| /// Performs "Ok-wrapping" on the result of an expression.
 |  | ||||||
| /// This is compatible with [`Result`], [`Option`], [`ControlFlow`], and any type that
 |  | ||||||
| /// implements the unstable [`std::ops::Try`] trait.
 |  | ||||||
| ///
 |  | ||||||
| /// The destination type must be specified with a type ascription somewhere.
 |  | ||||||
| #[macro_export] |  | ||||||
| macro_rules! wrap_ok { |  | ||||||
| 	($e:expr) => { |  | ||||||
| 		::core::iter::empty().try_fold($e, |_, __x: ::core::convert::Infallible| match __x {}) |  | ||||||
| 	}; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[macro_export] |  | ||||||
| macro_rules! try_block { |  | ||||||
|     { $($token:tt)* } => { |  | ||||||
|         (|| $crate::wrap_ok!({ |  | ||||||
|             $($token)* |  | ||||||
|         }))() |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[macro_export] |  | ||||||
| macro_rules! async_try_block { |  | ||||||
|     { $($token:tt)* } => { |  | ||||||
|         (async || $crate::wrap_ok!({ |  | ||||||
|             $($token)* |  | ||||||
|         }))().await |  | ||||||
|     } |  | ||||||
| } |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue