@@ -11,6 +11,7 @@ use serenity::{
11
11
model:: {
12
12
channel:: { GuildChannel , Message } ,
13
13
id:: { GuildId , UserId } ,
14
+ user:: User ,
14
15
} ,
15
16
} ;
16
17
use tokio:: time:: { Duration , Instant } ;
@@ -37,6 +38,7 @@ pub struct Handler {
37
38
}
38
39
39
40
impl Handler {
41
+ /// Constructs a new [`Handler`].
40
42
pub fn new ( rate_limit : Duration , reply_limit : usize , dry_run : bool ) -> Self {
41
43
Handler {
42
44
rate_limit,
@@ -45,28 +47,26 @@ impl Handler {
45
47
dry_run,
46
48
}
47
49
}
50
+
48
51
/// Check whether the bot can proceed with honoring this request,
49
52
/// performing preflight checks on server and channel configuration,
50
53
/// avoiding self-sends, and honoring ratelimits.
51
- async fn should_send ( & self , ctx : Context , message : Message ) -> bool {
52
- tracing :: trace! ( "parsing message: {:#?}" , message ) ;
53
- let message_info = match MessageInfo :: new ( message . clone ( ) , ctx . clone ( ) ) {
54
- Ok ( m ) => m ,
55
- Err ( e ) => {
56
- tracing :: error! ( %e , "failed to parse message" ) ;
57
- return false ;
58
- }
59
- } ;
54
+ async fn should_send (
55
+ & self ,
56
+ ctx : & Context ,
57
+ MessageInfo {
58
+ user_id ,
59
+ guild_channel ,
60
+ ..
61
+ } : & MessageInfo ,
62
+ ) -> bool {
60
63
let self_id = ctx. cache . current_user ( ) . id ;
61
64
62
65
// Stop if we're not allowed to respond in this channel
63
- if let Ok ( self_permissions) = message_info
64
- . guild_channel
65
- . permissions_for_user ( & ctx, self_id)
66
- {
66
+ if let Ok ( self_permissions) = guild_channel. permissions_for_user ( & ctx, self_id) {
67
67
if !self_permissions. send_messages ( ) {
68
68
tracing:: debug!(
69
- ?message_info . guild_channel,
69
+ ?guild_channel,
70
70
"not allowed to send messages in this channel"
71
71
) ;
72
72
return false ;
@@ -78,7 +78,7 @@ impl Handler {
78
78
// TODO: add check for channel id, bailing out if channel doesn't match
79
79
80
80
// Don't trigger on messages we ourselves send
81
- if message_info . user_id == self_id {
81
+ if * user_id == self_id {
82
82
tracing:: trace!( "detected message from ourselves" ) ;
83
83
return false ;
84
84
}
@@ -91,6 +91,7 @@ impl Handler {
91
91
/// Representation of a Discord message, containing only the fields
92
92
/// relevant for processing a faucet request.
93
93
// TODO: consider using `serenity::model::channel::Message` instead.
94
+ #[ derive( Debug ) ]
94
95
pub struct MessageInfo {
95
96
/// Discord user ID of the sender of the message.
96
97
pub user_id : UserId ,
@@ -103,10 +104,18 @@ pub struct MessageInfo {
103
104
}
104
105
105
106
impl MessageInfo {
106
- pub fn new ( message : Message , ctx : Context ) -> anyhow:: Result < MessageInfo > {
107
+ fn new (
108
+ message @ Message {
109
+ author : User { id, name, .. } ,
110
+ channel_id,
111
+ guild_id,
112
+ ..
113
+ } : & Message ,
114
+ ctx : & Context ,
115
+ ) -> anyhow:: Result < MessageInfo > {
107
116
// Get the guild id of this message. In Discord nomenclature,
108
117
// a "guild" is the overarching server that contains channels.
109
- let guild_id = match message . guild_id {
118
+ let guild_id = match guild_id {
110
119
Some ( guild_id) => guild_id,
111
120
None => {
112
121
// Assuming Galileo is targeting the Penumbra Labs Discord server,
@@ -117,7 +126,7 @@ impl MessageInfo {
117
126
} ;
118
127
119
128
// Get the channel of this message.
120
- let guild_channel = match ctx. cache . guild_channel ( message . channel_id ) {
129
+ let guild_channel = match ctx. cache . guild_channel ( channel_id) {
121
130
Some ( guild_channel) => guild_channel,
122
131
None => {
123
132
// As above, assuming Galileo is targeting the Penumbra Labs Discord server,
@@ -127,12 +136,10 @@ impl MessageInfo {
127
136
}
128
137
} ;
129
138
130
- let user_id = message. author . id ;
131
- let user_name = message. author . name . clone ( ) ;
132
139
Ok ( MessageInfo {
133
- user_id,
134
- user_name,
135
- guild_id,
140
+ user_id : * id ,
141
+ user_name : name . clone ( ) ,
142
+ guild_id : * guild_id ,
136
143
guild_channel,
137
144
} )
138
145
}
@@ -144,7 +151,7 @@ struct SendHistory {
144
151
}
145
152
146
153
impl SendHistory {
147
- pub fn new ( ) -> Self {
154
+ fn new ( ) -> Self {
148
155
SendHistory {
149
156
discord_users : VecDeque :: new ( ) ,
150
157
penumbra_addresses : VecDeque :: new ( ) ,
@@ -153,7 +160,7 @@ impl SendHistory {
153
160
154
161
/// Returns whether the given user is rate limited, and if so, when the rate limit will expire along with
155
162
/// the number of times the user has been notified of the rate limit.
156
- pub fn is_rate_limited (
163
+ fn is_rate_limited (
157
164
& mut self ,
158
165
user_id : UserId ,
159
166
addresses : & [ AddressOrAlmost ] ,
@@ -184,7 +191,7 @@ impl SendHistory {
184
191
} )
185
192
}
186
193
187
- pub fn record_request ( & mut self , user_id : UserId , addresses : & [ AddressOrAlmost ] ) {
194
+ fn record_request ( & mut self , user_id : UserId , addresses : & [ AddressOrAlmost ] ) {
188
195
self . discord_users . push_back ( ( user_id, Instant :: now ( ) , 1 ) ) ;
189
196
self . penumbra_addresses
190
197
. extend ( addresses. iter ( ) . map ( |address_or_almost| {
@@ -196,7 +203,7 @@ impl SendHistory {
196
203
} ) ) ;
197
204
}
198
205
199
- pub fn prune ( & mut self , rate_limit : Duration ) {
206
+ fn prune ( & mut self , rate_limit : Duration ) {
200
207
tracing:: trace!( "pruning discord user send history" ) ;
201
208
while let Some ( ( user, last_fulfilled, _) ) = self . discord_users . front ( ) {
202
209
if last_fulfilled. elapsed ( ) >= rate_limit {
@@ -220,7 +227,7 @@ impl SendHistory {
220
227
tracing:: trace!( "finished pruning penumbra address send history" ) ;
221
228
}
222
229
223
- pub fn record_failure ( & mut self , user_id : UserId , addresses : & [ AddressOrAlmost ] ) {
230
+ fn record_failure ( & mut self , user_id : UserId , addresses : & [ AddressOrAlmost ] ) {
224
231
// If the request failed, we set the notification count to zero, so that the rate
225
232
// limit will not apply to future requests
226
233
if let Some ( ( _, _, notified) ) = self
@@ -254,17 +261,16 @@ impl EventHandler for Handler {
254
261
/// window, then Galileo will respond instructing the user to wait longer.
255
262
async fn message ( & self , ctx : Context , message : Message ) {
256
263
// Check whether we should proceed.
257
- if !self . should_send ( ctx. clone ( ) , message. clone ( ) ) . await {
264
+ let message_info = MessageInfo :: new ( & message, & ctx) . unwrap ( ) ;
265
+ if !self . should_send ( & ctx, & message_info) . await {
258
266
return ;
259
267
}
260
268
261
- let message_info = MessageInfo :: new ( message. clone ( ) , ctx. clone ( ) ) . unwrap ( ) ;
262
-
263
269
// Prune the send history of all expired rate limit timeouts
264
270
self . send_history . lock ( ) . unwrap ( ) . prune ( self . rate_limit ) ;
265
271
266
272
// Check if the message contains a penumbra address and create a request for it if so
267
- let ( response, request) = if let Some ( parsed) = { Request :: try_new ( & message) } {
273
+ let ( response, request) = if let Some ( parsed) = Request :: try_new ( & message) {
268
274
parsed
269
275
} else {
270
276
tracing:: trace!( "no addresses found in message" ) ;
0 commit comments