libsignal_service/websocket/
account.rs1use chrono::{DateTime, Utc};
2use reqwest::Method;
3use serde::{Deserialize, Serialize};
4use uuid::Uuid;
5
6use crate::{
7 content::ServiceError,
8 proto::DeviceName,
9 utils::{
10 serde_device_id, serde_e164, serde_optional_base64,
11 serde_optional_prost_base64,
12 },
13 websocket,
14};
15
16use super::SignalWebSocket;
17
18#[derive(Debug, Serialize, Deserialize)]
19#[serde(rename_all = "camelCase")]
20pub struct DeviceId {
21 #[serde(with = "serde_device_id")]
22 pub device_id: libsignal_core::DeviceId,
23}
24
25#[derive(Debug, Serialize, Deserialize)]
26#[serde(rename_all = "camelCase")]
27pub struct DeviceInfo {
28 #[serde(with = "serde_device_id")]
29 pub id: libsignal_core::DeviceId,
30 pub registration_id: i32,
31 pub name: Option<String>,
32 #[serde(with = "chrono::serde::ts_milliseconds")]
33 pub created_at: DateTime<Utc>,
34 #[serde(with = "chrono::serde::ts_milliseconds")]
35 pub last_seen: DateTime<Utc>,
36}
37
38#[derive(Debug, Serialize, Deserialize)]
39#[serde(rename_all = "camelCase")]
40pub(crate) struct DeviceInfoEncrypted {
41 #[serde(with = "serde_device_id")]
42 pub id: libsignal_core::DeviceId,
43 pub name: Option<String>,
44 pub registration_id: i32,
45 pub created_at_ciphertext: String,
46 #[serde(with = "chrono::serde::ts_milliseconds")]
47 pub last_seen: DateTime<Utc>,
48}
49
50#[derive(Debug, Serialize, Deserialize)]
51#[serde(rename_all = "camelCase")]
52pub struct AccountAttributes {
54 pub fetches_messages: bool,
55 pub registration_id: u32,
56 pub pni_registration_id: u32,
57 #[serde(default, with = "serde_optional_prost_base64")]
58 pub name: Option<DeviceName>,
59 #[serde(default, skip_serializing_if = "Option::is_none")]
60 pub registration_lock: Option<String>,
61 #[serde(default, with = "serde_optional_base64")]
62 pub unidentified_access_key: Option<Vec<u8>>,
63 pub unrestricted_unidentified_access: bool,
64 pub capabilities: DeviceCapabilities,
65 pub discoverable_by_phone_number: bool,
66 pub pin: Option<String>,
67 #[serde(
68 default,
69 with = "serde_optional_base64",
70 skip_serializing_if = "Option::is_none"
71 )]
72 pub recovery_password: Option<Vec<u8>>,
73}
74
75#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Clone)]
76#[serde(rename_all = "camelCase")]
77pub struct DeviceCapabilities {
78 #[serde(default)]
79 pub storage: bool,
80 #[serde(default)]
81 pub transfer: bool,
82 #[serde(default)]
83 pub attachment_backfill: bool,
84 #[serde(default)]
85 pub spqr: bool,
86}
87
88impl Default for DeviceCapabilities {
89 fn default() -> Self {
90 DeviceCapabilities {
91 storage: false,
92 transfer: false,
93 attachment_backfill: false,
94 spqr: true,
95 }
96 }
97}
98
99#[derive(Debug, Deserialize)]
100#[serde(rename_all = "camelCase")]
101pub struct WhoAmIResponse {
102 #[serde(rename = "uuid")]
103 pub aci: Uuid,
104 #[serde(default)] pub pni: Uuid,
106 #[serde(with = "serde_e164")]
107 pub number: libsignal_core::E164,
108}
109
110impl SignalWebSocket<websocket::Identified> {
111 pub async fn whoami(&mut self) -> Result<WhoAmIResponse, ServiceError> {
113 self.http_request(Method::GET, "/v1/accounts/whoami")?
114 .send()
115 .await?
116 .service_error_for_status()
117 .await?
118 .json()
119 .await
120 }
121
122 pub(crate) async fn devices(
126 &mut self,
127 ) -> Result<Vec<DeviceInfoEncrypted>, ServiceError> {
128 #[derive(serde::Deserialize)]
129 struct DeviceInfoList {
130 devices: Vec<DeviceInfoEncrypted>,
131 }
132
133 let devices: DeviceInfoList = self
134 .http_request(Method::GET, "/v1/devices")?
135 .send()
136 .await?
137 .service_error_for_status()
138 .await?
139 .json()
140 .await?;
141
142 Ok(devices.devices)
143 }
144
145 pub async fn set_account_attributes(
146 &mut self,
147 attributes: AccountAttributes,
148 ) -> Result<(), ServiceError> {
149 assert!(
150 attributes.pin.is_none() || attributes.registration_lock.is_none(),
151 "only one of PIN and registration lock can be set."
152 );
153
154 self.http_request(Method::PUT, "/v1/accounts/attributes")?
155 .send_json(&attributes)
156 .await?
157 .service_error_for_status()
158 .await?;
159
160 Ok(())
161 }
162
163 pub async fn unregister_account(&mut self) -> Result<(), ServiceError> {
170 self.http_request(Method::DELETE, "/v1/accounts/me")?
171 .send()
172 .await?
173 .service_error_for_status()
174 .await?;
175
176 Ok(())
177 }
178}