0.8.9: Better frontend and idk what more
This commit is contained in:
parent
69fe5a3c58
commit
7ee5956970
6 changed files with 382 additions and 278 deletions
289
public/script.js
289
public/script.js
|
@ -1,140 +1,169 @@
|
|||
// By chatgpt becuase I hate frontend and javascript kill me
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const dropArea = document.getElementById("drop-area");
|
||||
const fileInput = document.getElementById("fileElem");
|
||||
const uploadStatus = document.getElementById("upload-status");
|
||||
const dropArea = document.getElementById("drop-area");
|
||||
const fileInput = document.getElementById("fileElem");
|
||||
const uploadStatus = document.getElementById("upload-status");
|
||||
|
||||
// Prevent default drag behaviors
|
||||
["dragenter", "dragover", "dragleave", "drop"].forEach(eventName => {
|
||||
dropArea.addEventListener(eventName, preventDefaults, false);
|
||||
document.body.addEventListener(eventName, preventDefaults, false);
|
||||
// Prevent default drag behaviors
|
||||
["dragenter", "dragover", "dragleave", "drop"].forEach((eventName) => {
|
||||
dropArea.addEventListener(eventName, preventDefaults, false);
|
||||
document.body.addEventListener(eventName, preventDefaults, false);
|
||||
});
|
||||
|
||||
// Highlight drop area when item is dragged over
|
||||
["dragenter", "dragover"].forEach((eventName) => {
|
||||
dropArea.addEventListener(eventName, highlight, false);
|
||||
});
|
||||
|
||||
["dragleave", "drop"].forEach((eventName) => {
|
||||
dropArea.addEventListener(eventName, unhighlight, false);
|
||||
});
|
||||
|
||||
// Handle dropped files
|
||||
dropArea.addEventListener("drop", handleDrop, false);
|
||||
dropArea.addEventListener("click", () => fileInput.click());
|
||||
|
||||
// Handle file selection
|
||||
fileInput.addEventListener(
|
||||
"change",
|
||||
() => {
|
||||
const files = fileInput.files;
|
||||
handleFiles(files);
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
// Handle pasted files
|
||||
document.addEventListener("paste", handlePaste, false);
|
||||
|
||||
function preventDefaults(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
function highlight() {
|
||||
dropArea.classList.add("highlight");
|
||||
}
|
||||
|
||||
function unhighlight() {
|
||||
dropArea.classList.remove("highlight");
|
||||
}
|
||||
|
||||
function handleDrop(e) {
|
||||
const dt = e.dataTransfer;
|
||||
const files = dt.files;
|
||||
handleFiles(files);
|
||||
}
|
||||
|
||||
function handlePaste(e) {
|
||||
const items = e.clipboardData.items;
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const item = items[i];
|
||||
if (item.kind === "file") {
|
||||
const file = item.getAsFile();
|
||||
handleFiles([file]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleFiles(files) {
|
||||
if (files.length > 0) {
|
||||
for (const file of files) {
|
||||
uploadFile(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function uploadFile(file) {
|
||||
const url = "upload"; // Replace with your upload URL
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
// Create a new upload status container and link elements
|
||||
const uploadContainer = document.createElement("div");
|
||||
const statusLink = document.createElement("div");
|
||||
const uploadText = document.createElement("span");
|
||||
const buttons = document.createElement("div");
|
||||
const copyButton = document.createElement("button");
|
||||
const deleteButton = document.createElement("button");
|
||||
|
||||
uploadContainer.className = "upload-status"; // Use the existing CSS class for styling
|
||||
uploadContainer.appendChild(uploadText);
|
||||
uploadContainer.appendChild(statusLink);
|
||||
buttons.appendChild(copyButton)
|
||||
buttons.appendChild(deleteButton)
|
||||
uploadContainer.appendChild(buttons)
|
||||
uploadStatus.appendChild(uploadContainer);
|
||||
|
||||
// Update upload text
|
||||
uploadText.innerHTML = "0%";
|
||||
uploadText.className = "percent";
|
||||
statusLink.className = "status";
|
||||
copyButton.className = "copy-button"; // Add class for styling
|
||||
copyButton.innerHTML = "Copiar"; // Set button text
|
||||
deleteButton.className = "delete-button";
|
||||
deleteButton.innerHTML = "Borrar";
|
||||
copyButton.style.display = "none";
|
||||
deleteButton.style.display = "none";
|
||||
|
||||
// Update progress text
|
||||
xhr.upload.addEventListener("progress", (e) => {
|
||||
if (e.lengthComputable) {
|
||||
const percentComplete = Math.round((e.loaded / e.total) * 100);
|
||||
uploadText.innerHTML = `${percentComplete}%`; // Update the text with the percentage
|
||||
}
|
||||
});
|
||||
|
||||
// Highlight drop area when item is dragged over
|
||||
["dragenter", "dragover"].forEach(eventName => {
|
||||
dropArea.addEventListener(eventName, highlight, false);
|
||||
});
|
||||
xhr.onerror = () => {
|
||||
console.error("Error:", xhr.status, xhr.statusText, xhr.responseText);
|
||||
statusLink.textContent = "Error desconocido";
|
||||
};
|
||||
|
||||
["dragleave", "drop"].forEach(eventName => {
|
||||
dropArea.addEventListener(eventName, unhighlight, false);
|
||||
});
|
||||
|
||||
// Handle dropped files
|
||||
dropArea.addEventListener("drop", handleDrop, false);
|
||||
dropArea.addEventListener("click", () => fileInput.click());
|
||||
|
||||
// Handle file selection
|
||||
fileInput.addEventListener("change", () => {
|
||||
const files = fileInput.files;
|
||||
handleFiles(files);
|
||||
}, false);
|
||||
|
||||
// Handle pasted files
|
||||
document.addEventListener("paste", handlePaste, false);
|
||||
|
||||
function preventDefaults(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
function highlight() {
|
||||
dropArea.classList.add("highlight");
|
||||
}
|
||||
|
||||
function unhighlight() {
|
||||
dropArea.classList.remove("highlight");
|
||||
}
|
||||
|
||||
function handleDrop(e) {
|
||||
const dt = e.dataTransfer;
|
||||
const files = dt.files;
|
||||
handleFiles(files);
|
||||
}
|
||||
|
||||
function handlePaste(e) {
|
||||
const items = e.clipboardData.items;
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const item = items[i];
|
||||
if (item.kind === "file") {
|
||||
const file = item.getAsFile();
|
||||
handleFiles([file]);
|
||||
}
|
||||
xhr.onload = () => {
|
||||
// console.log("Response Status:", xhr.status);
|
||||
// console.log("Response Text:", xhr.responseText);
|
||||
if (xhr.status === 200) {
|
||||
try {
|
||||
const response = JSON.parse(xhr.responseText);
|
||||
const fileLink = response.link;
|
||||
statusLink.innerHTML = `<a href="${fileLink}" target="_blank">${fileLink}</a>`;
|
||||
copyButton.style.display = "inline";
|
||||
copyButton.onclick = () => copyToClipboard(fileLink);
|
||||
deleteButton.style.display = "inline";
|
||||
deleteButton.onclick = () => {
|
||||
window.open(response.deleteLink, "_blank");
|
||||
};
|
||||
} catch (error) {
|
||||
statusLink.textContent =
|
||||
"Error desconocido, habla con el administrador";
|
||||
}
|
||||
}
|
||||
|
||||
function handleFiles(files) {
|
||||
if (files.length > 0) {
|
||||
for (const file of files) {
|
||||
uploadFile(file);
|
||||
}
|
||||
} else if (xhr.status >= 400 && xhr.status < 500) {
|
||||
try {
|
||||
const errorResponse = JSON.parse(xhr.responseText);
|
||||
statusLink.textContent = errorResponse.error || "Error del cliente.";
|
||||
} catch (e) {
|
||||
statusLink.textContent = "Error del cliente.";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
statusLink.textContent = "Error del servidor.";
|
||||
}
|
||||
};
|
||||
|
||||
function uploadFile(file) {
|
||||
const url = "upload"; // Replace with your upload URL
|
||||
const xhr = new XMLHttpRequest();
|
||||
// Send file
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
xhr.open("POST", url, true);
|
||||
xhr.send(formData);
|
||||
}
|
||||
|
||||
// Create a new upload status container and link elements
|
||||
const uploadContainer = document.createElement("div");
|
||||
const statusLink = document.createElement("div");
|
||||
const uploadText = document.createElement("span");
|
||||
const copyButton = document.createElement("button");
|
||||
|
||||
uploadContainer.className = "upload-status"; // Use the existing CSS class for styling
|
||||
uploadContainer.appendChild(uploadText);
|
||||
uploadContainer.appendChild(statusLink);
|
||||
uploadContainer.appendChild(copyButton);
|
||||
uploadStatus.appendChild(uploadContainer); // Append to the main upload status container
|
||||
|
||||
// Update upload text
|
||||
uploadText.innerHTML = "0%";
|
||||
uploadText.className = "percent"
|
||||
copyButton.className = "copy-button"; // Add class for styling
|
||||
copyButton.innerHTML = "Copiar"; // Set button text
|
||||
copyButton.style.display = "none"; // Hide initially
|
||||
|
||||
// Update progress text
|
||||
xhr.upload.addEventListener("progress", (e) => {
|
||||
if (e.lengthComputable) {
|
||||
const percentComplete = Math.round((e.loaded / e.total) * 100);
|
||||
uploadText.innerHTML = `${percentComplete}%`; // Update the text with the percentage
|
||||
}
|
||||
});
|
||||
|
||||
// Handle response
|
||||
xhr.onload = () => {
|
||||
if (xhr.status === 200) {
|
||||
try {
|
||||
const response = JSON.parse(xhr.responseText);
|
||||
const fileLink = response.link; // Assuming the response contains a key 'link'
|
||||
statusLink.innerHTML = `<a href="${fileLink}" target="_blank">${fileLink}</a>`;
|
||||
copyButton.style.display = "inline"; // Show the copy button
|
||||
copyButton.onclick = () => copyToClipboard(fileLink); // Set the copy action
|
||||
} catch (error) {
|
||||
statusLink.textContent = "File uploaded but failed to parse response.";
|
||||
}
|
||||
} else {
|
||||
statusLink.textContent = "File upload failed.";
|
||||
}
|
||||
};
|
||||
|
||||
// Handle errors
|
||||
xhr.onerror = () => {
|
||||
statusLink.textContent = "An error occurred during the file upload.";
|
||||
};
|
||||
|
||||
// Send file
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
xhr.open("POST", url, true);
|
||||
xhr.send(formData);
|
||||
}
|
||||
|
||||
// Function to copy the link to the clipboard
|
||||
function copyToClipboard(text) {
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
// alert("Link copied to clipboard!"); // Notify the user
|
||||
}).catch(err => {
|
||||
console.error("Failed to copy: ", err);
|
||||
});
|
||||
}
|
||||
// Function to copy the link to the clipboard
|
||||
function copyToClipboard(text) {
|
||||
navigator.clipboard
|
||||
.writeText(text)
|
||||
.then(() => {
|
||||
// alert("Link copied to clipboard!"); // Notify the user
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Failed to copy: ", err);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,172 +1,228 @@
|
|||
@font-face {
|
||||
font-family: "FG";
|
||||
font-weight: 500;
|
||||
src: url('framd.ttf');
|
||||
font-family: "FG";
|
||||
font-weight: 500;
|
||||
src: url('framd.ttf');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "FG";
|
||||
font-weight: 900;
|
||||
src: url('frahv.ttf');
|
||||
font-family: "FG";
|
||||
font-weight: 900;
|
||||
src: url('frahv.ttf');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "XFG";
|
||||
font-weight: 900;
|
||||
src: url('frahvmod.ttf');
|
||||
font-family: "XFG";
|
||||
font-weight: 900;
|
||||
src: url('frahvmod.ttf');
|
||||
}
|
||||
|
||||
html {
|
||||
font-family: "FG";
|
||||
background-image: linear-gradient(to bottom,
|
||||
rgba(11, 11, 11, 0.92),
|
||||
rgba(11, 11, 11, 0.92)),
|
||||
url(./bliss-small.avif);
|
||||
background-attachment: fixed;
|
||||
font-family: "FG";
|
||||
background-image: linear-gradient(to bottom,
|
||||
rgba(11, 11, 11, 0.92),
|
||||
rgba(11, 11, 11, 0.92)),
|
||||
url(./bliss-small.avif);
|
||||
background-attachment: fixed;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
|
||||
body {
|
||||
/* font-family: Arial, sans-serif; */
|
||||
/* background-color: #111; */
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
/* font-family: Arial, sans-serif; */
|
||||
/* background-color: #111; */
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
p, h1, h2, h3, h4, h5 {
|
||||
color: aliceblue
|
||||
p,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5 {
|
||||
color: aliceblue
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family: "FG";
|
||||
font-weight: 200;
|
||||
max-width: 100%;
|
||||
overflow-wrap: break-word;
|
||||
font-family: "FG";
|
||||
font-weight: 200;
|
||||
max-width: 100%;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
font-size: 0.9em;
|
||||
/* margin-top: 1ch;*/
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 0.9em;
|
||||
/* margin-top: 1ch;*/
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.bottom > p {
|
||||
margin: 10px 0px;
|
||||
.bottom>p {
|
||||
margin: 10px 0px;
|
||||
}
|
||||
|
||||
.percent {
|
||||
color: aliceblue
|
||||
color: aliceblue
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 700px;
|
||||
margin: auto;
|
||||
/* background: white; */
|
||||
/*! padding: 20px; */
|
||||
border-radius: 0px;
|
||||
/*! box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); */
|
||||
max-width: 800px;
|
||||
margin: auto;
|
||||
/* background: white; */
|
||||
/*! padding: 20px; */
|
||||
border-radius: 0px;
|
||||
/*! box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); */
|
||||
}
|
||||
|
||||
|
||||
#drop-area {
|
||||
/*! border: 2px solid #00ff00; */
|
||||
/*! border-radius: 6px; */
|
||||
/*! padding-left: 10px; */
|
||||
/*! padding-right: 10px; */
|
||||
text-align: center;
|
||||
position: relative;
|
||||
width: fit-content;
|
||||
margin: 0 auto; /* Center the element */
|
||||
display: block; /* Ensure it behaves as a block-level element */
|
||||
background: rgba(202,230,190,.75);
|
||||
border: 1px solid #b7d1a0;
|
||||
border-radius: 4px;
|
||||
color: #468847;
|
||||
cursor: pointer;
|
||||
/*! display: inline-block; */
|
||||
font-size: 24px;
|
||||
padding: 28px 48px;
|
||||
text-shadow: 0 1px hsla(0,0%,100%,.5);
|
||||
transition: background-color .25s,width .5s,height .5s;
|
||||
/*! border: 2px solid #00ff00; */
|
||||
/*! border-radius: 6px; */
|
||||
/*! padding-left: 10px; */
|
||||
/*! padding-right: 10px; */
|
||||
text-align: center;
|
||||
position: relative;
|
||||
width: fit-content;
|
||||
margin: 0 auto;
|
||||
/* Center the element */
|
||||
display: block;
|
||||
/* Ensure it behaves as a block-level element */
|
||||
background: rgba(202, 230, 190, .75);
|
||||
border: 1px solid #b7d1a0;
|
||||
border-radius: 4px;
|
||||
color: #468847;
|
||||
cursor: pointer;
|
||||
/*! display: inline-block; */
|
||||
font-size: 24px;
|
||||
padding: 28px 48px;
|
||||
text-shadow: 0 1px hsla(0, 0%, 100%, .5);
|
||||
transition: background-color .25s, width .5s, height .5s;
|
||||
}
|
||||
|
||||
.button {
|
||||
display: inline-block;
|
||||
padding: 10px 20px;
|
||||
/* background: #; */
|
||||
color: white;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
/* margin-top: 10px; */
|
||||
display: inline-block;
|
||||
padding: 10px 20px;
|
||||
/* background: #; */
|
||||
color: white;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
/* margin-top: 10px; */
|
||||
}
|
||||
|
||||
.upload-status {
|
||||
margin-top: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
nav a, nav > ul
|
||||
{
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
nav a,
|
||||
nav>ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#upload-status {
|
||||
margin: 20px; /* Adjust as needed */
|
||||
margin: 20px;
|
||||
/* Adjust as needed */
|
||||
}
|
||||
|
||||
.upload-status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border: 2px solid #999; /* Optional styling for the status box */
|
||||
padding: 5px; /* Optional padding */
|
||||
/*! border-radius: 6px; */ /* Optional rounded corners */
|
||||
/*! background-color: #f9f9f9; */ /* Optional background color */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border: 2px solid #999;
|
||||
/* Optional styling for the status box */
|
||||
padding: 5px;
|
||||
/* Optional padding */
|
||||
/*! border-radius: 6px; */
|
||||
/* Optional rounded corners */
|
||||
/*! background-color: #f9f9f9; */
|
||||
/* Optional background color */
|
||||
}
|
||||
|
||||
.link-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: auto; /* Pushes the link and button to the right */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: auto;
|
||||
/* Pushes the link and button to the right */
|
||||
}
|
||||
|
||||
.link {
|
||||
color: #ffb6c1;
|
||||
text-decoration: none; /* Remove underline from link */
|
||||
margin-right: 5px; /* Space between link and button */
|
||||
color: #ffb6c1;
|
||||
text-decoration: none;
|
||||
/* Remove underline from link */
|
||||
margin-right: 5px;
|
||||
/* Space between link and button */
|
||||
}
|
||||
|
||||
.link:hover {
|
||||
text-decoration: underline; /* Optional: underline on hover */
|
||||
text-decoration: underline;
|
||||
/* Optional: underline on hover */
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
display: inline;
|
||||
background-color: #5e5e5e; /* Button background color */
|
||||
color: white; /* Button text color */
|
||||
border: none; /* Remove border */
|
||||
border-radius: 3px; /* Rounded corners for the button */
|
||||
padding: 5px 10px; /* Button padding */
|
||||
cursor: pointer; /* Pointer cursor on hover */
|
||||
display: inline;
|
||||
background-color: #7a6fff;
|
||||
/* Button background color */
|
||||
color: white;
|
||||
/* Button text color */
|
||||
border: none;
|
||||
/* Remove border */
|
||||
border-radius: 3px;
|
||||
/* Rounded corners for the button */
|
||||
padding: 5px 10px;
|
||||
/* Button padding */
|
||||
cursor: pointer;
|
||||
/* Pointer cursor on hover */
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.delete-button {
|
||||
display: inline;
|
||||
background-color: #ff6f6f;
|
||||
/* Button background color */
|
||||
color: white;
|
||||
/* Button text color */
|
||||
border: none;
|
||||
/* Remove border */
|
||||
border-radius: 3px;
|
||||
/* Rounded corners for the button */
|
||||
padding: 5px 10px;
|
||||
/* Button padding */
|
||||
cursor: pointer;
|
||||
/* Pointer cursor on hover */
|
||||
margin-left: 6px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
.copy-button:hover {
|
||||
background-color: #404040; /* Darker shade on hover */
|
||||
background-color: #6057ce;
|
||||
/* Darker shade on hover */
|
||||
}
|
||||
|
||||
.delete-button:hover {
|
||||
background-color: #ce5757;
|
||||
/* Darker shade on hover */
|
||||
}
|
||||
|
||||
.status {
|
||||
color: rgb(255, 132, 0);
|
||||
}
|
||||
|
||||
a:link {
|
||||
color: #ffb6c1
|
||||
color: #ffb6c1
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #ffb6c1
|
||||
color: #ffb6c1
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #ffb6c1
|
||||
color: #ffb6c1
|
||||
}
|
|
@ -56,7 +56,7 @@ module Handling::Admin
|
|||
# Delete entry from db
|
||||
SQL.exec "DELETE FROM #{CONFIG.ipTableName} WHERE ip = ?", ip
|
||||
LOGGER.debug "Rate limit for '#{ip}' was deleted"
|
||||
successfull_ips << ip
|
||||
successfull_ips << ip
|
||||
rescue ex : DB::NoResultsError
|
||||
LOGGER.error("Rate limit for '#{ip}' doesn't exist or is not registered in the database: #{ex.message}")
|
||||
failed_ips << ip
|
||||
|
|
|
@ -20,6 +20,8 @@ module Jobs
|
|||
spawn do
|
||||
loop do
|
||||
Utils.retrieve_tor_exit_nodes
|
||||
# Updates the @@exit_nodes array instantly
|
||||
Routing.reload_exit_nodes
|
||||
sleep CONFIG.torExitNodesCheck
|
||||
end
|
||||
end
|
||||
|
@ -28,9 +30,7 @@ module Jobs
|
|||
def self.kemal
|
||||
spawn do
|
||||
if !CONFIG.unix_socket.nil?
|
||||
Kemal.run do |config|
|
||||
config.server.not_nil!.bind_unix "#{CONFIG.unix_socket}"
|
||||
end
|
||||
Kemal.run &.server.not_nil!.bind_unix "#{CONFIG.unix_socket}"
|
||||
else
|
||||
Kemal.run
|
||||
end
|
||||
|
|
|
@ -3,19 +3,10 @@ require "./http-errors"
|
|||
module Routing
|
||||
extend self
|
||||
@@exit_nodes = Array(String).new
|
||||
if CONFIG.blockTorAddresses
|
||||
spawn do
|
||||
# Wait a little for Utils.retrieve_tor_exit_nodes to execute first
|
||||
# or it will load an old exit node list
|
||||
# I think this can be replaced by channels which makes me able to
|
||||
# receive data from fibers
|
||||
sleep 5
|
||||
loop do
|
||||
LOGGER.debug "Updating Tor exit nodes array"
|
||||
@@exit_nodes = Utils.load_tor_exit_nodes
|
||||
sleep CONFIG.torExitNodesCheck + 5
|
||||
end
|
||||
end
|
||||
|
||||
def reload_exit_nodes
|
||||
LOGGER.debug "Updating Tor exit nodes array"
|
||||
@@exit_nodes = Utils.load_tor_exit_nodes
|
||||
end
|
||||
|
||||
before_post "/api/admin/*" do |env|
|
||||
|
@ -86,20 +77,21 @@ module Routing
|
|||
Handling.sharex_config(env)
|
||||
end
|
||||
|
||||
self.register_admin
|
||||
if CONFIG.adminEnabled
|
||||
self.register_admin
|
||||
end
|
||||
end
|
||||
|
||||
def register_admin
|
||||
if CONFIG.adminEnabled
|
||||
# post "/api/admin/upload" do |env|
|
||||
# Handling::Admin.delete_ip_limit(env)
|
||||
# end
|
||||
post "/api/admin/delete" do |env|
|
||||
Handling::Admin.delete_file(env)
|
||||
end
|
||||
end
|
||||
post "/api/admin/deleteiplimit" do |env|
|
||||
Handling::Admin.delete_ip_limit(env)
|
||||
# post "/api/admin/upload" do |env|
|
||||
# Handling::Admin.delete_ip_limit(env)
|
||||
# end
|
||||
post "/api/admin/delete" do |env|
|
||||
Handling::Admin.delete_file(env)
|
||||
end
|
||||
end
|
||||
|
||||
post "/api/admin/deleteiplimit" do |env|
|
||||
Handling::Admin.delete_ip_limit(env)
|
||||
end
|
||||
end
|
||||
|
|
71
src/utils.cr
71
src/utils.cr
|
@ -135,7 +135,8 @@ module Utils
|
|||
end
|
||||
end
|
||||
|
||||
# Delete socket if the server has not been previously cleaned by the server (Due to unclean exits, crashes, etc.)
|
||||
# Delete socket if the server has not been previously cleaned by the server
|
||||
# (Due to unclean exits, crashes, etc.)
|
||||
def delete_socket
|
||||
if File.exists?("#{CONFIG.unix_socket}")
|
||||
LOGGER.info "Deleting old unix socket"
|
||||
|
@ -167,21 +168,43 @@ module Utils
|
|||
msg("File '#{fileinfo[:filename]}' deleted successfully")
|
||||
end
|
||||
|
||||
MAGIC_BYTES = {
|
||||
# Images
|
||||
".png" => "89504e470d0a1a0a",
|
||||
".heic" => "6674797068656963",
|
||||
".jpg" => "ffd8ff",
|
||||
".gif" => "474946383",
|
||||
# Videos
|
||||
".mp4" => "66747970",
|
||||
".webm" => "1a45dfa3",
|
||||
".mov" => "6d6f6f76",
|
||||
".wmv" => "3026b2758e66cf11",
|
||||
".flv" => "464c5601",
|
||||
".mpeg" => "000001bx",
|
||||
# Audio
|
||||
".mp3" => "494433",
|
||||
".aac" => "fff1",
|
||||
".wav" => "57415645666d7420",
|
||||
".flac" => "664c614300000022",
|
||||
".ogg" => "4f67675300020000000000000000",
|
||||
".wma" => "3026b2758e66cf11a6d900aa0062ce6c",
|
||||
".aiff" => "464f524d00",
|
||||
# Whatever
|
||||
".7z" => "377abcaf271c",
|
||||
".gz" => "1f8b",
|
||||
".iso" => "4344303031",
|
||||
# Documents
|
||||
"pdf" => "25504446",
|
||||
"html" => "<!DOCTYPE html>",
|
||||
}
|
||||
|
||||
def detect_extension(file) : String
|
||||
magic_bytes = {
|
||||
".png" => "89504e470d0a1a0a",
|
||||
".jpg" => "ffd8ff",
|
||||
".webm" => "1a45dfa3",
|
||||
".mp4" => "66747970",
|
||||
".gif" => "474946383",
|
||||
".7z" => "377abcaf271c",
|
||||
".gz" => "1f8b",
|
||||
}
|
||||
file = File.open(file)
|
||||
slice = Bytes.new(8)
|
||||
slice = Bytes.new(16)
|
||||
hex = IO::Hexdump.new(file)
|
||||
# Reads the first 16 bytes of the file in Heap
|
||||
hex.read(slice)
|
||||
magic_bytes.each do |ext, mb|
|
||||
MAGIC_BYTES.each do |ext, mb|
|
||||
if slice.hexstring.includes?(mb)
|
||||
return ext
|
||||
end
|
||||
|
@ -191,17 +214,21 @@ module Utils
|
|||
|
||||
def retrieve_tor_exit_nodes
|
||||
LOGGER.debug "Retrieving Tor exit nodes list"
|
||||
resp = HTTP::Client.get(CONFIG.torExitNodesUrl) do |res|
|
||||
if res.success? && res.status_code == 200
|
||||
begin
|
||||
File.open(CONFIG.torExitNodesFile, "w") do |output|
|
||||
IO.copy(res.body_io, output)
|
||||
HTTP::Client.get(CONFIG.torExitNodesUrl) do |res|
|
||||
begin
|
||||
if res.success? && res.status_code == 200
|
||||
begin
|
||||
File.open(CONFIG.torExitNodesFile, "w") { |output| IO.copy(res.body_io, output) }
|
||||
rescue ex
|
||||
LOGGER.error "Failed to write to file: #{ex.message}"
|
||||
end
|
||||
rescue ex
|
||||
LOGGER.error "Failed to write to file: #{ex.message}"
|
||||
else
|
||||
LOGGER.error "Failed to retrieve exit nodes list. Status Code: #{res.status_code}"
|
||||
end
|
||||
else
|
||||
LOGGER.error "Failed to retrieve exit nodes list. Status Code: #{res.status_code}"
|
||||
rescue ex : Socket::ConnectError
|
||||
LOGGER.error "Failed to connect to #{CONFIG.torExitNodesUrl}: #{ex.message}"
|
||||
rescue ex
|
||||
LOGGER.error "Unknown error: #{ex.message}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -227,7 +254,7 @@ module Utils
|
|||
end
|
||||
|
||||
def host(env) : String
|
||||
begin
|
||||
begin
|
||||
return env.request.headers.try &.["X-Forwarded-Host"]
|
||||
rescue
|
||||
return env.request.headers["Host"]
|
||||
|
|
Loading…
Reference in a new issue