Added auto removal of expired pastas
This commit is contained in:
parent
5bae4310a3
commit
22b61fc793
7 changed files with 59 additions and 13 deletions
20
README.MD
Normal file
20
README.MD
Normal file
|
@ -0,0 +1,20 @@
|
|||
# MicroBin
|
||||
|
||||
![Screenshot](git/index.png)
|
||||
|
||||
MicroBin is a super tiny and simple self hosted pastebin app written in Rust. The executable is around 6MB and it uses 2MB memory (plus your pastas).
|
||||
|
||||
Features:
|
||||
- No CSS or JS, super lightweight and simple
|
||||
- Animal names instead of random numbers for pasta identifiers
|
||||
- Automatically expiring pastas
|
||||
- Never expiring pastas
|
||||
- Listing and manually removing pastas
|
||||
|
||||
Needed improvements:
|
||||
- Persisting pastas on disk (currently they are lost on restart)
|
||||
- Removing pasta after N reads
|
||||
- File uploads
|
||||
- URL shortening
|
||||
|
||||
![Screenshot](git/pasta.png)
|
25
src/main.rs
25
src/main.rs
|
@ -53,7 +53,7 @@ async fn create(data: web::Data<AppState>, pasta: web::Form<PastaFormData>) -> i
|
|||
} as i64;
|
||||
|
||||
let expiration = match innerPasta.expiration.as_str() {
|
||||
"firstread" => 1,
|
||||
"1min" => timenow + 60,
|
||||
"10min" => timenow + 60 * 10,
|
||||
"1hour" => timenow + 60 * 60,
|
||||
"24hour" => timenow + 60 * 60 * 24,
|
||||
|
@ -78,9 +78,11 @@ async fn create(data: web::Data<AppState>, pasta: web::Form<PastaFormData>) -> i
|
|||
|
||||
#[get("/pasta/{id}")]
|
||||
async fn getpasta(data: web::Data<AppState>, id: web::Path<String>) -> HttpResponse {
|
||||
let pastas = data.pastas.lock().unwrap();
|
||||
let mut pastas = data.pastas.lock().unwrap();
|
||||
let id = to_u64(&*id.into_inner());
|
||||
|
||||
remove_expired(&mut pastas);
|
||||
|
||||
for pasta in pastas.iter() {
|
||||
if pasta.id == id {
|
||||
return HttpResponse::Found().content_type("text/html").body(PastaTemplate { pasta }.render().unwrap());
|
||||
|
@ -92,9 +94,11 @@ async fn getpasta(data: web::Data<AppState>, id: web::Path<String>) -> HttpRespo
|
|||
|
||||
#[get("/rawpasta/{id}")]
|
||||
async fn getrawpasta(data: web::Data<AppState>, id: web::Path<String>) -> String {
|
||||
let pastas = data.pastas.lock().unwrap();
|
||||
let mut pastas = data.pastas.lock().unwrap();
|
||||
let id = to_u64(&*id.into_inner());
|
||||
|
||||
remove_expired(&mut pastas);
|
||||
|
||||
for pasta in pastas.iter() {
|
||||
if pasta.id == id {
|
||||
return pasta.content.to_owned();
|
||||
|
@ -109,6 +113,8 @@ async fn remove(data: web::Data<AppState>, id: web::Path<String>) -> HttpRespons
|
|||
let mut pastas = data.pastas.lock().unwrap();
|
||||
let id = to_u64(&*id.into_inner());
|
||||
|
||||
remove_expired(&mut pastas);
|
||||
|
||||
for (i, pasta) in pastas.iter().enumerate() {
|
||||
if pasta.id == id {
|
||||
pastas.remove(i);
|
||||
|
@ -123,6 +129,8 @@ async fn remove(data: web::Data<AppState>, id: web::Path<String>) -> HttpRespons
|
|||
async fn list(data: web::Data<AppState>) -> HttpResponse {
|
||||
let mut pastas = data.pastas.lock().unwrap();
|
||||
|
||||
remove_expired(&mut pastas);
|
||||
|
||||
HttpResponse::Found().content_type("text/html").body(PastaListTemplate { pastas: &pastas }.render().unwrap())
|
||||
}
|
||||
|
||||
|
@ -135,3 +143,14 @@ async fn main() -> std::io::Result<()> {
|
|||
HttpServer::new(move || App::new().app_data(data.clone()).service(index).service(create).service(getpasta).service(getrawpasta).service(remove).service(list)
|
||||
).bind("127.0.0.1:8080")?.run().await
|
||||
}
|
||||
|
||||
fn remove_expired(pastas: &mut Vec<Pasta>) {
|
||||
let timenow: i64 = match SystemTime::now().duration_since(UNIX_EPOCH) {
|
||||
Ok(n) => n.as_secs(),
|
||||
Err(_) => panic!("SystemTime before UNIX EPOCH!"),
|
||||
} as i64;
|
||||
|
||||
pastas.retain(|p| {
|
||||
p.expiration == 0 || p.expiration > timenow
|
||||
});
|
||||
}
|
||||
|
|
|
@ -3,7 +3,12 @@
|
|||
<title>MicroBin</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<body style="max-width: 720px; margin: auto; padding-left:0.5rem; padding-right:0.5rem; line-height: 1.5; font-size: 1.1em; font-family: sans-serif">
|
||||
<body style="max-width: 720px;
|
||||
margin: auto;
|
||||
padding-left:0.5rem;
|
||||
padding-right:0.5rem;
|
||||
line-height: 1.5;
|
||||
font-size: 1.1em;">
|
||||
<br>
|
||||
|
||||
<b style="margin-right: 0.5rem">
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<label for="expiration">Expiration</label><br>
|
||||
<select name="expiration" id="expiration">
|
||||
<optgroup label="Expire">
|
||||
<option value="firstread">First Read</option>
|
||||
<option value="1min">1 minute</option>
|
||||
<option value="10min">10 minutes</option>
|
||||
<option value="1hour">1 hour</option>
|
||||
<option selected value="24hour">24 hours</option>
|
||||
|
@ -18,6 +18,6 @@
|
|||
<textarea style="width: 100%; min-height: 100px" name="content"></textarea>
|
||||
<br>
|
||||
<br>
|
||||
<input style="width: 100px; background-color: limegreen" type="submit" value="Submit"/>
|
||||
<input style="width: 100px; background-color: limegreen"; type="submit" value="Save"/>
|
||||
</form>
|
||||
{% include "footer.html" %}
|
|
@ -1,5 +1,5 @@
|
|||
{% include "header.html" %}
|
||||
<a href="/rawpasta/{{pasta.id}}">Raw Pasta</a>
|
||||
<a href="/rawpasta/{{pasta.idAsAnimals()}}">Raw Pasta</a>
|
||||
<pre style="background: lightgray; border: 1px black solid; padding: 0.5rem; overflow: auto">
|
||||
{{pasta}}
|
||||
</pre>
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
{% include "header.html" %}
|
||||
|
||||
|
||||
{% if pastas.is_empty() %}
|
||||
<p>
|
||||
No pastas yet. 😔 Create one <a href="/">here</a>.
|
||||
</p>
|
||||
{%- else %}
|
||||
<table style="width: 100%" border="1">
|
||||
<tr style="background: lightgrey">
|
||||
<th>
|
||||
|
@ -31,10 +38,5 @@
|
|||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
{% if pastas.is_empty() %}
|
||||
<p>
|
||||
No Pastas :-(
|
||||
</p>
|
||||
{%- endif %}
|
||||
{% include "footer.html" %}
|
Loading…
Reference in a new issue