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)