Merge branch 'main' into 'main'

Implement /v1/api/miis?pids=

See merge request spfn/account!5
This commit is contained in:
red binder 2026-04-12 13:36:16 +00:00
commit 921cb82913
3 changed files with 122 additions and 0 deletions

View file

@ -144,6 +144,7 @@ async fn launch() -> _ {
nnid::people::get_device_owner, nnid::people::get_device_owner,
nnid::people::get_own_device, nnid::people::get_own_device,
nnid::people::change_mii, nnid::people::change_mii,
nnid::miis::get_miis,
nnid::oauth::generate_token::generate_token, nnid::oauth::generate_token::generate_token,
nnid::provider::get_nex_token, nnid::provider::get_nex_token,
nnid::provider::get_service_token, nnid::provider::get_service_token,

120
src/nnid/miis.rs Normal file
View file

@ -0,0 +1,120 @@
use rocket::{get, State};
use crate::Pool;
use crate::xml::{Xml, YesNoVal};
use crate::error::Errors;
use crate::mii_util::MII_PROVIDER_SERVER_URL;
use serde::Serialize;
use gxhash::gxhash32;
#[derive(Serialize)]
pub struct MiiImage {
pub cached_url: String,
pub id: u32,
pub url: String,
#[serde(rename = "type")]
pub image_type: String,
}
#[derive(Serialize)]
pub struct MiiImages {
pub image: Vec<MiiImage>,
}
#[derive(Serialize)]
pub struct MiiEntry {
pub data: String,
pub id: u32,
pub images: MiiImages,
pub name: String,
pub pid: i32,
pub primary: YesNoVal,
pub user_id: String,
}
#[derive(Serialize)]
#[serde(rename = "miis")]
pub struct MiisResponse {
#[serde(rename = "mii")]
pub miis: Vec<MiiEntry>,
}
#[get("/v1/api/miis?<pids>")]
pub async fn get_miis(
database: &State<Pool>,
pids: Option<String>,
) -> Result<Xml<MiisResponse>, Option<Errors<'static>>> {
let db = database.inner();
let input = pids.filter(|s| !s.is_empty()).ok_or(None)?;
let pid_list: Vec<i32> = input
.split(',')
.filter_map(|s| s.parse::<i32>().ok())
.collect();
if pid_list.is_empty() {
return Err(None);
}
let rows = sqlx::query!(
"SELECT pid, username, mii_data FROM users WHERE pid = ANY($1)",
&pid_list
)
.fetch_all(db)
.await
.map_err(|_| None)?;
if rows.is_empty() {
return Err(None);
}
let mut miis = Vec::new();
for row in rows {
let clean_mii_data = row.mii_data
.replace(['\r', '\n', '\t', ' '], "");
let mii_id = gxhash32(clean_mii_data.as_bytes(), 0);
let expression_types = [
("normal_face.png", "standard"),
("frustrated.png", "frustrated_face"),
("smile_open_mouth.png", "happy_face"),
("wink_left.png", "like_face"),
("normal_face.png", "normal_face"), // pretendo had this duplicated, and i'm not taking any chances
("sorrow.png", "puzzled_face"),
("surprised_open_mouth.png", "surprised_face"),
("body.png", "whole_body"),
];
let images = MiiImages {
image: expression_types
.iter()
.map(|(file, img_type)| {
// dummy URL for now
let url = format!("{}/{}/{}", &*MII_PROVIDER_SERVER_URL, row.pid, file);
MiiImage {
cached_url: url.clone(),
id: mii_id,
url,
image_type: img_type.to_string(),
}
})
.collect(),
};
miis.push(MiiEntry {
data: clean_mii_data,
id: mii_id,
images,
name: mii::MiiData::read(&row.mii_data)
.map(|v| v.name)
.unwrap_or_else(|| "Mii".to_string()),
pid: row.pid,
primary: YesNoVal(true), //assuming true here
user_id: row.username,
});
}
Ok(Xml(MiisResponse { miis }))
}

View file

@ -8,3 +8,4 @@ pub mod people;
pub mod provider; pub mod provider;
pub mod mapped_ids; pub mod mapped_ids;
pub mod support; pub mod support;
pub mod miis;