use std::collections::HashSet;
use serde_json::Value;
use crate::types::TwitterUser;
pub fn parse_user_list_response(data: &Value) -> Vec<TwitterUser> {
let instructions = data
.pointer("/data/user/result/timeline/timeline/instructions")
.and_then(|v| v.as_array());
let instructions = match instructions {
Some(i) => i,
None => return vec![],
};
let mut users = Vec::new();
let mut seen = HashSet::new();
for instruction in instructions {
let entries = match instruction.get("entries").and_then(|e| e.as_array()) {
Some(e) => e,
None => continue,
};
for entry in entries {
let entry_id = entry.get("entryId").and_then(|v| v.as_str()).unwrap_or("");
if !entry_id.starts_with("user-") {
continue;
}
if let Some(user) = entry.pointer("/content/itemContent/user_results/result") {
let legacy = user.get("legacy").unwrap_or(&Value::Null);
let core = user.get("core").unwrap_or(&Value::Null);
let screen_name = core
.get("screen_name")
.or_else(|| legacy.get("screen_name"))
.and_then(|v| v.as_str())
.unwrap_or("")
.to_string();
if screen_name.is_empty() || !seen.insert(screen_name.clone()) {
continue;
}
users.push(TwitterUser {
screen_name,
name: core
.get("name")
.or_else(|| legacy.get("name"))
.and_then(|v| v.as_str())
.unwrap_or("")
.to_string(),
bio: legacy
.get("description")
.and_then(|v| v.as_str())
.unwrap_or("")
.to_string(),
followers: legacy
.get("followers_count")
.and_then(|v| v.as_u64())
.unwrap_or(0),
});
}
}
}
users
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_user_list_response_one_user() {
let data = serde_json::json!({
"data": {
"user": {
"result": {
"timeline": {
"timeline": {
"instructions": [{
"entries": [{
"entryId": "user-123",
"content": {
"itemContent": {
"user_results": {
"result": {
"legacy": {
"screen_name": "charlie",
"name": "Charlie",
"description": "Hi there",
"followers_count": 42
}
}
}
}
}
}]
}]
}
}
}
}
}
});
let users = parse_user_list_response(&data);
assert_eq!(users.len(), 1);
assert_eq!(users[0].screen_name, "charlie");
assert_eq!(users[0].name, "Charlie");
assert_eq!(users[0].bio, "Hi there");
assert_eq!(users[0].followers, 42);
}
#[test]
fn test_parse_user_list_response_empty() {
let data = serde_json::json!({
"data": {
"user": {
"result": {
"timeline": {
"timeline": {
"instructions": [{
"entries": []
}]
}
}
}
}
}
});
let users = parse_user_list_response(&data);
assert!(users.is_empty());
}
}