1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use twilight_model::{
    gateway::presence::{Activity, ActivityFlags, ActivityType, Presence, Status},
    id::{
        marker::{ApplicationMarker, GuildMarker, UserMarker},
        Id,
    },
};

/// A cached activity
///
/// It is the same as [`twilight_model::gateway::presence::Activity`] except:
///
/// - `user_id` field is added, making it possible to return a user's activities
///
/// - `buttons` field is removed, as caching it is likely unnecessary, if you
///   need this field, please create an issue
///
/// - `assets`, `emoji`, `party` and `party` fields are flattened, making this
///   struct easier to cache
///
/// - `secrets` field is removed, as it's not sent to bots
#[derive(Clone, Debug)]
pub struct CachedActivity {
    pub user_id: Id<UserMarker>,
    pub application_id: Option<Id<ApplicationMarker>>,
    pub asset_large_image: Option<String>,
    pub asset_large_text: Option<String>,
    pub asset_small_image: Option<String>,
    pub asset_small_text: Option<String>,
    pub created_at: Option<u64>,
    pub details: Option<String>,
    pub emoji_animated: Option<bool>,
    pub emoji_name: Option<String>,
    pub emoji_id: Option<String>,
    pub flags: Option<ActivityFlags>,
    pub id: Option<String>,
    pub instance: Option<bool>,
    pub kind: ActivityType,
    pub name: String,
    pub party_id: Option<String>,
    pub party_size: Option<[u64; 2]>,
    pub state: Option<String>,
    pub timestamp_end: Option<u64>,
    pub timestamp_start: Option<u64>,
    pub url: Option<String>,
}

impl CachedActivity {
    /// Create a cached activity from a given activity and user ID
    #[must_use]
    pub fn from_activity(activity: &Activity, user_id: Id<UserMarker>) -> Self {
        Self {
            user_id,
            application_id: activity.application_id,
            asset_large_image: activity
                .assets
                .as_ref()
                .and_then(|asset| asset.large_image.clone()),
            asset_large_text: activity
                .assets
                .as_ref()
                .and_then(|asset| asset.large_text.clone()),
            asset_small_image: activity
                .assets
                .as_ref()
                .and_then(|asset| asset.small_image.clone()),
            asset_small_text: activity
                .assets
                .as_ref()
                .and_then(|asset| asset.small_text.clone()),
            created_at: activity.created_at,
            details: activity.details.clone(),
            emoji_animated: activity.emoji.as_ref().and_then(|emoji| emoji.animated),
            emoji_name: activity.emoji.as_ref().map(|emoji| emoji.name.clone()),
            emoji_id: activity.emoji.as_ref().and_then(|emoji| emoji.id.clone()),
            flags: activity.flags,
            id: activity.id.clone(),
            instance: activity.instance,
            kind: activity.kind,
            name: activity.name.clone(),
            party_id: activity.party.as_ref().and_then(|party| party.id.clone()),
            party_size: activity.party.as_ref().and_then(|party| party.size),
            state: activity.state.clone(),
            timestamp_end: activity
                .timestamps
                .as_ref()
                .and_then(|timestamp| timestamp.end),
            timestamp_start: activity
                .timestamps
                .as_ref()
                .and_then(|timestamp| timestamp.start),
            url: activity.url.clone(),
        }
    }
}

/// A cached presence
///
/// It's the same as [`twilight_model::gateway::presence::Presence`] except:
///
/// - `user` field is changed to a user ID, since users are cached separately
///
/// - `client_status` field is removed, as caching it is likely unnecessary, if
///   you need this field, please create an issue
///
/// - `activities` field is removed, since they're cached separately
#[derive(Clone, Copy, Debug)]
pub struct CachedPresence {
    pub guild_id: Id<GuildMarker>,
    pub status: Status,
    pub user: Id<UserMarker>,
}

impl From<&Presence> for CachedPresence {
    fn from(presence: &Presence) -> Self {
        Self {
            guild_id: presence.guild_id,
            status: presence.status,
            user: presence.user.id(),
        }
    }
}