118 lines
3.2 KiB
Rust
118 lines
3.2 KiB
Rust
// pastebin.run
|
|
// Copyright (C) 2020-2022 Konrad Borowski
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
use crate::schema::pastes;
|
|
use chrono::{DateTime, Utc};
|
|
use diesel::prelude::*;
|
|
use log::info;
|
|
use rand::seq::SliceRandom;
|
|
use rocket::response::{self, Debug, Responder};
|
|
use rocket::Request;
|
|
use serde::Serialize;
|
|
use serde_with::skip_serializing_none;
|
|
|
|
#[derive(Queryable)]
|
|
pub struct Paste {
|
|
pub identifier: String,
|
|
pub paste: String,
|
|
pub delete_at: Option<DateTime<Utc>>,
|
|
}
|
|
|
|
impl Paste {
|
|
pub fn delete_old(connection: &PgConnection) -> Result<(), diesel::result::Error> {
|
|
let pastes = diesel::delete(pastes::table)
|
|
.filter(pastes::delete_at.lt(Utc::now()))
|
|
.execute(connection)?;
|
|
if pastes > 0 {
|
|
info!("Deleted {} paste(s)", pastes);
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
const CHARACTERS: &[u8] = b"23456789bcdfghjkmnpqrstvwxz-";
|
|
|
|
#[derive(Insertable)]
|
|
#[table_name = "pastes"]
|
|
struct InsertPaste<'a> {
|
|
identifier: &'a str,
|
|
delete_at: Option<DateTime<Utc>>,
|
|
paste: &'a str,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum InsertionError {
|
|
Diesel(diesel::result::Error),
|
|
}
|
|
|
|
impl From<diesel::result::Error> for InsertionError {
|
|
fn from(e: diesel::result::Error) -> Self {
|
|
Self::Diesel(e)
|
|
}
|
|
}
|
|
|
|
impl<'r> Responder<'r, 'static> for InsertionError {
|
|
fn respond_to(self, request: &'r Request<'_>) -> response::Result<'static> {
|
|
match self {
|
|
Self::Diesel(e) => Debug(e).respond_to(request),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn insert(
|
|
connection: &PgConnection,
|
|
delete_at: Option<DateTime<Utc>>,
|
|
paste: &str,
|
|
) -> Result<String, InsertionError> {
|
|
let mut rng = rand::thread_rng();
|
|
let identifier: String = (0..12)
|
|
.map(|_| char::from(*CHARACTERS.choose(&mut rng).expect("a random character")))
|
|
.collect();
|
|
|
|
let insert_paste = InsertPaste {
|
|
identifier: &identifier,
|
|
delete_at,
|
|
paste,
|
|
};
|
|
diesel::insert_into(pastes::table)
|
|
.values(&insert_paste)
|
|
.execute(connection)?;
|
|
Ok(identifier)
|
|
}
|
|
|
|
#[skip_serializing_none]
|
|
#[derive(Serialize)]
|
|
pub struct ExternPaste {
|
|
pub identifier: Option<String>,
|
|
pub paste: String,
|
|
pub delete_at: Option<String>,
|
|
}
|
|
|
|
impl ExternPaste {
|
|
pub fn from_paste(paste: Paste) -> Self {
|
|
let Paste {
|
|
identifier,
|
|
paste,
|
|
delete_at,
|
|
} = paste;
|
|
Self {
|
|
identifier: Some(identifier),
|
|
paste,
|
|
delete_at: delete_at.map(|delete_at| delete_at.format("%Y-%m-%d %H:%M").to_string()),
|
|
}
|
|
}
|
|
}
|