1use super::client::DiscourseClient;
2use super::error::http_error;
3use anyhow::{Context, Result};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Deserialize, Serialize, Clone)]
9pub struct UserAction {
10 pub action_type: u32,
11 pub created_at: String,
12 #[serde(default)]
13 pub title: Option<String>,
14 #[serde(default)]
15 pub slug: Option<String>,
16 pub topic_id: u64,
17 #[serde(default)]
18 pub post_id: Option<u64>,
19 #[serde(default)]
20 pub post_number: Option<u64>,
21 #[serde(default)]
22 pub username: Option<String>,
23 #[serde(default)]
24 pub excerpt: Option<String>,
25}
26
27#[derive(Debug, Deserialize)]
28struct UserActionsResponse {
29 #[serde(default)]
30 user_actions: Vec<UserAction>,
31}
32
33impl DiscourseClient {
34 pub fn fetch_user_actions(
39 &self,
40 username: &str,
41 filter_types: &[u32],
42 offset: u32,
43 ) -> Result<Vec<UserAction>> {
44 let types_csv = filter_types
45 .iter()
46 .map(|n| n.to_string())
47 .collect::<Vec<_>>()
48 .join(",");
49 let path = format!(
50 "/user_actions.json?username={}&filter={}&offset={}",
51 username, types_csv, offset
52 );
53 let response = self.get(&path)?;
54 let status = response.status();
55 let text = response.text().context("reading user actions response")?;
56 if !status.is_success() {
57 return Err(http_error("user actions request", status, &text));
58 }
59 let body: UserActionsResponse =
60 serde_json::from_str(&text).context("parsing user actions response")?;
61 Ok(body.user_actions)
62 }
63}