mirror of
https://github.com/PluralKit/PluralKit.git
synced 2026-02-04 04:56:49 +00:00
[WIP] allowance update on subscription renew
This commit is contained in:
parent
def9285250
commit
a3da351e4b
1 changed files with 70 additions and 3 deletions
|
|
@ -17,10 +17,13 @@ use paddle_rust_sdk::{
|
||||||
use pk_macros::api_endpoint;
|
use pk_macros::api_endpoint;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use sqlx::postgres::Postgres;
|
use sqlx::postgres::Postgres;
|
||||||
|
use time::{Date, OffsetDateTime, format_description::well_known::Rfc3339};
|
||||||
use tracing::{error, info};
|
use tracing::{error, info};
|
||||||
|
|
||||||
use crate::fail;
|
use crate::fail;
|
||||||
|
|
||||||
|
const MONTHLY_ID_CHANGES: i32 = 10;
|
||||||
|
|
||||||
// ew
|
// ew
|
||||||
fn html_escape(s: &str) -> String {
|
fn html_escape(s: &str) -> String {
|
||||||
s.replace('&', "&")
|
s.replace('&', "&")
|
||||||
|
|
@ -51,7 +54,7 @@ const SUBSCRIPTION_QUERY: &str = r#"
|
||||||
select
|
select
|
||||||
p.id, p.provider, p.provider_id, p.email, p.system_id,
|
p.id, p.provider, p.provider_id, p.email, p.system_id,
|
||||||
s.hid as system_hid, s.name as system_name,
|
s.hid as system_hid, s.name as system_name,
|
||||||
p.status, p.next_renewal_at
|
p.allowance_id, p.status, p.next_renewal_at
|
||||||
from premium_subscriptions p
|
from premium_subscriptions p
|
||||||
left join systems s on p.system_id = s.id
|
left join systems s on p.system_id = s.id
|
||||||
"#;
|
"#;
|
||||||
|
|
@ -94,6 +97,7 @@ pub struct DbSubscription {
|
||||||
pub system_id: Option<i32>,
|
pub system_id: Option<i32>,
|
||||||
pub system_hid: Option<String>,
|
pub system_hid: Option<String>,
|
||||||
pub system_name: Option<String>,
|
pub system_name: Option<String>,
|
||||||
|
pub allowance_id: Option<i32>,
|
||||||
pub status: Option<String>,
|
pub status: Option<String>,
|
||||||
pub next_renewal_at: Option<String>,
|
pub next_renewal_at: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
@ -265,6 +269,45 @@ pub async fn fetch_subscriptions_for_email(
|
||||||
Ok(results)
|
Ok(results)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Allowances {
|
||||||
|
pub id_changes: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Allowances {
|
||||||
|
fn zero() -> Self {
|
||||||
|
Self { id_changes: 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn calculate_allowances(
|
||||||
|
ctx: &ApiContext,
|
||||||
|
provider_id: &str,
|
||||||
|
email: &str,
|
||||||
|
next_renew: Date,
|
||||||
|
) -> anyhow::Result<Allowances> {
|
||||||
|
let subscription = get_subscription(ctx, provider_id, email).await?;
|
||||||
|
let last_renew = if let Some(sub) = subscription {
|
||||||
|
if let Some(Ok(next)) = sub
|
||||||
|
.next_renewal_at
|
||||||
|
.map(|dt| Date::parse(dt.split('T').next().unwrap_or(&dt), &Rfc3339))
|
||||||
|
{
|
||||||
|
next
|
||||||
|
} else {
|
||||||
|
OffsetDateTime::now_utc().date()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
OffsetDateTime::now_utc().date()
|
||||||
|
};
|
||||||
|
|
||||||
|
// todo: this sucks
|
||||||
|
let month_diff = (next_renew - last_renew).whole_days() as i32 / 28i32;
|
||||||
|
|
||||||
|
Ok(Allowances {
|
||||||
|
id_changes: MONTHLY_ID_CHANGES * month_diff,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
async fn save_subscription(
|
async fn save_subscription(
|
||||||
ctx: &ApiContext,
|
ctx: &ApiContext,
|
||||||
sub: &Subscription,
|
sub: &Subscription,
|
||||||
|
|
@ -279,11 +322,34 @@ async fn save_subscription(
|
||||||
.and_then(|v| v.as_i64())
|
.and_then(|v| v.as_i64())
|
||||||
.map(|v| v as i32);
|
.map(|v| v as i32);
|
||||||
|
|
||||||
|
// update allowances
|
||||||
|
let allowances = if let Some(renewal) = &next_renewal_at {
|
||||||
|
calculate_allowances(ctx, "paddle", email, Date::parse(renewal, &Rfc3339)?).await?
|
||||||
|
} else {
|
||||||
|
Allowances::zero()
|
||||||
|
};
|
||||||
|
|
||||||
|
let allowance_id: i32 = sqlx::query_scalar(
|
||||||
|
r#"
|
||||||
|
insert into premium_allowances (system_id, id_changes_remaining)
|
||||||
|
values ($1, $2)
|
||||||
|
on conflict (system_id) do update set
|
||||||
|
id_changes_remaining = id_changes_remaining + excluded.id_changes_remaining
|
||||||
|
returning premium_allowances.id
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.bind(system_id)
|
||||||
|
.bind(allowances.id_changes)
|
||||||
|
.fetch_one(&ctx.db)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
// and then update subscription
|
||||||
sqlx::query::<Postgres>(
|
sqlx::query::<Postgres>(
|
||||||
r#"
|
r#"
|
||||||
insert into premium_subscriptions (provider, provider_id, email, system_id, status, next_renewal_at)
|
insert into premium_subscriptions (provider, provider_id, email, system_id, allowance_id, status, next_renewal_at)
|
||||||
values ('paddle', $1, $2, $3, $4, $5)
|
values ('paddle', $1, $2, $3, $4, $5, $6)
|
||||||
on conflict (provider, provider_id) do update set
|
on conflict (provider, provider_id) do update set
|
||||||
|
allowance_id = excluded.allowance_id,
|
||||||
status = excluded.status,
|
status = excluded.status,
|
||||||
next_renewal_at = excluded.next_renewal_at
|
next_renewal_at = excluded.next_renewal_at
|
||||||
"#,
|
"#,
|
||||||
|
|
@ -291,6 +357,7 @@ async fn save_subscription(
|
||||||
.bind(sub.id.as_ref())
|
.bind(sub.id.as_ref())
|
||||||
.bind(email)
|
.bind(email)
|
||||||
.bind(system_id)
|
.bind(system_id)
|
||||||
|
.bind(allowance_id)
|
||||||
.bind(&status)
|
.bind(&status)
|
||||||
.bind(&next_renewal_at)
|
.bind(&next_renewal_at)
|
||||||
.execute(&ctx.db)
|
.execute(&ctx.db)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue