mirror-chhoto-url/resources/static/script.js

338 lines
10 KiB
JavaScript
Raw Normal View History

2024-04-04 01:40:26 +00:00
// SPDX-FileCopyrightText: 2023 Sayantan Santra <sayantan.santra689@gmail.com>
// SPDX-License-Identifier: MIT
const prepSubdir = (link) => {
let thisPage = new URL(window.location.href);
let subdir = thisPage.pathname;
2024-04-01 07:07:43 +00:00
let out = (subdir + link).replace('//', '/');
console.log(out);
2024-04-01 07:07:43 +00:00
return (subdir + link).replace('//', '/');
}
2024-04-01 07:07:43 +00:00
const getSiteUrl = async () => {
let url = await fetch(prepSubdir("/api/siteurl"))
.then(res => res.text());
if (url == "unset") {
return window.location.host.replace(/\/$/, '');
}
else {
2024-04-03 02:02:11 +00:00
return url.replace(/\/$/, '').replace(/^"/, '').replace(/"$/, '');
2024-04-01 07:07:43 +00:00
}
}
2022-11-11 02:17:39 +00:00
2024-04-01 07:07:43 +00:00
const getVersion = async () => {
let ver = await fetch(prepSubdir("/api/version"))
.then(res => res.text());
return ver;
}
2024-02-11 01:41:50 +00:00
const showVersion = async () => {
let version = await getVersion();
link = document.getElementById("version-number");
link.innerText = "v" + version;
link.href = "https://github.com/SinTan1729/chhoto-url/releases/tag/" + version;
link.hidden = false;
}
const getLogin = async () => {
document.getElementById("container").style.filter = "blur(2px)";
document.getElementById("login-dialog").showModal();
document.getElementById("password").focus();
}
2023-04-12 00:17:04 +00:00
const refreshData = async () => {
2024-04-01 07:07:43 +00:00
let res = await fetch(prepSubdir("/api/all"));
if (!res.ok) {
let errorMsg = await res.text();
document.getElementById("url-table").innerHTML = '';
2024-04-01 07:07:43 +00:00
console.log(errorMsg);
if (errorMsg == "Using public mode.") {
document.getElementById("admin-button").hidden = false;
2024-11-01 06:45:13 +00:00
document.getElementById("api-key-button").hidden = true; // Hide initially
loading_text = document.getElementById("loading-text");
loading_text.hidden = true;
showVersion();
} else {
getLogin();
}
2023-04-08 07:52:16 +00:00
} else {
2024-04-01 07:07:43 +00:00
let data = await res.json();
2023-04-12 00:17:04 +00:00
displayData(data);
2024-11-01 06:45:13 +00:00
document.getElementById("api-key-button").hidden = false; // Show API Key button when logged in
2023-04-08 07:52:16 +00:00
}
2024-04-01 07:07:43 +00:00
}
2020-02-14 18:52:14 +00:00
2022-11-11 02:17:39 +00:00
const displayData = async (data) => {
showVersion();
2022-11-11 05:19:42 +00:00
let site = await getSiteUrl();
admin_button = document.getElementById("admin-button");
admin_button.innerText = "logout";
admin_button.href = "javascript:logOut()";
admin_button.hidden = false;
2024-02-11 01:41:50 +00:00
2024-11-01 06:45:13 +00:00
apikey_button = document.getElementById("api-key-button");
apikey_button.innerText = "API Key"
apikey_button.hidden = false;
table_box = document.getElementById("table-box");
loading_text = document.getElementById("loading-text");
const table = document.getElementById("url-table");
2023-06-03 23:49:59 +00:00
2022-11-10 00:55:50 +00:00
if (data.length == 0) {
table_box.hidden = true;
2023-06-03 23:49:59 +00:00
loading_text.innerHTML = "No active links.";
loading_text.hidden = false;
2022-11-10 00:55:50 +00:00
}
else {
loading_text.hidden = true;
if (!window.isSecureContext) {
const shortUrlHeader = document.getElementById("short-url-header");
shortUrlHeader.innerHTML = "Short URL<br>(right click and copy)";
}
table_box.hidden = false;
table.innerHTML = '';
2022-11-11 02:17:39 +00:00
data.forEach(tr => table.appendChild(TR(tr, site)));
2022-11-10 00:55:50 +00:00
}
2024-04-01 07:07:43 +00:00
}
2020-02-14 18:52:14 +00:00
const showAlert = async (text, col) => {
document.getElementById("alert-box")?.remove();
const controls = document.getElementById("controls");
2022-11-11 00:11:57 +00:00
const alertBox = document.createElement("p");
alertBox.id = "alert-box";
alertBox.style.color = col;
2022-11-11 05:19:42 +00:00
alertBox.innerHTML = text;
2022-11-11 00:11:57 +00:00
controls.appendChild(alertBox);
2024-04-01 07:07:43 +00:00
}
2022-11-09 01:18:14 +00:00
2022-11-11 02:17:39 +00:00
const TR = (row, site) => {
2020-02-14 18:52:14 +00:00
const tr = document.createElement("tr");
2024-03-31 20:38:59 +00:00
const longTD = TD(A_LONG(row["longlink"]), "Long URL");
var shortTD = null;
var isSafari = /Safari/.test(navigator.userAgent) && /Apple Computer/.test(navigator.vendor);
// For now, we disable copying on WebKit due to a possible bug. Manual copying is enabled instead.
// Take a look at https://github.com/SinTan1729/chhoto-url/issues/36
if (window.isSecureContext && !(isSafari)) {
2024-03-31 20:38:59 +00:00
shortTD = TD(A_SHORT(row["shortlink"], site), "Short URL");
2024-10-31 16:08:51 +00:00
} else {
2024-03-31 20:38:59 +00:00
shortTD = TD(A_SHORT_INSECURE(row["shortlink"], site), "Short URL");
}
2024-04-01 07:07:43 +00:00
let hitsTD = TD(row["hits"]);
2023-04-14 22:18:18 +00:00
hitsTD.setAttribute("label", "Hits");
hitsTD.setAttribute("name", "hitsColumn");
2024-10-31 16:08:51 +00:00
const deleteBtn = deleteButton(row["shortlink"]);
const editBtn = editButton(row["shortlink"]);
2020-02-14 18:52:14 +00:00
tr.appendChild(shortTD);
tr.appendChild(longTD);
2022-11-03 21:53:04 +00:00
tr.appendChild(hitsTD);
2024-10-31 16:08:51 +00:00
tr.appendChild(editBtn);
tr.appendChild(deleteBtn);
2020-02-14 18:52:14 +00:00
return tr;
2024-04-01 07:07:43 +00:00
}
2020-02-14 18:52:14 +00:00
2022-11-11 05:19:42 +00:00
const copyShortUrl = async (link) => {
const site = await getSiteUrl();
try {
navigator.clipboard.writeText(`${site}/${link}`);
showAlert(`Short URL ${link} was copied to clipboard!`, "green");
} catch (e) {
console.log(e);
showAlert(`Could not copy short URL to clipboard, please do it manually: <a href=${site}/${link}>${site}/${link}</a>`, "red");
}
2024-04-01 07:07:43 +00:00
}
const addProtocol = (input) => {
var url = input.value.trim();
2022-11-13 06:06:29 +00:00
if (url != "" && !~url.indexOf("://") && !~url.indexOf("magnet:")) {
url = "https://" + url;
}
input.value = url;
2024-04-01 07:07:43 +00:00
return input;
}
const A_LONG = (s) => `<a href='${s}'>${s}</a>`;
2022-11-13 05:01:21 +00:00
const A_SHORT = (s, t) => `<a href="javascript:copyShortUrl('${s}');">${s}</a>`;
const A_SHORT_INSECURE = (s, t) => `<a href="${t}/${s}">${s}</a>`;
2020-02-14 18:52:14 +00:00
2020-02-16 15:52:54 +00:00
const deleteButton = (shortUrl) => {
2022-11-10 00:55:50 +00:00
const td = document.createElement("td");
2024-03-19 00:27:58 +00:00
const div = document.createElement("div");
2020-02-16 15:52:54 +00:00
const btn = document.createElement("button");
btn.innerHTML = "&times;";
btn.onclick = e => {
e.preventDefault();
2022-11-09 23:58:15 +00:00
if (confirm("Do you want to delete the entry " + shortUrl + "?")) {
document.getElementById("alert-box")?.remove();
showAlert("&nbsp;", "black");
fetch(prepSubdir(`/api/del/${shortUrl}`), {
2022-11-09 23:58:15 +00:00
method: "DELETE"
2024-04-01 07:07:43 +00:00
}).then(res => {
if (res.ok) {
console.log("Deleted " + shortUrl);
} else {
console.log("Unable to delete " + shortUrl);
}
refreshData();
});
2022-11-09 23:58:15 +00:00
}
2020-02-16 15:52:54 +00:00
};
2022-11-10 00:55:50 +00:00
td.setAttribute("name", "deleteBtn");
2023-04-14 22:18:18 +00:00
td.setAttribute("label", "Delete");
2024-03-19 00:27:58 +00:00
div.appendChild(btn);
td.appendChild(div);
2022-11-10 00:55:50 +00:00
return td;
2024-04-01 07:07:43 +00:00
}
2020-02-16 15:52:54 +00:00
2024-10-31 16:08:51 +00:00
const editButton = (shortUrl) => {
const td = document.createElement("td");
const btn = document.createElement("button");
btn.innerHTML = "Edit";
btn.onclick = async (e) => {
e.preventDefault();
const newUrl = prompt("Enter the new long URL:");
if (newUrl) {
if (!isValidUrl(newUrl)) {
showAlert("Invalid URL format. Please enter a valid URL.", "red");
return;
}
const response = await fetch(prepSubdir(`/api/edit/${shortUrl}`), {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ longlink: newUrl }),
});
if (response.ok) {
showAlert(`Successfully updated ${shortUrl}.`, "green");
refreshData();
} else {
const errorMsg = await response.text();
showAlert(`Error: ${errorMsg}`, "red");
}
}
};
td.setAttribute("name", "editBtn");
td.appendChild(btn);
return td;
}
const isValidUrl = (urlString) => {
try {
new URL(urlString);
return true;
} catch (_) {
return false;
}
}
2023-04-14 22:18:18 +00:00
const TD = (s, u) => {
2020-02-14 18:52:14 +00:00
const td = document.createElement("td");
2022-11-03 20:19:22 +00:00
const div = document.createElement("div");
div.innerHTML = s;
td.appendChild(div);
2023-04-14 22:18:18 +00:00
td.setAttribute("label", u);
2020-02-14 18:52:14 +00:00
return td;
2024-04-01 07:07:43 +00:00
}
2020-02-14 18:52:14 +00:00
const submitForm = () => {
const form = document.forms.namedItem("new-url-form");
2024-04-01 07:07:43 +00:00
const data = {
"longlink": form.elements["longUrl"].value,
"shortlink": form.elements["shortUrl"].value,
};
2020-02-14 18:52:14 +00:00
const url = prepSubdir("/api/new");
2024-04-03 02:26:18 +00:00
let ok = false;
2020-02-14 18:52:14 +00:00
fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
2020-02-14 18:52:14 +00:00
})
2022-11-11 02:17:39 +00:00
.then(res => {
2024-04-03 02:26:18 +00:00
ok = res.ok;
return res.text();
})
.then(text => {
if (!ok) {
showAlert(text, "red");
2022-11-09 00:23:41 +00:00
}
else {
copyShortUrl(text);
longUrl.value = "";
shortUrl.value = "";
refreshData();
}
2024-04-01 07:07:43 +00:00
})
}
2020-02-14 18:52:14 +00:00
2023-04-12 00:17:04 +00:00
const submitLogin = () => {
const password = document.getElementById("password");
fetch(prepSubdir("/api/login"), {
2023-04-12 00:17:04 +00:00
method: "POST",
body: password.value
}).then(res => {
if (res.ok) {
document.getElementById("container").style.filter = "blur(0px)"
document.getElementById("login-dialog").close();
password.value = '';
2023-04-12 00:17:04 +00:00
refreshData();
} else {
const wrongPassBox = document.getElementById("wrong-pass");
wrongPassBox.innerHTML = "Wrong password!";
wrongPassBox.style.color = "red";
2023-04-12 00:17:04 +00:00
password.focus();
}
})
}
2024-11-01 06:45:13 +00:00
const fetchApiKey = async () => {
const response = await fetch(prepSubdir("/api/key"), {
method: "POST"
});
if (response.ok) {
const apiKey = await response.text();
prompt("API Key:", apiKey);
} else {
const error_text = await response.text();
alert("Failed to fetch API Key: " + error_text);
}
}
const logOut = async () => {
let reply = await fetch(prepSubdir("/api/logout"), {method: "DELETE"}).then(res => res.text());
console.log(reply);
document.getElementById("table-box").hidden = true;
document.getElementById("loading-text").hidden = false;
refreshData();
}
2020-02-14 18:52:14 +00:00
(async () => {
await refreshData();
2023-04-12 00:17:04 +00:00
2020-02-14 18:52:14 +00:00
const form = document.forms.namedItem("new-url-form");
form.onsubmit = e => {
e.preventDefault();
submitForm();
}
2023-04-12 00:17:04 +00:00
const login_form = document.forms.namedItem("login-form");
login_form.onsubmit = e => {
e.preventDefault();
submitLogin();
}
2024-04-01 07:07:43 +00:00
})()