Completed HashyMagnet; Update Ecoji;

This commit is contained in:
octospacc 2022-09-07 20:25:23 +02:00
parent 05c2ee7351
commit 0f07037db7
3 changed files with 196 additions and 40 deletions

View File

@ -50,7 +50,7 @@ Body {
#Links > Div { #Links > Div {
Max-Width: Fit-Content; Max-Width: Fit-Content;
Margin: Auto !Important; Margin: Auto;
Padding: 16px; Padding: 16px;
Background-Color: RGBA(16,16,16,0.8); Background-Color: RGBA(16,16,16,0.8);
} }

View File

@ -1,7 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<!-- <!--
This is an unaffiliated fork of the Ecoji v1 webapp. This is an unaffiliated fork of the Ecoji v1 webapp.
| Last modified: 2022-09-06. | Last updated: 2022-09-07.
Original Ecoji project info: Original Ecoji project info:
| https://github.com/keith-turner/ecoji | https://github.com/keith-turner/ecoji
@ -9,7 +9,7 @@
Changes in this Web build (directly edited from the gh-pages branch): Changes in this Web build (directly edited from the gh-pages branch):
| Simplified the CSS, | Simplified the CSS,
| handling decode URIs with "#d=" instead of "?d=", | handling decode URIs with "#d=" instead of "?d=",
| // TODO: autoremove whitespace in decode box, | automatically ignore whitespace in decode box,
| added JavaScript notice, | added JavaScript notice,
| made the app a self-contained AHTML bundle and added notice. | made the app a self-contained AHTML bundle and added notice.
@ -61,7 +61,7 @@ Header > Div > * {
Margin-Right: 40px; Margin-Right: 40px;
White-Space: NoWrap; White-Space: NoWrap;
} }
NoScript P { NoScript, NoScript P {
Font-Size: XX-Large; Font-Size: XX-Large;
Padding: 8px; Padding: 8px;
Padding-Bottom: 48px; Padding-Bottom: 48px;
@ -581,6 +581,7 @@ function doEncode(){
function doDecode(){ function doDecode(){
var data = document.getElementById('encoded').value var data = document.getElementById('encoded').value
.replaceAll("\n", "").replaceAll("\r", "").replaceAll("\t", "").replaceAll(" ", "")
var decoded = ecojiDecode(data) var decoded = ecojiDecode(data)
document.getElementById('plain').value = decoded document.getElementById('plain').value = decoded
} }

View File

@ -2,9 +2,9 @@
<html lang="en"> <html lang="en">
<head> <head>
<title>HashyMagnet</title> <title>HashyMagnet</title>
<meta name="description" content="Generate Magnet URIs from BitTorrent Hashes!"> <meta name="description" content="Generate full BitTorrent Magnet Links from Info Hashes!">
<meta property="og:title" content="HashyMagnet"> <meta property="og:title" content="HashyMagnet">
<meta property="og:description" content="Generate Magnet URIs from BitTorrent Hashes!"> <meta property="og:description" content="Generate full BitTorrent Magnet Links from Info Hashes!">
<meta property="og:url" content="https://hub.octt.eu.org/HashyMagnet"> <meta property="og:url" content="https://hub.octt.eu.org/HashyMagnet">
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@ -21,8 +21,32 @@ Body {
Text-Align: Center; Text-Align: Center;
Font-Family: Sans-Serif; Font-Family: Sans-Serif;
} }
Input, Button { Body:Not(Input, TextArea) {
User-Select: None;
}
A {
Color: #17C3EA;
}
A:Active {
Color: #0B69BC;
}
A:Hover {
Background: #101060;
Color: #E9FFEE;
}
NoScript, NoScript P {
Font-Size: XX-Large;
}
Input {
Height: 2em; Height: 2em;
}
Button {
Height: 2.25em;
}
Input, Button {
Font-Size: Initial; Font-Size: Initial;
} }
Input, TextArea { Input, TextArea {
@ -30,7 +54,46 @@ Input, TextArea {
Margin-Top: 8px; Margin-Top: 8px;
Margin-Bottom: 8px; Margin-Bottom: 8px;
} }
Input:Disabled, TextArea:Disabled {
Color: #000000;
Background-Color: #EEEEEE;
}
Input, TextArea, Button {
Color: #000000;
Background-Color: #EEFFFF;
Border: Solid #808080 1px;
Border-Radius: 4px;
}
Button {
Color: #202020;
Padding-Left: 0.5em;
Padding-Right: 0.5em;
}
Button:Hover {
Color: #101010;
}
Button:Active {
Color: #000000;
Background-Color: #DDEEEE;
}
Button:Disabled {
Color: #808080;
Background-Color: RGBA(16,16,48,0.5);
}
.Section {
Margin: 4px;
}
.NoWrap {
White-Space: NoWrap;
}
.LeftAlign {
Text-Align: Left;
Margin-Left: Calc(5% + 8px);
}
#Main { #Main {
Overflow-X: Hidden;
Overflow-Y: Scroll; Overflow-Y: Scroll;
Max-Height: 100vh; Max-Height: 100vh;
Position: Absolute; Position: Absolute;
@ -40,42 +103,90 @@ Input, TextArea {
Right: 0px; Right: 0px;
Z-Index: 4; Z-Index: 4;
} }
.Section { /*
Margin: 4px; #Title, #Title > Div {
Max-Width: Fit-Content;
Margin: Auto;
} }
.NoWrap { */
White-Space: NoWrap;
#ResetBtn {
Color: #FF0000;
Padding-Bottom: 4px;
Width: 2em;
}
#ResetBtn:Active, #ResetBtn:Hover {
Color: #FFFFFF;
Background-Color: #FF0000;
} }
</style> </style>
</head> </head>
<body> <body>
<div id="Main"> <div id="Main">
<div class="Section"> <div id="Title" class="Section"><div>
<h3>HashyMagnet</h3> <div id="TitleTitle">
<p>Generate a full Bit<span style="Color:#AAFFFF;">Torrent</span> Magnet Link from an Info Hash!</p> <h3>HashyMagnet</h3>
<p>Generate a full Bit<span style="Color:#AAFFFF;">Torrent</span> Magnet Link from an Info Hash...</p>
</div>
<noscript><p> <noscript><p>
This is an actual app, not a badly-made website. This is an actual app, not a badly-made website.
<br> <br>
It needs JavaScript, so you need to enable it. It needs JavaScript to work, so you need to enable it.
<br> <br>
The code is fully open, and you can review it with "View Page Source". The code is fully open, and you can review it with "View Page Source".
</p></noscript> </p></noscript>
</div> <div id="Info">
<h4>Info</h4>
<p>With this app you can generate full <a href="https://en.m.wikipedia.org/wiki/Magnet_URI_scheme" target="_blank" rel="noopener nofollow">BitTorrent Magnet links</a>, complete with trackers, from a simple Info Hash.</p>
<p>You can input your own list of trackers, or you can use the one that's autogenerated by the app from up-to-date lists.</p>
<p>Last updated: 2022-09-07.</p>
<h4>Special Thanks and Credits</h4>
<p>
Tracker lists providers:
<ul id="ListsProviders">
<li><a href="https://github.com/ngosang/trackerslist" target="_blank" rel="noopener nofollow">https://github.com/ngosang/trackerslist</a></li>
<li><a href="https://newtrackon.com" target="_blank" rel="noopener nofollow">https://newtrackon.com</a></li>
</ul>
</p>
<p>
Background animations:
<br>
<a href="https://codinhood.com/micro/animate-octocat-sprite-css" target="_blank" rel="noopener nofollow">https://codinhood.com/micro/animate-octocat-sprite-css</a></p>
<h4>License</h4>
<pre>HashyMagnet
Copyright (C) 2022, OctoSpacc
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <a href="https://www.gnu.org/licenses" target="_blank" rel="noopener nofollow">https://www.gnu.org/licenses</a>.
</pre>
<br>
</div>
</div></div>
<br> <br>
<div class="Section"> <div class="Section">
<div class="NoWrap"> <div class="NoWrap">
<button id="ResetBtn"></button> <button id="ResetBtn"><big><b>x</b></big></button>
<input id="TextBox" placeholder="📝 Paste Info Hash here..."> <input id="TextBox" placeholder="📝 Paste Hash here...">
</div> </div>
<div class="NoWrap"> <div class="NoWrap">
<button id="GenerateBtn">Generate Magnet!</button> <button id="GenerateBtn">🧲 Generate Magnet!</button>
<button id="CopyBtn">Copy link</button> <button id="CopyBtn">📋 Copy</button>
<button id="OpenBtn">Open link</button> <button id="OpenBtn">🔗 Open</button>
</div> </div>
</div> </div>
<br> <br>
<div class="Section"> <div class="Section">
<div class="NoWrap"> <div class="NoWrap LeftAlign">
<label for="TrackersBtn">Trackers list:</label> <label for="TrackersBtn">Trackers list:</label>
<button id="TrackersBtn"></button> <button id="TrackersBtn"></button>
</div> </div>
@ -86,38 +197,50 @@ Input, TextArea {
<div class="ocean"><div class="bubble bubble-1"></div><div class="bubble bubble-2"></div><div class="bubble bubble-3"></div><div class="bubble bubble-4"></div><div class="bubble bubble-5"></div><div class="bubble bubble-6"></div><div class="bubble bubble-7"></div><div class="bubble bubble-8"></div><div class="bubble bubble-9"></div><div class="bubble bubble-10"></div><div class="bubble bubble-11"></div></div> <div class="ocean"><div class="bubble bubble-1"></div><div class="bubble bubble-2"></div><div class="bubble bubble-3"></div><div class="bubble bubble-4"></div><div class="bubble bubble-5"></div><div class="bubble bubble-6"></div><div class="bubble bubble-7"></div><div class="bubble bubble-8"></div><div class="bubble bubble-9"></div><div class="bubble bubble-10"></div><div class="bubble bubble-11"></div></div>
<script> <script>
var Generated = false; var Generated = false;
var Trackers = []; var Trackers = [],
var TrackersNum = 35; FetchTrackers = [];
var MaxFetchTrackers = 40;
const TrackersSources = [ const TrackersSources = [
"https://ngosang.github.io/trackerslist/trackers_best.txt", "https://ngosang.github.io/trackerslist/trackers_best.txt",
"https://newtrackon.com/api/stable", "https://newtrackon.com/api/stable",
]; ];
async function FetchTrackers() { function SplitLines(Text) {
if (Text == "") {
return [];
} else {
return Text.trim().replaceAll("\r","").replace(/\n\s*\n/g,"\n").split("\n")
}
}
async function DoFetchTrackers() {
for (let i = 0; i < TrackersSources.length; i++) { for (let i = 0; i < TrackersSources.length; i++) {
let Req = await fetch(TrackersSources[i]); let Req = await fetch(TrackersSources[i]);
let Data = await Req.text(); let Data = await Req.text();
Trackers = Trackers.concat(Data.replaceAll("\n\n","\n").split("\n")); FetchTrackers = FetchTrackers.concat(SplitLines(Data));
} }
Trackers = Trackers.slice(0,TrackersNum); FetchTrackers = FetchTrackers.slice(0,MaxFetchTrackers);
} }
function WriteTrackers() { function WriteFetchTrackers() {
for (let i = 0; i < Trackers.length; i++) { for (let i = 0; i < FetchTrackers.length; i++) {
TrackersArea.value += Trackers[i] + "\n\n"; TrackersArea.value += FetchTrackers[i] + "\n\n";
} }
StoreTrackers();
DoRedraw(); DoRedraw();
} }
function StoreTrackers() { function StoreTrackers() {
Trackers = SplitLines(TrackersArea.value);
} }
async function FetchWriteTrackers() { async function CallWriteFetchTrackers() {
await FetchTrackers(); await DoFetchTrackers();
WriteTrackers(); WriteFetchTrackers();
} }
GenerateBtn.onclick = function() { GenerateBtn.onclick = function() {
TextBox.value = TextBox.value.substr(TextBox.value.lastIndexOf(":")+1);
TextBox.value = "magnet:?xt=urn:btih:" + TextBox.value; TextBox.value = "magnet:?xt=urn:btih:" + TextBox.value;
for (let i = 0; i < Trackers.length; i++) { for (let i = 0; i < Trackers.length; i++) {
TextBox.value += "&tr=" + encodeURIComponent(Trackers[i]); TextBox.value += "&tr=" + encodeURIComponent(Trackers[i]);
@ -127,21 +250,31 @@ GenerateBtn.onclick = function() {
}; };
function DoRedraw() { function DoRedraw() {
TextBox.style = "";
let TextBoxWidth = TextBox.offsetWidth;
if (Generated) { if (Generated) {
TextBox.disabled = true;
GenerateBtn.disabled = true;
GenerateBtn.hidden = true; GenerateBtn.hidden = true;
ResetBtn.hidden = false; ResetBtn.hidden = false;
TextBox.style = "Width:" + (TextBoxWidth - ResetBtn.offsetWidth - 12) + "px;"
CopyBtn.hidden = false; CopyBtn.hidden = false;
OpenBtn.hidden = false; OpenBtn.hidden = false;
} else { } else {
TextBox.disabled = false;
GenerateBtn.disabled = false;
GenerateBtn.hidden = false; GenerateBtn.hidden = false;
ResetBtn.hidden = true; ResetBtn.hidden = true;
CopyBtn.hidden = true; CopyBtn.hidden = true;
OpenBtn.hidden = true; OpenBtn.hidden = true;
} }
if (TextBox.value) {
GenerateBtn.disabled = false;
} else {
GenerateBtn.disabled = true;
}
if (TrackersArea.value) { if (TrackersArea.value) {
TrackersBtn.textContent = "🧹 Clear"; TrackersBtn.textContent = "🗑️ Clear";
} else { } else {
TrackersBtn.textContent = "🔄 Refresh"; TrackersBtn.textContent = "🔄 Refresh";
} }
@ -164,17 +297,39 @@ OpenBtn.onclick = function() {
TrackersBtn.onclick = function() { TrackersBtn.onclick = function() {
if (TrackersArea.value) { if (TrackersArea.value) {
TrackersArea.value = ""; TrackersArea.value = "";
StoreTrackers();
} else { } else {
WriteTrackers(); WriteFetchTrackers();
} }
DoRedraw(); DoRedraw();
}; };
TrackersArea.onchange = StoreTrackers; function TrackersAreaOnChange() {
StoreTrackers();
DoRedraw();
}
TrackersArea.onchange = TrackersAreaOnChange;
TrackersArea.oninput = TrackersAreaOnChange;
TrackersArea.onpaste = TrackersAreaOnChange;
TextBox.onkeydown = function(e) {
if (e.keyCode == 13 && !Generated) {
GenerateBtn.click();
}
};
TextBox.onchange = DoRedraw;
TextBox.oninput = DoRedraw;
TextBox.onpaste = DoRedraw;
window.onresize = DoRedraw;
Info.hidden = true;
TitleTitle.onclick = function() {
Info.hidden = !Info.hidden;
};
DoRedraw(); DoRedraw();
FetchWriteTrackers(); CallWriteFetchTrackers();
TrackersBtn.hidden = true;
</script> </script>
</body> </body>
</html> </html>