Add patreon-sharing option

This commit is contained in:
jude
2025-10-04 18:09:31 +01:00
parent 5ae4baa2a6
commit 91310d47d3
11 changed files with 232 additions and 30 deletions
+2 -2
View File
@@ -12,8 +12,6 @@ pub mod dashboard;
#[cfg(not(test))]
pub mod delete;
#[cfg(not(test))]
pub mod donate;
#[cfg(not(test))]
pub mod help;
#[cfg(not(test))]
pub mod info;
@@ -26,6 +24,8 @@ pub mod nudge;
#[cfg(not(test))]
pub mod offset;
#[cfg(not(test))]
pub mod patreon;
#[cfg(not(test))]
pub mod pause;
#[cfg(not(test))]
pub mod remind;
@@ -15,8 +15,8 @@ impl Recordable for Options {
let footer = footer(ctx);
ctx.send(CreateReply::default().embed(CreateEmbed::new().title("Donate")
.description("Thinking of adding a monthly contribution?
Click below for my Patreon and official bot server :)
.description("Thinking of subscribing?
Click below for my Patreon and official bot server
**https://www.patreon.com/jellywx/**
**https://discord.jellywx.com/**
@@ -26,7 +26,7 @@ With your new rank, you'll be able to:
Set repeating reminders with `/remind` or the dashboard
Use unlimited uploads on SoundFX
(Also, members of servers you __own__ will be able to set repeating reminders via commands)
Members of servers you __own__ will be able to set repeating reminders via commands. You can also choose to share your membership with one other server.
Just $2 USD/month!
@@ -41,8 +41,8 @@ Just $2 USD/month!
}
}
/// Details on supporting the bot and Patreon benefits
#[poise::command(slash_command, rename = "patreon", identifying_name = "patreon")]
pub async fn command(ctx: Context<'_>) -> Result<(), Error> {
/// Show Patreon information
#[poise::command(slash_command, rename = "info", identifying_name = "patreon_info")]
pub async fn info(ctx: Context<'_>) -> Result<(), Error> {
(Options {}).run(ctx).await
}
+73
View File
@@ -0,0 +1,73 @@
use poise::CreateReply;
use serde::{Deserialize, Serialize};
use crate::{
utils::{check_user_subscription, Extract, Recordable},
Context, Error,
};
#[derive(Serialize, Deserialize, Extract)]
pub struct Options;
impl Recordable for Options {
async fn run(self, ctx: Context<'_>) -> Result<(), Error> {
let guild_id = ctx.guild_id().ok_or("This command must be used in a server")?;
let user_id = ctx.author().id;
// Check if user has Patreon subscription
if !check_user_subscription(ctx, user_id).await {
ctx.send(CreateReply::default()
.content("❌ You must be a Patreon subscriber to use this command. Use `/patreon info` for more information.")
.ephemeral(true)
).await?;
return Ok(());
}
let existing_link = sqlx::query!(
"SELECT linked_at FROM patreon_link WHERE user_id = ? AND linked_at > NOW() - INTERVAL 4 WEEK",
user_id.get()
)
.fetch_optional(&ctx.data().database)
.await?;
if existing_link.is_some() {
ctx.send(
CreateReply::default()
.content("❌ You can only link once every 4 weeks. Please try again later.")
.ephemeral(true),
)
.await?;
return Ok(());
}
// Insert or update the patreon_link entry
sqlx::query!(
"INSERT INTO patreon_link (user_id, guild_id, linked_at) VALUES (?, ?, NOW())
ON DUPLICATE KEY UPDATE user_id = user_id",
user_id.get(),
guild_id.get()
)
.execute(&ctx.data().database)
.await?;
ctx.send(
CreateReply::default()
.content("✅ Successfully linked your Patreon subscription to this server!")
.ephemeral(true),
)
.await?;
Ok(())
}
}
/// Link your Patreon subscription to this server. This command can be run once every four weeks
#[poise::command(
slash_command,
rename = "link",
identifying_name = "patreon_link",
guild_only = true
)]
pub async fn link(ctx: Context<'_>) -> Result<(), Error> {
(Options {}).run(ctx).await
}
+11
View File
@@ -0,0 +1,11 @@
pub mod info;
pub mod link;
pub mod unlink;
use crate::{Context, Error};
/// Manage Patreon subscription features
#[poise::command(slash_command, rename = "patreon", identifying_name = "patreon")]
pub async fn command(_ctx: Context<'_>) -> Result<(), Error> {
Ok(())
}
+55
View File
@@ -0,0 +1,55 @@
use poise::CreateReply;
use serde::{Deserialize, Serialize};
use crate::{
utils::{Extract, Recordable},
Context, Error,
};
#[derive(Serialize, Deserialize, Extract)]
pub struct Options;
impl Recordable for Options {
async fn run(self, ctx: Context<'_>) -> Result<(), Error> {
let guild_id = ctx.guild_id().ok_or("This command must be used in a server")?;
let user_id = ctx.author().id;
// Remove the patreon_link entry
let result = sqlx::query!(
"DELETE FROM patreon_link WHERE user_id = ? AND guild_id = ?",
user_id.get(),
guild_id.get()
)
.execute(&ctx.data().database)
.await?;
if result.rows_affected() > 0 {
ctx.send(
CreateReply::default()
.content("✅ Successfully unlinked your Patreon subscription from this server!")
.ephemeral(true),
)
.await?;
} else {
ctx.send(
CreateReply::default()
.content("❌ No existing Patreon link found for this server.")
.ephemeral(true),
)
.await?;
}
Ok(())
}
}
/// Unlink your Patreon subscription from this server
#[poise::command(
slash_command,
rename = "unlink",
identifying_name = "patreon_unlink",
guild_only = true
)]
pub async fn unlink(ctx: Context<'_>) -> Result<(), Error> {
(Options {}).run(ctx).await
}