aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-11-04 01:08:31 +0100
committersalmonik <salmonik@tuta.io>2026-11-04 01:08:31 +0100
commitfeb0e771a11b71855d268fa1b4f141f28ed53db3 (patch)
tree0e9d1a666897fc7bc6cf31ece59bf64b332fa9da
parentcommands: gate admin, trigger, cron and recording behind permissions (diff)
downloadsenator-sperma-feb0e771a11b71855d268fa1b4f141f28ed53db3.tar.gz
senator-sperma-feb0e771a11b71855d268fa1b4f141f28ed53db3.zip
cron: scope jobs to the guild that created them
-rw-r--r--src/commands/cron.rs16
-rw-r--r--src/database/mod.rs50
2 files changed, 47 insertions, 19 deletions
diff --git a/src/commands/cron.rs b/src/commands/cron.rs
index 47c3d62..ebaa96d 100644
--- a/src/commands/cron.rs
+++ b/src/commands/cron.rs
@@ -44,8 +44,10 @@ pub async fn dodaj_audio(
44 ctx.data().copyparty.build_url_no_pw(&audio_filename) 44 ctx.data().copyparty.build_url_no_pw(&audio_filename)
45 }; 45 };
46 46
47 let guild_id = ctx.guild_id().ok_or_else(lang::err_not_in_guild)?;
47 database::add_cron_job( 48 database::add_cron_job(
48 &ctx.data().db_pool, 49 &ctx.data().db_pool,
50 guild_id.get() as i64,
49 &cron_expression, 51 &cron_expression,
50 "audio", 52 "audio",
51 channel_id, 53 channel_id,
@@ -72,8 +74,10 @@ pub async fn dodaj_wiadomość(
72 _ => return Err(lang::err_bad_channel_type()), 74 _ => return Err(lang::err_bad_channel_type()),
73 }; 75 };
74 76
77 let guild_id = ctx.guild_id().ok_or_else(lang::err_not_in_guild)?;
75 database::add_cron_job( 78 database::add_cron_job(
76 &ctx.data().db_pool, 79 &ctx.data().db_pool,
80 guild_id.get() as i64,
77 &cron_expression, 81 &cron_expression,
78 "wiadomość", 82 "wiadomość",
79 channel_id, 83 channel_id,
@@ -89,7 +93,8 @@ pub async fn dodaj_wiadomość(
89/// List all cron jobs 93/// List all cron jobs
90#[poise::command(slash_command, guild_only, required_permissions = "MANAGE_GUILD")] 94#[poise::command(slash_command, guild_only, required_permissions = "MANAGE_GUILD")]
91pub async fn pokaż(ctx: Context<'_>) -> Result<()> { 95pub async fn pokaż(ctx: Context<'_>) -> Result<()> {
92 let jobs = database::list_cron_jobs(&ctx.data().db_pool).await?; 96 let guild_id = ctx.guild_id().ok_or_else(lang::err_not_in_guild)?;
97 let jobs = database::list_cron_jobs(&ctx.data().db_pool, guild_id.get() as i64).await?;
93 if jobs.is_empty() { 98 if jobs.is_empty() {
94 ctx.say(lang::L_CRON_NONE).await?; 99 ctx.say(lang::L_CRON_NONE).await?;
95 return Ok(()); 100 return Ok(());
@@ -126,7 +131,8 @@ pub async fn usuń(
126 ctx: Context<'_>, 131 ctx: Context<'_>,
127 #[description = "ID pracy do usunięcia"] job_id: i64, 132 #[description = "ID pracy do usunięcia"] job_id: i64,
128) -> Result<()> { 133) -> Result<()> {
129 if database::delete_cron_job(&ctx.data().db_pool, job_id).await? { 134 let guild_id = ctx.guild_id().ok_or_else(lang::err_not_in_guild)?;
135 if database::delete_cron_job(&ctx.data().db_pool, job_id, guild_id.get() as i64).await? {
130 ctx.say(lang::fmt_cron_deleted(job_id)).await?; 136 ctx.say(lang::fmt_cron_deleted(job_id)).await?;
131 } else { 137 } else {
132 ctx.say(lang::fmt_cron_not_found(job_id)).await?; 138 ctx.say(lang::fmt_cron_not_found(job_id)).await?;
@@ -140,7 +146,8 @@ pub async fn pauza(
140 ctx: Context<'_>, 146 ctx: Context<'_>,
141 #[description = "ID pracy do zapauzowania"] job_id: i64, 147 #[description = "ID pracy do zapauzowania"] job_id: i64,
142) -> Result<()> { 148) -> Result<()> {
143 if database::set_cron_job_active(&ctx.data().db_pool, job_id, false).await? { 149 let guild_id = ctx.guild_id().ok_or_else(lang::err_not_in_guild)?;
150 if database::set_cron_job_active(&ctx.data().db_pool, job_id, guild_id.get() as i64, false).await? {
144 ctx.say(lang::fmt_cron_paused(job_id)).await?; 151 ctx.say(lang::fmt_cron_paused(job_id)).await?;
145 } else { 152 } else {
146 ctx.say(lang::fmt_cron_not_found(job_id)).await?; 153 ctx.say(lang::fmt_cron_not_found(job_id)).await?;
@@ -154,7 +161,8 @@ pub async fn wznów(
154 ctx: Context<'_>, 161 ctx: Context<'_>,
155 #[description = "ID pracy cron do wznowienia"] job_id: i64, 162 #[description = "ID pracy cron do wznowienia"] job_id: i64,
156) -> Result<()> { 163) -> Result<()> {
157 if database::set_cron_job_active(&ctx.data().db_pool, job_id, true).await? { 164 let guild_id = ctx.guild_id().ok_or_else(lang::err_not_in_guild)?;
165 if database::set_cron_job_active(&ctx.data().db_pool, job_id, guild_id.get() as i64, true).await? {
158 ctx.say(lang::fmt_cron_resumed(job_id)).await?; 166 ctx.say(lang::fmt_cron_resumed(job_id)).await?;
159 } else { 167 } else {
160 ctx.say(lang::fmt_cron_not_found(job_id)).await?; 168 ctx.say(lang::fmt_cron_not_found(job_id)).await?;
diff --git a/src/database/mod.rs b/src/database/mod.rs
index b68d927..9679811 100644
--- a/src/database/mod.rs
+++ b/src/database/mod.rs
@@ -55,17 +55,22 @@ async fn run_migrations(pool: &DbPool) -> Result<()> {
55 audio_filename TEXT, 55 audio_filename TEXT,
56 message TEXT, 56 message TEXT,
57 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, 57 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
58 last_run TIMESTAMP 58 last_run TIMESTAMP,
59 guild_id INTEGER NOT NULL DEFAULT 0
59 )", 60 )",
60 ) 61 )
61 .execute(pool) 62 .execute(pool)
62 .await?; 63 .await?;
63 64
64 // Add last_run column for pre-existing databases that lack it. 65 // Add columns for pre-existing databases that lack them.
65 sqlx::query("ALTER TABLE cron_jobs ADD COLUMN last_run TIMESTAMP") 66 sqlx::query("ALTER TABLE cron_jobs ADD COLUMN last_run TIMESTAMP")
66 .execute(pool) 67 .execute(pool)
67 .await 68 .await
68 .ok(); 69 .ok();
70 sqlx::query("ALTER TABLE cron_jobs ADD COLUMN guild_id INTEGER NOT NULL DEFAULT 0")
71 .execute(pool)
72 .await
73 .ok();
69 74
70 sqlx::query( 75 sqlx::query(
71 "CREATE TABLE IF NOT EXISTS triggers ( 76 "CREATE TABLE IF NOT EXISTS triggers (
@@ -305,6 +310,8 @@ pub async fn get_user_rank(pool: &DbPool, user_id: &str, metric: &str) -> Result
305#[derive(Debug, Clone, FromRow)] 310#[derive(Debug, Clone, FromRow)]
306pub struct CronJob { 311pub struct CronJob {
307 pub id: i64, 312 pub id: i64,
313 #[allow(dead_code)]
314 pub guild_id: i64,
308 pub cron_expression: String, 315 pub cron_expression: String,
309 pub r#type: String, 316 pub r#type: String,
310 pub channel_id: i64, 317 pub channel_id: i64,
@@ -317,10 +324,13 @@ pub struct CronJob {
317} 324}
318 325
319#[allow(dead_code)] 326#[allow(dead_code)]
320pub async fn list_cron_jobs(pool: &DbPool) -> Result<Vec<CronJob>> { 327pub async fn list_cron_jobs(pool: &DbPool, guild_id: i64) -> Result<Vec<CronJob>> {
321 Ok(sqlx::query_as("SELECT * FROM cron_jobs ORDER BY id") 328 Ok(
322 .fetch_all(pool) 329 sqlx::query_as("SELECT * FROM cron_jobs WHERE guild_id = ? ORDER BY id")
323 .await?) 330 .bind(guild_id)
331 .fetch_all(pool)
332 .await?,
333 )
324} 334}
325 335
326#[allow(dead_code)] 336#[allow(dead_code)]
@@ -332,6 +342,7 @@ pub async fn list_active_cron_jobs(pool: &DbPool) -> Result<Vec<CronJob>> {
332 342
333pub async fn add_cron_job( 343pub async fn add_cron_job(
334 pool: &DbPool, 344 pool: &DbPool,
345 guild_id: i64,
335 cron_expression: &str, 346 cron_expression: &str,
336 r#type: &str, 347 r#type: &str,
337 channel_id: i64, 348 channel_id: i64,
@@ -353,9 +364,10 @@ pub async fn add_cron_job(
353 }).unwrap_or(existing.len() as i64 + 1); 364 }).unwrap_or(existing.len() as i64 + 1);
354 365
355 let result = sqlx::query( 366 let result = sqlx::query(
356 "INSERT INTO cron_jobs (id, cron_expression, type, channel_id, audio_filename, message) VALUES (?, ?, ?, ?, ?, ?)", 367 "INSERT INTO cron_jobs (id, guild_id, cron_expression, type, channel_id, audio_filename, message) VALUES (?, ?, ?, ?, ?, ?, ?)",
357 ) 368 )
358 .bind(next_id) 369 .bind(next_id)
370 .bind(guild_id)
359 .bind(cron_expression) 371 .bind(cron_expression)
360 .bind(r#type) 372 .bind(r#type)
361 .bind(channel_id) 373 .bind(channel_id)
@@ -366,9 +378,10 @@ pub async fn add_cron_job(
366 Ok(result.last_insert_rowid()) 378 Ok(result.last_insert_rowid())
367} 379}
368 380
369pub async fn delete_cron_job(pool: &DbPool, id: i64) -> Result<bool> { 381pub async fn delete_cron_job(pool: &DbPool, id: i64, guild_id: i64) -> Result<bool> {
370 let result = sqlx::query("DELETE FROM cron_jobs WHERE id = ?") 382 let result = sqlx::query("DELETE FROM cron_jobs WHERE id = ? AND guild_id = ?")
371 .bind(id) 383 .bind(id)
384 .bind(guild_id)
372 .execute(pool) 385 .execute(pool)
373 .await?; 386 .await?;
374 Ok(result.rows_affected() > 0) 387 Ok(result.rows_affected() > 0)
@@ -383,12 +396,19 @@ pub async fn update_cron_last_run(pool: &DbPool, id: i64, last_run: DateTime<Utc
383 Ok(()) 396 Ok(())
384} 397}
385 398
386pub async fn set_cron_job_active(pool: &DbPool, id: i64, active: bool) -> Result<bool> { 399pub async fn set_cron_job_active(
387 let result = sqlx::query("UPDATE cron_jobs SET active = ? WHERE id = ?") 400 pool: &DbPool,
388 .bind(if active { 1 } else { 0 }) 401 id: i64,
389 .bind(id) 402 guild_id: i64,
390 .execute(pool) 403 active: bool,
391 .await?; 404) -> Result<bool> {
405 let result =
406 sqlx::query("UPDATE cron_jobs SET active = ? WHERE id = ? AND guild_id = ?")
407 .bind(if active { 1 } else { 0 })
408 .bind(id)
409 .bind(guild_id)
410 .execute(pool)
411 .await?;
392 Ok(result.rows_affected() > 0) 412 Ok(result.rows_affected() > 0)
393} 413}
394 414