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

Commit 38f2765

Browse files
committed
Add per-VC target channels
1 parent 03cdc6b commit 38f2765

File tree

5 files changed

+136
-60
lines changed

5 files changed

+136
-60
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
CREATE TABLE per_voice_channel_settings
2+
(
3+
channel_id BIGINT NOT NULL PRIMARY KEY,
4+
target_channel BIGINT NULL DEFAULT NULL
5+
);

scripty_bot_utils/src/handler/normal/voice_state_update.rs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -185,22 +185,36 @@ pub async fn voice_state_update(ctx: &Context, new: &VoiceState) {
185185
.fetch_optional(db)
186186
.await
187187
{
188-
Ok(res) => res,
188+
Ok(Some(res)) => res,
189+
Ok(None) => {
190+
warn!(%guild_id, "guild has auto join enabled with no default settings: something's wrong");
191+
return;
192+
}
189193
Err(e) => {
190194
error!(%guild_id, "failed to fetch default settings for guild: {}", e);
191195
return;
192196
}
193197
};
194-
195-
let Some(defaults) = defaults else {
196-
warn!(%guild_id, "guild has auto join enabled with no default settings: something's wrong");
197-
return;
198+
let maybe_target = match sqlx::query!(
199+
"SELECT target_channel FROM per_voice_channel_settings WHERE channel_id = $1",
200+
voice_channel_id.get() as i64
201+
)
202+
.fetch_optional(db)
203+
.await
204+
.map(|maybe_row| maybe_row.and_then(|r| r.target_channel))
205+
{
206+
Ok(maybe_target) => maybe_target.map(|cid| ChannelId::new(cid as u64)),
207+
Err(e) => {
208+
error!(%guild_id, "error fetching target channel from per_voice_channel_settings: {}", e);
209+
return;
210+
}
198211
};
199212

200-
let Some(target_channel_id) = defaults
201-
.target_channel
202-
.map(|target_channel| ChannelId::new(target_channel as u64))
203-
else {
213+
let Some(target_channel_id) = maybe_target.or_else(|| {
214+
defaults
215+
.target_channel
216+
.map(|target_channel| ChannelId::new(target_channel as u64))
217+
}) else {
204218
warn!(%guild_id, "guild has no default target channel, ignoring join");
205219
return;
206220
};

scripty_commands/src/cmds/config/default_settings/target_channel.rs

Lines changed: 69 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,39 +15,87 @@ use serenity::model::{
1515
)]
1616
pub async fn config_default_settings_target_channel(
1717
ctx: Context<'_>,
18-
#[channel_types("Text", "Forum", "Voice", "Stage", "News")] target_channel: Option<
19-
GuildChannel,
20-
>,
18+
#[description = "Default value for target_channel on the join command"]
19+
#[channel_types("Text", "Forum", "Voice", "Stage", "News")]
20+
target_channel: Option<GuildChannel>,
21+
#[description = "If this is set, this target channel will only apply when Scripty joins this \
22+
voice channel"]
23+
#[channel_types("Voice", "Stage")]
24+
modify_channel: Option<GuildChannel>,
2125
) -> Result<(), Error> {
2226
let guild_id = ctx.guild_id().ok_or_else(Error::expected_guild)?;
2327
let resolved_language =
2428
scripty_i18n::get_resolved_language(ctx.author().id.get(), Some(guild_id.get())).await;
2529
let db = scripty_db::get_db();
2630

27-
if let Some(error_translation_key) =
28-
do_preflight_target_channel(&ctx, guild_id, target_channel.as_ref()).await?
31+
if let Some(error_translation_key) = do_preflight_target_channel(
32+
&ctx,
33+
guild_id,
34+
target_channel.as_ref(),
35+
modify_channel.is_some(),
36+
)
37+
.await?
2938
{
3039
ctx.say(format_message!(resolved_language, error_translation_key))
3140
.await?;
3241
return Ok(());
3342
}
3443

3544
super::ensure_guild_exists(guild_id, db).await?;
36-
sqlx::query!(
37-
"INSERT INTO default_join_settings (guild_id, target_channel)
38-
VALUES ($1, $2)
39-
ON CONFLICT ON CONSTRAINT default_join_settings_pkey
40-
DO UPDATE SET target_channel = $2",
41-
guild_id.get() as i64,
42-
target_channel.as_ref().map(|x| x.id.get() as i64),
43-
)
44-
.execute(db)
45-
.await?;
46-
47-
let resp_str = if let Some(ref target_channel) = target_channel {
48-
format_message!(resolved_language, "config-default-target-channel-enabled", targetChannelMention: target_channel.mention().to_string())
45+
if let Some(ref modify_channel) = modify_channel {
46+
sqlx::query!(
47+
"INSERT INTO per_voice_channel_settings (channel_id, target_channel)
48+
VALUES ($1, $2)
49+
ON CONFLICT ON CONSTRAINT per_voice_channel_settings_pkey
50+
DO UPDATE SET target_channel = $2",
51+
modify_channel.id.get() as i64,
52+
target_channel.as_ref().map(|x| x.id.get() as i64)
53+
)
54+
.execute(db)
55+
.await?;
4956
} else {
50-
format_message!(resolved_language, "config-default-target-channel-disabled")
57+
sqlx::query!(
58+
"INSERT INTO default_join_settings (guild_id, target_channel)
59+
VALUES ($1, $2)
60+
ON CONFLICT ON CONSTRAINT default_join_settings_pkey
61+
DO UPDATE SET target_channel = $2",
62+
guild_id.get() as i64,
63+
target_channel.as_ref().map(|x| x.id.get() as i64),
64+
)
65+
.execute(db)
66+
.await?;
67+
}
68+
69+
let resp_str = match (&target_channel, &modify_channel) {
70+
(Some(target_channel), Some(modify_channel)) => {
71+
// modifying modify_channel to send transcripts to target_channel by default
72+
format_message!(
73+
resolved_language,
74+
"config-default-target-channel-enabled-per-channel",
75+
targetChannelMention: target_channel.mention().to_string(),
76+
modifyChannelMention: modify_channel.mention().to_string()
77+
)
78+
}
79+
(None, Some(modify_channel)) => {
80+
// modifying modify_channel to send transcripts to the guild default
81+
format_message!(
82+
resolved_language,
83+
"config-default-target-channel-disabled-per-channel",
84+
modifyChannelMention: modify_channel.mention().to_string()
85+
)
86+
}
87+
(Some(target_channel), None) => {
88+
// setting the guild default to target_channel
89+
format_message!(
90+
resolved_language,
91+
"config-default-target-channel-enabled",
92+
targetChannelMention: target_channel.mention().to_string()
93+
)
94+
}
95+
(None, None) => {
96+
// resetting the guild default to empty
97+
format_message!(resolved_language, "config-default-target-channel-disabled")
98+
}
5199
};
52100
ctx.say(resp_str).await?;
53101

@@ -58,6 +106,7 @@ async fn do_preflight_target_channel(
58106
_ctx: &Context<'_>,
59107
guild_id: GuildId,
60108
target_channel: Option<&GuildChannel>,
109+
is_channel_level: bool,
61110
) -> Result<Option<&'static str>, Error> {
62111
let db = scripty_db::get_db();
63112

@@ -95,7 +144,7 @@ async fn do_preflight_target_channel(
95144
_ => {}
96145
}
97146
}
98-
} else {
147+
} else if !is_channel_level {
99148
let auto_join = sqlx::query!(
100149
"SELECT auto_join FROM guilds WHERE guild_id = $1",
101150
guild_id.get() as i64

scripty_commands/src/cmds/join.rs

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,30 @@ pub async fn join(
5454
let db = scripty_db::get_db();
5555
let cfg = scripty_config::get_config();
5656

57+
let (guild_id, voice_channel) = {
58+
let guild = ctx.guild().ok_or_else(Error::expected_guild)?;
59+
(
60+
guild.id,
61+
voice_channel.ok_or_else(|| {
62+
guild
63+
.voice_states
64+
.get(&ctx.author().id)
65+
.and_then(|state| state.channel_id)
66+
}),
67+
)
68+
};
69+
let voice_channel = match voice_channel {
70+
Ok(vc) => vc,
71+
Err(Some(state)) => state.to_guild_channel(&ctx, ctx.guild_id()).await?,
72+
Err(None) => {
73+
ctx.say(
74+
format_message!(resolved_language, "no-channel-specified", contextPrefix: ctx.prefix()),
75+
)
76+
.await?;
77+
return Ok(());
78+
}
79+
};
80+
5781
let defaults = sqlx::query!(
5882
"SELECT record_transcriptions, target_channel, new_thread, ephemeral FROM \
5983
default_join_settings WHERE guild_id = $1",
@@ -66,12 +90,17 @@ pub async fn join(
6690
let target_channel = match target_channel {
6791
Some(target_channel) => target_channel,
6892
None => {
69-
defaults
70-
.as_ref()
71-
.and_then(|x| {
72-
x.target_channel
73-
.map(|target_channel| GenericChannelId::new(target_channel as u64))
74-
})
93+
let maybe_target = sqlx::query!(
94+
"SELECT target_channel FROM per_voice_channel_settings WHERE channel_id = $1",
95+
voice_channel.id.get() as i64
96+
)
97+
.fetch_optional(db)
98+
.await?
99+
.and_then(|r| r.target_channel);
100+
101+
maybe_target
102+
.or_else(|| defaults.as_ref().and_then(|r| r.target_channel))
103+
.map(|cid| GenericChannelId::new(cid as u64))
75104
.unwrap_or_else(|| ctx.channel_id())
76105
.to_channel(&ctx, Some(guild_id))
77106
.await?
@@ -162,19 +191,6 @@ pub async fn join(
162191
return Ok(());
163192
}
164193

165-
let (guild_id, voice_channel) = {
166-
let guild = ctx.guild().ok_or_else(Error::expected_guild)?;
167-
(
168-
guild.id,
169-
voice_channel.ok_or_else(|| {
170-
guild
171-
.voice_states
172-
.get(&ctx.author().id)
173-
.and_then(|state| state.channel_id)
174-
}),
175-
)
176-
};
177-
178194
let res = sqlx::query!(
179195
"SELECT trial_used FROM guilds WHERE guild_id = $1",
180196
guild_id.get() as i64
@@ -183,18 +199,6 @@ pub async fn join(
183199
.await?;
184200
let trial_used = res.as_ref().is_some_and(|row| row.trial_used);
185201

186-
let voice_channel = match voice_channel {
187-
Ok(vc) => vc,
188-
Err(Some(state)) => state.to_guild_channel(&ctx, ctx.guild_id()).await?,
189-
Err(None) => {
190-
ctx.say(
191-
format_message!(resolved_language, "no-channel-specified", contextPrefix: ctx.prefix()),
192-
)
193-
.await?;
194-
return Ok(());
195-
}
196-
};
197-
198202
match voice_channel.base.kind {
199203
ChannelType::Voice | ChannelType::Stage => {}
200204
_ => {

scripty_i18n/locales/en.ftl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,10 @@ cmds_config_default_settings_target_channel = target_channel
243243
.description = Set the default target channel where Scripty will output transcripts if none are specified.
244244
.target_channel = target_channel
245245
.target_channel-description = Default value for target_channel on the join command
246+
.modify_channel = modify_channel
247+
.modify_channel-description = If this is set, this target channel will only apply when Scripty joins this voice channel.
248+
config-default-target-channel-enabled-per-channel = Scripty will now, by default, send all transcripts to { $targetChannelMention } when joining { $modifyChannelMention }.
249+
config-default-target-channel-disabled-per-channel = Scripty will now, by default, send all transcripts to the server default target channel when joining { $modifyChannelMention }.
246250
config-default-target-channel-enabled = Scripty will now, by default, send all transcripts to { $targetChannelMention }.
247251
config-default-target-channel-disabled = Scripty will now, by default, send all transcripts to the channel where `/join` is executed.
248252
config-default-target-channel-cant-disable-with-auto-join = You can't remove any default target channel if auto-join is enabled. Either disable auto-join or change the target channel instead of removing it.

0 commit comments

Comments
 (0)