Compare commits
5 commits
10cf09ee76
...
ec6b1b6477
Author | SHA1 | Date | |
---|---|---|---|
ec6b1b6477 | |||
923103c5ef | |||
29936813f0 | |||
31e2cab280 | |||
1da83c0016 |
8 changed files with 92 additions and 9 deletions
5
queries/records/delete_expired_records.sql
Normal file
5
queries/records/delete_expired_records.sql
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
DELETE FROM records
|
||||||
|
WHERE
|
||||||
|
downloads >= max_downloads
|
||||||
|
OR julianday('now') - julianday(uploaded) > 3
|
||||||
|
RETURNING cache_name;
|
7
queries/records/get_expired_records.sql
Normal file
7
queries/records/get_expired_records.sql
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
SELECT
|
||||||
|
cache_name,
|
||||||
|
downloads,
|
||||||
|
max_downloads,
|
||||||
|
julianday('now') - julianday(uploaded) AS age
|
||||||
|
FROM records
|
||||||
|
WHERE downloads >= max_downloads OR age > 5;
|
6
queries/records/get_records.sql
Normal file
6
queries/records/get_records.sql
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
SELECT
|
||||||
|
cache_name,
|
||||||
|
uploaded,
|
||||||
|
downloads,
|
||||||
|
max_downloads
|
||||||
|
FROM records;
|
7
queries/records/get_records_page.sql
Normal file
7
queries/records/get_records_page.sql
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
SELECT
|
||||||
|
cache_name,
|
||||||
|
uploaded,
|
||||||
|
downloads,
|
||||||
|
max_downloads
|
||||||
|
FROM records
|
||||||
|
LIMIT ? OFFSET ?;
|
|
@ -4,9 +4,14 @@ use axum::{
|
||||||
routing::get,
|
routing::get,
|
||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
|
use axum_extra::TypedHeader;
|
||||||
use reqwest::StatusCode;
|
use reqwest::StatusCode;
|
||||||
|
|
||||||
use crate::{templates::DownloadLinkTemplate, AppState, AsyncRemoveRecord};
|
use crate::{
|
||||||
|
templates::{self, DownloadLinkTemplate},
|
||||||
|
util::headers::HxRequest,
|
||||||
|
AppState, AsyncRemoveRecord,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn get_link_router() -> Router<AppState> {
|
pub fn get_link_router() -> Router<AppState> {
|
||||||
// Link pages
|
// Link pages
|
||||||
|
@ -62,12 +67,22 @@ async fn link_delete(
|
||||||
|
|
||||||
async fn remaining(
|
async fn remaining(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
|
hx_request: Option<TypedHeader<HxRequest>>,
|
||||||
axum::extract::Path(id): axum::extract::Path<String>,
|
axum::extract::Path(id): axum::extract::Path<String>,
|
||||||
) -> impl IntoResponse {
|
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
||||||
let records = state.records.lock().await;
|
if hx_request.is_none() {
|
||||||
if let Some(record) = records.get(&id) {
|
return Err((
|
||||||
Html(crate::templates::get_downloads_remaining_text(record))
|
StatusCode::BAD_REQUEST,
|
||||||
} else {
|
"Attempt to fetch html fragment from non-htmx request".to_string(),
|
||||||
Html("?".to_string())
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let records = state.records.lock().await;
|
||||||
|
|
||||||
|
Ok(Html(
|
||||||
|
records
|
||||||
|
.get(&id)
|
||||||
|
.map(templates::get_downloads_remaining_text)
|
||||||
|
.unwrap_or_else(|| "?".to_string()),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,3 +31,38 @@ impl Header for ForwardedFor {
|
||||||
values.extend(std::iter::once(HeaderValue::from_str(&self.0).unwrap()));
|
values.extend(std::iter::once(HeaderValue::from_str(&self.0).unwrap()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct HxRequest;
|
||||||
|
|
||||||
|
pub static HXR_TEXT: &str = "hx-request";
|
||||||
|
|
||||||
|
pub static HXR_NAME: HeaderName = HeaderName::from_static(HXR_TEXT);
|
||||||
|
|
||||||
|
impl Header for HxRequest {
|
||||||
|
fn name() -> &'static HeaderName {
|
||||||
|
&FF_NAME
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode<'i, I>(values: &mut I) -> Result<Self, headers::Error>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
I: Iterator<Item = &'i headers::HeaderValue>,
|
||||||
|
{
|
||||||
|
let value = values
|
||||||
|
.next()
|
||||||
|
.ok_or_else(headers::Error::invalid)?
|
||||||
|
.to_str()
|
||||||
|
.map_err(|_| headers::Error::invalid())?
|
||||||
|
.to_owned();
|
||||||
|
|
||||||
|
match &value[..] {
|
||||||
|
"true" => Ok(HxRequest),
|
||||||
|
_ => Err(headers::Error::invalid()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode<E: Extend<headers::HeaderValue>>(&self, values: &mut E) {
|
||||||
|
values.extend(std::iter::once(HeaderValue::from_static("true")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -39,6 +39,12 @@ pub struct DownloadLinkFragment {
|
||||||
pub record: UploadRecord,
|
pub record: UploadRecord,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "link.html", block = "downloads_remaining")]
|
||||||
|
pub struct DownloadsRemainingFragment {
|
||||||
|
pub record: UploadRecord,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
#[template(path = "linklist.html")]
|
#[template(path = "linklist.html")]
|
||||||
pub struct LinkListTemplate {
|
pub struct LinkListTemplate {
|
||||||
|
|
|
@ -10,9 +10,11 @@
|
||||||
<div
|
<div
|
||||||
class="link-wrapper"
|
class="link-wrapper"
|
||||||
hx-get="/link/{{ id }}/remaining"
|
hx-get="/link/{{ id }}/remaining"
|
||||||
hx-trigger="click from:#link delay:0.2s, every 10s"
|
hx-trigger="click from:#link delay:0.2s, every 60s"
|
||||||
>
|
>
|
||||||
{{ self::get_downloads_remaining_text(record) }}
|
{% block downloads_remaining %}
|
||||||
|
{{ self::get_downloads_remaining_text(record) }}
|
||||||
|
{% endblock downloads_remaining %}
|
||||||
</div>
|
</div>
|
||||||
<button class="return-button" onclick="clipboard()">
|
<button class="return-button" onclick="clipboard()">
|
||||||
Copy to Clipboard
|
Copy to Clipboard
|
||||||
|
|
Loading…
Reference in a new issue