Skip to content

Commit 96ab0e9

Browse files
committed
feat(playmatch): add game metadata command
1 parent b634d8d commit 96ab0e9

1 file changed

Lines changed: 119 additions & 1 deletion

File tree

src/command/playmatch.rs

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ use playmatch_client::types::ManualMatchMode::{Admin, Trusted};
1010
use playmatch_client::types::MetadataProvider::Igdb;
1111
use playmatch_client::types::{
1212
CompanyOrPlatformMatchRequest, CompanyOrPlatformSuggestionRequest, CreateOrGetUserRequest,
13-
GameMatchRequest, GameSuggestionRequest, UpdateUserPermissionsRequest, UserPermissions,
13+
GameMatchRequest, GameMatchType, GameSuggestionRequest, UpdateUserPermissionsRequest,
14+
UserPermissions,
1415
};
16+
use poise::CreateReply;
1517
use reqwest::StatusCode;
1618
use serenity::all::{
1719
ButtonStyle, Cache, ChannelId, ComponentInteractionDataKind, CreateEmbedFooter, ShardMessenger,
@@ -82,6 +84,122 @@ pub async fn list_platforms(ctx: CommandContext<'_>) -> CommandResult {
8284
paginate_playmatch_response(ctx, companies).await
8385
}
8486

87+
/// Gets metadata for a game on Playmatch by hashes or file name and size.
88+
#[poise::command(slash_command, category = "Playmatch", rename = "game")]
89+
pub async fn get_game_metadata(
90+
ctx: CommandContext<'_>,
91+
md5_hash: Option<String>,
92+
sha1_hash: Option<String>,
93+
sha256_hash: Option<String>,
94+
file_name: String,
95+
file_size: i64,
96+
) -> CommandResult {
97+
let response = ctx
98+
.data()
99+
.playmatch_client
100+
.identify_game_and_relations(
101+
&file_name,
102+
file_size,
103+
md5_hash.as_deref(),
104+
sha1_hash.as_deref(),
105+
sha256_hash.as_deref(),
106+
)
107+
.await?;
108+
109+
let inner = response.into_inner();
110+
111+
if inner.game_match_type == GameMatchType::NoMatch {
112+
ctx.reply("No matching game found for the provided hashes or file name and size.")
113+
.await?;
114+
return Ok(());
115+
}
116+
117+
let game = inner.game.ok_or(anyhow!(
118+
"No game found for the provided hashes or file name"
119+
))?;
120+
let game_files = inner.game_files;
121+
let platform = inner.platform.ok_or(anyhow!(
122+
"No platform found for the provided hashes or file name"
123+
))?;
124+
let company = inner.company;
125+
let dat_file = inner.dat_file.ok_or(anyhow!(
126+
"No DAT file found for the provided hashes or file name"
127+
))?;
128+
let signature_group = inner.signature_group.ok_or(anyhow!(
129+
"No signature group found for the provided hashes or file name"
130+
))?;
131+
132+
let files_info = game_files
133+
.iter()
134+
.enumerate()
135+
.map(|(i, file)| {
136+
let mut out = format!("**{}. {}**", i + 1, file.file_name);
137+
if let Some(size) = file.file_size_in_bytes {
138+
out.push_str(&format!("Size: `{:.2} MB`", size as f64 / 1024.0 / 1024.0));
139+
}
140+
if let Some(serial) = &file.serial {
141+
out.push_str(&format!("\nSerial: `{}`", serial));
142+
}
143+
if let Some(crc) = &file.crc {
144+
out.push_str(&format!("\nCRC32: `{}`", crc));
145+
}
146+
if let Some(md5) = &file.md5 {
147+
out.push_str(&format!("\nMD5: `{}`", md5));
148+
}
149+
if let Some(sha1) = &file.sha1 {
150+
out.push_str(&format!("\nSHA1: `{}`", sha1));
151+
}
152+
if let Some(sha256) = &file.sha256 {
153+
out.push_str(&format!("\nSHA256: `{}`", sha256));
154+
}
155+
out
156+
})
157+
.collect::<Vec<_>>()
158+
.join("\n\n");
159+
160+
let dat_file_value = match dat_file.tags {
161+
None => format!(
162+
"**{}**\nCurrent Version: `{}`\n",
163+
dat_file.name, dat_file.current_version
164+
),
165+
Some(tags) => format!(
166+
"**{}**\nCurrent Version: `{}`\nTags: `{}`",
167+
dat_file.name,
168+
dat_file.current_version,
169+
tags.join(", ")
170+
),
171+
};
172+
173+
let signature_group_value = match signature_group.website_link {
174+
None => signature_group.name,
175+
Some(website_link) => format!("[{}]({})", signature_group.name, website_link),
176+
};
177+
178+
// Build the embed
179+
let mut embed = CreateEmbed::new()
180+
.title(game.name)
181+
.color(0x2ecc71)
182+
.field("Match Type", format!("`{}`", inner.game_match_type), true)
183+
.field("Platform", platform.name, true);
184+
185+
if let Some(c) = company {
186+
embed = embed.field("Company", c.name, true)
187+
}
188+
189+
embed = embed
190+
.field("ROM Files", files_info, false)
191+
.field("DAT File", dat_file_value, true)
192+
.field("Signature Group", signature_group_value, false)
193+
.footer(CreateEmbedFooter::new(format!(
194+
"Playmatch Game ID: {}",
195+
game.id
196+
)));
197+
198+
ctx.send(CreateReply::default().embed(embed)).await?;
199+
200+
Ok(())
201+
}
202+
85203
/// Creates a metadata match suggestion for a Game by hashes or name to the IGDB database.
86204
#[poise::command(slash_command, category = "Playmatch", rename = "game", check = is_user_trusted_or_above)]
87205
pub async fn create_game_suggestion(

0 commit comments

Comments
 (0)