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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
use once_cell::sync::Lazy;
use std::{fmt, ops::Add};

/// Abstract channel type
pub enum ChannelType {
    SavedMessages,
    DirectMessage,
    Group,
    ServerChannel,
    Unknown,
}

/// Permission value on Revolt
///
/// This should be restricted to the lower 52 bits to prevent any
/// potential issues with Javascript. Also leave empty spaces for
/// future permission flags to be added.
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "try-from-primitive", derive(num_enum::TryFromPrimitive))]
#[repr(u64)]
pub enum ChannelPermission {
    // * Generic permissions
    /// Manage the channel or channels on the server
    ManageChannel = 1 << 0,
    /// Manage the server
    ManageServer = 1 << 1,
    /// Manage permissions on servers or channels
    ManagePermissions = 1 << 2,
    /// Manage roles on server
    ManageRole = 1 << 3,
    /// Manage server customisation (includes emoji)
    ManageCustomisation = 1 << 4,

    // % 1 bit reserved

    // * Member permissions
    /// Kick other members below their ranking
    KickMembers = 1 << 6,
    /// Ban other members below their ranking
    BanMembers = 1 << 7,
    /// Timeout other members below their ranking
    TimeoutMembers = 1 << 8,
    /// Assign roles to members below their ranking
    AssignRoles = 1 << 9,
    /// Change own nickname
    ChangeNickname = 1 << 10,
    /// Change or remove other's nicknames below their ranking
    ManageNicknames = 1 << 11,
    /// Change own avatar
    ChangeAvatar = 1 << 12,
    /// Remove other's avatars below their ranking
    RemoveAvatars = 1 << 13,

    // % 7 bits reserved

    // * Channel permissions
    /// View a channel
    ViewChannel = 1 << 20,
    /// Read a channel's past message history
    ReadMessageHistory = 1 << 21,
    /// Send a message in a channel
    SendMessage = 1 << 22,
    /// Delete messages in a channel
    ManageMessages = 1 << 23,
    /// Manage webhook entries on a channel
    ManageWebhooks = 1 << 24,
    /// Create invites to this channel
    InviteOthers = 1 << 25,
    /// Send embedded content in this channel
    SendEmbeds = 1 << 26,
    /// Send attachments and media in this channel
    UploadFiles = 1 << 27,
    /// Masquerade messages using custom nickname and avatar
    Masquerade = 1 << 28,
    /// React to messages with emojis
    React = 1 << 29,

    // * Voice permissions
    /// Connect to a voice channel
    Connect = 1 << 30,
    /// Speak in a voice call
    Speak = 1 << 31,
    /// Share video in a voice call
    Video = 1 << 32,
    /// Mute other members with lower ranking in a voice call
    MuteMembers = 1 << 33,
    /// Deafen other members with lower ranking in a voice call
    DeafenMembers = 1 << 34,
    /// Move members between voice channels
    MoveMembers = 1 << 35,

    // * Misc. permissions
    // % Bits 36 to 52: free area
    // % Bits 53 to 64: do not use

    // * Grant all permissions
    /// Safely grant all permissions
    GrantAllSafe = 0x000F_FFFF_FFFF_FFFF,

    /// Grant all permissions
    GrantAll = u64::MAX,
}

impl fmt::Display for ChannelPermission {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self, f)
    }
}

impl_op_ex!(+ |a: &ChannelPermission, b: &ChannelPermission| -> u64 { *a as u64 | *b as u64 });
impl_op_ex_commutative!(+ |a: &u64, b: &ChannelPermission| -> u64 { *a | *b as u64 });

pub static ALLOW_IN_TIMEOUT: Lazy<u64> =
    Lazy::new(|| ChannelPermission::ViewChannel + ChannelPermission::ReadMessageHistory);

pub static DEFAULT_PERMISSION_VIEW_ONLY: Lazy<u64> =
    Lazy::new(|| ChannelPermission::ViewChannel + ChannelPermission::ReadMessageHistory);

pub static DEFAULT_PERMISSION: Lazy<u64> = Lazy::new(|| {
    DEFAULT_PERMISSION_VIEW_ONLY.add(
        ChannelPermission::SendMessage
            + ChannelPermission::InviteOthers
            + ChannelPermission::SendEmbeds
            + ChannelPermission::UploadFiles
            + ChannelPermission::Connect
            + ChannelPermission::Speak,
    )
});

pub static DEFAULT_PERMISSION_SAVED_MESSAGES: u64 = ChannelPermission::GrantAllSafe as u64;

pub static DEFAULT_PERMISSION_DIRECT_MESSAGE: Lazy<u64> = Lazy::new(|| {
    DEFAULT_PERMISSION.add(ChannelPermission::ManageChannel + ChannelPermission::React)
});

pub static DEFAULT_PERMISSION_SERVER: Lazy<u64> = Lazy::new(|| {
    DEFAULT_PERMISSION.add(
        ChannelPermission::React
            + ChannelPermission::ChangeNickname
            + ChannelPermission::ChangeAvatar,
    )
});

pub static DEFAULT_WEBHOOK_PERMISSIONS: Lazy<u64> = Lazy::new(|| {
    ChannelPermission::SendMessage
        + ChannelPermission::SendEmbeds
        + ChannelPermission::Masquerade
        + ChannelPermission::React
});