use crate::client::{format_req_param, TrendsClient};
use crate::models::{RelatedItem, RelatedQueries, WidgetToken};
use crate::{Result, TrendsError};
impl TrendsClient {
pub async fn related_queries(&self, token: &WidgetToken) -> Result<RelatedQueries> {
let url = "https://trends.google.com/trends/api/widgetdata/relatedsearches";
let req_str = format_req_param(&token.request)?;
let tz_str = self.tz.to_string();
let params = vec![
("hl", self.hl.as_str()),
("tz", tz_str.as_str()),
("req", req_str.as_str()),
("token", token.token.as_str()),
];
let result = self.get_json_with_params(url, ¶ms).await?;
let ranked_list = result
.pointer("/default/rankedList")
.and_then(|r| r.as_array())
.ok_or_else(|| {
TrendsError::TokenNotFound(
"Missing 'default/rankedList' in relatedsearches response".into(),
)
})?;
let mut top_queries = Vec::new();
let mut rising_queries = Vec::new();
for (index, list) in ranked_list.iter().enumerate() {
let Some(items) = list.get("rankedKeyword").and_then(|rk| rk.as_array()) else {
continue;
};
let list_type = list
.get("rankedListType")
.and_then(|t| t.as_str())
.unwrap_or_default()
.to_ascii_uppercase();
let target = if list_type == "TOP" {
&mut top_queries
} else if list_type == "RISING" {
&mut rising_queries
} else if index == 0 {
&mut top_queries
} else if index == 1 {
&mut rising_queries
} else {
continue;
};
for item in items {
let value_str = item
.get("formattedValue")
.and_then(|v| v.as_str())
.or_else(|| item.get("value").and_then(|v| v.as_str()))
.map(|v| v.to_string())
.or_else(|| item.get("value").map(|v| v.to_string()))
.unwrap_or_default();
target.push(RelatedItem {
query: item
.get("query")
.and_then(|v| v.as_str())
.unwrap_or("")
.to_string(),
value: value_str,
link: item
.get("link")
.and_then(|v| v.as_str())
.unwrap_or("")
.to_string(),
});
}
}
Ok(RelatedQueries {
top: top_queries,
rising: rising_queries,
})
}
}