Skip to content

Commit 5e064fa

Browse files
committed
fix: improve mihomo error logging to not cause exceptions
1 parent decf0f0 commit 5e064fa

1 file changed

Lines changed: 77 additions & 3 deletions

File tree

src/mihomo.rs

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use serde_json::Value;
77
use sqlx::PgPool;
88
use utoipa::ToSchema;
99

10-
use anyhow::Result;
10+
use anyhow::{bail, Context, Result};
1111

1212
use crate::{database, Language};
1313

@@ -50,6 +50,55 @@ fn load_cached(language: &Language, uid: i32) -> Result<Option<Mihomo>> {
5050
}
5151
}
5252

53+
async fn fetch_json(url: &str, uid: i32, language: Language, label: &str) -> Result<Value> {
54+
let response = reqwest::get(url)
55+
.await
56+
.with_context(|| format!("{label} request failed for uid {uid} language {language}"))?;
57+
58+
let status = response.status();
59+
if !status.is_success() {
60+
let body = response.text().await.unwrap_or_default();
61+
warn!(
62+
uid,
63+
language = %language,
64+
url = %url,
65+
status = %status,
66+
body = %body,
67+
label,
68+
"response was not successful"
69+
);
70+
bail!(
71+
"{label} request returned non-success status {status} for uid {uid} language {language}"
72+
);
73+
}
74+
75+
let text = response
76+
.text()
77+
.await
78+
.with_context(|| format!("mihomo {label} body read failed for uid {uid} language {language}"))?;
79+
80+
match serde_json::from_str(&text) {
81+
Ok(json) => Ok(json),
82+
Err(err) => {
83+
warn!(
84+
uid,
85+
language = %language,
86+
url = %url,
87+
status = %status,
88+
body = %text,
89+
label,
90+
error = %err,
91+
"response decode failed"
92+
);
93+
Err(err).with_context(|| {
94+
format!(
95+
"{label} json decode failed for uid {uid} language {language} status {status}"
96+
)
97+
})
98+
}
99+
}
100+
}
101+
53102
pub async fn get(uid: i32, language: Language, pool: &PgPool) -> Result<Value> {
54103
let path = cache_path(&language, uid);
55104

@@ -79,23 +128,41 @@ pub async fn get(uid: i32, language: Language, pool: &PgPool) -> Result<Value> {
79128

80129
pub async fn update_and_get(uid: i32, language: Language, pool: &PgPool) -> Result<Value> {
81130
let now = Utc::now();
131+
debug!(uid, language = %language, "mihomo update_and_get start");
82132

83133
let url = format!(
84134
"https://api.mihomo.me/sr_info_parsed/{uid}?lang={}&version=v2",
85135
language.mihomo()
86136
);
137+
debug!(uid, language = %language, url = %url, "fetching mihomo payload");
87138

88-
let mut json: Value = reqwest::get(&url).await?.json().await?;
139+
let mut json: Value = match fetch_json(&url, uid, language, "localized").await {
140+
Ok(json) => json,
141+
Err(err) => {
142+
warn!(uid, language = %language, url = %url, error = %err, "mihomo localized fetch failed");
143+
return Err(err);
144+
}
145+
};
146+
debug!(uid, language = %language, "fetched mihomo payload");
89147
if let Some(o) = json.as_object_mut() {
90148
o.insert("updated_at".to_string(), serde_json::to_value(now)?);
91149
}
92150

93151
let (en_json, is_english) = if language == Language::En {
152+
debug!(uid, language = %language, "using fetched payload as english payload");
94153
(json.clone(), true)
95154
} else {
96155
let en_url = format!("https://api.mihomo.me/sr_info_parsed/{uid}?lang=en&version=v2",);
156+
debug!(uid, language = %language, url = %en_url, "fetching english mihomo payload");
97157

98-
let mut en_json: Value = reqwest::get(&en_url).await?.json().await?;
158+
let mut en_json: Value = match fetch_json(&en_url, uid, language, "english").await {
159+
Ok(json) => json,
160+
Err(err) => {
161+
warn!(uid, language = %language, url = %en_url, error = %err, "mihomo english fetch failed");
162+
return Err(err);
163+
}
164+
};
165+
debug!(uid, language = %language, "fetched english mihomo payload");
99166
if let Some(o) = en_json.as_object_mut() {
100167
o.insert("updated_at".to_string(), serde_json::to_value(now)?);
101168
}
@@ -108,6 +175,9 @@ pub async fn update_and_get(uid: i32, language: Language, pool: &PgPool) -> Resu
108175
let writer = brotli::CompressorWriter::new(file, 4096, 4, 22);
109176

110177
serde_json::to_writer(writer, &json)?;
178+
debug!(uid, language = %language, "cached mihomo payload");
179+
} else {
180+
debug!(uid, language = %language, "skipped caching localized mihomo payload");
111181
}
112182

113183
if !is_english && serde_json::from_value::<Mihomo>(en_json.clone()).is_ok() {
@@ -116,6 +186,9 @@ pub async fn update_and_get(uid: i32, language: Language, pool: &PgPool) -> Resu
116186
let writer = brotli::CompressorWriter::new(file, 4096, 4, 22);
117187

118188
serde_json::to_writer(writer, &en_json)?;
189+
debug!(uid, language = %language, "cached english mihomo payload");
190+
} else if !is_english {
191+
debug!(uid, language = %language, "skipped caching english mihomo payload");
119192
}
120193

121194
let mihomo: Mihomo = serde_json::from_value(en_json)?;
@@ -177,6 +250,7 @@ pub async fn update_and_get(uid: i32, language: Language, pool: &PgPool) -> Resu
177250
};
178251

179252
database::achievement_scores::set(&db_score_achievement, pool).await?;
253+
debug!(uid, language = %language, timestamp = %timestamp, "mihomo update_and_get complete");
180254

181255
Ok(json)
182256
}

0 commit comments

Comments
 (0)