1
0
Fork 0
mirror of https://github.com/SinTan1729/chhoto-url synced 2025-04-20 11:50:01 -05:00

Compare commits

..

No commits in common. "a0f0eb5280babf806f95113f950ddb417079e37c" and "6659452c5196c2f1325971cdee45eb799321d327" have entirely different histories.

6 changed files with 42 additions and 56 deletions

View file

@ -13,11 +13,9 @@ build-dev:
docker-local: build-dev docker-local: build-dev
docker build --tag chhoto-url --build-arg TARGETARCH=amd64 -f Dockerfile.multiarch . docker build --tag chhoto-url --build-arg TARGETARCH=amd64 -f Dockerfile.multiarch .
docker-stop: docker-test: docker-local
docker ps -q --filter "name=chhoto-url" | xargs -r docker stop docker ps -q --filter "name=chhoto-url" | xargs -r docker stop
docker ps -aq --filter "name=chhoto-url" | xargs -r docker rm docker ps -aq --filter "name=chhoto-url" | xargs -r docker rm
docker-test: docker-local docker-stop
docker run -p 4567:4567 --name chhoto-url -e password="${PASSWORD}" -d chhoto-url docker run -p 4567:4567 --name chhoto-url -e password="${PASSWORD}" -d chhoto-url
docker logs chhoto-url -f docker logs chhoto-url -f
@ -42,4 +40,4 @@ clean:
docker ps -aq --filter "name=chhoto-url" | xargs -r docker rm docker ps -aq --filter "name=chhoto-url" | xargs -r docker rm
cargo clean --manifest-path=actix/Cargo.toml cargo clean --manifest-path=actix/Cargo.toml
.PHONY: build-dev docker-local docker-stop build-release .PHONY: build-dev docker-local build-release

4
actix/Cargo.lock generated
View file

@ -475,7 +475,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "chhoto-url" name = "chhoto-url"
version = "5.2.1" version = "5.2.0"
dependencies = [ dependencies = [
"actix-files", "actix-files",
"actix-session", "actix-session",
@ -485,8 +485,6 @@ dependencies = [
"rand", "rand",
"regex", "regex",
"rusqlite", "rusqlite",
"serde",
"serde_json",
] ]
[[package]] [[package]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "chhoto-url" name = "chhoto-url"
version = "5.2.1" version = "5.2.0"
edition = "2021" edition = "2021"
authors = ["Sayantan Santra <sayantan[dot]santra689[at]gmail[dot]com"] authors = ["Sayantan Santra <sayantan[dot]santra689[at]gmail[dot]com"]
license = "mit" license = "mit"
@ -32,5 +32,3 @@ rand = "0.8.5"
actix-session = { version = "0.9.0", features = ["cookie-session"] } actix-session = { version = "0.9.0", features = ["cookie-session"] }
env_logger = "0.11.1" env_logger = "0.11.1"
nanoid = "0.4.0" nanoid = "0.4.0"
serde_json = "1.0.115"
serde = { version = "1.0.197", features = [ "derive" ] }

View file

@ -1,12 +1,4 @@
use rusqlite::Connection; use rusqlite::Connection;
use serde::Serialize;
#[derive(Serialize)]
pub struct DBRow {
shortlink: String,
longlink: String,
hits: i64,
}
pub fn find_url(shortlink: &str, db: &Connection) -> Option<String> { pub fn find_url(shortlink: &str, db: &Connection) -> Option<String> {
let mut statement = db let mut statement = db
@ -18,19 +10,17 @@ pub fn find_url(shortlink: &str, db: &Connection) -> Option<String> {
.ok() .ok()
} }
pub fn getall(db: &Connection) -> Vec<DBRow> { pub fn getall(db: &Connection) -> Vec<String> {
let mut statement = db.prepare_cached("SELECT * FROM urls").unwrap(); let mut statement = db.prepare_cached("SELECT * FROM urls").unwrap();
let mut data = statement.query([]).unwrap(); let mut data = statement.query([]).unwrap();
let mut links: Vec<DBRow> = Vec::new(); let mut links: Vec<String> = Vec::new();
while let Some(row) = data.next().unwrap() { while let Some(row) = data.next().unwrap() {
let row_struct = DBRow { let short_url: String = row.get("short_url").unwrap();
shortlink: row.get("short_url").unwrap(), let long_url: String = row.get("long_url").unwrap();
longlink: row.get("long_url").unwrap(), let hits: i64 = row.get("hits").unwrap();
hits: row.get("hits").unwrap(), links.push(format!("{short_url},{long_url},{hits}"));
};
links.push(row_struct);
} }
links links

View file

@ -5,13 +5,6 @@ use nanoid::nanoid;
use rand::seq::SliceRandom; use rand::seq::SliceRandom;
use regex::Regex; use regex::Regex;
use rusqlite::Connection; use rusqlite::Connection;
use serde::Deserialize;
#[derive(Deserialize)]
struct URLPair {
shortlink: String,
longlink: String,
}
pub fn get_longurl(shortlink: String, db: &Connection) -> Option<String> { pub fn get_longurl(shortlink: String, db: &Connection) -> Option<String> {
if validate_link(&shortlink) { if validate_link(&shortlink) {
@ -28,11 +21,12 @@ fn validate_link(link: &str) -> bool {
pub fn getall(db: &Connection) -> String { pub fn getall(db: &Connection) -> String {
let links = database::getall(db); let links = database::getall(db);
serde_json::to_string(&links).unwrap() links.join("\n")
} }
pub fn add_link(req: String, db: &Connection) -> (bool, String) { pub fn add_link(req: String, db: &Connection) -> (bool, String) {
let mut chunks: URLPair = serde_json::from_str(&req).unwrap(); let chunks: Vec<&str> = req.split(';').collect();
let longlink = String::from(chunks[0]);
let style = env::var("slug_style").unwrap_or(String::from("Pair")); let style = env::var("slug_style").unwrap_or(String::from("Pair"));
let len_str = env::var("slug_length").unwrap_or(String::from("8")); let len_str = env::var("slug_length").unwrap_or(String::from("8"));
@ -41,16 +35,20 @@ pub fn add_link(req: String, db: &Connection) -> (bool, String) {
len = 4; len = 4;
} }
if chunks.shortlink.is_empty() { let mut shortlink;
chunks.shortlink = gen_link(style, len); if chunks.len() > 1 {
shortlink = chunks[1].to_string().to_lowercase();
if shortlink.is_empty() {
shortlink = gen_link(style, len);
}
} else {
shortlink = gen_link(style, len);
} }
if validate_link(chunks.shortlink.as_str()) if validate_link(shortlink.as_str()) && get_longurl(shortlink.clone(), db).is_none() {
&& get_longurl(chunks.shortlink.clone(), db).is_none()
{
( (
database::add_link(chunks.shortlink.clone(), chunks.longlink, db), database::add_link(shortlink.clone(), longlink, db),
chunks.shortlink, shortlink,
) )
} else { } else {
(false, String::from("shortUrl not valid or already in use")) (false, String::from("shortUrl not valid or already in use"))

View file

@ -31,7 +31,16 @@ const refreshData = async () => {
document.getElementById("login-dialog").showModal(); document.getElementById("login-dialog").showModal();
document.getElementById("password").focus(); document.getElementById("password").focus();
} else { } else {
data = JSON.parse(reply) data = reply
.split("\n")
.filter(line => line !== "")
.map(line => line.split(","))
.map(arr => ({
short: arr[0],
long: arr[1],
hits: arr[2]
}));
displayData(data); displayData(data);
} }
}; };
@ -78,18 +87,18 @@ const showAlert = async (text, col) => {
const TR = (row, site) => { const TR = (row, site) => {
const tr = document.createElement("tr"); const tr = document.createElement("tr");
const longTD = TD(A_LONG(row["longlink"]), "Long URL"); const longTD = TD(A_LONG(row.long), "Long URL");
var shortTD = null; var shortTD = null;
if (window.isSecureContext) { if (window.isSecureContext) {
shortTD = TD(A_SHORT(row["shortlink"], site), "Short URL"); shortTD = TD(A_SHORT(row.short, site), "Short URL");
} }
else { else {
shortTD = TD(A_SHORT_INSECURE(row["shortlink"], site), "Short URL"); shortTD = TD(A_SHORT_INSECURE(row.short, site), "Short URL");
} }
hitsTD = TD(row["hits"]); hitsTD = TD(row.hits);
hitsTD.setAttribute("label", "Hits"); hitsTD.setAttribute("label", "Hits");
hitsTD.setAttribute("name", "hitsColumn"); hitsTD.setAttribute("name", "hitsColumn");
const btn = deleteButton(row["shortlink"]); const btn = deleteButton(row.short);
tr.appendChild(shortTD); tr.appendChild(shortTD);
tr.appendChild(longTD); tr.appendChild(longTD);
@ -159,19 +168,14 @@ const TD = (s, u) => {
const submitForm = () => { const submitForm = () => {
const form = document.forms.namedItem("new-url-form"); const form = document.forms.namedItem("new-url-form");
const data ={ const longUrl = form.elements["longUrl"];
"longlink": form.elements["longUrl"].value, const shortUrl = form.elements["shortUrl"];
"shortlink": form.elements["shortUrl"].value,
};
const url = prepSubdir("/api/new"); const url = prepSubdir("/api/new");
fetch(url, { fetch(url, {
method: "POST", method: "POST",
headers: { body: `${longUrl.value};${shortUrl.value}`
"Content-Type": "application/json",
},
body: JSON.stringify(data),
}) })
.then(res => { .then(res => {
if (!res.ok) { if (!res.ok) {