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
//! Client for a user (`/v2/users/{userId}` or `/v2/users/me`).
use serde::Serialize;
use serde_json::Value;
use crate::clients::base::{get_resource, get_resource_required, ResourceContext};
use crate::common::QueryParams;
use crate::error::ApifyClientResult;
use crate::http_client::HttpClient;
use crate::models::User;
/// Client for a specific user (or the current user via [`ApifyClient::me`]).
///
/// [`ApifyClient::me`]: crate::ApifyClient::me
#[derive(Debug, Clone)]
pub struct UserClient {
ctx: ResourceContext,
is_me: bool,
}
impl UserClient {
pub(crate) fn new(http: HttpClient, base_url: &str, id: &str) -> Self {
Self {
ctx: ResourceContext::single(http, base_url, "users", id),
is_me: id == crate::client::ME_USER_PLACEHOLDER,
}
}
/// Fetches the user account information.
///
/// For the current user (`me`) this returns private account details; for other users
/// it returns the public profile.
pub async fn get(&self) -> ApifyClientResult<Option<User>> {
get_resource(&self.ctx, None, &QueryParams::new()).await
}
/// Returns the current user's monthly usage for the current month. Only valid for the `me`
/// client. To fetch usage for a specific month, use [`UserClient::monthly_usage_for_date`].
pub async fn monthly_usage(&self) -> ApifyClientResult<Value> {
self.monthly_usage_for_date_named(None, "monthly_usage")
.await
}
/// Returns the current user's monthly usage, optionally for the month containing `date`.
///
/// `date` is an optional `YYYY-MM-DD` string selecting the month to report (the spec's
/// optional `date` query parameter on `GET /v2/users/me/usage/monthly`); passing `None`
/// returns the current month, which is equivalent to [`UserClient::monthly_usage`]. Only
/// valid for the `me` client.
pub async fn monthly_usage_for_date(&self, date: Option<&str>) -> ApifyClientResult<Value> {
self.monthly_usage_for_date_named(date, "monthly_usage_for_date")
.await
}
/// Shared implementation for [`UserClient::monthly_usage`] and
/// [`UserClient::monthly_usage_for_date`]. `method` is the caller's own public method name,
/// so the `me`-only guard error names the method the caller actually invoked.
async fn monthly_usage_for_date_named(
&self,
date: Option<&str>,
method: &str,
) -> ApifyClientResult<Value> {
self.require_me(method)?;
let mut params = QueryParams::new();
params.add_str("date", date);
get_resource_required(&self.ctx, Some("usage/monthly"), ¶ms).await
}
/// Returns the current user's account and usage limits. Only valid for the `me` client.
pub async fn limits(&self) -> ApifyClientResult<Value> {
self.require_me("limits")?;
get_resource_required(&self.ctx, Some("limits"), &QueryParams::new()).await
}
/// Updates the current user's limits. Only valid for the `me` client.
pub async fn update_limits<T: Serialize>(&self, new_limits: &T) -> ApifyClientResult<()> {
self.require_me("update_limits")?;
let body = serde_json::to_vec(new_limits)?;
let url = self.ctx.url(Some("limits"));
let mut headers = std::collections::HashMap::new();
headers.insert("Content-Type".to_string(), "application/json".to_string());
self.ctx
.http
.call(crate::http_client::HttpRequest {
method: crate::http_client::HttpMethod::Put,
url,
headers,
body: Some(body),
timeout: crate::clients::base::DEFAULT_REQUEST_TIMEOUT,
})
.await?;
Ok(())
}
fn require_me(&self, method: &str) -> ApifyClientResult<()> {
if !self.is_me {
return Err(crate::error::ApifyClientError::InvalidArgument(format!(
"`{method}` is only available for the current user (use ApifyClient::me())"
)));
}
Ok(())
}
}