Skip to main content

apify_client/clients/
user.rs

1//! Client for a user (`/v2/users/{userId}` or `/v2/users/me`).
2
3use serde::Serialize;
4use serde_json::Value;
5
6use crate::clients::base::{get_resource, get_resource_required, ResourceContext};
7use crate::common::QueryParams;
8use crate::error::ApifyClientResult;
9use crate::http_client::HttpClient;
10use crate::models::User;
11
12/// Client for a specific user (or the current user via [`ApifyClient::me`]).
13///
14/// [`ApifyClient::me`]: crate::ApifyClient::me
15#[derive(Debug, Clone)]
16pub struct UserClient {
17    ctx: ResourceContext,
18    is_me: bool,
19}
20
21impl UserClient {
22    pub(crate) fn new(http: HttpClient, base_url: &str, id: &str) -> Self {
23        Self {
24            ctx: ResourceContext::single(http, base_url, "users", id),
25            is_me: id == crate::client::ME_USER_PLACEHOLDER,
26        }
27    }
28
29    /// Fetches the user account information.
30    ///
31    /// For the current user (`me`) this returns private account details; for other users
32    /// it returns the public profile.
33    pub async fn get(&self) -> ApifyClientResult<Option<User>> {
34        get_resource(&self.ctx, None, &QueryParams::new()).await
35    }
36
37    /// Returns the current user's monthly usage for the current month. Only valid for the `me`
38    /// client. To fetch usage for a specific month, use [`UserClient::monthly_usage_for_date`].
39    pub async fn monthly_usage(&self) -> ApifyClientResult<Value> {
40        self.monthly_usage_for_date_named(None, "monthly_usage")
41            .await
42    }
43
44    /// Returns the current user's monthly usage, optionally for the month containing `date`.
45    ///
46    /// `date` is an optional `YYYY-MM-DD` string selecting the month to report (the spec's
47    /// optional `date` query parameter on `GET /v2/users/me/usage/monthly`); passing `None`
48    /// returns the current month, which is equivalent to [`UserClient::monthly_usage`]. Only
49    /// valid for the `me` client.
50    pub async fn monthly_usage_for_date(&self, date: Option<&str>) -> ApifyClientResult<Value> {
51        self.monthly_usage_for_date_named(date, "monthly_usage_for_date")
52            .await
53    }
54
55    /// Shared implementation for [`UserClient::monthly_usage`] and
56    /// [`UserClient::monthly_usage_for_date`]. `method` is the caller's own public method name,
57    /// so the `me`-only guard error names the method the caller actually invoked.
58    async fn monthly_usage_for_date_named(
59        &self,
60        date: Option<&str>,
61        method: &str,
62    ) -> ApifyClientResult<Value> {
63        self.require_me(method)?;
64        let mut params = QueryParams::new();
65        params.add_str("date", date);
66        get_resource_required(&self.ctx, Some("usage/monthly"), &params).await
67    }
68
69    /// Returns the current user's account and usage limits. Only valid for the `me` client.
70    pub async fn limits(&self) -> ApifyClientResult<Value> {
71        self.require_me("limits")?;
72        get_resource_required(&self.ctx, Some("limits"), &QueryParams::new()).await
73    }
74
75    /// Updates the current user's limits. Only valid for the `me` client.
76    pub async fn update_limits<T: Serialize>(&self, new_limits: &T) -> ApifyClientResult<()> {
77        self.require_me("update_limits")?;
78        let body = serde_json::to_vec(new_limits)?;
79        let url = self.ctx.url(Some("limits"));
80        let mut headers = std::collections::HashMap::new();
81        headers.insert("Content-Type".to_string(), "application/json".to_string());
82        self.ctx
83            .http
84            .call(crate::http_client::HttpRequest {
85                method: crate::http_client::HttpMethod::Put,
86                url,
87                headers,
88                body: Some(body),
89                timeout: crate::clients::base::DEFAULT_REQUEST_TIMEOUT,
90            })
91            .await?;
92        Ok(())
93    }
94
95    fn require_me(&self, method: &str) -> ApifyClientResult<()> {
96        if !self.is_me {
97            return Err(crate::error::ApifyClientError::InvalidArgument(format!(
98                "`{method}` is only available for the current user (use ApifyClient::me())"
99            )));
100        }
101        Ok(())
102    }
103}