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
|
@ -1,20 +1,21 @@
|
||||||
|
// By chatgpt becuase I hate frontend and javascript kill me
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
const dropArea = document.getElementById("drop-area");
|
const dropArea = document.getElementById("drop-area");
|
||||||
const fileInput = document.getElementById("fileElem");
|
const fileInput = document.getElementById("fileElem");
|
||||||
const uploadStatus = document.getElementById("upload-status");
|
const uploadStatus = document.getElementById("upload-status");
|
||||||
|
|
||||||
// Prevent default drag behaviors
|
// Prevent default drag behaviors
|
||||||
["dragenter", "dragover", "dragleave", "drop"].forEach(eventName => {
|
["dragenter", "dragover", "dragleave", "drop"].forEach((eventName) => {
|
||||||
dropArea.addEventListener(eventName, preventDefaults, false);
|
dropArea.addEventListener(eventName, preventDefaults, false);
|
||||||
document.body.addEventListener(eventName, preventDefaults, false);
|
document.body.addEventListener(eventName, preventDefaults, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Highlight drop area when item is dragged over
|
// Highlight drop area when item is dragged over
|
||||||
["dragenter", "dragover"].forEach(eventName => {
|
["dragenter", "dragover"].forEach((eventName) => {
|
||||||
dropArea.addEventListener(eventName, highlight, false);
|
dropArea.addEventListener(eventName, highlight, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
["dragleave", "drop"].forEach(eventName => {
|
["dragleave", "drop"].forEach((eventName) => {
|
||||||
dropArea.addEventListener(eventName, unhighlight, false);
|
dropArea.addEventListener(eventName, unhighlight, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -23,10 +24,14 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||||
dropArea.addEventListener("click", () => fileInput.click());
|
dropArea.addEventListener("click", () => fileInput.click());
|
||||||
|
|
||||||
// Handle file selection
|
// Handle file selection
|
||||||
fileInput.addEventListener("change", () => {
|
fileInput.addEventListener(
|
||||||
|
"change",
|
||||||
|
() => {
|
||||||
const files = fileInput.files;
|
const files = fileInput.files;
|
||||||
handleFiles(files);
|
handleFiles(files);
|
||||||
}, false);
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
// Handle pasted files
|
// Handle pasted files
|
||||||
document.addEventListener("paste", handlePaste, false);
|
document.addEventListener("paste", handlePaste, false);
|
||||||
|
@ -77,20 +82,28 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||||
const uploadContainer = document.createElement("div");
|
const uploadContainer = document.createElement("div");
|
||||||
const statusLink = document.createElement("div");
|
const statusLink = document.createElement("div");
|
||||||
const uploadText = document.createElement("span");
|
const uploadText = document.createElement("span");
|
||||||
|
const buttons = document.createElement("div");
|
||||||
const copyButton = document.createElement("button");
|
const copyButton = document.createElement("button");
|
||||||
|
const deleteButton = document.createElement("button");
|
||||||
|
|
||||||
uploadContainer.className = "upload-status"; // Use the existing CSS class for styling
|
uploadContainer.className = "upload-status"; // Use the existing CSS class for styling
|
||||||
uploadContainer.appendChild(uploadText);
|
uploadContainer.appendChild(uploadText);
|
||||||
uploadContainer.appendChild(statusLink);
|
uploadContainer.appendChild(statusLink);
|
||||||
uploadContainer.appendChild(copyButton);
|
buttons.appendChild(copyButton)
|
||||||
uploadStatus.appendChild(uploadContainer); // Append to the main upload status container
|
buttons.appendChild(deleteButton)
|
||||||
|
uploadContainer.appendChild(buttons)
|
||||||
|
uploadStatus.appendChild(uploadContainer);
|
||||||
|
|
||||||
// Update upload text
|
// Update upload text
|
||||||
uploadText.innerHTML = "0%";
|
uploadText.innerHTML = "0%";
|
||||||
uploadText.className = "percent"
|
uploadText.className = "percent";
|
||||||
|
statusLink.className = "status";
|
||||||
copyButton.className = "copy-button"; // Add class for styling
|
copyButton.className = "copy-button"; // Add class for styling
|
||||||
copyButton.innerHTML = "Copiar"; // Set button text
|
copyButton.innerHTML = "Copiar"; // Set button text
|
||||||
copyButton.style.display = "none"; // Hide initially
|
deleteButton.className = "delete-button";
|
||||||
|
deleteButton.innerHTML = "Borrar";
|
||||||
|
copyButton.style.display = "none";
|
||||||
|
deleteButton.style.display = "none";
|
||||||
|
|
||||||
// Update progress text
|
// Update progress text
|
||||||
xhr.upload.addEventListener("progress", (e) => {
|
xhr.upload.addEventListener("progress", (e) => {
|
||||||
|
@ -100,28 +113,41 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle response
|
xhr.onerror = () => {
|
||||||
|
console.error("Error:", xhr.status, xhr.statusText, xhr.responseText);
|
||||||
|
statusLink.textContent = "Error desconocido";
|
||||||
|
};
|
||||||
|
|
||||||
xhr.onload = () => {
|
xhr.onload = () => {
|
||||||
|
// console.log("Response Status:", xhr.status);
|
||||||
|
// console.log("Response Text:", xhr.responseText);
|
||||||
if (xhr.status === 200) {
|
if (xhr.status === 200) {
|
||||||
try {
|
try {
|
||||||
const response = JSON.parse(xhr.responseText);
|
const response = JSON.parse(xhr.responseText);
|
||||||
const fileLink = response.link; // Assuming the response contains a key 'link'
|
const fileLink = response.link;
|
||||||
statusLink.innerHTML = `<a href="${fileLink}" target="_blank">${fileLink}</a>`;
|
statusLink.innerHTML = `<a href="${fileLink}" target="_blank">${fileLink}</a>`;
|
||||||
copyButton.style.display = "inline"; // Show the copy button
|
copyButton.style.display = "inline";
|
||||||
copyButton.onclick = () => copyToClipboard(fileLink); // Set the copy action
|
copyButton.onclick = () => copyToClipboard(fileLink);
|
||||||
|
deleteButton.style.display = "inline";
|
||||||
|
deleteButton.onclick = () => {
|
||||||
|
window.open(response.deleteLink, "_blank");
|
||||||
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
statusLink.textContent = "File uploaded but failed to parse response.";
|
statusLink.textContent =
|
||||||
|
"Error desconocido, habla con el administrador";
|
||||||
|
}
|
||||||
|
} 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 {
|
} else {
|
||||||
statusLink.textContent = "File upload failed.";
|
statusLink.textContent = "Error del servidor.";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle errors
|
|
||||||
xhr.onerror = () => {
|
|
||||||
statusLink.textContent = "An error occurred during the file upload.";
|
|
||||||
};
|
|
||||||
|
|
||||||
// Send file
|
// Send file
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("file", file);
|
formData.append("file", file);
|
||||||
|
@ -131,9 +157,12 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
|
||||||
// Function to copy the link to the clipboard
|
// Function to copy the link to the clipboard
|
||||||
function copyToClipboard(text) {
|
function copyToClipboard(text) {
|
||||||
navigator.clipboard.writeText(text).then(() => {
|
navigator.clipboard
|
||||||
|
.writeText(text)
|
||||||
|
.then(() => {
|
||||||
// alert("Link copied to clipboard!"); // Notify the user
|
// alert("Link copied to clipboard!"); // Notify the user
|
||||||
}).catch(err => {
|
})
|
||||||
|
.catch((err) => {
|
||||||
console.error("Failed to copy: ", err);
|
console.error("Failed to copy: ", err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
src: url('frahv.ttf');
|
src: url('frahv.ttf');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "XFG";
|
font-family: "XFG";
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
|
@ -22,8 +23,11 @@ html {
|
||||||
rgba(11, 11, 11, 0.92)),
|
rgba(11, 11, 11, 0.92)),
|
||||||
url(./bliss-small.avif);
|
url(./bliss-small.avif);
|
||||||
background-attachment: fixed;
|
background-attachment: fixed;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
body {
|
body {
|
||||||
/* font-family: Arial, sans-serif; */
|
/* font-family: Arial, sans-serif; */
|
||||||
/* background-color: #111; */
|
/* background-color: #111; */
|
||||||
|
@ -31,7 +35,12 @@ body {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
p, h1, h2, h3, h4, h5 {
|
p,
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5 {
|
||||||
color: aliceblue
|
color: aliceblue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +71,7 @@ a {
|
||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
max-width: 700px;
|
max-width: 800px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
/* background: white; */
|
/* background: white; */
|
||||||
/*! padding: 20px; */
|
/*! padding: 20px; */
|
||||||
|
@ -79,8 +88,10 @@ a {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
margin: 0 auto; /* Center the element */
|
margin: 0 auto;
|
||||||
display: block; /* Ensure it behaves as a block-level element */
|
/* Center the element */
|
||||||
|
display: block;
|
||||||
|
/* Ensure it behaves as a block-level element */
|
||||||
background: rgba(202, 230, 190, .75);
|
background: rgba(202, 230, 190, .75);
|
||||||
border: 1px solid #b7d1a0;
|
border: 1px solid #b7d1a0;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
@ -107,8 +118,8 @@ a {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
nav a, nav > ul
|
nav a,
|
||||||
{
|
nav>ul {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -116,47 +127,92 @@ nav a, nav > ul
|
||||||
}
|
}
|
||||||
|
|
||||||
#upload-status {
|
#upload-status {
|
||||||
margin: 20px; /* Adjust as needed */
|
margin: 20px;
|
||||||
|
/* Adjust as needed */
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload-status {
|
.upload-status {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
border: 2px solid #999; /* Optional styling for the status box */
|
border: 2px solid #999;
|
||||||
padding: 5px; /* Optional padding */
|
/* Optional styling for the status box */
|
||||||
/*! border-radius: 6px; */ /* Optional rounded corners */
|
padding: 5px;
|
||||||
/*! background-color: #f9f9f9; */ /* Optional background color */
|
/* Optional padding */
|
||||||
|
/*! border-radius: 6px; */
|
||||||
|
/* Optional rounded corners */
|
||||||
|
/*! background-color: #f9f9f9; */
|
||||||
|
/* Optional background color */
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-container {
|
.link-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-left: auto; /* Pushes the link and button to the right */
|
margin-left: auto;
|
||||||
|
/* Pushes the link and button to the right */
|
||||||
}
|
}
|
||||||
|
|
||||||
.link {
|
.link {
|
||||||
color: #ffb6c1;
|
color: #ffb6c1;
|
||||||
text-decoration: none; /* Remove underline from link */
|
text-decoration: none;
|
||||||
margin-right: 5px; /* Space between link and button */
|
/* Remove underline from link */
|
||||||
|
margin-right: 5px;
|
||||||
|
/* Space between link and button */
|
||||||
}
|
}
|
||||||
|
|
||||||
.link:hover {
|
.link:hover {
|
||||||
text-decoration: underline; /* Optional: underline on hover */
|
text-decoration: underline;
|
||||||
|
/* Optional: underline on hover */
|
||||||
}
|
}
|
||||||
|
|
||||||
.copy-button {
|
.copy-button {
|
||||||
display: inline;
|
display: inline;
|
||||||
background-color: #5e5e5e; /* Button background color */
|
background-color: #7a6fff;
|
||||||
color: white; /* Button text color */
|
/* Button background color */
|
||||||
border: none; /* Remove border */
|
color: white;
|
||||||
border-radius: 3px; /* Rounded corners for the button */
|
/* Button text color */
|
||||||
padding: 5px 10px; /* Button padding */
|
border: none;
|
||||||
cursor: pointer; /* Pointer cursor on hover */
|
/* 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 {
|
.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 {
|
a:link {
|
||||||
|
|
|
@ -20,6 +20,8 @@ module Jobs
|
||||||
spawn do
|
spawn do
|
||||||
loop do
|
loop do
|
||||||
Utils.retrieve_tor_exit_nodes
|
Utils.retrieve_tor_exit_nodes
|
||||||
|
# Updates the @@exit_nodes array instantly
|
||||||
|
Routing.reload_exit_nodes
|
||||||
sleep CONFIG.torExitNodesCheck
|
sleep CONFIG.torExitNodesCheck
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -28,9 +30,7 @@ module Jobs
|
||||||
def self.kemal
|
def self.kemal
|
||||||
spawn do
|
spawn do
|
||||||
if !CONFIG.unix_socket.nil?
|
if !CONFIG.unix_socket.nil?
|
||||||
Kemal.run do |config|
|
Kemal.run &.server.not_nil!.bind_unix "#{CONFIG.unix_socket}"
|
||||||
config.server.not_nil!.bind_unix "#{CONFIG.unix_socket}"
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
Kemal.run
|
Kemal.run
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,19 +3,10 @@ require "./http-errors"
|
||||||
module Routing
|
module Routing
|
||||||
extend self
|
extend self
|
||||||
@@exit_nodes = Array(String).new
|
@@exit_nodes = Array(String).new
|
||||||
if CONFIG.blockTorAddresses
|
|
||||||
spawn do
|
def reload_exit_nodes
|
||||||
# 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"
|
LOGGER.debug "Updating Tor exit nodes array"
|
||||||
@@exit_nodes = Utils.load_tor_exit_nodes
|
@@exit_nodes = Utils.load_tor_exit_nodes
|
||||||
sleep CONFIG.torExitNodesCheck + 5
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
before_post "/api/admin/*" do |env|
|
before_post "/api/admin/*" do |env|
|
||||||
|
@ -86,11 +77,12 @@ module Routing
|
||||||
Handling.sharex_config(env)
|
Handling.sharex_config(env)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if CONFIG.adminEnabled
|
||||||
self.register_admin
|
self.register_admin
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def register_admin
|
def register_admin
|
||||||
if CONFIG.adminEnabled
|
|
||||||
# post "/api/admin/upload" do |env|
|
# post "/api/admin/upload" do |env|
|
||||||
# Handling::Admin.delete_ip_limit(env)
|
# Handling::Admin.delete_ip_limit(env)
|
||||||
# end
|
# end
|
||||||
|
@ -98,8 +90,8 @@ module Routing
|
||||||
Handling::Admin.delete_file(env)
|
Handling::Admin.delete_file(env)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
post "/api/admin/deleteiplimit" do |env|
|
post "/api/admin/deleteiplimit" do |env|
|
||||||
Handling::Admin.delete_ip_limit(env)
|
Handling::Admin.delete_ip_limit(env)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
49
src/utils.cr
49
src/utils.cr
|
@ -135,7 +135,8 @@ module Utils
|
||||||
end
|
end
|
||||||
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
|
def delete_socket
|
||||||
if File.exists?("#{CONFIG.unix_socket}")
|
if File.exists?("#{CONFIG.unix_socket}")
|
||||||
LOGGER.info "Deleting old unix socket"
|
LOGGER.info "Deleting old unix socket"
|
||||||
|
@ -167,21 +168,43 @@ module Utils
|
||||||
msg("File '#{fileinfo[:filename]}' deleted successfully")
|
msg("File '#{fileinfo[:filename]}' deleted successfully")
|
||||||
end
|
end
|
||||||
|
|
||||||
def detect_extension(file) : String
|
MAGIC_BYTES = {
|
||||||
magic_bytes = {
|
# Images
|
||||||
".png" => "89504e470d0a1a0a",
|
".png" => "89504e470d0a1a0a",
|
||||||
|
".heic" => "6674797068656963",
|
||||||
".jpg" => "ffd8ff",
|
".jpg" => "ffd8ff",
|
||||||
".webm" => "1a45dfa3",
|
|
||||||
".mp4" => "66747970",
|
|
||||||
".gif" => "474946383",
|
".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",
|
".7z" => "377abcaf271c",
|
||||||
".gz" => "1f8b",
|
".gz" => "1f8b",
|
||||||
|
".iso" => "4344303031",
|
||||||
|
# Documents
|
||||||
|
"pdf" => "25504446",
|
||||||
|
"html" => "<!DOCTYPE html>",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def detect_extension(file) : String
|
||||||
file = File.open(file)
|
file = File.open(file)
|
||||||
slice = Bytes.new(8)
|
slice = Bytes.new(16)
|
||||||
hex = IO::Hexdump.new(file)
|
hex = IO::Hexdump.new(file)
|
||||||
|
# Reads the first 16 bytes of the file in Heap
|
||||||
hex.read(slice)
|
hex.read(slice)
|
||||||
magic_bytes.each do |ext, mb|
|
MAGIC_BYTES.each do |ext, mb|
|
||||||
if slice.hexstring.includes?(mb)
|
if slice.hexstring.includes?(mb)
|
||||||
return ext
|
return ext
|
||||||
end
|
end
|
||||||
|
@ -191,18 +214,22 @@ module Utils
|
||||||
|
|
||||||
def retrieve_tor_exit_nodes
|
def retrieve_tor_exit_nodes
|
||||||
LOGGER.debug "Retrieving Tor exit nodes list"
|
LOGGER.debug "Retrieving Tor exit nodes list"
|
||||||
resp = HTTP::Client.get(CONFIG.torExitNodesUrl) do |res|
|
HTTP::Client.get(CONFIG.torExitNodesUrl) do |res|
|
||||||
|
begin
|
||||||
if res.success? && res.status_code == 200
|
if res.success? && res.status_code == 200
|
||||||
begin
|
begin
|
||||||
File.open(CONFIG.torExitNodesFile, "w") do |output|
|
File.open(CONFIG.torExitNodesFile, "w") { |output| IO.copy(res.body_io, output) }
|
||||||
IO.copy(res.body_io, output)
|
|
||||||
end
|
|
||||||
rescue ex
|
rescue ex
|
||||||
LOGGER.error "Failed to write to file: #{ex.message}"
|
LOGGER.error "Failed to write to file: #{ex.message}"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
LOGGER.error "Failed to retrieve exit nodes list. Status Code: #{res.status_code}"
|
LOGGER.error "Failed to retrieve exit nodes list. Status Code: #{res.status_code}"
|
||||||
end
|
end
|
||||||
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue