1pub mod events;
4pub mod state;
5
6use crate::{user::User, Error};
7use serde::Deserialize;
8#[cfg(test)]
9use serde::Serialize;
10
11#[derive(Copy, Clone, Debug, PartialEq, Eq, serde_repr::Deserialize_repr)]
12#[cfg_attr(test, derive(serde_repr::Serialize_repr))]
13#[repr(u8)]
14pub enum RelationKind {
15 None = 0,
17 Friend = 1,
19 Blocked = 2,
21 PendingIncoming = 3,
23 PendingOutgoing = 4,
25 Implicit = 5,
27}
28
29#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize)]
30#[cfg_attr(test, derive(Serialize))]
31#[serde(rename_all = "snake_case")]
32pub enum RelationStatus {
33 Offline,
35 Online,
37 Idle,
39 #[serde(rename = "dnd")]
41 DoNotDisturb,
42}
43
44#[derive(Default, Clone, Debug, Deserialize)]
48#[cfg_attr(test, derive(Serialize))]
49pub struct RelationshipActivityTimestamps {
50 #[serde(
51 skip_serializing_if = "Option::is_none",
52 with = "crate::util::datetime_opt",
53 default
54 )]
55 pub start: Option<time::OffsetDateTime>,
56 #[serde(
57 skip_serializing_if = "Option::is_none",
58 with = "crate::util::datetime_opt",
59 default
60 )]
61 pub end: Option<time::OffsetDateTime>,
62}
63
64use crate::activity;
65
66#[derive(Default, Clone, Debug, Deserialize)]
67#[cfg_attr(test, derive(Serialize))]
68pub struct RelationshipActivity {
69 #[serde(skip_serializing_if = "Option::is_none")]
71 pub session_id: Option<String>,
72 #[serde(skip_serializing, with = "crate::util::datetime_opt")]
74 pub created_at: Option<time::OffsetDateTime>,
75 #[serde(skip_serializing_if = "Option::is_none")]
77 pub state: Option<String>,
78 #[serde(skip_serializing_if = "Option::is_none")]
80 pub details: Option<String>,
81 #[serde(skip_serializing_if = "Option::is_none")]
83 pub timestamps: Option<RelationshipActivityTimestamps>,
84 #[serde(skip_serializing_if = "Option::is_none")]
86 pub assets: Option<activity::Assets>,
87 #[serde(skip_serializing_if = "Option::is_none")]
89 pub party: Option<activity::Party>,
90 #[serde(skip_serializing_if = "Option::is_none")]
92 pub secrets: Option<activity::Secrets>,
93 #[serde(rename = "type")]
94 pub kind: activity::ActivityKind,
95 #[serde(default)]
96 pub instance: bool,
98}
99
100#[derive(Debug, Clone, Deserialize)]
101#[cfg_attr(test, derive(Serialize))]
102pub struct RelationshipPresence {
103 pub status: RelationStatus,
104 pub activity: Option<RelationshipActivity>,
105}
106
107#[derive(Debug, Clone, Deserialize)]
108#[cfg_attr(test, derive(Serialize))]
109pub struct Relationship {
110 #[serde(rename = "type")]
112 pub kind: RelationKind,
113 pub user: User,
114 pub presence: RelationshipPresence,
115}
116
117impl crate::Discord {
118 pub async fn get_relationships(&self) -> Result<Vec<Relationship>, Error> {
126 let rx = self.send_rpc(crate::proto::CommandKind::GetRelationships, ())?;
127
128 handle_response!(rx, crate::proto::Command::GetRelationships { relationships } => {
129 Ok(relationships)
130 })
131 }
132}
133
134#[cfg(test)]
135mod test {
136 use super::*;
137 use crate::{activity, proto::event};
138
139 #[test]
140 fn deserializes() {
141 let event = r#"{"cmd":"DISPATCH","data":{"type":1,"user":{"id":"682969165652689005","username":"jake.shadle","discriminator":"7557","avatar":"15bbd75c8ee6610d045852e7ea998a35","bot":false,"flags":0,"premium_type":0},"presence":{"status":"online","activity":{"created_at":"1632819046295","id":"e92ece5eb4ce629","name":"Ark [dev debug]","timestamps":{"start":"1632819046199"},"type":0}}},"evt":"RELATIONSHIP_UPDATE","nonce":null}"#;
142
143 let update: crate::proto::event::EventFrame =
144 serde_json::from_str(event).expect("failed to deserialize");
145
146 insta::assert_json_snapshot!(update);
147 }
148
149 #[test]
150 fn serde() {
151 let eve = event::EventFrame {
152 inner: event::Event::RelationshipUpdate(std::sync::Arc::new(Relationship {
153 kind: RelationKind::Friend,
154 user: User {
155 id: crate::types::Snowflake(123414231424),
156 username: "name".to_owned(),
157 discriminator: Some(52),
158 avatar: Some(crate::user::Avatar([
159 0xf6, 0x2f, 0x2a, 0x75, 0x5c, 0xb1, 0x8c, 0x94, 0xdc, 0x5c, 0xda, 0x94,
160 0x44, 0x10, 0x24, 0xf1,
161 ])),
162 is_bot: false,
163 },
164 presence: RelationshipPresence {
165 status: RelationStatus::DoNotDisturb,
166 activity: Some(RelationshipActivity {
167 session_id: Some("6bb1ddaea510750e905615286709d632".to_owned()),
168 created_at: Some(crate::util::timestamp(1628629162447)),
169 assets: Some(activity::Assets {
170 large_image: Some(
171 "spotify:ab67616d0000b273d1e326d10706f3d8562d77f8".to_owned(),
172 ),
173 large_text: Some("To the Moon".to_owned()),
174 small_image: None,
175 small_text: None,
176 }),
177 details: Some("To the Moon".to_owned()),
178 instance: false,
179 kind: activity::ActivityKind::Listening,
180 party: Some(activity::Party {
181 id: "spotify: 216453179196440576".to_owned(),
182 size: None,
183 privacy: None,
184 }),
185 secrets: None,
186 state: Some("Rob Curly".to_owned()),
187 timestamps: Some(RelationshipActivityTimestamps {
188 start: Some(crate::util::timestamp(1628629161811)),
189 end: Some(crate::util::timestamp(1628629327961)),
190 }),
191 }),
192 },
193 })),
194 };
195
196 insta::assert_json_snapshot!(eve);
197 }
198}