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
+
-
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