diff --git a/crates/app/src/public/html/economy/ad.lisp b/crates/app/src/public/html/economy/ad.lisp index 8649284..fe4581f 100644 --- a/crates/app/src/public/html/economy/ad.lisp +++ b/crates/app/src/public/html/economy/ad.lisp @@ -48,7 +48,7 @@ .display_tag { position: absolute; - bottom: 0.5rem; + top: 0.5rem; left: 0.5rem; padding: 0.15rem 0.5rem; background: hsla(0, 0%, 0%, 50%); @@ -59,4 +59,5 @@ pointer-events: none; border-radius: 0.4rem; box-shadow: 0 0 2px hsla(0, 0%, 0%, 25%); + opacity: 25%; }")))) diff --git a/crates/app/src/routes/api/v1/ads.rs b/crates/app/src/routes/api/v1/ads.rs index 338b586..aba8682 100644 --- a/crates/app/src/routes/api/v1/ads.rs +++ b/crates/app/src/routes/api/v1/ads.rs @@ -17,7 +17,7 @@ use tetratto_core::model::{ }; use super::{CreateAd, UpdateAdIsRunning}; -const MAXIMUM_AD_FILE_SIZE: usize = 4_194_304; +const MAXIMUM_AD_FILE_SIZE: usize = 2_097_152; pub async fn create_request( jar: CookieJar, @@ -104,6 +104,15 @@ pub async fn update_is_running_request( None => return Json(Error::NotAllowed.into()), }; + if user.coins < 50 { + return Json( + Error::MiscError( + "You must have a minimum of 50 coins in your balance to run ads".to_string(), + ) + .into(), + ); + } + match data .update_ad_is_running(id, &user, if req.is_running { 1 } else { 0 }) .await diff --git a/crates/app/src/routes/pages/economy.rs b/crates/app/src/routes/pages/economy.rs index 6d093ce..97fc264 100644 --- a/crates/app/src/routes/pages/economy.rs +++ b/crates/app/src/routes/pages/economy.rs @@ -257,7 +257,6 @@ pub async fn random_ad_request( let ad = match data.0.random_ad_charged(props.size.clone()).await { Ok(x) => x, Err(_) => UserAd { - // polyfill ad id: 0, created: 0, upload_id: 0, diff --git a/crates/core/src/database/ads.rs b/crates/core/src/database/ads.rs index ce7ff91..03d0936 100644 --- a/crates/core/src/database/ads.rs +++ b/crates/core/src/database/ads.rs @@ -56,6 +56,30 @@ impl DataManager { Ok(res.unwrap()) } + /// Disable all ads by the given user. + /// + /// # Arguments + /// * `id` - the ID of the user to kill ads from + pub async fn stop_all_ads_by_user(&self, id: usize) -> Result> { + let conn = match self.0.connect().await { + Ok(c) => c, + Err(e) => return Err(Error::DatabaseConnection(e.to_string())), + }; + + let res = query_rows!( + &conn, + "UPDATE ads SET is_running = 0 WHERE owner = $1", + &[&(id as i64)], + |x| { Self::get_ad_from_row(x) } + ); + + if let Err(e) = res { + return Err(Error::DatabaseError(e.to_string())); + } + + Ok(res.unwrap()) + } + /// Create a new ad in the database. /// /// # Arguments @@ -161,7 +185,7 @@ impl DataManager { const MINIMUM_DELTA_FOR_CHARGE: usize = 604_800_000; // 7 days /// The amount charged to a [`UserAd`] owner each day the ad is running (and is pulled from the pool). - pub const AD_RUN_CHARGE: i32 = 50; + pub const AD_RUN_CHARGE: i32 = 25; /// The amount charged to a [`UserAd`] owner each time the ad is clicked. pub const AD_CLICK_CHARGE: i32 = 2; @@ -173,17 +197,23 @@ impl DataManager { let delta = now - ad.last_charge_time; if delta >= Self::MINIMUM_DELTA_FOR_CHARGE { - self.create_transfer( - &mut CoinTransfer::new( - ad.owner, - self.0.0.system_user, - Self::AD_RUN_CHARGE, - CoinTransferMethod::Transfer, - CoinTransferSource::AdCharge, - ), - true, - ) - .await?; + if let Err(e) = self + .create_transfer( + &mut CoinTransfer::new( + ad.owner, + self.0.0.system_user, + Self::AD_RUN_CHARGE, + CoinTransferMethod::Transfer, + CoinTransferSource::AdCharge, + ), + true, + ) + .await + { + // boo user cannot afford to keep running their ads + self.stop_all_ads_by_user(ad.owner).await?; + return Err(e); + }; self.update_ad_last_charge_time(ad.id, now as i64).await?; } @@ -212,17 +242,22 @@ impl DataManager { } // create click transfer - self.create_transfer( - &mut CoinTransfer::new( - ad.owner, - host, - Self::AD_CLICK_CHARGE, - CoinTransferMethod::Transfer, - CoinTransferSource::AdClick, - ), - true, - ) - .await?; + if let Err(e) = self + .create_transfer( + &mut CoinTransfer::new( + ad.owner, + host, + Self::AD_CLICK_CHARGE, + CoinTransferMethod::Transfer, + CoinTransferSource::AdClick, + ), + true, + ) + .await + { + self.stop_all_ads_by_user(ad.owner).await?; + return Err(e); + } // return Ok(ad.target)