Skip to content
This repository was archived by the owner on Jun 17, 2025. It is now read-only.

Commit 0c2a93a

Browse files
committed
Temporarily disable auto join on some errors
1 parent a141f89 commit 0c2a93a

File tree

1 file changed

+67
-2
lines changed

1 file changed

+67
-2
lines changed

scripty_bot_utils/src/handler/normal/voice_state_update.rs

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,48 @@ pub async fn voice_state_update(ctx: &Context, new: &VoiceState) {
110110
return;
111111
}
112112

113+
// is auto join temporarily disabled?
114+
let auto_join_key_name = format!("guild_{{{}}}_auto_join_disabled", guild_id.get());
115+
let r = scripty_redis::run_transaction::<i64>("PEXPIRETIME", |cmd| {
116+
cmd.arg(&auto_join_key_name);
117+
})
118+
.await;
119+
match r {
120+
Ok(-1) => {
121+
// key exists without expiration time: delete and continue because this is bad
122+
if let Err(e) = scripty_redis::run_transaction::<i64>("DEL", |cmd| {
123+
cmd.arg(&auto_join_key_name);
124+
})
125+
.await
126+
{
127+
error!(%guild_id, "failed to delete key that never expires: {}", e);
128+
}
129+
}
130+
Ok(-2) => {
131+
// key doesn't exist so continue normally
132+
}
133+
Ok(disabled_until) => {
134+
// temporarily disabled
135+
let disabled_until =
136+
SystemTime::UNIX_EPOCH + Duration::from_millis(disabled_until as u64);
137+
let delta_time = disabled_until.duration_since(SystemTime::now());
138+
match delta_time {
139+
Ok(time_left) => {
140+
debug!(%guild_id, "guild auto join disabled for another {:?}", time_left);
141+
return;
142+
}
143+
Err(time_since) => {
144+
let time_since = time_since.duration();
145+
warn!(%guild_id, "guild auto join was disabled, but it's been {:?} since auto join timeout expired", time_since);
146+
}
147+
}
148+
}
149+
Err(e) => {
150+
error!(%guild_id, "error fetching temporarily disabled state: {}", e);
151+
return;
152+
}
153+
}
154+
113155
// now we need to check the voice channel the user is joining
114156
// discord doesn't give us the channel id, so we need to get it from the guild's voice states
115157
let vs = {
@@ -194,6 +236,22 @@ pub async fn voice_state_update(ctx: &Context, new: &VoiceState) {
194236
{
195237
error!(%guild_id, "error joining voice channel: {:?}", e);
196238

239+
if e.is_dropped() || e.is_timed_out() {
240+
debug!(%guild_id, "got a Dropped/TimedOut error, disabling auto join for five minutes");
241+
242+
// set a key that expires after 5 minutes to disable auto join temporarily
243+
if let Err(e) = scripty_redis::run_transaction::<()>("SETEX", |cmd| {
244+
cmd.arg(format!("guild_{{{}}}_auto_join_disabled", guild_id.get()))
245+
.arg(true)
246+
.arg("EX")
247+
.arg(5 * 60);
248+
})
249+
.await
250+
{
251+
error!(%guild_id, "failed to set auto_join disable key: {}", e);
252+
}
253+
}
254+
197255
let target_channel = match sqlx::query!(
198256
r#"SELECT target_channel AS "target_channel!"
199257
FROM default_join_settings
@@ -217,8 +275,15 @@ pub async fn voice_state_update(ctx: &Context, new: &VoiceState) {
217275
&ctx.http,
218276
format!(
219277
"Failed to join voice channel due to auto-join error: {}\nYou may want to \
220-
report this in our support server.",
221-
e
278+
report this in our support server.{}",
279+
e,
280+
if e.is_dropped() || e.is_timed_out() {
281+
"Because of the nature of this error, auto-join has been disabled for \
282+
five minutes. If you want Scripty to join anyway, run `/leave` and \
283+
`/join` manually."
284+
} else {
285+
""
286+
}
222287
),
223288
)
224289
.await;

0 commit comments

Comments
 (0)