Initial setup
This commit is contained in:
7 files changed
+1863
No files matched your search
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
Generated
+1765
File diff suppressed because it is too large.
Load diff
+12
@@ -0,0 +1,12 @@
|
|||||||
|
[package]
|
||||||
|
name = "pastable"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
askama = "0.16.1"
|
||||||
|
axum = "0.8.9"
|
||||||
|
irosashi = "0.3.1"
|
||||||
|
serde = { version = "1.0.229", features = ["derive"] }
|
||||||
|
sqlx = { version = "0.9.0", features = ["runtime-tokio", "sqlite"] }
|
||||||
|
tokio = { version = "1.54.1", features = ["rt-multi-thread"] }
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# Pastable
|
||||||
|
|
||||||
|
Pastable is a free and open-source Plabble initiative to Pastebin.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
- Paste text and code
|
||||||
|
- Optional expiration
|
||||||
|
- Self destruct option (view N times)
|
||||||
|
- URL shortener
|
||||||
|
- One-time password share
|
||||||
|
|
||||||
|
## Routes
|
||||||
|
|
||||||
|
- GET `/` - Home page with explanation
|
||||||
|
- GET `/:id` - based on Accept header, syntax-highlighted HTML or plain text
|
||||||
|
- POST `/` - create a new paste (default no expiration and infinite views), plain text raw body.
|
||||||
|
OR: form parameters `content`, and optional `language`, `expires` (UNIX timestamp) and `max_views` (integer)
|
||||||
|
Returns generated id as plain text.
|
||||||
|
- POST `/:id` - same as POST `/`, but uses the ID if available. Else it returns a random id.
|
||||||
|
- POST `/once` - same as POST `/`, but sets `max_views` to 1
|
||||||
|
- POST `/once/:id` - same as POST `/:id`, but sets `max_views` to 1
|
||||||
|
- GET `/to/:id` - navigate to shortcut link (redirects using HTTP if found)
|
||||||
|
- POST `/to` - create a new link (plain text raw body)
|
||||||
|
OR: form parameter `href`.
|
||||||
|
Returns generated id as plain text.
|
||||||
|
- POST `/to/:id` - same but uses the ID if available, else it returns a random id.
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize database
|
||||||
|
*/
|
||||||
|
pub async fn init_db(pool: &SqlitePool) -> Result<(), sqlx::Error> {
|
||||||
|
sqlx::query(
|
||||||
|
r#"
|
||||||
|
CREATE TABLE IF NOT EXISTS notes (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
type INTEGER NOT NULL,
|
||||||
|
content TEXT NOT NULL,
|
||||||
|
language TEXT,
|
||||||
|
expiration INTEGER,
|
||||||
|
max_views INTEGER,
|
||||||
|
views INTEGER NOT NULL DEFAULT 0,
|
||||||
|
created_at INTEGER NOT NULL,
|
||||||
|
updated_at INTEGER,
|
||||||
|
password TEXT
|
||||||
|
)
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
.execute(pool)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
use axum::{Router, extract::Path, http::{HeaderMap, header::ACCEPT}, response::{Html, IntoResponse}, routing::get, serve};
|
||||||
|
use tokio::net::TcpListener;
|
||||||
|
mod db;
|
||||||
|
mod paste;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
let app = Router::new()
|
||||||
|
.route("/", get(|| async {}))
|
||||||
|
.route("/{id}", get(get_note));
|
||||||
|
|
||||||
|
let listener = TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
|
println!("Listening on http://localhost:3000");
|
||||||
|
serve(listener, app).await.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_note(Path(id): Path<String>, headers: HeaderMap) -> impl IntoResponse {
|
||||||
|
let return_html = headers.get(ACCEPT)
|
||||||
|
.and_then(|v|v.to_str().ok())
|
||||||
|
.and_then(|h| Some(h.contains("text/html")))
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
Html::from("test")
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* Paste type
|
||||||
|
*/
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum PasteType {
|
||||||
|
TextV1 = 0,
|
||||||
|
UrlV1 = 100
|
||||||
|
}
|
||||||
Reference in new issue
Block a user