mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 05:25:40 +09:00
feat(premium): let self-hosted instances sell premium and gifts (#3025)
This commit is contained in:
1 parent
192cec689a
commit
3736d94d73
159 files changed
+15802
-9067
No files matched your search
@@ -1,7 +1,18 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use crate::config::AdminConfig;
|
||||
use std::sync::Arc;
|
||||
use crate::{
|
||||
api::{
|
||||
client::{AdminApiClient, ApiResultExt},
|
||||
types::PremiumBranding,
|
||||
},
|
||||
config::AdminConfig,
|
||||
};
|
||||
use std::{
|
||||
sync::{Arc, Mutex},
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
const PREMIUM_BRANDING_TTL: Duration = Duration::from_secs(60);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AppState {
|
||||
@@ -11,6 +22,7 @@ pub struct AppState {
|
||||
struct AppStateInner {
|
||||
pub config: AdminConfig,
|
||||
pub http_client: reqwest::Client,
|
||||
premium_branding: Mutex<Option<(Instant, PremiumBranding)>>,
|
||||
}
|
||||
|
||||
impl AppState {
|
||||
@@ -23,6 +35,7 @@ impl AppState {
|
||||
inner: Arc::new(AppStateInner {
|
||||
config,
|
||||
http_client,
|
||||
premium_branding: Mutex::new(None),
|
||||
}),
|
||||
}
|
||||
}
|
||||
@@ -34,6 +47,40 @@ impl AppState {
|
||||
pub fn http_client(&self) -> &reqwest::Client {
|
||||
&self.inner.http_client
|
||||
}
|
||||
|
||||
pub fn cached_premium_branding(&self) -> Option<PremiumBranding> {
|
||||
let cache = self
|
||||
.inner
|
||||
.premium_branding
|
||||
.lock()
|
||||
.unwrap_or_else(|poisoned| poisoned.into_inner());
|
||||
cache
|
||||
.as_ref()
|
||||
.filter(|(fetched_at, _)| fetched_at.elapsed() < PREMIUM_BRANDING_TTL)
|
||||
.map(|(_, branding)| branding.clone())
|
||||
}
|
||||
|
||||
pub fn remember_premium_branding(&self, branding: PremiumBranding) {
|
||||
*self
|
||||
.inner
|
||||
.premium_branding
|
||||
.lock()
|
||||
.unwrap_or_else(|poisoned| poisoned.into_inner()) = Some((Instant::now(), branding));
|
||||
}
|
||||
|
||||
pub async fn premium_branding(&self, client: &AdminApiClient) -> Option<PremiumBranding> {
|
||||
if let Some(branding) = self.cached_premium_branding() {
|
||||
return Some(branding);
|
||||
}
|
||||
let branding = PremiumBranding::from_discovery(
|
||||
&client
|
||||
.get_instance_premium_discovery()
|
||||
.await
|
||||
.log_error("load premium branding")?,
|
||||
);
|
||||
self.remember_premium_branding(branding.clone());
|
||||
Some(branding)
|
||||
}
|
||||
}
|
||||
|
||||
impl axum::extract::FromRef<AppState> for AdminConfig {
|
||||
|
||||
Reference in new issue
Block a user