forked from tcp.direct/tcp.ac
just havin a rinse bub nbd
This commit is contained in:
parent
6bfc79cc6f
commit
bcc5279a21
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,111 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>{{ title }}</title>
|
||||
<style>
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
background: #000;
|
||||
color: #f8f8f8;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote,
|
||||
.hljs-meta {
|
||||
color: #7c7c7c;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-tag,
|
||||
.hljs-name {
|
||||
color: #96cbfe;
|
||||
}
|
||||
|
||||
.hljs-attribute,
|
||||
.hljs-selector-id {
|
||||
color: #ffffb6;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo,
|
||||
.hljs-addition {
|
||||
color: #a8ff60;
|
||||
}
|
||||
|
||||
.hljs-subst {
|
||||
color: #daefa3;
|
||||
}
|
||||
|
||||
.hljs-regexp,
|
||||
.hljs-link {
|
||||
color: #e9c062;
|
||||
}
|
||||
|
||||
.hljs-title,
|
||||
.hljs-section,
|
||||
.hljs-type,
|
||||
.hljs-doctag {
|
||||
color: #ffffb6;
|
||||
}
|
||||
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-literal {
|
||||
color: #c6c5fe;
|
||||
}
|
||||
|
||||
.hljs-number,
|
||||
.hljs-deletion {
|
||||
color:#ff73fd;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
overflow: hidden;
|
||||
}
|
||||
html,
|
||||
body,
|
||||
pre {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
code {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo,
|
||||
monospace;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<pre><code>{{ contents }}</code></pre>
|
||||
<script
|
||||
src="js/highlight.min.js"></script>
|
||||
{{ languages }}
|
||||
<script>
|
||||
hljs.initHighlightingOnLoad();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,437 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="css/spectre.min.css"/>
|
||||
<link rel="stylesheet" href="css/spectre-icons.min.css"/>
|
||||
<style>
|
||||
div[id$="-form"]:not(.active) {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<title>tcp.ac</title>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="container mb-2 pb-2">
|
||||
<div class="columns">
|
||||
<div
|
||||
class="column col-sm-12 col-md-10 col-lg-8 col-6 col-mx-auto"
|
||||
>
|
||||
<ul class="tab tab-block">
|
||||
<li id="img-tab" class="tab-item">
|
||||
<a href="#">img</a>
|
||||
</li>
|
||||
<li id="url-tab" class="tab-item active">
|
||||
<a href="#">url</a>
|
||||
</li>
|
||||
<li id="txt-tab" class="tab-item">
|
||||
<a href="#">txt</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<main class="container mt-2 pt-2">
|
||||
<div class="columns">
|
||||
<div
|
||||
id="img-form"
|
||||
class="column col-sm-12 col-md-10 col-lg-8 col-6 col-mx-auto"
|
||||
>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="img-url">url</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">/f/</span>
|
||||
<input
|
||||
id="img-url"
|
||||
class="form-input"
|
||||
type="text"
|
||||
placeholder="a1b2c3"
|
||||
required
|
||||
/>
|
||||
<button
|
||||
class="btn btn-primary input-group-btn"
|
||||
id="img-submit"
|
||||
disabled
|
||||
>
|
||||
<i class="icon icon-upload"></i>
|
||||
</button>
|
||||
</div>
|
||||
<p class="form-input-hint">Press space to randomize</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="img-file">File</label>
|
||||
<input
|
||||
class="form-input"
|
||||
id="img-file"
|
||||
type="file"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
id="url-form"
|
||||
class="column col-sm-12 col-md-10 col-lg-8 col-6 col-mx-auto active"
|
||||
>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="url-url">url</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">/l/</span>
|
||||
<input
|
||||
id="url-url"
|
||||
class="form-input"
|
||||
type="text"
|
||||
placeholder="a1b2c3"
|
||||
required
|
||||
/>
|
||||
<button
|
||||
class="btn btn-primary input-group-btn"
|
||||
id="url-submit"
|
||||
disabled
|
||||
>
|
||||
<i class="icon icon-upload"></i>
|
||||
</button>
|
||||
</div>
|
||||
<p class="form-input-hint">Press space to randomize</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="url-forward"
|
||||
>Forward</label
|
||||
>
|
||||
<input
|
||||
id="url-forward"
|
||||
class="form-input"
|
||||
type="url"
|
||||
placeholder="http://example.com/"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
id="txt-form"
|
||||
class="column col-sm-12 col-md-10 col-lg-8 col-6 col-mx-auto"
|
||||
>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="txt-url">url</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">/t/</span>
|
||||
<input
|
||||
id="txt-url"
|
||||
class="form-input"
|
||||
type="text"
|
||||
placeholder="a1b2c3"
|
||||
required
|
||||
/>
|
||||
<button
|
||||
class="btn btn-primary input-group-btn"
|
||||
id="txt-submit"
|
||||
disabled
|
||||
>
|
||||
<i class="icon icon-upload"></i>
|
||||
</button>
|
||||
</div>
|
||||
<p class="form-input-hint">Press space to randomize</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="txt-contents"
|
||||
>Contents</label
|
||||
>
|
||||
<textarea
|
||||
id="txt-contents"
|
||||
class="form-input"
|
||||
placeholder="Hello, World!"
|
||||
required
|
||||
></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-switch">
|
||||
<input id="txt-highlight" type="checkbox" />
|
||||
<i class="form-icon"></i> Syntax highlighting
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<div id="modal" class="modal">
|
||||
<a id="modal-bg" href="#" class="modal-overlay"></a>
|
||||
<div class="modal-container">
|
||||
<div class="modal-header">
|
||||
<div class="modal-title h6">Success</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="content">
|
||||
<div class="form-group">
|
||||
<div class="has-icon-right">
|
||||
<input
|
||||
id="modal-input"
|
||||
type="url"
|
||||
class="form-input"
|
||||
/>
|
||||
<i class="form-icon icon icon-copy"></i>
|
||||
</div>
|
||||
<p class="form-input-hint" id="modal-hint">
|
||||
Click to copy to clipboard
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
const tabs = {
|
||||
img: [
|
||||
document.querySelector("#img-tab"),
|
||||
document.querySelector("#img-form"),
|
||||
],
|
||||
url: [
|
||||
document.querySelector("#url-tab"),
|
||||
document.querySelector("#url-form"),
|
||||
],
|
||||
txt: [
|
||||
document.querySelector("#txt-tab"),
|
||||
document.querySelector("#txt-form"),
|
||||
],
|
||||
};
|
||||
|
||||
const inputs = {
|
||||
img: [
|
||||
document.querySelector("#img-url"),
|
||||
document.querySelector("#img-file"),
|
||||
document.querySelector("#img-submit"),
|
||||
],
|
||||
url: [
|
||||
document.querySelector("#url-url"),
|
||||
document.querySelector("#url-forward"),
|
||||
document.querySelector("#url-submit"),
|
||||
],
|
||||
txt: [
|
||||
document.querySelector("#txt-url"),
|
||||
document.querySelector("#txt-contents"),
|
||||
document.querySelector("#txt-highlight"),
|
||||
document.querySelector("#txt-submit"),
|
||||
],
|
||||
};
|
||||
|
||||
const used = {
|
||||
img: [],
|
||||
url: [],
|
||||
txt: [],
|
||||
};
|
||||
|
||||
let baseurl = `${location.protocol}//${location.host}${location.pathname}`;
|
||||
if (!baseurl.endsWith("/")) {
|
||||
baseurl += "/";
|
||||
}
|
||||
|
||||
const modal = {
|
||||
self: document.querySelector("#modal"),
|
||||
input: document.querySelector("#modal-input"),
|
||||
bg: document.querySelector("#modal-bg"),
|
||||
hint: document.querySelector("#modal-hint"),
|
||||
};
|
||||
const openModal = (text) => {
|
||||
modal.input.value = text;
|
||||
modal.hint.innerText = "Click to copy to clipboard";
|
||||
modal.self.classList.add("active");
|
||||
};
|
||||
const closeModal = () => {
|
||||
modal.hint.innerText = "Copied to clipboard";
|
||||
setTimeout(() => {
|
||||
modal.self.classList.remove("active");
|
||||
modal.input.value = "";
|
||||
}, 1000);
|
||||
};
|
||||
modal.input.onclick = (e) => {
|
||||
e.preventDefault();
|
||||
modal.input.select();
|
||||
document.execCommand("copy");
|
||||
closeModal();
|
||||
};
|
||||
modal.bg.onclick = closeModal;
|
||||
|
||||
const fetchUsed = () => {
|
||||
fetch(`${baseurl}f`)
|
||||
.then((response) => response.json())
|
||||
.then((json) => (used.img = json));
|
||||
fetch(`${baseurl}l`)
|
||||
.then((response) => response.json())
|
||||
.then((json) => (used.url = json));
|
||||
fetch(`${baseurl}t`)
|
||||
.then((response) => response.json())
|
||||
.then((json) => (used.txt = json));
|
||||
};
|
||||
fetchUsed();
|
||||
|
||||
const randomurl = () => {
|
||||
return Math.floor(Math.random() * 2147483647).toString(36);
|
||||
};
|
||||
|
||||
for (const group in tabs) {
|
||||
tabs[group][0].onclick = () => {
|
||||
const active = document.querySelectorAll(".active");
|
||||
for (const el of active) {
|
||||
el.classList.remove("active");
|
||||
}
|
||||
for (const el of tabs[group]) {
|
||||
el.classList.add("active");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
for (const group in inputs) {
|
||||
const submitButton = inputs[group][inputs[group].length - 1];
|
||||
|
||||
const urlInput = inputs[group][0];
|
||||
urlInput.addEventListener("input", (e) => {
|
||||
if (urlInput.value[urlInput.value.length - 1] === " ") {
|
||||
urlInput.value = randomurl();
|
||||
checkValidity();
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
urlInput.value = urlInput.value
|
||||
.replace(/[^0-9A-Za-z]/g, "")
|
||||
.toLowerCase();
|
||||
if (parseInt(urlInput.value, 36) > 2147483647) {
|
||||
urlInput.setCustomValidity(
|
||||
"Base 36 integer below or equal to zik0zj"
|
||||
);
|
||||
} else {
|
||||
urlInput.setCustomValidity("");
|
||||
}
|
||||
});
|
||||
|
||||
const checkValidity = () => {
|
||||
if (
|
||||
used[group].some(
|
||||
(x) => x.id === parseInt(urlInput.value, 36)
|
||||
)
|
||||
) {
|
||||
urlInput.setCustomValidity("ID already in use");
|
||||
} else {
|
||||
urlInput.setCustomValidity("");
|
||||
}
|
||||
submitButton.disabled = inputs[group].some(
|
||||
(input) =>
|
||||
input.validity !== undefined &&
|
||||
!input.validity.valid
|
||||
);
|
||||
};
|
||||
checkValidity();
|
||||
|
||||
for (const input of inputs[group].filter(
|
||||
(input) =>
|
||||
input instanceof HTMLInputElement ||
|
||||
input instanceof HTMLTextAreaElement
|
||||
)) {
|
||||
input.addEventListener("input", () => checkValidity());
|
||||
input.addEventListener("change", () => checkValidity());
|
||||
}
|
||||
|
||||
const clearInputs = () => {
|
||||
for (const input of inputs[group].filter(
|
||||
(input) =>
|
||||
input instanceof HTMLInputElement ||
|
||||
input instanceof HTMLTextAreaElement
|
||||
)) {
|
||||
input.value = "";
|
||||
}
|
||||
submitButton.disabled = true;
|
||||
};
|
||||
|
||||
if (group === "img") {
|
||||
submitButton.addEventListener("click", () => {
|
||||
const imgFileInput = inputs.img[1];
|
||||
const file = imgFileInput.img[0];
|
||||
|
||||
if (!file) {
|
||||
alert(new Error("No file selected"));
|
||||
return;
|
||||
}
|
||||
|
||||
const fd = new FormData();
|
||||
fd.append("file", file);
|
||||
const id = urlInput.value;
|
||||
const url = `${baseurl}f/${id}`;
|
||||
|
||||
let status;
|
||||
fetch(url, {
|
||||
method: "PUT",
|
||||
body: fd,
|
||||
})
|
||||
.then((response) => {
|
||||
status = response.status;
|
||||
return response.text();
|
||||
})
|
||||
.then((text) => {
|
||||
if (status !== 201) {
|
||||
throw new Error(text);
|
||||
} else {
|
||||
openModal(url);
|
||||
clearInputs();
|
||||
fetchUsed();
|
||||
}
|
||||
})
|
||||
.catch((error) => alert(error));
|
||||
});
|
||||
} else if (group === "url") {
|
||||
submitButton.addEventListener("click", () => {
|
||||
const id = urlInput.value;
|
||||
const forward = inputs.url[1].value;
|
||||
|
||||
const url = `${baseurl}l/${id}`;
|
||||
let status;
|
||||
fetch(url, {
|
||||
method: "PUT",
|
||||
body: JSON.stringify({ forward }),
|
||||
headers: { "Content-Type": "application/json" },
|
||||
})
|
||||
.then((response) => {
|
||||
status = response.status;
|
||||
return response.text();
|
||||
})
|
||||
.then((text) => {
|
||||
if (status !== 201) {
|
||||
throw new Error(text);
|
||||
} else {
|
||||
openModal(url);
|
||||
clearInputs();
|
||||
fetchUsed();
|
||||
}
|
||||
})
|
||||
.catch((error) => alert(error));
|
||||
});
|
||||
} else if (group === "txt") {
|
||||
submitButton.addEventListener("click", () => {
|
||||
const id = urlInput.value;
|
||||
const contents = inputs.txt[1].value;
|
||||
const highlight = inputs.txt[2].checked;
|
||||
|
||||
const url = `${baseurl}t/${id}`;
|
||||
let status;
|
||||
fetch(url, {
|
||||
method: "PUT",
|
||||
body: JSON.stringify({ contents, highlight }),
|
||||
headers: { "Content-Type": "application/json" },
|
||||
})
|
||||
.then((response) => {
|
||||
status = response.status;
|
||||
return response.text();
|
||||
})
|
||||
.then((text) => {
|
||||
if (status !== 201) {
|
||||
throw new Error(text);
|
||||
} else {
|
||||
openModal(url);
|
||||
clearInputs();
|
||||
fetchUsed();
|
||||
}
|
||||
})
|
||||
.catch((error) => alert(error));
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue