add: store ad clicked state in cookies

This commit is contained in:
trisua 2025-08-12 15:09:08 -04:00
parent 83971b3d20
commit befd9096b1
5 changed files with 119 additions and 65 deletions

View file

@ -6,8 +6,9 @@ use crate::{
};
use axum::{
extract::Path,
response::{IntoResponse, Redirect},
response::{Html, IntoResponse},
Extension, Json,
http::StatusCode,
};
use tetratto_core::model::{
economy::UserAd,
@ -139,8 +140,56 @@ pub async fn click_request(
let data = &(data.read().await).0;
let user = get_user_from_token!(jar, data);
let bad_return = (
StatusCode::FOUND,
[
(
"Set-Cookie".to_string(),
format!(
"Atto-Clicked=true; Path=/api/v1/ads/host/{host}/{id}/click; Max-Age=86400"
),
),
("Location".to_string(), data.0.0.host.clone()),
],
Html(""),
);
if jar.get("Atto-Clicked").is_some() {
// we've already clicked this ad, don't charge
match data.get_ad_by_id(id).await {
Ok(x) => {
return (
StatusCode::FOUND,
[
(
"Set-Cookie".to_string(),
format!(
"Atto-Clicked=true; Path=/api/v1/ads/host/{host}/{id}/click; Max-Age=86400"
),
),
("Location".to_string(), x.target),
],
Html(""),
);
}
Err(_) => return bad_return,
}
}
match data.ad_click(host, id, user).await {
Ok(t) => Redirect::to(&t),
Err(_) => Redirect::to(&data.0.0.host),
Ok(t) => (
StatusCode::FOUND,
[
(
"Set-Cookie".to_string(),
format!(
"Atto-Clicked=true; Path=/api/v1/ads/host/{host}/{id}/click; Max-Age=86400"
),
),
("Location".to_string(), t),
],
Html(""),
),
Err(_) => bad_return,
}
}

View file

@ -348,12 +348,25 @@ pub async fn channels_request(
None
};
let membership = match data
.0
.get_membership_by_owner_community(user.id, community)
.await
{
Ok(m) => m,
Err(e) => return Err(Html(render_error(e, &jar, &data, &Some(user)).await)),
};
let can_manage_channels = membership.role.check(CommunityPermission::MANAGE_CHANNELS)
| user.permissions.check(FinePermission::MANAGE_CHANNELS);
let lang = get_lang!(jar, data.0);
let mut context = initial_context(&data.0.0.0, lang, &Some(user)).await;
context.insert("channels", &channels);
context.insert("page", &props.page);
context.insert("can_manage_channels", &can_manage_channels);
context.insert("members", &members);
context.insert("channel", &channel);

View file

@ -5,7 +5,7 @@ use axum::{
};
use crate::cookie::CookieJar;
use tetratto_core::model::{
economy::{CoinTransferMethod, UserAd, UserAdSize},
economy::{CoinTransferMethod, UserAdSize},
Error,
};
use crate::{assets::initial_context, get_lang, get_user_from_token, State};
@ -254,18 +254,17 @@ pub async fn random_ad_request(
Query(props): Query<RandomAdQuery>,
) -> impl IntoResponse {
let data = data.read().await;
let headers = [(
"content-security-policy",
"default-src 'self' *.spotify.com musicbrainz.org; img-src * data:; media-src *; font-src *; style-src 'unsafe-inline' 'self' *; script-src 'self' 'unsafe-inline' *; worker-src * blob:; object-src 'self' *; upgrade-insecure-requests; connect-src * localhost; frame-src 'self' blob: *; frame-ancestors *",
)];
let ad = match data.0.random_ad_charged(props.size.clone()).await {
Ok(x) => x,
Err(_) => UserAd {
id: 0,
created: 0,
upload_id: 0,
owner: data.0.0.0.system_user,
target: data.0.0.0.host.clone(),
last_charge_time: 0,
is_running: true,
size: props.size,
},
Err(_) => {
// no ad found, show nothing
return (headers, Html(String::new()));
}
};
let mut context = tera::Context::new();
@ -276,10 +275,7 @@ pub async fn random_ad_request(
// return
(
[(
"content-security-policy",
"default-src 'self' *.spotify.com musicbrainz.org; img-src * data:; media-src *; font-src *; style-src 'unsafe-inline' 'self' *; script-src 'self' 'unsafe-inline' *; worker-src * blob:; object-src 'self' *; upgrade-insecure-requests; connect-src * localhost; frame-src 'self' blob: *; frame-ancestors *",
)],
headers,
Html(data.1.render("economy/ad.html", &context).unwrap()),
)
}
@ -291,19 +287,17 @@ pub async fn known_ad_request(
Path(id): Path<usize>,
) -> impl IntoResponse {
let data = data.read().await;
let headers = [
(
"content-security-policy",
"default-src 'self' *.spotify.com musicbrainz.org; img-src * data:; media-src *; font-src *; style-src 'unsafe-inline' 'self' *; script-src 'self' 'unsafe-inline' *; worker-src * blob:; object-src 'self' *; upgrade-insecure-requests; connect-src * localhost; frame-src 'self' blob: *; frame-ancestors *",
),
("Cache-Control", "no-cache"),
];
let ad = match data.0.get_ad_by_id(id).await {
Ok(x) => x,
Err(_) => UserAd {
// polyfill ad
id: 0,
created: 0,
upload_id: 0,
owner: data.0.0.0.system_user,
target: data.0.0.0.host.clone(),
last_charge_time: 0,
is_running: true,
size: props.size,
},
Err(_) => return (headers, Html(String::new())),
};
let mut context = tera::Context::new();
@ -314,13 +308,7 @@ pub async fn known_ad_request(
// return
(
[
(
"content-security-policy",
"default-src 'self' *.spotify.com musicbrainz.org; img-src * data:; media-src *; font-src *; style-src 'unsafe-inline' 'self' *; script-src 'self' 'unsafe-inline' *; worker-src * blob:; object-src 'self' *; upgrade-insecure-requests; connect-src * localhost; frame-src 'self' blob: *; frame-ancestors *",
),
("Cache-Control", "no-cache"),
],
headers,
Html(data.1.render("economy/ad.html", &context).unwrap()),
)
}