libsignal_service/websocket/
account.rs1use chrono::{DateTime, Utc};
2use phonenumber::PhoneNumber;
3use reqwest::Method;
4use serde::{Deserialize, Serialize};
5use uuid::Uuid;
6
7use crate::{
8 content::ServiceError, utils::serde_optional_base64,
9 utils::serde_phone_number, websocket,
10};
11
12use super::SignalWebSocket;
13
14#[derive(Debug, Serialize, Deserialize)]
15#[serde(rename_all = "camelCase")]
16pub struct DeviceId {
17 pub device_id: u32,
18}
19
20#[derive(Debug, Serialize, Deserialize)]
21#[serde(rename_all = "camelCase")]
22pub struct DeviceInfo {
23 pub id: u8,
24 pub name: Option<String>,
25 #[serde(with = "chrono::serde::ts_milliseconds")]
26 pub created: DateTime<Utc>,
27 #[serde(with = "chrono::serde::ts_milliseconds")]
28 pub last_seen: DateTime<Utc>,
29}
30
31#[derive(Debug, Serialize, Deserialize)]
32#[serde(rename_all = "camelCase")]
33pub struct AccountAttributes {
34 #[serde(default, with = "serde_optional_base64")]
35 pub signaling_key: Option<Vec<u8>>,
36 pub registration_id: u32,
37 pub pni_registration_id: u32,
38 pub voice: bool,
39 pub video: bool,
40 pub fetches_messages: bool,
41 pub pin: Option<String>,
42 pub registration_lock: Option<String>,
43 #[serde(default, with = "serde_optional_base64")]
44 pub unidentified_access_key: Option<Vec<u8>>,
45 pub unrestricted_unidentified_access: bool,
46 pub discoverable_by_phone_number: bool,
47 pub capabilities: DeviceCapabilities,
48 pub name: Option<String>,
49}
50
51#[derive(Debug, Serialize, Deserialize, Default, Eq, PartialEq, Clone)]
52#[serde(rename_all = "camelCase")]
53pub struct DeviceCapabilities {
54 #[serde(default)]
55 pub storage: bool,
56 #[serde(default)]
57 pub sender_key: bool,
58 #[serde(default)]
59 pub announcement_group: bool,
60 #[serde(default)]
61 pub change_number: bool,
62 #[serde(default)]
63 pub stories: bool,
64 #[serde(default)]
65 pub gift_badges: bool,
66 #[serde(default)]
67 pub pni: bool,
68 #[serde(default)]
69 pub payment_activation: bool,
70}
71
72#[derive(Debug, Deserialize)]
73#[serde(rename_all = "camelCase")]
74pub struct WhoAmIResponse {
75 #[serde(rename = "uuid")]
76 pub aci: Uuid,
77 #[serde(default)] pub pni: Uuid,
79 #[serde(with = "serde_phone_number")]
80 pub number: PhoneNumber,
81}
82
83impl SignalWebSocket<websocket::Identified> {
84 pub async fn whoami(&mut self) -> Result<WhoAmIResponse, ServiceError> {
86 self.http_request(Method::GET, "/v1/accounts/whoami")?
87 .send()
88 .await?
89 .service_error_for_status()
90 .await?
91 .json()
92 .await
93 }
94
95 pub async fn devices(&mut self) -> Result<Vec<DeviceInfo>, ServiceError> {
99 #[derive(serde::Deserialize)]
100 struct DeviceInfoList {
101 devices: Vec<DeviceInfo>,
102 }
103
104 let devices: DeviceInfoList = self
105 .http_request(Method::GET, "/v1/devices")?
106 .send()
107 .await?
108 .service_error_for_status()
109 .await?
110 .json()
111 .await?;
112
113 Ok(devices.devices)
114 }
115
116 pub async fn set_account_attributes(
117 &mut self,
118 attributes: AccountAttributes,
119 ) -> Result<(), ServiceError> {
120 assert!(
121 attributes.pin.is_none() || attributes.registration_lock.is_none(),
122 "only one of PIN and registration lock can be set."
123 );
124
125 self.http_request(Method::PUT, "/v1/accounts/attributes")?
126 .send_json(&attributes)
127 .await?
128 .service_error_for_status()
129 .await?
130 .json()
131 .await
132 }
133}