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