diff --git a/css/style.css b/css/style.css index 51d333e..03b5d08 100644 --- a/css/style.css +++ b/css/style.css @@ -11,6 +11,13 @@ body { background: #eff1f5; color: #4c4f69; + + font-family: "Terminess Nerd Font Mono", monospace; +} + +a { + color: #8839ef; + text-decoration: none; } @media (prefers-color-scheme: dark) { @@ -18,6 +25,15 @@ body { background: #1e1e2e; color: #cdd6f4; } + + a { + color: #cba6f7; + } +} + +th, +td { + text-align: left; } fieldset { diff --git a/css/terminess.css b/css/terminess.css new file mode 100644 index 0000000..68bb21d --- /dev/null +++ b/css/terminess.css @@ -0,0 +1,39 @@ +@font-face { + font-family: 'Terminess Nerd Font Mono'; + src: local('Terminess Nerd Font Mono Bold Italic'), local('TerminessNFM-BoldItalic'), + url('TerminessNFM-BoldItalic.woff2') format('woff2'), + url('TerminessNFM-BoldItalic.woff') format('woff'); + font-weight: bold; + font-style: italic; + font-display: swap; +} + +@font-face { + font-family: 'Terminess Nerd Font Mono'; + src: local('Terminess Nerd Font Mono Bold'), local('TerminessNFM-Bold'), + url('TerminessNFM-Bold.woff2') format('woff2'), + url('TerminessNFM-Bold.woff') format('woff'); + font-weight: bold; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Terminess Nerd Font Mono'; + src: local('Terminess Nerd Font Mono Italic'), local('TerminessNFM-Italic'), + url('TerminessNFM-Italic.woff2') format('woff2'), + url('TerminessNFM-Italic.woff') format('woff'); + font-weight: 500; + font-style: italic; + font-display: swap; +} + +@font-face { + font-family: 'Terminess Nerd Font Mono'; + src: local('Terminess Nerd Font Mono'), local('TerminessNFM'), + url('TerminessNFM.woff2') format('woff2'), + url('TerminessNFM.woff') format('woff'); + font-weight: 500; + font-style: normal; + font-display: swap; +} \ No newline at end of file diff --git a/fonts/TerminessNFM-Bold.woff b/fonts/TerminessNFM-Bold.woff new file mode 100644 index 0000000..9035975 Binary files /dev/null and b/fonts/TerminessNFM-Bold.woff differ diff --git a/fonts/TerminessNFM-Bold.woff2 b/fonts/TerminessNFM-Bold.woff2 new file mode 100644 index 0000000..db6343a Binary files /dev/null and b/fonts/TerminessNFM-Bold.woff2 differ diff --git a/fonts/TerminessNFM-BoldItalic.woff b/fonts/TerminessNFM-BoldItalic.woff new file mode 100644 index 0000000..8b73e94 Binary files /dev/null and b/fonts/TerminessNFM-BoldItalic.woff differ diff --git a/fonts/TerminessNFM-BoldItalic.woff2 b/fonts/TerminessNFM-BoldItalic.woff2 new file mode 100644 index 0000000..da5905d Binary files /dev/null and b/fonts/TerminessNFM-BoldItalic.woff2 differ diff --git a/fonts/TerminessNFM-Italic.woff b/fonts/TerminessNFM-Italic.woff new file mode 100644 index 0000000..d027a2e Binary files /dev/null and b/fonts/TerminessNFM-Italic.woff differ diff --git a/fonts/TerminessNFM-Italic.woff2 b/fonts/TerminessNFM-Italic.woff2 new file mode 100644 index 0000000..757bab5 Binary files /dev/null and b/fonts/TerminessNFM-Italic.woff2 differ diff --git a/fonts/TerminessNFM.woff b/fonts/TerminessNFM.woff new file mode 100644 index 0000000..58de1af Binary files /dev/null and b/fonts/TerminessNFM.woff differ diff --git a/fonts/TerminessNFM.woff2 b/fonts/TerminessNFM.woff2 new file mode 100644 index 0000000..521870c Binary files /dev/null and b/fonts/TerminessNFM.woff2 differ diff --git a/index.html b/index.html index bc1d546..04fecfc 100644 --- a/index.html +++ b/index.html @@ -5,26 +5,15 @@ opentracker + -
opentracker - - - - - - - - - - -
Seeder(s)
Leecher(s)
- - Loading... +
+ Please wait...
diff --git a/js/script.js b/js/script.js index d46a328..6e6896f 100644 --- a/js/script.js +++ b/js/script.js @@ -1,50 +1,78 @@ -function xml2json(xml) { - var obj = {}; - - if (xml.nodeType == 1) { - if (xml.attributes.length > 0) { - obj["@attributes"] = {}; - for (var j = 0; j < xml.attributes.length; j++) { - var attribute = xml.attributes.item(j); - obj["@attributes"][attribute.nodeName] = attribute.nodeValue; - } - } - } else if (xml.nodeType == 3) { - obj = xml.nodeValue.trim(); - } - - var textNodes = [].slice.call(xml.childNodes).filter(function (node) { - return node.nodeType === 3; - }); - if (xml.hasChildNodes() && xml.childNodes.length === textNodes.length) { - obj = [].slice.call(xml.childNodes).reduce(function (text, node) { - return text + node.nodeValue.trim(); - }, ""); - } else if (xml.hasChildNodes()) { - for (var i = 0; i < xml.childNodes.length; i++) { - var item = xml.childNodes.item(i); - var nodeName = item.nodeName; - if (nodeName == "#text") continue; - if (typeof obj[nodeName] == "undefined") { - obj[nodeName] = xml2json(item); - } else { - if (typeof obj[nodeName].push == "undefined") { - var old = obj[nodeName]; - obj[nodeName] = []; - obj[nodeName].push(old); - } - obj[nodeName].push(xml2json(item)); - } - } - } - return obj; -} - const parser = new DOMParser(); -fetch("stats?mode=everything").then(r => r.text()).then(r => { - var data = xml2json(parser.parseFromString(r, "text/xml")).stats; - document.querySelector("#s").textContent = data.seeds.count; - document.querySelector("#l").textContent = data.completed.count; - document.querySelector("#footer").textContent = `serving ${data.torrents.count_mutex} torrents`; +var host = "stats?mode=%"; + +if (["localhost", "127.0.0.1", "[::]"].includes(location.hostname)) { + host = "sample/%.txt" +} + +fetch(host.replace("%", "torr")).then(r => r.text()).then(r => { + document.querySelector("#footer").textContent = r.split("\n")[2]; +}); + +var i = { + "S": "\uf062", + "P": "\uf063", + "L": "\uf46f" +} + +fetch(host.replace("%", "top10")).then(r => r.text()).then(r => { + var lines = r.split("\n"); + var current = ""; + var data = {} + var hashes = {} + for (const line of lines) { + if (line.trim() == "") continue; + + if (!line.startsWith("\t")) { + current = line.slice(line.indexOf("by ") + 3, -1); + data[current] = []; + } else { + var segments = line.trim().split("\t"); + var info = { + num: parseInt(segments[0]), + hash: segments[1] + } + hashes[info.hash] = hashes[info.hash] ?? { "seeds": 0 }; + hashes[info.hash][current] = hashes[info.hash][current] ?? 0; + + hashes[info.hash][current] += info.num; + data[current].push(info); + } + } + + var tr = document.createElement("tr"); + + var th = document.createElement("th"); + th.textContent = "\uf4df"; + tr.appendChild(th); + + for (const t of Object.keys(hashes[Object.keys(hashes)[0]])) { + var th = document.createElement("th"); + th.textContent = i[t.slice(0, 1).toUpperCase()]; + tr.appendChild(th); + } + + document.querySelector("#torrents").appendChild(tr); + + for (const hash of Object.keys(hashes)) { + var data = hashes[hash]; + var tr = document.createElement("tr"); + tr.style = "font-family:monospace"; + + var td = document.createElement("td"); + var a = document.createElement("a"); + a.href = `magnet:?xt=urn:btih:${hash}&tr=https://${location.hostname}/announce&tr=http://${location.hostname}/announce&tr=udp://${location.hostname}:6969/announce`; + a.textContent = hash; + td.appendChild(a); + tr.appendChild(td); + + for (const key of Object.keys(data)) { + var td = document.createElement("td"); + td.textContent = data[key]; + tr.appendChild(td); + } + + document.querySelector("#torrents").appendChild(tr); + } }); \ No newline at end of file diff --git a/sample/everything.txt b/sample/everything.txt new file mode 100644 index 0000000..4d43619 --- /dev/null +++ b/sample/everything.txt @@ -0,0 +1,101 @@ + + + 964180315 + + https://erdgeist.org/gitweb/opentracker/commit/?id=c854b3db9bf620e86481acfcc9fc31eba64bc8e6 + + 6392 + + 59 + 59 + + + 118 + + + 118 + + + 3 + + + + 324 + 64 + 3 + + + 156 + 14 + 123 + 19 + 0 + + + 0 + + + + + 1 + 1 + 31 + 26 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 2 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + 1 + 0 + 13 + 0 + 0 + 0 + 0 + 6 + 1 + + + 0 + + + \ No newline at end of file diff --git a/sample/top10.txt b/sample/top10.txt new file mode 100644 index 0000000..7dc8bab --- /dev/null +++ b/sample/top10.txt @@ -0,0 +1,23 @@ +Top 10 torrents by peers: + 2 03C2E7E18CA5314E39A3FFC753D1024FBFB20784 + 2 04EBCEDCE991140547F9480EDD8051EEAB2BB668 + 2 060FCE53DFE77485BAD7FBB919C5ED543472EB30 + 2 08A47A77872979C7C086F412143916A7096369CD + 2 0E1610F5C681BBE8E908DDB7F73DC890899994F4 + 2 16AA39B7F784C6D3519D1D9893EE3B1EAF3B3AAD + 2 174187E47484B3A46D34ACCEC66245F504932081 + 2 1B5EF508045EB4B0B28261311E63800B7B50A2F2 + 2 2187F35114A736DC847113878687EC0EEBA1B854 + 2 23C8467227E53AE940BC22423FB2D603B9B4FF7C +Top 10 torrents by seeds: + 2 03C2E7E18CA5314E39A3FFC753D1024FBFB20784 + 2 04EBCEDCE991140547F9480EDD8051EEAB2BB668 + 2 060FCE53DFE77485BAD7FBB919C5ED543472EB30 + 2 08A47A77872979C7C086F412143916A7096369CD + 2 0E1610F5C681BBE8E908DDB7F73DC890899994F4 + 2 16AA39B7F784C6D3519D1D9893EE3B1EAF3B3AAD + 2 174187E47484B3A46D34ACCEC66245F504932081 + 2 1B5EF508045EB4B0B28261311E63800B7B50A2F2 + 2 2187F35114A736DC847113878687EC0EEBA1B854 + 2 23C8467227E53AE940BC22423FB2D603B9B4FF7C +Top 10 torrents by leechers: diff --git a/sample/top100.txt b/sample/top100.txt new file mode 100644 index 0000000..1ce252b --- /dev/null +++ b/sample/top100.txt @@ -0,0 +1,121 @@ +Top 100 torrents by peers: + 2 03C2E7E18CA5314E39A3FFC753D1024FBFB20784 + 2 04EBCEDCE991140547F9480EDD8051EEAB2BB668 + 2 060FCE53DFE77485BAD7FBB919C5ED543472EB30 + 2 08A47A77872979C7C086F412143916A7096369CD + 2 0E1610F5C681BBE8E908DDB7F73DC890899994F4 + 2 16AA39B7F784C6D3519D1D9893EE3B1EAF3B3AAD + 2 174187E47484B3A46D34ACCEC66245F504932081 + 2 1B5EF508045EB4B0B28261311E63800B7B50A2F2 + 2 2187F35114A736DC847113878687EC0EEBA1B854 + 2 23C8467227E53AE940BC22423FB2D603B9B4FF7C + 2 2C5F3C95275151B88FE5F2C0D9FDFB99124133F1 + 2 2FC843BCB8137E88B75B98B5C553CD071552852B + 2 31D6E5FD572688BC51460E86FDD83B1BE5651F6E + 2 3359EEE1F8BB251A8E1C5F12984BBADE267C1A02 + 2 396C9CF961703CCC8B8E9368BBDD5E6182A2160E + 2 39B7654A7F415EBB4B86F78D384054792856111A + 2 3DF7FA24521A67005B7B4E0A08F0C9E2D45E086F + 2 3F09A805066876F2A54BD4CED55178D25E05BF10 + 2 40762B23D0AF64AE6D10EAD50022D83155E93827 + 2 4BEC5076C6CF7382EB6AD20156394C7230D590E7 + 2 4DCCED4A8C502C0C7E92B0BD5F63DD7814D86FC5 + 2 4FAB99B5620FA761A665DA5DC73CEA43A09A7D2B + 2 56BA092EBBD70D1F389F7C207D89867300A33D49 + 2 7888264FFFD96AB2FA5A188A060A4BC9D0AEDAED + 2 7A8217D9C65441C4ABEE33A0291CBA437BF844CA + 2 8A7403772FAA4B3C987C613D99A783E26FD9BC93 + 2 8C7BB67E61065C5CEAB44D757D0CA2CB69BEED31 + 2 8C873164EBB96A4C3C15F111DD06575F770C9001 + 2 8D732DA24D0011D82F770B4AF8BC3539A6A89BC4 + 2 9239D8792C8226F533EAFCACDC88AF470D2670D4 + 2 93A06433A4217130FED11FFF7F9186A5FDB66628 + 2 9C12DF3391A4BFE4E51DE96EB3A98C1C8D5BA92E + 2 AC35536AF8E7FE0BFF25CD8783747F7B96C53E8F + 2 AF8C7138AA1869DA4D65099BDF4EE3C09DAF2EB1 + 2 B06F3E1FF3573905C4653892B22F15C491A28CB8 + 2 B1C6A489D03B2AC090EFAED2B8897064D591A386 + 2 B85BF16A2DA3D73B135471C41DF3E1640E57A48B + 2 BC55684FFD49F37118C86E4B78653FC57B9D1721 + 2 C1C12677F61F58EC920AB5A5526D3A2906AF72A1 + 2 C578A179954753693176292D44380F2BF5200EC6 + 2 C6BE5D71C483B3E952524CFE782C151E60C72152 + 2 C6E943B742BF05F648AF7AF03D0954F819A66CE1 + 2 C7F5234582D772BD16011F0E480F06706CD12F14 + 2 CA3E8DE93CD7BA71C28FDCC71C1828D6DF45006A + 2 CDC00E20D451A1C9BC674A58A2014A84C66AE9F7 + 2 CDFAC041819603EF8345EF6E241FF67477E2BF55 + 2 CE0C28F10F87830254E80D6F54516F2AD2E7F5C2 + 2 CFEC68E6D5EC4713ECF50301DFC26AE0443B3620 + 2 D0341227B45EC1415C54D13C3FB670E760BD95D5 + 2 D2B10F9480B70664835BEC6401EA3D72343D645A + 2 D62B82A02E718CB86282812624C0C63F8246693D + 2 D7B41897BCCB71AE27AB646BB0FA1E98D5BAABA6 + 2 D813DBB9A69B979AD745CFC17895068A73F1C81B + 2 D8D32670CDB2264416A0A88FB33D246F6B85CC24 + 2 E59712FDEA810860CDE3DAE8494B047BFA947E0D + 2 E8027DD86E35A2F146C4690B69B9EDE793F527E8 + 2 F235B0E32828A3D5CE873C738F8553720F92E796 + 2 F3542CBB1AB193FADDF3204A0C936E37F3381055 + 2 FC3278EF007EA723D8ACED9B0A73C7F55C5ECAD5 +Top 100 torrents by seeds: + 2 03C2E7E18CA5314E39A3FFC753D1024FBFB20784 + 2 04EBCEDCE991140547F9480EDD8051EEAB2BB668 + 2 060FCE53DFE77485BAD7FBB919C5ED543472EB30 + 2 08A47A77872979C7C086F412143916A7096369CD + 2 0E1610F5C681BBE8E908DDB7F73DC890899994F4 + 2 16AA39B7F784C6D3519D1D9893EE3B1EAF3B3AAD + 2 174187E47484B3A46D34ACCEC66245F504932081 + 2 1B5EF508045EB4B0B28261311E63800B7B50A2F2 + 2 2187F35114A736DC847113878687EC0EEBA1B854 + 2 23C8467227E53AE940BC22423FB2D603B9B4FF7C + 2 2C5F3C95275151B88FE5F2C0D9FDFB99124133F1 + 2 2FC843BCB8137E88B75B98B5C553CD071552852B + 2 31D6E5FD572688BC51460E86FDD83B1BE5651F6E + 2 3359EEE1F8BB251A8E1C5F12984BBADE267C1A02 + 2 396C9CF961703CCC8B8E9368BBDD5E6182A2160E + 2 39B7654A7F415EBB4B86F78D384054792856111A + 2 3DF7FA24521A67005B7B4E0A08F0C9E2D45E086F + 2 3F09A805066876F2A54BD4CED55178D25E05BF10 + 2 40762B23D0AF64AE6D10EAD50022D83155E93827 + 2 4BEC5076C6CF7382EB6AD20156394C7230D590E7 + 2 4DCCED4A8C502C0C7E92B0BD5F63DD7814D86FC5 + 2 4FAB99B5620FA761A665DA5DC73CEA43A09A7D2B + 2 56BA092EBBD70D1F389F7C207D89867300A33D49 + 2 7888264FFFD96AB2FA5A188A060A4BC9D0AEDAED + 2 7A8217D9C65441C4ABEE33A0291CBA437BF844CA + 2 8A7403772FAA4B3C987C613D99A783E26FD9BC93 + 2 8C7BB67E61065C5CEAB44D757D0CA2CB69BEED31 + 2 8C873164EBB96A4C3C15F111DD06575F770C9001 + 2 8D732DA24D0011D82F770B4AF8BC3539A6A89BC4 + 2 9239D8792C8226F533EAFCACDC88AF470D2670D4 + 2 93A06433A4217130FED11FFF7F9186A5FDB66628 + 2 9C12DF3391A4BFE4E51DE96EB3A98C1C8D5BA92E + 2 AC35536AF8E7FE0BFF25CD8783747F7B96C53E8F + 2 AF8C7138AA1869DA4D65099BDF4EE3C09DAF2EB1 + 2 B06F3E1FF3573905C4653892B22F15C491A28CB8 + 2 B1C6A489D03B2AC090EFAED2B8897064D591A386 + 2 B85BF16A2DA3D73B135471C41DF3E1640E57A48B + 2 BC55684FFD49F37118C86E4B78653FC57B9D1721 + 2 C1C12677F61F58EC920AB5A5526D3A2906AF72A1 + 2 C578A179954753693176292D44380F2BF5200EC6 + 2 C6BE5D71C483B3E952524CFE782C151E60C72152 + 2 C6E943B742BF05F648AF7AF03D0954F819A66CE1 + 2 C7F5234582D772BD16011F0E480F06706CD12F14 + 2 CA3E8DE93CD7BA71C28FDCC71C1828D6DF45006A + 2 CDC00E20D451A1C9BC674A58A2014A84C66AE9F7 + 2 CDFAC041819603EF8345EF6E241FF67477E2BF55 + 2 CE0C28F10F87830254E80D6F54516F2AD2E7F5C2 + 2 CFEC68E6D5EC4713ECF50301DFC26AE0443B3620 + 2 D0341227B45EC1415C54D13C3FB670E760BD95D5 + 2 D2B10F9480B70664835BEC6401EA3D72343D645A + 2 D62B82A02E718CB86282812624C0C63F8246693D + 2 D7B41897BCCB71AE27AB646BB0FA1E98D5BAABA6 + 2 D813DBB9A69B979AD745CFC17895068A73F1C81B + 2 D8D32670CDB2264416A0A88FB33D246F6B85CC24 + 2 E59712FDEA810860CDE3DAE8494B047BFA947E0D + 2 E8027DD86E35A2F146C4690B69B9EDE793F527E8 + 2 F235B0E32828A3D5CE873C738F8553720F92E796 + 2 F3542CBB1AB193FADDF3204A0C936E37F3381055 + 2 FC3278EF007EA723D8ACED9B0A73C7F55C5ECAD5 +Top 100 torrents by leechers: diff --git a/sample/torr.txt b/sample/torr.txt new file mode 100644 index 0000000..a204925 --- /dev/null +++ b/sample/torr.txt @@ -0,0 +1,4 @@ +59 +0 +opentracker serving 59 torrents +opentracker \ No newline at end of file