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
use serde::{Deserialize, Serialize};
macro_rules! scope_impls {
($($i:ident,$rename:literal,$doc:literal);* $(;)? ) => {
#[doc = "Scopes for twitch."]
#[doc = ""]
#[doc = "<https://dev.twitch.tv/docs/authentication/#scopes>"]
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
#[non_exhaustive]
#[serde(from = "String")]
#[serde(into = "String")]
pub enum Scope {
$(
#[doc = $doc]
#[doc = "\n\n"]
#[doc = "`"]
#[doc = $rename]
#[doc = "`"]
#[serde(rename = $rename)]
$i,
)*
#[doc = "Other scope that is not implemented."]
Other(String),
}
impl std::fmt::Display for Scope {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
Scope::Other(s) => s.as_str(),
$(
Scope::$i => $rename,
)*
})
}
}
impl Scope {
#[doc = "Get a vec of all defined twitch [Scopes][Scope]."]
#[doc = "\n\n"]
#[doc = "Please not that this may not work for you, as some auth flows and \"apis\" don't accept all scopes"]
pub fn all() -> Vec<Scope> {
vec![
$(Scope::$i,)*
]
}
#[doc = "Make a scope from string"]
pub fn parse(s: &str) -> Scope {
match s {
$($rename => {Scope::$i})*,
other => Scope::Other(other.to_string())
}
}
}
};
}
scope_impls!(
AnalyticsReadExtensions, "analytics:read:extensions", "View analytics data for your extensions.";
AnalyticsReadGames, "analytics:read:games", "View analytics data for your games.";
BitsRead, "bits:read", "View bits information for your channel.";
ChannelSubscriptions, "channel_subscriptions", "\\[DEPRECATED\\] Read all subscribers to your channel.";
ChannelEditCommercial, "channel:edit:commercial", "Start a commercial on authorized channels";
ChannelManageBroadcast, "channel:manage:broadcast", "Manage your channel’s broadcast configuration, including updating channel configuration and managing stream markers and stream tags.";
ChannelManageExtension, "channel:manage:extension", "Manage your channel’s extension configuration, including activating extensions.";
ChannelModerate, "channel:moderate", "Perform moderation actions in a channel";
ChannelReadHypeTrain, "channel:read:hype_train", "Read hype trains";
ChannelReadRedemptions, "channel:read:redemptions", "View your channel points custom reward redemptions";
ChannelReadSubscriptions, "channel:read:subscriptions", "Get a list of all subscribers to your channel and check if a user is subscribed to your channel";
ChatEdit, "chat:edit", "Send live Stream Chat and Rooms messages";
ChatRead, "chat:read", "View live Stream Chat and Rooms messages";
ClipsEdit, "clips:edit", "Create and edit clips as a specific user.";
ModerationRead, "moderation:read", "View your channel's moderation data including Moderators, Bans, Timeouts and Automod settings";
UserEdit, "user:edit", "Manage a user object.";
UserEditBroadcast, "user:edit:broadcast", "Edit your channel's broadcast configuration, including extension configuration. (This scope implies user:read:broadcast capability.)";
UserEditFollows, "user:edit:follows", "Edit your follows.";
UserReadBroadcast, "user:read:broadcast", "View your broadcasting configuration, including extension configurations.";
UserReadEmail, "user:read:email", "Read authorized user's email address.";
UserReadStreamKey, "user:read:stream_key", "Read authorized user’s stream key.";
WhispersEdit, "whispers:edit", "Send whisper messages.";
WhispersRead, "whispers:read", "View your whisper messages.";
);
impl Scope {
pub fn as_oauth_scope(&self) -> oauth2::Scope { oauth2::Scope::new(self.to_string()) }
}
impl From<oauth2::Scope> for Scope {
fn from(scope: oauth2::Scope) -> Self { Scope::parse(scope.as_str()) }
}
impl From<String> for Scope {
fn from(s: String) -> Self { Scope::parse(&s) }
}
impl From<Scope> for String {
fn from(s: Scope) -> Self { s.to_string() }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn custom_scope() {
assert_eq!(
Scope::Other(String::from("custom_scope")),
Scope::parse("custom_scope")
)
}
#[test]
fn roundabout() {
for scope in Scope::all() {
assert_eq!(scope, Scope::parse(&scope.to_string()))
}
}
}