twilight_model/gateway/payload/outgoing/
update_presence.rs

1use crate::gateway::{
2    opcode::OpCode,
3    presence::{Activity, Status},
4};
5use serde::{Deserialize, Serialize};
6use std::{
7    error::Error,
8    fmt::{Display, Formatter, Result as FmtResult},
9};
10
11/// Error emitted when the payload can not be created as configured.
12#[derive(Debug)]
13pub struct UpdatePresenceError {
14    kind: UpdatePresenceErrorType,
15}
16
17impl UpdatePresenceError {
18    /// Immutable reference to the type of error that occurred.
19    #[must_use = "retrieving the type has no effect if let unused"]
20    pub const fn kind(&self) -> &UpdatePresenceErrorType {
21        &self.kind
22    }
23
24    /// Consume the error, returning the source error if there is any.
25    #[allow(clippy::unused_self)]
26    #[must_use = "consuming the error and retrieving the source has no effect if let unused"]
27    pub fn into_source(self) -> Option<Box<dyn Error + Send + Sync>> {
28        None
29    }
30
31    /// Consume the error, returning the owned error type and the source error.
32    #[must_use = "consuming the error into its parts has no effect if left unused"]
33    pub fn into_parts(
34        self,
35    ) -> (
36        UpdatePresenceErrorType,
37        Option<Box<dyn Error + Send + Sync>>,
38    ) {
39        (self.kind, None)
40    }
41}
42
43impl Display for UpdatePresenceError {
44    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
45        match self.kind {
46            UpdatePresenceErrorType::MissingActivity => {
47                f.write_str("at least one activity must be provided")
48            }
49        }
50    }
51}
52
53impl Error for UpdatePresenceError {}
54
55/// Type of [`UpdatePresenceError`] that occurred.
56#[derive(Debug)]
57#[non_exhaustive]
58pub enum UpdatePresenceErrorType {
59    /// No activities provided.
60    MissingActivity,
61}
62
63#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
64pub struct UpdatePresence {
65    pub d: UpdatePresencePayload,
66    pub op: OpCode,
67}
68
69impl UpdatePresence {
70    /// Create a new, valid [`UpdatePresence`] payload.
71    ///
72    /// # Errors
73    ///
74    /// Returns an error of type [`UpdatePresenceErrorType::MissingActivity`] if
75    /// an empty set of activities is provided.
76    pub fn new(
77        activities: impl Into<Vec<Activity>>,
78        afk: bool,
79        since: impl Into<Option<u64>>,
80        status: impl Into<Status>,
81    ) -> Result<Self, UpdatePresenceError> {
82        let d = UpdatePresencePayload::new(activities, afk, since, status)?;
83
84        Ok(Self {
85            d,
86            op: OpCode::PresenceUpdate,
87        })
88    }
89}
90
91#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
92pub struct UpdatePresencePayload {
93    /// User's activities.
94    ///
95    /// At least one is required.
96    pub activities: Vec<Activity>,
97    pub afk: bool,
98    pub since: Option<u64>,
99    pub status: Status,
100}
101
102impl UpdatePresencePayload {
103    /// Create a validated stats update info struct.
104    ///
105    /// # Errors
106    ///
107    /// Returns an [`UpdatePresenceErrorType::MissingActivity`] error type if an
108    /// empty set of activities is provided.
109    pub fn new(
110        activities: impl Into<Vec<Activity>>,
111        afk: bool,
112        since: impl Into<Option<u64>>,
113        status: impl Into<Status>,
114    ) -> Result<Self, UpdatePresenceError> {
115        Self::_new(activities.into(), afk, since.into(), status.into())
116    }
117
118    fn _new(
119        activities: Vec<Activity>,
120        afk: bool,
121        since: Option<u64>,
122        status: Status,
123    ) -> Result<Self, UpdatePresenceError> {
124        if activities.is_empty() {
125            return Err(UpdatePresenceError {
126                kind: UpdatePresenceErrorType::MissingActivity,
127            });
128        }
129
130        Ok(Self {
131            activities,
132            afk,
133            since,
134            status,
135        })
136    }
137}