1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use super::Observation;
use memory_lol::model::{Account, ScreenNameResult};
use reqwest::Url;
use std::collections::HashMap;
const MEMORY_LOL_BASE: &str = "https://memory.lol/";
lazy_static::lazy_static! {
pub static ref MEMORY_LOL_BASE_URL: Url = Url::parse(MEMORY_LOL_BASE).unwrap();
}
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("HTTP client error")]
HttpClient(#[from] reqwest::Error),
#[error("Invalid URL error")]
Url(#[from] url::ParseError),
#[error("Invalid date range")]
InvalidDateRange(Vec<String>),
}
pub struct Client {
base: Url,
}
impl Client {
pub fn new(base: &Url) -> Self {
Self { base: base.clone() }
}
pub async fn lookup_tw_user_id(&self, user_id: u64) -> Result<Vec<Observation>, Error> {
let url = self.base.join(&format!("tw/id/{}", user_id))?;
let account = reqwest::get(url).await?.json::<Account>().await?;
Ok(Observation::from_account(&account))
}
pub async fn lookup_tw_screen_name(
&self,
screen_name: &str,
) -> Result<HashMap<u64, Vec<Observation>>, Error> {
let url = self.base.join(&format!("tw/{}", screen_name))?;
let accounts = reqwest::get(url).await?.json::<ScreenNameResult>().await?;
Ok(accounts
.accounts
.into_iter()
.map(|account| (account.id, Observation::from_account(&account)))
.collect())
}
}
impl Default for Client {
fn default() -> Self {
Self::new(&MEMORY_LOL_BASE_URL)
}
}
#[cfg(test)]
mod tests {
use super::super::Observation;
use super::*;
use chrono::NaiveDate;
use serial_test::serial;
use tokio::time::Duration;
#[tokio::test]
#[serial]
async fn lookup_tw_user_id() {
let client = Client::default();
let result = client.lookup_tw_user_id(1015295486612291585).await.unwrap();
assert_eq!(result.len(), 19);
}
#[tokio::test]
#[serial]
async fn lookup_tw_screen_name() {
tokio::time::sleep(Duration::from_millis(500)).await;
let client = Client::default();
let result = client.lookup_tw_screen_name("WLMact").await.unwrap();
let expected = vec![(
1470631321496084481,
vec![
Observation::new(
"i_am_not_a_nazi".to_string(),
Some((
NaiveDate::from_ymd(2022, 05, 19),
NaiveDate::from_ymd(2022, 06, 08),
)),
),
Observation::new(
"WLMact".to_string(),
Some((
NaiveDate::from_ymd(2022, 06, 10),
NaiveDate::from_ymd(2022, 07, 10),
)),
),
],
)]
.into_iter()
.collect();
assert_eq!(result, expected);
}
}