Skip to main content

futu_backend/
user_profile.rs

1use prost::Message;
2
3use crate::conn::BackendConn;
4use futu_core::error::{FutuError, Result};
5
6pub const CMD_QUERY_USER_PROFILE: u16 = 7506;
7const QUERY_PROFILE_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(5);
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct BackendUserProfile {
11    pub user_id: u64,
12    pub nick_name: String,
13    pub avatar_url: String,
14}
15
16pub fn build_query_user_profile_request(user_id: u64) -> Vec<u8> {
17    use crate::proto_internal::ft_cmd_sns_profile as pb;
18
19    let req = pb::GetUserProfilesReq {
20        uid: Some(user_id),
21        filter: Some(pb::UserProfile {
22            uid: Some(user_id),
23            nick: Some("1".to_string()),
24            icon: Some("1".to_string()),
25        }),
26        avatar_size: Some(120),
27    };
28    req.encode_to_vec()
29}
30
31pub fn decode_query_user_profile_response(body: &[u8]) -> Result<BackendUserProfile> {
32    let rsp: crate::proto_internal::ft_cmd_sns_profile::GetUserProfilesRsp =
33        Message::decode(body).map_err(FutuError::Proto)?;
34
35    let errcode = rsp.errcode.unwrap_or(0);
36    if errcode != 0 {
37        return Err(FutuError::ServerError {
38            ret_type: errcode,
39            msg: rsp
40                .errmsg
41                .unwrap_or_else(|| format!("CMD7506 QueryUserProfile failed: {errcode}")),
42        });
43    }
44
45    let user_data = rsp.user_data.ok_or_else(|| FutuError::ServerError {
46        ret_type: -1,
47        msg: "CMD7506 QueryUserProfile missing user_data".to_string(),
48    })?;
49
50    Ok(BackendUserProfile {
51        user_id: user_data.uid.unwrap_or(0),
52        nick_name: user_data.nick.unwrap_or_default(),
53        avatar_url: user_data.icon.unwrap_or_default(),
54    })
55}
56
57pub async fn query_user_profile(backend: &BackendConn, user_id: u64) -> Result<BackendUserProfile> {
58    let body = build_query_user_profile_request(user_id);
59    let frame = tokio::time::timeout(
60        QUERY_PROFILE_TIMEOUT,
61        backend.request(CMD_QUERY_USER_PROFILE, body),
62    )
63    .await
64    .map_err(|_| FutuError::Timeout)??;
65
66    decode_query_user_profile_response(frame.body.as_ref())
67}