game_manager_lib/services/integration/pcgamingwiki/
parsers.rs1use serde_json::Value;
7
8type L10nLists = (
9 Option<Vec<String>>,
10 Option<Vec<String>>,
11 Option<Vec<String>>,
12);
13
14pub(crate) fn parse_l10n_rows(rows: &[Value]) -> L10nLists {
20 let mut interface_langs = Vec::new();
21 let mut audio_langs = Vec::new();
22 let mut subtitle_langs = Vec::new();
23
24 for row in rows {
25 let title = match row.get("title") {
26 Some(t) => t,
27 None => continue,
28 };
29
30 let language = match title.get("language").and_then(|v| v.as_str()) {
31 Some(l) if !l.is_empty() => l.to_string(),
32 _ => continue,
33 };
34
35 let is_supported = |key: &str| -> bool {
36 title
37 .get(key)
38 .and_then(|v| v.as_str())
39 .map(|s| s == "true" || s == "hackable")
40 .unwrap_or(false)
41 };
42
43 if is_supported("interface") {
44 interface_langs.push(language.clone());
45 }
46 if is_supported("audio") {
47 audio_langs.push(language.clone());
48 }
49 if is_supported("subtitles") {
50 subtitle_langs.push(language.clone());
51 }
52 }
53
54 (
55 if interface_langs.is_empty() {
56 None
57 } else {
58 Some(interface_langs)
59 },
60 if audio_langs.is_empty() {
61 None
62 } else {
63 Some(audio_langs)
64 },
65 if subtitle_langs.is_empty() {
66 None
67 } else {
68 Some(subtitle_langs)
69 },
70 )
71}
72
73pub(crate) fn extract_field(rows: &[Value], key: &str) -> Option<String> {
75 rows.first()
76 .and_then(|row| row.get("title"))
77 .and_then(|title| title.get(key))
78 .and_then(|v| v.as_str())
79 .map(|s| s.trim().to_string())
80 .filter(|s| !s.is_empty())
81}
82
83pub(crate) fn normalize_bool_field(value: Option<String>) -> Option<String> {
88 value.map(|v| v.to_lowercase()).filter(|v| !v.is_empty())
89}