mirror of https://github.com/zer0bin-dev/zer0bin
Merge pull request #47 from zer0bin-dev/main
Merge upstream single-view-pastes
This commit is contained in:
commit
51f3293279
|
@ -2,10 +2,13 @@ CREATE TABLE IF NOT EXISTS pastes (
|
|||
"id" TEXT PRIMARY KEY,
|
||||
"content" TEXT NOT NULL,
|
||||
"views" BIGINT DEFAULT 0,
|
||||
"single_view" BOOLEAN DEFAULT false,
|
||||
"expires_at" TIMESTAMP WITHOUT TIME ZONE,
|
||||
"created_at" TIMESTAMP WITHOUT TIME ZONE DEFAULT(NOW() AT TIME ZONE 'utc')
|
||||
);
|
||||
|
||||
-- ALTER TABLE pastes ADD COLUMN single_view BOOLEAN DEFAULT false;
|
||||
|
||||
CREATE OR REPLACE FUNCTION deleteExpiredPastes() RETURNS trigger AS $pastes_expire$ BEGIN
|
||||
DELETE FROM pastes
|
||||
WHERE "expires_at" IS NOT NULL
|
||||
|
|
|
@ -7,12 +7,14 @@ pub struct Paste {
|
|||
pub id: String,
|
||||
pub content: String,
|
||||
pub views: i64,
|
||||
pub single_view: bool,
|
||||
pub expires_at: Option<NaiveDateTime>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct PartialPaste {
|
||||
pub content: String,
|
||||
pub single_view: bool
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
|
@ -25,6 +27,7 @@ pub struct ApiResponse<T> {
|
|||
pub struct NewPasteResponse {
|
||||
pub id: String,
|
||||
pub content: String,
|
||||
pub single_view: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
|
@ -32,6 +35,7 @@ pub struct GetPasteResponse {
|
|||
pub id: String,
|
||||
pub content: String,
|
||||
pub views: i64,
|
||||
pub single_view: bool,
|
||||
pub expires_at: Option<NaiveDateTime>,
|
||||
}
|
||||
|
||||
|
|
|
@ -32,14 +32,21 @@ pub async fn get_paste(state: web::Data<AppState>, id: web::Path<String>) -> imp
|
|||
|
||||
match res {
|
||||
Ok(p) => {
|
||||
// this may be worth handling at some point..
|
||||
let _ = sqlx::query(r#"UPDATE pastes SET "views" = "views" + 1 WHERE "id" = $1"#)
|
||||
.bind(id.clone())
|
||||
.execute(&state.pool)
|
||||
.await;
|
||||
// Only increment views if its not a single view paste
|
||||
if p.single_view {
|
||||
let _ = sqlx::query(r#"DELETE FROM pastes WHERE "id" = $1"#)
|
||||
.bind(id.clone())
|
||||
.execute(&state.pool)
|
||||
.await;
|
||||
} else {
|
||||
let _ = sqlx::query(r#"UPDATE pastes SET "views" = "views" + 1 WHERE "id" = $1"#)
|
||||
.bind(id.clone())
|
||||
.execute(&state.pool)
|
||||
.await;
|
||||
}
|
||||
|
||||
if state.config.logging.on_get_paste {
|
||||
println!("[GET] id={} views={}", id, p.views + 1);
|
||||
println!("[GET] id={} views={} single_view={}", id, p.views + 1, p.single_view);
|
||||
}
|
||||
|
||||
HttpResponse::Ok().json(ApiResponse {
|
||||
|
@ -48,6 +55,7 @@ pub async fn get_paste(state: web::Data<AppState>, id: web::Path<String>) -> imp
|
|||
id: p.id,
|
||||
content: p.content,
|
||||
views: p.views + 1,
|
||||
single_view: p.single_view,
|
||||
expires_at: p.expires_at,
|
||||
},
|
||||
})
|
||||
|
@ -87,13 +95,25 @@ pub async fn get_raw_paste(state: web::Data<AppState>, id: web::Path<String>) ->
|
|||
|
||||
match res {
|
||||
Ok(p) => {
|
||||
// this may be worth handling at some point..
|
||||
let _ = sqlx::query(r#"UPDATE pastes SET "views" = "views" + 1 WHERE "id" = $1"#)
|
||||
.bind(id.clone())
|
||||
.execute(&state.pool)
|
||||
.await;
|
||||
if p.single_view {
|
||||
let _ = sqlx::query(r#"DELETE FROM pastes WHERE "id" = $1"#)
|
||||
.bind(id.clone())
|
||||
.execute(&state.pool)
|
||||
.await;
|
||||
} else {
|
||||
let _ = sqlx::query(r#"UPDATE pastes SET "views" = "views" + 1 WHERE "id" = $1"#)
|
||||
.bind(id.clone())
|
||||
.execute(&state.pool)
|
||||
.await;
|
||||
}
|
||||
|
||||
HttpResponse::Ok().content_type("text/plain").body(p.content)
|
||||
if state.config.logging.on_get_paste {
|
||||
println!("[GET] raw id={} views={} single_view={}", id, p.views + 1, p.single_view);
|
||||
}
|
||||
|
||||
HttpResponse::Ok()
|
||||
.content_type("text/plain")
|
||||
.body(p.content)
|
||||
}
|
||||
Err(e) => match e {
|
||||
sqlx::Error::RowNotFound => {
|
||||
|
@ -144,11 +164,13 @@ pub async fn new_paste(
|
|||
};
|
||||
|
||||
let content = data.content.clone();
|
||||
let single_view = data.single_view;
|
||||
|
||||
let res =
|
||||
sqlx::query(r#"INSERT INTO pastes("id", "content", "expires_at") VALUES ($1, $2, $3)"#)
|
||||
sqlx::query(r#"INSERT INTO pastes("id", "content", "single_view", "expires_at") VALUES ($1, $2, $3, $4)"#)
|
||||
.bind(id.clone())
|
||||
.bind(content.clone())
|
||||
.bind(single_view)
|
||||
.bind(expires_at)
|
||||
.execute(&state.pool)
|
||||
.await;
|
||||
|
@ -156,11 +178,15 @@ pub async fn new_paste(
|
|||
match res {
|
||||
Ok(_) => {
|
||||
if state.config.logging.on_post_paste {
|
||||
println!("[POST] id={} length={}", id, content.len());
|
||||
println!("[POST] id={} length={} single_view={}", id, content.len(), single_view);
|
||||
}
|
||||
HttpResponse::Ok().json(ApiResponse {
|
||||
success: true,
|
||||
data: NewPasteResponse { id, content },
|
||||
data: NewPasteResponse {
|
||||
id,
|
||||
content,
|
||||
single_view,
|
||||
},
|
||||
})
|
||||
}
|
||||
Err(e) => {
|
||||
|
|
|
@ -51,7 +51,8 @@ function enable(element: HTMLButtonElement) {
|
|||
}
|
||||
|
||||
async function postPaste(content: string, callback: Function) {
|
||||
const payload = { content }
|
||||
let single_view = true;
|
||||
const payload = { content, single_view }
|
||||
await fetch(`${apiUrl}/p/n`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
|
|
Loading…
Reference in New Issue