Compare commits
49 commits
Author | SHA1 | Date | |
---|---|---|---|
34cd588fa9 | |||
3dc5f6574b | |||
5df7ceebf3 | |||
309d357d0b | |||
7b7f6cab6a | |||
ba06ec32c0 | |||
b28555b7e4 | |||
a8a22773aa | |||
98c4cd1a03 | |||
967f6bc1e7 | |||
a21bbd9a0a | |||
54b1b6236c | |||
40a6050329 | |||
ec27da906b | |||
3b05a957da | |||
e0f1a59d86 | |||
c6918b659b | |||
faaf3d1b13 | |||
a081c6a44b | |||
e43c470147 | |||
35e367a1e7 | |||
9cd8a604ff | |||
4241c69887 | |||
8fc147b75f | |||
d21e4c3007 | |||
6565431867 | |||
ec1f2a934d | |||
c60ff08abf | |||
5a55a4843e | |||
b5115b8a64 | |||
6d36b0fd88 | |||
dfbf1c6d64 | |||
e813ec4b39 | |||
c7883652b0 | |||
8aa3d5531d | |||
36cab4cba2 | |||
a37e1a52e4 | |||
385551a510 | |||
20c00dd33d | |||
96020c395a | |||
100ec476e1 | |||
2099648300 | |||
d2d5cf7161 | |||
92c481343b | |||
3b43e6bc6b | |||
accf418bbf | |||
b8697b0a6e | |||
8707ae9e39 | |||
db77ca5ccd |
2
.gitignore
vendored
|
@ -5,3 +5,5 @@ output/
|
||||||
|
|
||||||
# the world isn't ready yet
|
# the world isn't ready yet
|
||||||
views/projects/item/wavetapper
|
views/projects/item/wavetapper
|
||||||
|
views/projects/item/dice_2
|
||||||
|
views/projects/item/text
|
14
embeds/attr.html
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<p id="attr">
|
||||||
|
Image attribution:
|
||||||
|
<a href="https://exok.com/games/celeste/" target="_blank">Celeste</a>
|
||||||
|
</p>
|
||||||
|
<style>
|
||||||
|
#attr {
|
||||||
|
display: inline-block;
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
color: white !important;
|
||||||
|
text-shadow: 0 0.1em 0.5em black;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -19,7 +19,7 @@
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<h1>Loading...</h1>
|
<h1>Loading...</h1>
|
||||||
<h2>Please wait.</h2>
|
<p>Please wait.</p>
|
||||||
<p>If this page does not load, try enabling JavaScript.</p>
|
<p>If this page does not load, try enabling JavaScript.</p>
|
||||||
<small>(This site won't work well without it.)</small>
|
<small>(This site won't work well without it.)</small>
|
||||||
<p>Or <a href="/">go back home</a>.</p>
|
<p>Or <a href="/">go back home</a>.</p>
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
<section class="nav" role="navigation" aria-label="Site navigation">
|
<section class="nav" role="navigation" aria-label="Site navigation">
|
||||||
<p>
|
<p>
|
||||||
<a href="/">Home</a> <a href="/branding/">Branding</a>
|
<a href="/">Home</a>
|
||||||
<a href="/site/">Site Information</a>
|
<a href="https://blog.abtmtr.link/mtr/quick-q-and-a">FAQ</a>
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a href="/projects/">Projects</a>
|
<a href="/projects/">Projects</a>
|
||||||
<a href="/domain/">Domain</a>
|
|
||||||
<a href="/links/">Links</a>
|
<a href="/links/">Links</a>
|
||||||
|
<!-- <a href="/whois/">Who are we?</a> -->
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
BIN
views/assets/88x31/acidicalchemist_neocities_org.gif
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
views/assets/88x31/arimelody_me.gif
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
views/assets/88x31/esoteric/gnu-linux.gif
Normal file
After Width: | Height: | Size: 550 B |
BIN
views/assets/88x31/esoteric/html.gif
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
views/assets/88x31/esoteric/ublock.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
views/assets/88x31/esoteric/vivaldi.gif
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
views/assets/88x31/esoteric/xkcd.gif
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
views/assets/88x31/freeplay_floof_company.png
Normal file
After Width: | Height: | Size: 3 KiB |
BIN
views/assets/88x31/invoxiplaygames_uk.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
views/assets/88x31/ioletsgo_gay.gif
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
views/assets/88x31/jaiden_sh.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
views/assets/88x31/mae_wtf.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
views/assets/88x31/micro_pages_gay.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
views/assets/88x31/moth_monster.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
views/assets/88x31/owenzimmerman_com.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
views/assets/88x31/sneexy_pages_gay.gif
Normal file
After Width: | Height: | Size: 690 B |
BIN
views/assets/88x31/translunar_academy.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
views/assets/88x31/whois_slipfox_xyz.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
views/assets/bg.jpg
Normal file
After Width: | Height: | Size: 260 KiB |
|
@ -1,127 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<title>Branding - abtmtr.link</title>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<link rel="stylesheet" href="/styles/normal.css" />
|
|
||||||
<link rel="stylesheet" href="/styles/style.css" />
|
|
||||||
<style>
|
|
||||||
:root {
|
|
||||||
--base-color: 0, 0%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chip {
|
|
||||||
background-color: var(--mainColor);
|
|
||||||
display: inline-block;
|
|
||||||
width: 12em;
|
|
||||||
aspect-ratio: 1/1;
|
|
||||||
padding: 1em;
|
|
||||||
vertical-align: top;
|
|
||||||
margin: 0.5em;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<header>
|
|
||||||
<section>
|
|
||||||
<h1>Branding</h1>
|
|
||||||
</section>
|
|
||||||
<$ nav.html $>
|
|
||||||
<section id="accessibility" hidden></section>
|
|
||||||
</header>
|
|
||||||
<main>
|
|
||||||
<section>
|
|
||||||
<p>
|
|
||||||
I don't really have strict branding guidelines, but I do have a few
|
|
||||||
important rules if you would like to refer to me in a professional or
|
|
||||||
formal context.
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>Name</h2>
|
|
||||||
<p>
|
|
||||||
If you would like to refer to me online, you'll usually be able to use
|
|
||||||
my username <b>MeowcaTheoRange</b>. If that's too long, you can always
|
|
||||||
shorten it to <strong>MTR</strong>.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Please make sure to keep the styling. It's <b>MeowcaTheoRange</b>, not<!-- -->
|
|
||||||
<strong>MeowcatHeOrange</strong>, <strong>MeowcaTheOrange</strong>,
|
|
||||||
nor <strong>Meowca Theo Range</strong>.
|
|
||||||
</p>
|
|
||||||
<p class="hv">
|
|
||||||
The styling <strong>meowcatheorange</strong> is OK if necessary.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
If you would like to refer to me in a more professional context,
|
|
||||||
<a href="https://pronouns.cc/@MeowcaTheoRange" target="_blank"
|
|
||||||
>check my pronouns.cc page for my preferred names.</a
|
|
||||||
>
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
<section id="characters" style="display: none">
|
|
||||||
<h2>Characters</h2>
|
|
||||||
<p>
|
|
||||||
If you would like to use a character to represent me, I'd prefer you
|
|
||||||
use <b class="characterName"></b>
|
|
||||||
<small>(<span class="pronouns"></span>)</small>.
|
|
||||||
</p>
|
|
||||||
<img class="characterImage" />
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h2>Colors</h2>
|
|
||||||
<h3>Main Colors</h3>
|
|
||||||
<p>
|
|
||||||
If you would like to use colors to refer to me, whether that be the
|
|
||||||
primary color on a card, or the color of my name, I recommend you use
|
|
||||||
these colors:
|
|
||||||
</p>
|
|
||||||
<div style="--mainColor: #00c0ff; color: #000000" class="chip">
|
|
||||||
<b>Iszac Blue</b><br /><small>Primary</small>
|
|
||||||
<p>#00c0ff</p>
|
|
||||||
</div>
|
|
||||||
<div style="--mainColor: #ff4000; color: #000000" class="chip">
|
|
||||||
<b>Rocco Orange</b><br /><small>Primary Negative</small>
|
|
||||||
<p>#ff4000</p>
|
|
||||||
</div>
|
|
||||||
<p>
|
|
||||||
<b>Iszac Blue</b> is literally <strong>Rocco Orange</strong> but
|
|
||||||
inverted. This color is named after <strong>Iszac</strong>.<br />If
|
|
||||||
you were to use any of these colors to represnt me as a
|
|
||||||
<strong>person</strong>, use this one.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<b>Rocco Orange</b> is my favourite color orange, but now more red.
|
|
||||||
The name comes from my character <strong>Rocco</strong>.<br />If you
|
|
||||||
were to use any of these colors to represnt me as an
|
|
||||||
<strong>entity</strong>, use this one whenever possible.
|
|
||||||
</p>
|
|
||||||
<h3>Sub Colors</h3>
|
|
||||||
<p>
|
|
||||||
If you need filler colors for something that refers to me, feel free
|
|
||||||
to use these extra colors:
|
|
||||||
</p>
|
|
||||||
<div style="--mainColor: #8000ff; color: #000000" class="chip">
|
|
||||||
<b>Grape Soda</b><br /><small>Secondary</small>
|
|
||||||
<p>#8000ff</p>
|
|
||||||
</div>
|
|
||||||
<div style="--mainColor: #80ff00; color: #000000" class="chip">
|
|
||||||
<b>Avalonian Waste</b><br /><small>Secondary Negative</small>
|
|
||||||
<p>#80ff00</p>
|
|
||||||
</div>
|
|
||||||
<p>
|
|
||||||
<b>Grape Soda</b> represents my love for grape soda.<br />My favourite
|
|
||||||
is Fanta Grape. :]
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<b>Avalonian Waste</b> is also literally
|
|
||||||
<strong>Grape Soda</strong> but inverted. This represents some old
|
|
||||||
lore that I'm still screwing with.
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
</main>
|
|
||||||
<section id="accessibility" hidden></section>
|
|
||||||
<script src="/scripts/accessibility.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,22 +0,0 @@
|
||||||
const characters = document.getElementById("characters");
|
|
||||||
|
|
||||||
const CURRENT_CHARACTER = "meowcatheorange/iszac";
|
|
||||||
|
|
||||||
fetch(`https://beta.trollcall.xyz/api/troll/${CURRENT_CHARACTER}`)
|
|
||||||
.then((x) => x.json())
|
|
||||||
.then((char) => {
|
|
||||||
var name = char.name
|
|
||||||
.map((string) => {
|
|
||||||
string = string[0].toUpperCase() + string.slice(1);
|
|
||||||
return string;
|
|
||||||
})
|
|
||||||
.join(" ");
|
|
||||||
characters.querySelector(
|
|
||||||
".characterName"
|
|
||||||
).innerHTML = `<a href="https://beta.trollcall.xyz/troll/${CURRENT_CHARACTER}" target="_blank">${name}</a>`;
|
|
||||||
characters.querySelector(".characterImage").src = char.images[0];
|
|
||||||
characters.querySelector(".pronouns").innerHTML = char.pronouns
|
|
||||||
.map((pronoun) => pronoun[0])
|
|
||||||
.join("/");
|
|
||||||
characters.style.display = null;
|
|
||||||
});
|
|
|
@ -1,14 +0,0 @@
|
||||||
const data_get = document.getElementById("data_get");
|
|
||||||
fetch("https://blog.abtmtr.link/api/collections/paste/posts/domain")
|
|
||||||
.then((x) => x.json())
|
|
||||||
.then((paste) => {
|
|
||||||
const data = JSON.parse(paste.data.body);
|
|
||||||
data_get.innerHTML = data.reduce(
|
|
||||||
(html, subdomain) =>
|
|
||||||
html +
|
|
||||||
`<h1><a href="${subdomain.url}" target="_blank">${subdomain.name}</a></h1>
|
|
||||||
${subdomain.description.map((x) => `<p>${x}</p>`).join("")}
|
|
||||||
<img src="${subdomain.src}" alt="${subdomain.name}" title="${subdomain.name}" />`,
|
|
||||||
""
|
|
||||||
);
|
|
||||||
});
|
|
Before Width: | Height: | Size: 22 KiB |
118
views/index.html
|
@ -7,62 +7,96 @@
|
||||||
<link rel="stylesheet" href="/styles/normal.css" />
|
<link rel="stylesheet" href="/styles/normal.css" />
|
||||||
<link rel="stylesheet" href="/styles/windows.css" />
|
<link rel="stylesheet" href="/styles/windows.css" />
|
||||||
<link rel="stylesheet" href="/styles/style.css" />
|
<link rel="stylesheet" href="/styles/style.css" />
|
||||||
|
<link rel="stylesheet" href="./styles/buttonroll.css" />
|
||||||
<style>
|
<style>
|
||||||
:root {
|
.header {
|
||||||
--base-color: 195, 100%;
|
width: 100%;
|
||||||
|
aspect-ratio: 3 / 1;
|
||||||
|
background: url("/assets/bg.jpg");
|
||||||
|
background-position: center;
|
||||||
|
background-size: cover;
|
||||||
|
background-attachment: fixed;
|
||||||
|
text-align: center;
|
||||||
|
color: white;
|
||||||
|
text-shadow: 0 0.1em 0.5em black;
|
||||||
|
box-shadow: inset 0 0 1em var(--accent-color);
|
||||||
|
font-size: 1.5em;
|
||||||
|
border-radius: 2rem;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
margin: 0.5em 0;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
.header h1 {
|
||||||
|
line-height: 1em;
|
||||||
|
margin-bottom: 0.35em;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.horizontal {
|
||||||
|
display: grid;
|
||||||
|
grid-auto-flow: column;
|
||||||
|
gap: 1em;
|
||||||
|
}
|
||||||
|
@keyframes wave {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
20% {
|
||||||
|
transform: rotate(-15deg);
|
||||||
|
}
|
||||||
|
40% {
|
||||||
|
transform: rotate(15deg);
|
||||||
|
}
|
||||||
|
60% {
|
||||||
|
transform: rotate(-15deg);
|
||||||
|
}
|
||||||
|
80% {
|
||||||
|
transform: rotate(15deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.waving {
|
||||||
|
transform-origin: 60% 60%;
|
||||||
|
cursor: none;
|
||||||
|
}
|
||||||
|
.waving:hover {
|
||||||
|
animation: infinite wave 0.5s;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<section>
|
<h1><small><small>welcome to</small></small> ABTMTR.LINK</h1>
|
||||||
<h1>ABTMTR.LINK</h1>
|
|
||||||
</section>
|
|
||||||
<$ nav.html $>
|
<$ nav.html $>
|
||||||
<section id="accessibility" hidden></section>
|
<section id="accessibility" hidden></section>
|
||||||
|
<div id="buttonroll" hidden></div>
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main>
|
||||||
<section>
|
<section>
|
||||||
<h2>Welcome! 👋</h2>
|
<h1>
|
||||||
<section id="data_whoami">
|
Hey!
|
||||||
<p>
|
<span class="rs waving">👋</span>
|
||||||
I'm...
|
</h1>
|
||||||
<small
|
<p>Welcome to abtmtr.link.</p>
|
||||||
><a href="https://pronouns.cc/@MeowcaTheoRange" target="_blank"
|
<p>abtmtr.link is a domain for a suite of services, ranging from <b>micro-blogging</b> to <b>web search</b>.</p>
|
||||||
>not loading</a
|
<p>This site was once a little less personal. That should be over for now.</p>
|
||||||
>.</small
|
<p>Check out our <a href="/projects/">projects</a>!</p>
|
||||||
>
|
|
||||||
</p>
|
|
||||||
</section>
|
</section>
|
||||||
<p>
|
<section id="data_get">
|
||||||
I'm a web developer, Fediverse enthusiast, and compulsory Minnesotan.
|
<h1>Getting domain indexes...</h1>
|
||||||
</p>
|
|
||||||
<p>I run this domain and all of the services on it!</p>
|
|
||||||
<p id="no-fetchy" style="display: none">
|
|
||||||
For me, it is <b id="time">12:00 PM</b> on a
|
|
||||||
<b id="weekday">Sunday</b>. <b id="timezone">(UTC-0)</b><br />
|
|
||||||
<small
|
|
||||||
>data locally fetched from
|
|
||||||
<a href="https://pronouns.cc/@MeowcaTheoRange" target="_blank"
|
|
||||||
>pronouns.cc</a
|
|
||||||
></small
|
|
||||||
>
|
|
||||||
</p>
|
|
||||||
</section>
|
</section>
|
||||||
<section id="status"></section>
|
|
||||||
<section id="about"></section>
|
|
||||||
<button id="buttonflags" disabled>Cool Flags</button>
|
|
||||||
<section id="fields"></section>
|
|
||||||
</main>
|
</main>
|
||||||
<div id="WindowHolder"></div>
|
|
||||||
<script src="/scripts/windows.js"></script>
|
|
||||||
<script src="/scripts/accessibility.js"></script>
|
<script src="/scripts/accessibility.js"></script>
|
||||||
<script src="./scripts/data_get_whoami.js"></script>
|
<script src="./scripts/roll_buttons.js"></script>
|
||||||
<script src="/projects/item/hex/scripts/index.js"></script>
|
<script src="./scripts/data_get_domain.js"></script>
|
||||||
<script>
|
|
||||||
window.manager = new WindowManager(
|
|
||||||
document.getElementById("WindowHolder")
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -6,18 +6,14 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<link rel="stylesheet" href="/styles/normal.css" />
|
<link rel="stylesheet" href="/styles/normal.css" />
|
||||||
<link rel="stylesheet" href="/styles/style.css" />
|
<link rel="stylesheet" href="/styles/style.css" />
|
||||||
<style>
|
<style></style>
|
||||||
:root {
|
|
||||||
--base-color: 270, 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<$ loader.html $>
|
<$ loader.html $>
|
||||||
<header>
|
<header>
|
||||||
<section>
|
<section>
|
||||||
<h1>Links</h1>
|
<h1>Links</h1>
|
||||||
<p>Where else you can find me.</p>
|
<p>Where else you can find traces of abtmtr.link.</p>
|
||||||
</section>
|
</section>
|
||||||
<$ nav.html $>
|
<$ nav.html $>
|
||||||
<section id="accessibility" hidden></section>
|
<section id="accessibility" hidden></section>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const data_get = document.getElementById("data_get");
|
const data_get = document.getElementById("data_get");
|
||||||
fetch("https://pronouns.cc/api/v1/users/MeowcaTheoRange")
|
fetch_ask("https://pronouns.cc/api/v1/users/clhd8desmggedm3q1t3g")
|
||||||
.then((x) => x.json())
|
.then((x) => x.json())
|
||||||
.then((user) => {
|
.then((user) => {
|
||||||
data_get.innerHTML = user.links.reduce(
|
data_get.innerHTML = user.links.reduce(
|
||||||
|
|
|
@ -7,18 +7,14 @@
|
||||||
<link rel="stylesheet" href="/styles/normal.css" />
|
<link rel="stylesheet" href="/styles/normal.css" />
|
||||||
<link rel="stylesheet" href="/styles/windows.css" />
|
<link rel="stylesheet" href="/styles/windows.css" />
|
||||||
<link rel="stylesheet" href="/styles/style.css" />
|
<link rel="stylesheet" href="/styles/style.css" />
|
||||||
<style>
|
<style></style>
|
||||||
:root {
|
|
||||||
--base-color: 15, 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<$ loader.html $>
|
<$ loader.html $>
|
||||||
<header>
|
<header>
|
||||||
<section>
|
<section>
|
||||||
<h1>Projects</h1>
|
<h1>Projects</h1>
|
||||||
<p>Various projects I've made.</p>
|
<p>Various projects.</p>
|
||||||
</section>
|
</section>
|
||||||
<$ nav.html $>
|
<$ nav.html $>
|
||||||
<section id="accessibility" hidden></section>
|
<section id="accessibility" hidden></section>
|
||||||
|
|
|
@ -8,14 +8,16 @@ function reqData(start) {
|
||||||
if (resp != prevSha) {
|
if (resp != prevSha) {
|
||||||
window.sessionStorage.setItem("commitsha", resp);
|
window.sessionStorage.setItem("commitsha", resp);
|
||||||
if (start) return;
|
if (start) return;
|
||||||
document.querySelector("#updatesha").innerHTML = `from job v. ${prevSha} to job v. ${resp}`;
|
document.querySelector(
|
||||||
|
"#updatesha"
|
||||||
|
).innerHTML = `from job v. ${prevSha} to job v. ${resp}`;
|
||||||
document.querySelector("#updatedialog").classList.add("open");
|
document.querySelector("#updatedialog").classList.add("open");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fetch("https://ClockCheckGithub.meowcatheorange.repl.co")
|
fetch_ask("https://ClockCheckGithub.meowcatheorange.repl.co")
|
||||||
.then(x => x.text())
|
.then((x) => x.text())
|
||||||
.then(y => donedata(y));
|
.then((y) => donedata(y));
|
||||||
}
|
}
|
||||||
|
|
||||||
setInterval(reqData, 60000);
|
setInterval(reqData, 60000);
|
||||||
|
|
175
views/projects/item/fediverse-madness/index.html
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>Fediverse Madness - abtmtr.link</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<link rel="stylesheet" href="/styles/normal.css" />
|
||||||
|
<link rel="stylesheet" href="/styles/myapp.css" />
|
||||||
|
<link rel="stylesheet" href="./style.css" />
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--base-color: 60, 40%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<section>
|
||||||
|
<h1>Fediverse Madness</h1>
|
||||||
|
<p>Competitive bracket-based comparisons of Fediverse users.</p>
|
||||||
|
<p>Requires JavaScript.</p>
|
||||||
|
</section>
|
||||||
|
<section id="accessibility" hidden></section>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<section id="whoami" hidden>
|
||||||
|
<h3>Who are you?</h3>
|
||||||
|
<span class="userinputbox">
|
||||||
|
<span>@</span>
|
||||||
|
<input type="text" name="user" id="user" class="userinstance" />
|
||||||
|
<span>@</span>
|
||||||
|
<input type="text" name="instance" id="instance" class="userinstance" />
|
||||||
|
</span>
|
||||||
|
<br />
|
||||||
|
<hr />
|
||||||
|
<button id="submitwhoami_followers">Play (Followers)</button>
|
||||||
|
<button id="submitwhoami_following">Play (Following)</button>
|
||||||
|
<button id="submitwhoami_manual">Play (Manual)</button>
|
||||||
|
<p id="errorwhoami"></p>
|
||||||
|
</section>
|
||||||
|
<section id="followers" hidden>
|
||||||
|
<h3>Followers list</h3>
|
||||||
|
<p id="loadingfollowers">Retrieving followers... Please wait.</p>
|
||||||
|
<table id="listfollowers" hidden>
|
||||||
|
<tr id="listfollowersvalues">
|
||||||
|
<th>S.</th>
|
||||||
|
<th>Av.</th>
|
||||||
|
<th>User</th>
|
||||||
|
<th>Handle</th>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<div>
|
||||||
|
<button id="selectallfollowers">Select all</button>
|
||||||
|
<button id="selectnofollowers">Select none</button>
|
||||||
|
<button id="selectrandomfollowers">Select random</button>
|
||||||
|
<button id="deselectrandomfollowers">Deselect random</button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button id="morefollowers">Load more</button>
|
||||||
|
<button id="savehandlesfollowers">Save selection</button>
|
||||||
|
<button id="loadhandlesfollowers">Load selection</button>
|
||||||
|
</div>
|
||||||
|
<button id="submitfollowers" disabled>Done</button>
|
||||||
|
</section>
|
||||||
|
<section id="following" hidden>
|
||||||
|
<h3>Following list</h3>
|
||||||
|
<p id="loadingfollowing">Retrieving following... Please wait.</p>
|
||||||
|
<table id="listfollowing" hidden>
|
||||||
|
<tr id="listfollowingvalues">
|
||||||
|
<th>S.</th>
|
||||||
|
<th>Av.</th>
|
||||||
|
<th>User</th>
|
||||||
|
<th>Handle</th>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<div>
|
||||||
|
<button id="selectallfollowing">Select all</button>
|
||||||
|
<button id="selectnofollowing">Select none</button>
|
||||||
|
<button id="selectrandomfollowing">Select random</button>
|
||||||
|
<button id="deselectrandomfollowing">Deselect random</button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button id="morefollowing">Load more</button>
|
||||||
|
<button id="savehandlesfollowing">Save selection</button>
|
||||||
|
<button id="loadhandlesfollowing">Load selection</button>
|
||||||
|
</div>
|
||||||
|
<button id="submitfollowing" disabled>Done</button>
|
||||||
|
</section>
|
||||||
|
<section id="manual" hidden>
|
||||||
|
<h3>Manual list</h3>
|
||||||
|
<p id="loadingmanual"></p>
|
||||||
|
<table id="listmanual" hidden>
|
||||||
|
<tr id="listmanualvalues">
|
||||||
|
<th>S.</th>
|
||||||
|
<th>Av.</th>
|
||||||
|
<th>User</th>
|
||||||
|
<th>Handle</th>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<div>
|
||||||
|
<button id="selectallmanual">Select all</button>
|
||||||
|
<button id="selectnomanual">Select none</button>
|
||||||
|
<button id="selectrandommanual">Select random</button>
|
||||||
|
<button id="deselectrandommanual">Deselect random</button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span class="userinputbox">
|
||||||
|
<span>@</span>
|
||||||
|
<input type="text" name="user" id="manualuser" class="userinstance" />
|
||||||
|
<span>@</span>
|
||||||
|
<input type="text" name="instance" id="manualinstance" class="userinstance" />
|
||||||
|
</span>
|
||||||
|
<button id="moremanual">Fetch</button>
|
||||||
|
</div>
|
||||||
|
<button id="submitmanual" disabled>Done</button>
|
||||||
|
</section>
|
||||||
|
<section id="game" hidden>
|
||||||
|
<h3>Fight!</h3>
|
||||||
|
<p id="gameBracketLevel">Bracket Level ...</p>
|
||||||
|
<p id="gameBracketFight">Round ...</p>
|
||||||
|
<div class="gridUsersVert">
|
||||||
|
<div class="gridUser" id="gameUserOne">
|
||||||
|
<img src="" id="gameUserOneImage" width="128" height="128" />
|
||||||
|
<div>
|
||||||
|
<h3 id="gameUserOneName"></h3>
|
||||||
|
<p id="gameUserOneId"></p>
|
||||||
|
<!-- <p id="gameUserOneNote"></p>
|
||||||
|
<table id="gameUserOneFields">
|
||||||
|
</table> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="gridUser" id="gameUserTwo">
|
||||||
|
<img src="" id="gameUserTwoImage" width="128" height="128" />
|
||||||
|
<div>
|
||||||
|
<h3 id="gameUserTwoName"></h3>
|
||||||
|
<p id="gameUserTwoId"></p>
|
||||||
|
<!-- <p id="gameUserTwoNote"></p>
|
||||||
|
<table id="gameUserTwoFields">
|
||||||
|
</table> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<button id="gameSubmitLeft" disabled>Please wait...</button>
|
||||||
|
<button id="gameSubmitRight" disabled>Please wait...</button>
|
||||||
|
</section>
|
||||||
|
<section id="winner" hidden>
|
||||||
|
<h3>Winner</h3>
|
||||||
|
<p id="winnermessage">Congratulations, ...</p>
|
||||||
|
<div class="gridUser" id="winnerUser">
|
||||||
|
<img src="" id="winnerUserImage" width="128" height="128" />
|
||||||
|
<div>
|
||||||
|
<h3 id="winnerUserName"></h3>
|
||||||
|
<p id="winnerUserId"></p>
|
||||||
|
<!-- <p id="winnerUserNote"></p>
|
||||||
|
<table id="winnerUserFields">
|
||||||
|
</table> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h3>Bracket</h3>
|
||||||
|
<div class="flexUsersVert" id="winnerusers">
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<button id="winnerPlayAgain">Play Again</button>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
<section id="accessibility" hidden></section>
|
||||||
|
<script src="/scripts/accessibility.js"></script>
|
||||||
|
<script>
|
||||||
|
let game = null;
|
||||||
|
</script>
|
||||||
|
<script src="./script.js"></script>
|
||||||
|
<script src="./scripts/game.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
0
views/projects/item/fediverse-madness/script.js
Normal file
735
views/projects/item/fediverse-madness/scripts/game.js
Normal file
|
@ -0,0 +1,735 @@
|
||||||
|
function escapeHtml(unsafe)
|
||||||
|
{
|
||||||
|
return unsafe
|
||||||
|
.replace(/<\/?script\/?>/g, "")
|
||||||
|
.replace(/<\/?img\/?>/g, "")
|
||||||
|
.replace(/<\/?iframe\/?>/g, "")
|
||||||
|
.replace(/<\/?xml\/?>/g, "")
|
||||||
|
.replace(/<\/?audio\/?>/g, "")
|
||||||
|
.replace(/<\/?video\/?>/g, "")
|
||||||
|
.replace(/<\/?object\/?>/g, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
const n=x=>null;
|
||||||
|
|
||||||
|
const el_id_user = document.querySelector("#user");
|
||||||
|
const el_id_instance = document.querySelector("#instance");
|
||||||
|
const el_id_whoami = document.querySelector("#whoami");
|
||||||
|
const el_id_submitwhoamiFollowers = document.querySelector("#submitwhoami_followers");
|
||||||
|
const el_id_submitwhoamiFollowing = document.querySelector("#submitwhoami_following");
|
||||||
|
const el_id_submitwhoamiManual = document.querySelector("#submitwhoami_manual");
|
||||||
|
const el_id_errorwhoami = document.querySelector("#errorwhoami");
|
||||||
|
let gamemodeFollowers = "";
|
||||||
|
|
||||||
|
el_id_user.addEventListener("input", (e) => {
|
||||||
|
console.log(e);
|
||||||
|
// User types @ Chrome autofill
|
||||||
|
if (e.data === "@" || e.data === undefined) {
|
||||||
|
el_id_user.value =
|
||||||
|
el_id_user.value.replace(/@/gim, "");
|
||||||
|
el_id_instance.focus();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
async function verify() {
|
||||||
|
const username = el_id_user.value.replace(/[^a-z0-9_]/gim, "");
|
||||||
|
const instance = el_id_instance.value.replace(/@/gim, "");
|
||||||
|
el_id_user.value = username;
|
||||||
|
el_id_instance.value = instance;
|
||||||
|
if (username.length < 1) return null;
|
||||||
|
if (instance.length < 1) return null;
|
||||||
|
|
||||||
|
// webfinger domain delegation
|
||||||
|
const domain = await fetch(`https://${instance}/.well-known/webfinger?resource=acct:${username}@${instance}`).catch(n);
|
||||||
|
if (domain == null || !domain.ok) return null;
|
||||||
|
const domain_json = (await domain.json());
|
||||||
|
const domain_url = new URL(domain_json.links.find(x=>x.type=="application/activity+json").href).hostname;
|
||||||
|
|
||||||
|
const user_req = await fetch(`https://${domain_url}/api/v1/accounts/lookup?acct=${username}`).catch(n);
|
||||||
|
if (user_req == null || !domain.ok) return null;
|
||||||
|
const user_json = await user_req.json();
|
||||||
|
|
||||||
|
window.localStorage.setItem("fediversemadness_game", JSON.stringify({ username, instance }));
|
||||||
|
|
||||||
|
return {
|
||||||
|
USER_ID: user_json.id,
|
||||||
|
INSTANCE: domain_url
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function lookupUser() {
|
||||||
|
const lsGame = JSON.parse(window.localStorage.getItem("fediversemadness_game"));
|
||||||
|
if (lsGame != null) {
|
||||||
|
el_id_user.value = lsGame.username;
|
||||||
|
el_id_instance.value = lsGame.instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lookupUser();
|
||||||
|
|
||||||
|
async function doVerif() {
|
||||||
|
el_id_submitwhoamiFollowers.disabled = true;
|
||||||
|
el_id_submitwhoamiFollowing.disabled = true;
|
||||||
|
el_id_submitwhoamiManual.disabled = true;
|
||||||
|
game = await verify();
|
||||||
|
el_id_submitwhoamiFollowers.disabled = false;
|
||||||
|
el_id_submitwhoamiFollowing.disabled = false;
|
||||||
|
el_id_submitwhoamiManual.disabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
el_id_submitwhoamiFollowers.addEventListener("click", async (e) => {
|
||||||
|
el_id_errorwhoami.innerHTML = "";
|
||||||
|
await doVerif();
|
||||||
|
if (game == null) {
|
||||||
|
el_id_errorwhoami.innerHTML = "Invalid user!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
gamemodeFollowers = "followers";
|
||||||
|
startFollowers();
|
||||||
|
})
|
||||||
|
|
||||||
|
el_id_submitwhoamiFollowing.addEventListener("click", async (e) => {
|
||||||
|
el_id_errorwhoami.innerHTML = "";
|
||||||
|
await doVerif();
|
||||||
|
if (game == null) {
|
||||||
|
el_id_errorwhoami.innerHTML = "Invalid user!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
gamemodeFollowers = "following";
|
||||||
|
startFollowing();
|
||||||
|
})
|
||||||
|
|
||||||
|
el_id_submitwhoamiManual.addEventListener("click", async (e) => {
|
||||||
|
el_id_errorwhoami.innerHTML = "";
|
||||||
|
await doVerif();
|
||||||
|
if (game == null) {
|
||||||
|
el_id_errorwhoami.innerHTML = "Invalid user!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
gamemodeFollowers = "manual";
|
||||||
|
startManual();
|
||||||
|
})
|
||||||
|
|
||||||
|
// Followers
|
||||||
|
|
||||||
|
const el_id_followers = document.querySelector("#followers");
|
||||||
|
const el_id_loadingfollowers = document.querySelector("#loadingfollowers");
|
||||||
|
const el_id_listfollowers = document.querySelector("#listfollowers");
|
||||||
|
const el_id_listfollowersvalues = document.querySelector("#listfollowersvalues");
|
||||||
|
const el_id_selectallfollowers = document.querySelector("#selectallfollowers");
|
||||||
|
const el_id_selectrandomfollowers = document.querySelector("#selectrandomfollowers");
|
||||||
|
const el_id_deselectrandomfollowers = document.querySelector("#deselectrandomfollowers");
|
||||||
|
const el_id_selectnofollowers = document.querySelector("#selectnofollowers");
|
||||||
|
const el_id_morefollowers = document.querySelector("#morefollowers");
|
||||||
|
const el_id_submitfollowers = document.querySelector("#submitfollowers");
|
||||||
|
const el_id_savehandlesfollowers = document.querySelector("#savehandlesfollowers");
|
||||||
|
const el_id_loadhandlesfollowers = document.querySelector("#loadhandlesfollowers");
|
||||||
|
let selectboxes = [];
|
||||||
|
let userList = [];
|
||||||
|
let lastId = "";
|
||||||
|
let selectedUsers = [];
|
||||||
|
|
||||||
|
function generateFollowersMap() {
|
||||||
|
const checks = Array.from(el_id_listfollowers.querySelectorAll(".follower_checkbox"));
|
||||||
|
let codeMap = {};
|
||||||
|
checks.forEach((checkbox) => {
|
||||||
|
const handle = checkbox.parentElement.parentElement.querySelector(".follower_checkname");
|
||||||
|
codeMap[handle.innerHTML] = checkbox.checked;
|
||||||
|
});
|
||||||
|
return codeMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readFollowersMap(m) {
|
||||||
|
if (m == null) return;
|
||||||
|
const handles = Array.from(el_id_listfollowers.querySelectorAll(".follower_checkname"));
|
||||||
|
handles.forEach((handle) => {
|
||||||
|
const checkbox = handle.parentElement.querySelector(".follower_checkbox");
|
||||||
|
if (m[handle.innerHTML] != null)
|
||||||
|
checkbox.checked = m[handle.innerHTML];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderNameHTML(name, user) {
|
||||||
|
return `<span>${escapeHtml(name).replace(/:([a-z0-9_-]+?):/gim, (m, p1) => {
|
||||||
|
const emoji = user.emojis.find(x => x.shortcode == p1);
|
||||||
|
if (emoji == null) return null;
|
||||||
|
return `<img src="${emoji.url}" width="16" height="16" title=":${emoji.shortcode}:" />`;
|
||||||
|
})}</span>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function startFollowers(reload = true) {
|
||||||
|
goToState("followers");
|
||||||
|
if (reload) {
|
||||||
|
selectboxes = [];
|
||||||
|
userList = [];
|
||||||
|
lastId = "";
|
||||||
|
selectedUsers = [];
|
||||||
|
el_id_listfollowers.innerHTML = "";
|
||||||
|
}
|
||||||
|
getFollowers(!reload);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getFollowers(dontLoadNew = false) {
|
||||||
|
el_id_submitfollowers.disabled = true;
|
||||||
|
el_id_morefollowers.disabled = true;
|
||||||
|
let res;
|
||||||
|
let out;
|
||||||
|
if (!dontLoadNew) {
|
||||||
|
el_id_loadingfollowers.innerHTML = `Retrieving followers... Please wait.`;
|
||||||
|
res = await fetch(`https://${game.INSTANCE}/api/v1/accounts/${game.USER_ID}/followers${lastId.length > 0 ? `?max_id=${lastId}` : ""}`);
|
||||||
|
out = await res.json();
|
||||||
|
}
|
||||||
|
el_id_submitfollowers.disabled = false;
|
||||||
|
el_id_morefollowers.disabled = false;
|
||||||
|
if (dontLoadNew) return false;
|
||||||
|
if (out.length < 1) {
|
||||||
|
el_id_loadingfollowers.innerHTML = `No followers found.`;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
el_id_listfollowers.hidden = false;
|
||||||
|
out.forEach((cuser) => {
|
||||||
|
const element = document.createElement("tr");
|
||||||
|
element.innerHTML = `<td><input type="checkbox" class="follower_checkbox" checked onchange="checkSelectedAmtFollowers()" /></td>
|
||||||
|
<td><img src="${cuser.avatar}" width="32" height="32" /></td>
|
||||||
|
<td class="follower_namelabel">
|
||||||
|
<a href="${cuser.url}" target="_blank">
|
||||||
|
${renderNameHTML(cuser.display_name, cuser)}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td class="follower_namelabel follower_checkname">@${cuser.fqn}</td>`;
|
||||||
|
el_id_listfollowers.appendChild(element);
|
||||||
|
});
|
||||||
|
userList.push(...out.map(user => ({
|
||||||
|
fqn: user.fqn || user.acct,
|
||||||
|
avatar: user.avatar,
|
||||||
|
bot: user.bot,
|
||||||
|
created_at: user.created_at,
|
||||||
|
display_name: user.display_name,
|
||||||
|
emojis: user.emojis,
|
||||||
|
fields: user.fields,
|
||||||
|
id: user.id,
|
||||||
|
note: user.note,
|
||||||
|
url: user.url
|
||||||
|
})));
|
||||||
|
lastId = userList.at(-1).id;
|
||||||
|
selectboxes = Array.from(el_id_listfollowers.querySelectorAll(".follower_checkbox"));
|
||||||
|
checkSelectedAmtFollowers();
|
||||||
|
}
|
||||||
|
|
||||||
|
el_id_selectallfollowers.addEventListener("click", () => {
|
||||||
|
selectboxes.forEach(x => x.checked = true);
|
||||||
|
checkSelectedAmtFollowers();
|
||||||
|
})
|
||||||
|
|
||||||
|
el_id_selectrandomfollowers.addEventListener("click", () => {
|
||||||
|
const unselectedPick = selectboxes.filter(x => !x.checked);
|
||||||
|
const selected = unselectedPick[Math.floor(Math.random() * (unselectedPick.length - 1))];
|
||||||
|
if (selected == null) return;
|
||||||
|
selected.checked = true;
|
||||||
|
checkSelectedAmtFollowers();
|
||||||
|
})
|
||||||
|
|
||||||
|
el_id_deselectrandomfollowers.addEventListener("click", () => {
|
||||||
|
const selectedPick = selectboxes.filter(x => x.checked);
|
||||||
|
const selected = selectedPick[Math.floor(Math.random() * (selectedPick.length - 1))];
|
||||||
|
if (selected == null) return;
|
||||||
|
selected.checked = false;
|
||||||
|
checkSelectedAmtFollowers();
|
||||||
|
})
|
||||||
|
|
||||||
|
el_id_selectnofollowers.addEventListener("click", () => {
|
||||||
|
selectboxes.forEach(x => x.checked = false);
|
||||||
|
checkSelectedAmtFollowers();
|
||||||
|
})
|
||||||
|
|
||||||
|
el_id_savehandlesfollowers.addEventListener("click", () => window.localStorage.setItem("fediversemadness_followerssel", JSON.stringify(generateFollowersMap())));
|
||||||
|
el_id_loadhandlesfollowers.addEventListener("click", () => readFollowersMap(JSON.parse(window.localStorage.getItem("fediversemadness_followerssel"))));
|
||||||
|
|
||||||
|
el_id_morefollowers.addEventListener("click", () => getFollowers());
|
||||||
|
|
||||||
|
el_id_submitfollowers.addEventListener("click", () => {
|
||||||
|
selectedUsers = [];
|
||||||
|
selectboxes.forEach(({checked}, i) => {
|
||||||
|
if (checked) selectedUsers.push(userList.at(i));
|
||||||
|
});
|
||||||
|
if (selectedUsers.length < 2) {
|
||||||
|
el_id_loadingfollowers.innerHTML = `Selected user count is less than 2! (${selectboxes.filter(x => x.checked).length} selected)`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sortSelectedUsers();
|
||||||
|
})
|
||||||
|
|
||||||
|
function checkSelectedAmtFollowers() {
|
||||||
|
el_id_loadingfollowers.innerHTML = `${selectboxes.filter(x => x.checked).length} selected`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Following
|
||||||
|
|
||||||
|
const el_id_following = document.querySelector("#following");
|
||||||
|
const el_id_loadingfollowing = document.querySelector("#loadingfollowing");
|
||||||
|
const el_id_listfollowing = document.querySelector("#listfollowing");
|
||||||
|
const el_id_listfollowingvalues = document.querySelector("#listfollowingvalues");
|
||||||
|
const el_id_selectallfollowing = document.querySelector("#selectallfollowing");
|
||||||
|
const el_id_selectrandomfollowing = document.querySelector("#selectrandomfollowing");
|
||||||
|
const el_id_deselectrandomfollowing = document.querySelector("#deselectrandomfollowing");
|
||||||
|
const el_id_selectnofollowing = document.querySelector("#selectnofollowing");
|
||||||
|
const el_id_morefollowing = document.querySelector("#morefollowing");
|
||||||
|
const el_id_submitfollowing = document.querySelector("#submitfollowing");
|
||||||
|
const el_id_savehandlesfollowing = document.querySelector("#savehandlesfollowing");
|
||||||
|
const el_id_loadhandlesfollowing = document.querySelector("#loadhandlesfollowing");
|
||||||
|
|
||||||
|
function generateFollowingMap() {
|
||||||
|
const checks = Array.from(el_id_listfollowing.querySelectorAll(".following_checkbox"));
|
||||||
|
let codeMap = {};
|
||||||
|
checks.forEach((checkbox) => {
|
||||||
|
const handle = checkbox.parentElement.parentElement.querySelector(".following_checkname");
|
||||||
|
codeMap[handle.innerHTML] = checkbox.checked;
|
||||||
|
});
|
||||||
|
return codeMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readFollowingMap(m) {
|
||||||
|
if (m == null) return;
|
||||||
|
const handles = Array.from(el_id_listfollowing.querySelectorAll(".following_checkname"));
|
||||||
|
handles.forEach((handle) => {
|
||||||
|
const checkbox = handle.parentElement.querySelector(".following_checkbox");
|
||||||
|
if (m[handle.innerHTML] != null)
|
||||||
|
checkbox.checked = m[handle.innerHTML];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function startFollowing(reload = true) {
|
||||||
|
goToState("following");
|
||||||
|
if (reload) {
|
||||||
|
selectboxes = [];
|
||||||
|
userList = [];
|
||||||
|
lastId = "";
|
||||||
|
selectedUsers = [];
|
||||||
|
el_id_listfollowing.innerHTML = "";
|
||||||
|
}
|
||||||
|
getFollowing(!reload);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getFollowing(dontLoadNew = false) {
|
||||||
|
el_id_submitfollowing.disabled = true;
|
||||||
|
el_id_morefollowing.disabled = true;
|
||||||
|
let res;
|
||||||
|
let out;
|
||||||
|
if (!dontLoadNew) {
|
||||||
|
el_id_loadingfollowing.innerHTML = `Retrieving following... Please wait.`;
|
||||||
|
res = await fetch(`https://${game.INSTANCE}/api/v1/accounts/${game.USER_ID}/following${lastId.length > 0 ? `?max_id=${lastId}` : ""}`);
|
||||||
|
out = await res.json();
|
||||||
|
}
|
||||||
|
el_id_submitfollowing.disabled = false;
|
||||||
|
el_id_morefollowing.disabled = false;
|
||||||
|
if (dontLoadNew) return false;
|
||||||
|
if (out.length < 1) {
|
||||||
|
el_id_loadingfollowing.innerHTML = `No following found.`;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
el_id_listfollowing.hidden = false;
|
||||||
|
out.forEach((cuser) => {
|
||||||
|
const element = document.createElement("tr");
|
||||||
|
element.innerHTML = `<td><input type="checkbox" class="following_checkbox" checked onchange="checkSelectedAmtFollowing()" /></td>
|
||||||
|
<td><img src="${cuser.avatar}" width="32" height="32" /></td>
|
||||||
|
<td class="following_namelabel">
|
||||||
|
<a href="${cuser.url}" target="_blank">
|
||||||
|
${renderNameHTML(cuser.display_name, cuser)}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td class="following_namelabel following_checkname">@${cuser.fqn}</td>`;
|
||||||
|
el_id_listfollowing.appendChild(element);
|
||||||
|
});
|
||||||
|
userList.push(...out.map(user => ({
|
||||||
|
fqn: user.fqn,
|
||||||
|
avatar: user.avatar,
|
||||||
|
bot: user.bot,
|
||||||
|
created_at: user.created_at,
|
||||||
|
display_name: user.display_name,
|
||||||
|
emojis: user.emojis,
|
||||||
|
fields: user.fields,
|
||||||
|
id: user.id,
|
||||||
|
note: user.note,
|
||||||
|
url: user.url
|
||||||
|
})));
|
||||||
|
lastId = userList.at(-1).id;
|
||||||
|
selectboxes = Array.from(el_id_listfollowing.querySelectorAll(".following_checkbox"));
|
||||||
|
checkSelectedAmtFollowing();
|
||||||
|
}
|
||||||
|
|
||||||
|
el_id_selectallfollowing.addEventListener("click", () => {
|
||||||
|
selectboxes.forEach(x => x.checked = true);
|
||||||
|
checkSelectedAmtFollowing();
|
||||||
|
})
|
||||||
|
|
||||||
|
el_id_selectrandomfollowing.addEventListener("click", () => {
|
||||||
|
const unselectedPick = selectboxes.filter(x => !x.checked);
|
||||||
|
const selected = unselectedPick[Math.floor(Math.random() * (unselectedPick.length - 1))];
|
||||||
|
if (selected == null) return;
|
||||||
|
selected.checked = true;
|
||||||
|
checkSelectedAmtFollowing();
|
||||||
|
})
|
||||||
|
|
||||||
|
el_id_deselectrandomfollowing.addEventListener("click", () => {
|
||||||
|
const selectedPick = selectboxes.filter(x => x.checked);
|
||||||
|
const selected = selectedPick[Math.floor(Math.random() * (selectedPick.length - 1))];
|
||||||
|
if (selected == null) return;
|
||||||
|
selected.checked = false;
|
||||||
|
checkSelectedAmtFollowing();
|
||||||
|
})
|
||||||
|
|
||||||
|
el_id_selectnofollowing.addEventListener("click", () => {
|
||||||
|
selectboxes.forEach(x => x.checked = false);
|
||||||
|
checkSelectedAmtFollowing();
|
||||||
|
})
|
||||||
|
|
||||||
|
el_id_savehandlesfollowing.addEventListener("click", () => window.localStorage.setItem("fediversemadness_followingsel", JSON.stringify(generateFollowingMap())));
|
||||||
|
el_id_loadhandlesfollowing.addEventListener("click", () => readFollowingMap(JSON.parse(window.localStorage.getItem("fediversemadness_followingsel"))));
|
||||||
|
|
||||||
|
el_id_morefollowing.addEventListener("click", () => getFollowing());
|
||||||
|
|
||||||
|
el_id_submitfollowing.addEventListener("click", () => {
|
||||||
|
selectedUsers = [];
|
||||||
|
selectboxes.forEach(({checked}, i) => {
|
||||||
|
if (checked) selectedUsers.push(userList.at(i));
|
||||||
|
});
|
||||||
|
if (selectedUsers.length < 2) {
|
||||||
|
el_id_loadingfollowing.innerHTML = `Selected user count is less than 2! (${selectboxes.filter(x => x.checked).length} selected)`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sortSelectedUsers();
|
||||||
|
})
|
||||||
|
|
||||||
|
function checkSelectedAmtFollowing() {
|
||||||
|
el_id_loadingfollowing.innerHTML = `${selectboxes.filter(x => x.checked).length} selected`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manual
|
||||||
|
|
||||||
|
const el_id_manual = document.querySelector("#manual");
|
||||||
|
const el_id_loadingmanual = document.querySelector("#loadingmanual");
|
||||||
|
const el_id_listmanual = document.querySelector("#listmanual");
|
||||||
|
const el_id_listmanualvalues = document.querySelector("#listmanualvalues");
|
||||||
|
const el_id_selectallmanual = document.querySelector("#selectallmanual");
|
||||||
|
const el_id_selectrandommanual = document.querySelector("#selectrandommanual");
|
||||||
|
const el_id_deselectrandommanual = document.querySelector("#deselectrandommanual");
|
||||||
|
const el_id_selectnomanual = document.querySelector("#selectnomanual");
|
||||||
|
const el_id_manualuser = document.querySelector("#manualuser");
|
||||||
|
const el_id_manualinstance = document.querySelector("#manualinstance");
|
||||||
|
const el_id_moremanual = document.querySelector("#moremanual");
|
||||||
|
const el_id_submitmanual = document.querySelector("#submitmanual");
|
||||||
|
|
||||||
|
function startManual(reload = true) {
|
||||||
|
goToState("manual");
|
||||||
|
if (reload) {
|
||||||
|
selectboxes = [];
|
||||||
|
userList = [];
|
||||||
|
lastId = "";
|
||||||
|
selectedUsers = [];
|
||||||
|
el_id_listmanual.innerHTML = "";
|
||||||
|
}
|
||||||
|
checkSelectedAmtManual();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function addUserToManual() {
|
||||||
|
const username = el_id_manualuser.value.replace(/[^a-z0-9_]/gim, "");
|
||||||
|
const instance = el_id_manualinstance.value.replace(/@/gim, "");
|
||||||
|
el_id_manualuser.value = username;
|
||||||
|
el_id_manualinstance.value = instance;
|
||||||
|
if (username.length < 1) return null;
|
||||||
|
if (instance.length < 1) return null;
|
||||||
|
el_id_submitmanual.disabled = true;
|
||||||
|
el_id_moremanual.disabled = true;
|
||||||
|
el_id_loadingmanual.innerHTML = `Finding user...`;
|
||||||
|
let res = await fetch(`https://${game.INSTANCE}/api/v1/accounts/lookup?acct=${username}@${instance}`);
|
||||||
|
let out = await res.json();
|
||||||
|
el_id_submitmanual.disabled = false;
|
||||||
|
el_id_moremanual.disabled = false;
|
||||||
|
if (out.length < 1) {
|
||||||
|
el_id_loadingmanual.innerHTML = `No manual found.`;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
el_id_listmanual.hidden = false;
|
||||||
|
const element = document.createElement("tr");
|
||||||
|
element.innerHTML = `<td><input type="checkbox" class="manual_checkbox" checked onchange="checkSelectedAmtManual()" /></td>
|
||||||
|
<td><img src="${out.avatar}" width="32" height="32" /></td>
|
||||||
|
<td class="manual_namelabel">
|
||||||
|
<a href="${out.url}" target="_blank">
|
||||||
|
${renderNameHTML(out.display_name, out)}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td class="manual_namelabel manual_checkname">@${out.fqn}</td>`;
|
||||||
|
el_id_listmanual.appendChild(element);
|
||||||
|
userList.push({
|
||||||
|
fqn: out.fqn,
|
||||||
|
avatar: out.avatar,
|
||||||
|
bot: out.bot,
|
||||||
|
created_at: out.created_at,
|
||||||
|
display_name: out.display_name,
|
||||||
|
emojis: out.emojis,
|
||||||
|
fields: out.fields,
|
||||||
|
id: out.id,
|
||||||
|
note: out.note,
|
||||||
|
url: out.url
|
||||||
|
});
|
||||||
|
selectboxes = Array.from(el_id_listmanual.querySelectorAll(".manual_checkbox"));
|
||||||
|
checkSelectedAmtManual();
|
||||||
|
}
|
||||||
|
|
||||||
|
el_id_selectallmanual.addEventListener("click", () => {
|
||||||
|
selectboxes.forEach(x => x.checked = true);
|
||||||
|
checkSelectedAmtManual();
|
||||||
|
})
|
||||||
|
|
||||||
|
el_id_selectrandommanual.addEventListener("click", () => {
|
||||||
|
const unselectedPick = selectboxes.filter(x => !x.checked);
|
||||||
|
const selected = unselectedPick[Math.floor(Math.random() * (unselectedPick.length - 1))];
|
||||||
|
if (selected == null) return;
|
||||||
|
selected.checked = true;
|
||||||
|
checkSelectedAmtManual();
|
||||||
|
})
|
||||||
|
|
||||||
|
el_id_deselectrandommanual.addEventListener("click", () => {
|
||||||
|
const selectedPick = selectboxes.filter(x => x.checked);
|
||||||
|
const selected = selectedPick[Math.floor(Math.random() * (selectedPick.length - 1))];
|
||||||
|
if (selected == null) return;
|
||||||
|
selected.checked = false;
|
||||||
|
checkSelectedAmtManual();
|
||||||
|
})
|
||||||
|
|
||||||
|
el_id_selectnomanual.addEventListener("click", () => {
|
||||||
|
selectboxes.forEach(x => x.checked = false);
|
||||||
|
checkSelectedAmtManual();
|
||||||
|
})
|
||||||
|
|
||||||
|
el_id_moremanual.addEventListener("click", () => addUserToManual());
|
||||||
|
|
||||||
|
el_id_submitmanual.addEventListener("click", () => {
|
||||||
|
selectedUsers = [];
|
||||||
|
selectboxes.forEach(({checked}, i) => {
|
||||||
|
if (checked) selectedUsers.push(userList.at(i));
|
||||||
|
});
|
||||||
|
if (selectedUsers.length < 2) {
|
||||||
|
el_id_loadingmanual.innerHTML = `Selected user count is less than 2! (${selectboxes.filter(x => x.checked).length} selected)`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sortSelectedUsers();
|
||||||
|
})
|
||||||
|
|
||||||
|
function checkSelectedAmtManual() {
|
||||||
|
el_id_loadingmanual.innerHTML = `${selectboxes.filter(x => x.checked).length} selected`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Brackets
|
||||||
|
|
||||||
|
function shuf(array) {
|
||||||
|
var count = array.length,
|
||||||
|
randomnumber,
|
||||||
|
temp;
|
||||||
|
while (count) {
|
||||||
|
randomnumber = Math.random() * count-- | 0;
|
||||||
|
temp = array[count];
|
||||||
|
array[count] = array[randomnumber];
|
||||||
|
array[randomnumber] = temp
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
function chunk(arr, size) {
|
||||||
|
return Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
|
||||||
|
arr.slice(i * size, i * size + size)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const el_id_game = document.querySelector("#game");
|
||||||
|
const el_id_gameUserOne = document.querySelector("#gameUserOne");
|
||||||
|
const el_id_gameUserOneImage = document.querySelector("#gameUserOneImage");
|
||||||
|
const el_id_gameUserOneName = document.querySelector("#gameUserOneName");
|
||||||
|
const el_id_gameUserOneId = document.querySelector("#gameUserOneId");
|
||||||
|
// const el_id_gameUserOneNote = document.querySelector("#gameUserOneNote");
|
||||||
|
// const el_id_gameUserOneFields = document.querySelector("#gameUserOneFields");
|
||||||
|
const el_id_gameUserTwo = document.querySelector("#gameUserTwo");
|
||||||
|
const el_id_gameUserTwoImage = document.querySelector("#gameUserTwoImage");
|
||||||
|
const el_id_gameUserTwoName = document.querySelector("#gameUserTwoName");
|
||||||
|
const el_id_gameUserTwoId = document.querySelector("#gameUserTwoId");
|
||||||
|
// const el_id_gameUserTwoNote = document.querySelector("#gameUserTwoNote");
|
||||||
|
// const el_id_gameUserTwoFields = document.querySelector("#gameUserTwoFields");
|
||||||
|
const el_id_gameSubmitLeft = document.querySelector("#gameSubmitLeft");
|
||||||
|
const el_id_gameSubmitRight = document.querySelector("#gameSubmitRight");
|
||||||
|
const el_id_gameBracketLevel = document.querySelector("#gameBracketLevel");
|
||||||
|
const el_id_gameBracketFight = document.querySelector("#gameBracketFight");
|
||||||
|
|
||||||
|
let state = [];
|
||||||
|
let curDepth = 0;
|
||||||
|
let curFight = 0;
|
||||||
|
|
||||||
|
function sortSelectedUsers() {
|
||||||
|
goToState("game");
|
||||||
|
state = [];
|
||||||
|
curDepth = 0;
|
||||||
|
curFight = 0;
|
||||||
|
state.push(chunk(shuf(selectedUsers), 2));
|
||||||
|
state.push([]);
|
||||||
|
prepareGameStage();
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepareGameStage() {
|
||||||
|
el_id_gameSubmitLeft.innerHTML = "Please wait...";
|
||||||
|
el_id_gameSubmitRight.innerHTML = "Please wait...";
|
||||||
|
el_id_gameUserOneImage.src = "";
|
||||||
|
el_id_gameUserTwoImage.src = "";
|
||||||
|
el_id_gameBracketLevel.innerHTML = "Bracket Level " + (curDepth + 1);
|
||||||
|
el_id_gameBracketFight.innerHTML = "Round " + (curFight + 1);
|
||||||
|
const curSubStage = state[curDepth][curFight];
|
||||||
|
el_id_gameUserOneImage.src = curSubStage[0].avatar;
|
||||||
|
el_id_gameUserOneName.innerHTML = `<a href="${curSubStage[0].url}" target="_blank">${renderNameHTML(escapeHtml(curSubStage[0].display_name), curSubStage[0])}</a>`;
|
||||||
|
el_id_gameUserOneId.innerHTML = "@" + curSubStage[0].fqn;
|
||||||
|
// el_id_gameUserOneNote.innerHTML = escapeHtml(curSubStage[0].note);
|
||||||
|
// el_id_gameUserOneFields.innerHTML = curSubStage[0].fields.reduce((pv, fields) => pv + `<tr><td>${escapeHtml(fields.name)}</td><td>${escapeHtml(fields.value)}</td></tr>`, "");
|
||||||
|
el_id_gameUserTwoImage.src = curSubStage[1].avatar;
|
||||||
|
el_id_gameUserTwoName.innerHTML = `<a href="${curSubStage[1].url}" target="_blank">${renderNameHTML(escapeHtml(curSubStage[1].display_name), curSubStage[1])}</a>`;
|
||||||
|
el_id_gameUserTwoId.innerHTML = "@" + curSubStage[1].fqn;
|
||||||
|
// el_id_gameUserTwoNote.innerHTML = escapeHtml(curSubStage[1].note);
|
||||||
|
// el_id_gameUserTwoFields.innerHTML = curSubStage[1].fields.reduce((pv, fields) => pv + `<tr><td>${escapeHtml(fields.name)}</td><td>${escapeHtml(fields.value)}</td></tr>`, "");
|
||||||
|
el_id_gameSubmitLeft.disabled = false;
|
||||||
|
el_id_gameSubmitRight.disabled = false;
|
||||||
|
el_id_gameSubmitLeft.innerHTML = "Pick " + "@" + curSubStage[0].fqn;
|
||||||
|
el_id_gameSubmitRight.innerHTML = "Pick " + "@" + curSubStage[1].fqn;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addNewThingy(thingy) {
|
||||||
|
if (state[curDepth + 1] == null) state.push([]);
|
||||||
|
if (curFight % 2 == 0)
|
||||||
|
state[curDepth + 1][Math.floor(curFight / 2)] = [];
|
||||||
|
state[curDepth + 1][Math.floor(curFight / 2)].push(thingy);
|
||||||
|
}
|
||||||
|
|
||||||
|
el_id_gameSubmitLeft.addEventListener("click", () => {
|
||||||
|
addNewThingy(state[curDepth][curFight][0]);
|
||||||
|
nextStage();
|
||||||
|
})
|
||||||
|
|
||||||
|
el_id_gameSubmitRight.addEventListener("click", () => {
|
||||||
|
addNewThingy(state[curDepth][curFight][1]);
|
||||||
|
nextStage();
|
||||||
|
})
|
||||||
|
|
||||||
|
function nextStage() {
|
||||||
|
if (curFight >= state[curDepth].length - 1) {
|
||||||
|
curDepth++;
|
||||||
|
curFight = 0;
|
||||||
|
} else curFight++;
|
||||||
|
console.log(state, curFight, curDepth);
|
||||||
|
if (state[curDepth][curFight].length < 2) {
|
||||||
|
if (state[curDepth].length < 2) {
|
||||||
|
endGame();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addNewThingy(state[curDepth][curFight][0]);
|
||||||
|
curDepth++;
|
||||||
|
curFight = 0;
|
||||||
|
}
|
||||||
|
prepareGameStage();
|
||||||
|
}
|
||||||
|
|
||||||
|
// End
|
||||||
|
|
||||||
|
const el_id_winner = document.querySelector("#winner");
|
||||||
|
const el_id_winnerUser = document.querySelector("#winnerUser");
|
||||||
|
const el_id_winnerUserImage = document.querySelector("#winnerUserImage");
|
||||||
|
const el_id_winnerUserName = document.querySelector("#winnerUserName");
|
||||||
|
const el_id_winnerUserId = document.querySelector("#winnerUserId");
|
||||||
|
// const el_id_winnerUserNote = document.querySelector("#winnerUserNote");
|
||||||
|
// const el_id_winnerUserFields = document.querySelector("#winnerUserFields");
|
||||||
|
const el_id_winnermessage = document.querySelector("#winnermessage");
|
||||||
|
const el_id_winnerusers = document.querySelector("#winnerusers");
|
||||||
|
const el_id_winnerPlayAgain = document.querySelector("#winnerPlayAgain");
|
||||||
|
|
||||||
|
function endGame() {
|
||||||
|
goToState("winner");
|
||||||
|
const winningPlayer = state[curDepth][curFight][0];
|
||||||
|
el_id_winnerUserImage.src = winningPlayer.avatar;
|
||||||
|
el_id_winnerUserName.innerHTML = `<a href="${winningPlayer.url}" target="_blank">${renderNameHTML(escapeHtml(winningPlayer.display_name), winningPlayer)}</a>`;
|
||||||
|
el_id_winnerUserId.innerHTML = "@" + winningPlayer.fqn;
|
||||||
|
// el_id_winnerUserNote.innerHTML = escapeHtml(winningPlayer.note);
|
||||||
|
// el_id_winnerUserFields.innerHTML = winningPlayer.fields.reduce((pv, fields) => pv + `<tr><td>${escapeHtml(fields.name)}</td><td>${escapeHtml(fields.value)}</td></tr>`, "");
|
||||||
|
|
||||||
|
el_id_winnermessage.innerHTML = `Congratulations, ${renderNameHTML(escapeHtml(winningPlayer.display_name), winningPlayer)}! You won the bracket!`;
|
||||||
|
el_id_winnerusers.innerHTML = state.reduce((pv, cs) => {
|
||||||
|
return pv + `<div class="flexUser">${cs.reduce((pvus, cus) => {
|
||||||
|
console.log(cus);
|
||||||
|
return pvus + `<div class="flexUserGroup"><div class="flexUserUser">
|
||||||
|
<img src="${cus[0].avatar}" width="64" height="64" />
|
||||||
|
<h3><a href="${cus[0].url}" target="_blank">${renderNameHTML(escapeHtml(cus[0].display_name), cus[0])}</a></h3>
|
||||||
|
<p>@${cus[0].fqn}</p>
|
||||||
|
</div>${cus[1] ? `<div class="flexUserUser">
|
||||||
|
<img src="${cus[1].avatar}" width="64" height="64" />
|
||||||
|
<h3><a href="${cus[1].url}" target="_blank">${renderNameHTML(escapeHtml(cus[1].display_name), cus[1])}</a></h3>
|
||||||
|
<p>@${cus[1].fqn}</p>
|
||||||
|
</div>` : ""}</div>`
|
||||||
|
}, "")}</div>`
|
||||||
|
}, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
el_id_winnerPlayAgain.addEventListener("click", (x) => {
|
||||||
|
state = [];
|
||||||
|
selectedUsers = [];
|
||||||
|
curDepth = 0;
|
||||||
|
curFight = 0;
|
||||||
|
switch (gamemodeFollowers) {
|
||||||
|
case "followers":
|
||||||
|
startFollowers(false);
|
||||||
|
break;
|
||||||
|
case "following":
|
||||||
|
startFollowing(false);
|
||||||
|
break;
|
||||||
|
case "manual":
|
||||||
|
startManual(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Game state
|
||||||
|
|
||||||
|
const gameStates = new Map([
|
||||||
|
["whoami", {
|
||||||
|
state: el_id_whoami
|
||||||
|
}],
|
||||||
|
["followers", {
|
||||||
|
state: el_id_followers
|
||||||
|
}],
|
||||||
|
["following", {
|
||||||
|
state: el_id_following
|
||||||
|
}],
|
||||||
|
["manual", {
|
||||||
|
state: el_id_manual
|
||||||
|
}],
|
||||||
|
["game", {
|
||||||
|
state: el_id_game,
|
||||||
|
links: {
|
||||||
|
"winner": () => gamemodeFollowers
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
["winner", {
|
||||||
|
state: el_id_winner
|
||||||
|
}]
|
||||||
|
]);
|
||||||
|
|
||||||
|
let prevState = "";
|
||||||
|
function goToState(state) {
|
||||||
|
window.location.hash = state;
|
||||||
|
const curState = gameStates.get(state);
|
||||||
|
if (curState.links != null)
|
||||||
|
if (curState.links[prevState])
|
||||||
|
return goToState(curState.links[prevState]());
|
||||||
|
gameStates.forEach(x => x.state.hidden = true);
|
||||||
|
curState.state.hidden = false;
|
||||||
|
prevState = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
goToState("whoami");
|
||||||
|
|
||||||
|
addEventListener("popstate", () => goToState(window.location.hash.slice(1)));
|
91
views/projects/item/fediverse-madness/style.css
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
.userinstance {
|
||||||
|
border: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.userinputbox {
|
||||||
|
display: inline-block;
|
||||||
|
border: var(--border-width) var(--border-style) var(--border-color);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
padding-inline: 0.25em;
|
||||||
|
padding-block: 0.25em;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .userinputbox * {
|
||||||
|
vertical-align: 0%;
|
||||||
|
} */
|
||||||
|
|
||||||
|
#listfollowers, #listfollowing {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 31.25em;
|
||||||
|
overflow:auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#listfollowers #listfollowersvalues,
|
||||||
|
#listfollowing #listfollowingvalues {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
background-color: var(--background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.followers_namelabel,
|
||||||
|
.following_namelabel {
|
||||||
|
max-width: 20em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gridUser {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 128px auto;
|
||||||
|
overflow: auto;
|
||||||
|
gap: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gridUsersVert {
|
||||||
|
display: grid;
|
||||||
|
overflow: auto;
|
||||||
|
gap: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexUsersVert {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: stretch;
|
||||||
|
overflow: auto;
|
||||||
|
gap: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexUser {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
justify-content: space-around;
|
||||||
|
gap: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexUserUser {
|
||||||
|
text-align: center;
|
||||||
|
width: 256px;
|
||||||
|
min-width: 256px;
|
||||||
|
height: 150px;
|
||||||
|
min-height: 150px;
|
||||||
|
box-sizing: content-box;
|
||||||
|
overflow: hidden;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexUserGroup {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
justify-content: space-around;
|
||||||
|
gap: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexUserUser * {
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
|
@ -5,12 +5,58 @@
|
||||||
"normalize": "#808080"
|
"normalize": "#808080"
|
||||||
},
|
},
|
||||||
"items": [
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "Fediverse Madness",
|
||||||
|
"date": 1710804730000,
|
||||||
|
"description": [
|
||||||
|
"A March Madness style bracket-based competition for the entities on the Fediverse.",
|
||||||
|
"Compare your friends! Have a meltdown-sized crisis over who you like more!",
|
||||||
|
"This project will make you do it.",
|
||||||
|
"CONTENT WARNING // uncomfortable decisions"
|
||||||
|
],
|
||||||
|
"url": "/projects/item/fediverse-madness/",
|
||||||
|
"tags": [
|
||||||
|
"normalize"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LastFMDownloader",
|
||||||
|
"date": 1708382160000,
|
||||||
|
"description": [
|
||||||
|
"Downloader from Last.fm scrobble to MP3 file. Uploads to Nextcloud because it can.",
|
||||||
|
"Not piracy. I don't think so?"
|
||||||
|
],
|
||||||
|
"url": "https://git.abtmtr.link/MeowcaTheoRange/LastFMDownloader",
|
||||||
|
"hotlink": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "XKCDViewer",
|
||||||
|
"date": 1702875360000,
|
||||||
|
"description": [
|
||||||
|
"Unofficial XKCD Reader for Roku®."
|
||||||
|
],
|
||||||
|
"url": "https://git.abtmtr.link/MeowcaTheoRange/XKCDViewer",
|
||||||
|
"hotlink": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Karkat Public License",
|
||||||
|
"date": 1704316500000,
|
||||||
|
"description": [
|
||||||
|
"The Karkat Public License"
|
||||||
|
],
|
||||||
|
"url": "https://git.abtmtr.link/MeowcaTheoRange/KarkatPublicLicense",
|
||||||
|
"hotlink": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "DiceApp",
|
"name": "DiceApp",
|
||||||
"date": 1655589660000,
|
"date": 1655589660000,
|
||||||
"description": ["An app. For managing virtual dice."],
|
"description": [
|
||||||
|
"An app. For managing virtual dice."
|
||||||
|
],
|
||||||
"url": "/projects/item/dice/",
|
"url": "/projects/item/dice/",
|
||||||
"tags": ["old"]
|
"tags": [
|
||||||
|
"old"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "FunnyClock²",
|
"name": "FunnyClock²",
|
||||||
|
@ -19,16 +65,9 @@
|
||||||
"FunnyClock² is the successor of FunnyClock, an application made for my school to show when smartboards are idle."
|
"FunnyClock² is the successor of FunnyClock, an application made for my school to show when smartboards are idle."
|
||||||
],
|
],
|
||||||
"url": "/projects/item/clock/",
|
"url": "/projects/item/clock/",
|
||||||
"tags": ["old"]
|
"tags": [
|
||||||
},
|
"old"
|
||||||
{
|
]
|
||||||
"name": "MTRUWSaDMfHTML5",
|
|
||||||
"date": 1701743828350,
|
|
||||||
"description": [
|
|
||||||
"MeowcaTheoRange's Unnecessary Windowing System and Desktop Manager for HTML5.<br />Works best outside of windowed mode."
|
|
||||||
],
|
|
||||||
"url": "/projects/item/wm/",
|
|
||||||
"tags": ["normalize", "new"]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Normalize",
|
"name": "Normalize",
|
||||||
|
@ -37,7 +76,9 @@
|
||||||
"Normalize is a simple CSS library made to provide good-looking yet simple HTML element styles."
|
"Normalize is a simple CSS library made to provide good-looking yet simple HTML element styles."
|
||||||
],
|
],
|
||||||
"url": "/projects/item/normalize/",
|
"url": "/projects/item/normalize/",
|
||||||
"tags": ["normalize"]
|
"tags": [
|
||||||
|
"normalize"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "JellyBean's Mid-Sim",
|
"name": "JellyBean's Mid-Sim",
|
||||||
|
@ -46,8 +87,13 @@
|
||||||
"JellyBean's Mid-Sim, a 1K rhythm game made in the HTML5-JS game engine Kaboom."
|
"JellyBean's Mid-Sim, a 1K rhythm game made in the HTML5-JS game engine Kaboom."
|
||||||
],
|
],
|
||||||
"url": "/projects/item/midsim/",
|
"url": "/projects/item/midsim/",
|
||||||
"size": [700, 400],
|
"size": [
|
||||||
"tags": ["old"]
|
700,
|
||||||
|
400
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"old"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "WozSteamGen",
|
"name": "WozSteamGen",
|
||||||
|
@ -57,7 +103,9 @@
|
||||||
"It's an API-less adaptation of Steam The Woz, running completely locally."
|
"It's an API-less adaptation of Steam The Woz, running completely locally."
|
||||||
],
|
],
|
||||||
"url": "/projects/item/woz/",
|
"url": "/projects/item/woz/",
|
||||||
"tags": ["normalize"]
|
"tags": [
|
||||||
|
"normalize"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "HexFlagGen",
|
"name": "HexFlagGen",
|
||||||
|
@ -67,7 +115,9 @@
|
||||||
"I dislike DRM and support trans rights."
|
"I dislike DRM and support trans rights."
|
||||||
],
|
],
|
||||||
"url": "/projects/item/hex/",
|
"url": "/projects/item/hex/",
|
||||||
"tags": ["normalize"]
|
"tags": [
|
||||||
|
"normalize"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
const data_get = document.getElementById("data_get");
|
const data_get = document.getElementById("data_get");
|
||||||
fetch("./public/projects.json")
|
|
||||||
|
fetch_ask("./public/projects.json")
|
||||||
.then((x) => x.json())
|
.then((x) => x.json())
|
||||||
.then((projects) => {
|
.then((projects) => {
|
||||||
data_get.innerHTML = projects.items
|
data_get.innerHTML = projects.items
|
||||||
|
@ -26,7 +27,7 @@ fetch("./public/projects.json")
|
||||||
(html, descfragment) => html + `<p>${descfragment}</p>`,
|
(html, descfragment) => html + `<p>${descfragment}</p>`,
|
||||||
""
|
""
|
||||||
)}
|
)}
|
||||||
<p>
|
${project.hotlink ? `` : `<p>
|
||||||
<button
|
<button
|
||||||
onclick="window.manager.createWindow('${project.url}', false${
|
onclick="window.manager.createWindow('${project.url}', false${
|
||||||
project.size?.[0] ? ", " + project.size[0] : ""
|
project.size?.[0] ? ", " + project.size[0] : ""
|
||||||
|
@ -34,7 +35,7 @@ fetch("./public/projects.json")
|
||||||
>
|
>
|
||||||
Open Window
|
Open Window
|
||||||
</button>
|
</button>
|
||||||
</p>`,
|
</p>`}`,
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
});
|
});
|
96
views/robots.txt
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
# https://seirdy.one/robots.txt
|
||||||
|
|
||||||
|
User-agent: *
|
||||||
|
Disallow: /noindex/
|
||||||
|
Disallow: /misc/
|
||||||
|
|
||||||
|
# I opt out of online advertising so malware that injects ads on my site won't get paid.
|
||||||
|
# You should do the same. my ads.txt file contains a standard placeholder to forbid any
|
||||||
|
# compliant ad networks from paying for ad placement on my domain.
|
||||||
|
User-Agent: Adsbot
|
||||||
|
Disallow: /
|
||||||
|
Allow: /ads.txt
|
||||||
|
Allow: /app-ads.txt
|
||||||
|
|
||||||
|
## IP-violation scanners ##
|
||||||
|
|
||||||
|
# The next three are borrowed from https://www.videolan.org/robots.txt
|
||||||
|
|
||||||
|
# > This robot collects content from the Internet for the sole purpose of # helping educational institutions prevent plagiarism. [...] we compare student papers against the content we find on the Internet to see if we # can find similarities. (http://www.turnitin.com/robot/crawlerinfo.html)
|
||||||
|
# --> fuck off.
|
||||||
|
User-Agent: TurnitinBot
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
# > NameProtect engages in crawling activity in search of a wide range of brand and other intellectual property violations that may be of interest to our clients. (http://www.nameprotect.com/botinfo.html)
|
||||||
|
# --> fuck off.
|
||||||
|
User-Agent: NPBot
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
# iThenticate is a new service we have developed to combat the piracy of intellectual property and ensure the originality of written work for# publishers, non-profit agencies, corporations, and newspapers. (http://www.slysearch.com/)
|
||||||
|
# --> fuck off.
|
||||||
|
User-Agent: SlySearch
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
# BLEXBot assists internet marketers to get information on the link structure of sites and their interlinking on the web, to avoid any technical and possible legal issues and improve overall online experience. (http://webmeup-crawler.com/)
|
||||||
|
# --> fuck off.
|
||||||
|
User-Agent: BLEXBot
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
# Providing Intellectual Property professionals with superior brand protection services by artfully merging the latest technology with expert analysis. (https://www.checkmarknetwork.com/spider.html/)
|
||||||
|
# "The Internet is just way to big to effectively police alone." (ACTUAL quote)
|
||||||
|
# --> fuck off.
|
||||||
|
User-agent: CheckMarkNetwork/1.0 (+https://www.checkmarknetwork.com/spider.html)
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
# Stop trademark violations and affiliate non-compliance in paid search. Automatically monitor your partner and affiliates’ online marketing to protect yourself from harmful brand violations and regulatory risks. We regularly crawl websites on behalf of our clients to ensure content compliance with brand and regulatory guidelines. (https://www.brandverity.com/why-is-brandverity-visiting-me)
|
||||||
|
# --> fuck off.
|
||||||
|
User-agent: BrandVerity/1.0
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
## Misc. icky stuff ##
|
||||||
|
|
||||||
|
# Pipl assembles online identity information from multiple independent sources to create the most complete picture of a digital identity and connect it to real people and their offline identity records. When all the fragments of online identity data are collected, connected, and corroborated, the result is a more trustworthy identity.
|
||||||
|
# --> fuck off.
|
||||||
|
User-agent: PiplBot
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
## Gen-AI data scrapers ##
|
||||||
|
|
||||||
|
# Eat shit, OpenAI.
|
||||||
|
User-agent: ChatGPT-User
|
||||||
|
Disallow: /
|
||||||
|
User-agent: GPTBot
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
# Official way to opt-out of Google's generative AI training:
|
||||||
|
# <https://developers.google.com/search/docs/crawling-indexing/overview-google-crawlers>
|
||||||
|
User-agent: Google-Extended
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
# There isn't any public documentation for this AFAICT.
|
||||||
|
# Reuters thinks this works so I might as well give it a shot.
|
||||||
|
User-agent: anthropic-ai
|
||||||
|
Disallow: /
|
||||||
|
User-agent: Claude-Web
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
# FacebookBot crawls public web pages to improve language models for our speech recognition technology.
|
||||||
|
# <https://developers.facebook.com/docs/sharing/bot/?_fb_noscript=1>
|
||||||
|
User-Agent: FacebookBot
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
# I'm not blocking CCBot for now. It publishes a free index for anyone to use.
|
||||||
|
# Googe used this to train the initial version of Bard (now called Gemini).
|
||||||
|
# I allow CCBot since its index is also used for upstart/hobbyist search engines
|
||||||
|
# like Alexandria and for genuinely useful academic work I personally like.
|
||||||
|
# I allow Owler for similar reasons:
|
||||||
|
# <https://openwebsearch.eu/owler/#owler-opt-out>
|
||||||
|
# <https://openwebsearch.eu/common-goals-with-common-crawl/>.
|
||||||
|
# Omgilibot/Omgili is similar to CCBot, except it sells the scrape results.
|
||||||
|
# I'm not familiar enough with Omgili to make a call here.
|
||||||
|
# In the long run, my embedded robots meta-tags and headers could cover gen-AI
|
||||||
|
|
||||||
|
# I don't block cohere-ai or Perplexitybot: they don't appear to actually scrape data for LLM training purposes. The crawling powers search engines with integrated pre-trained LLMs.
|
||||||
|
# TODO: investigate whether YouBot scrapes to train its own in-house LLM.
|
||||||
|
|
||||||
|
Sitemap: https://seirdy.one/sitemap.xml
|
|
@ -13,18 +13,21 @@ var accBase;
|
||||||
var propagateStyles = propagateStyles ?? null;
|
var propagateStyles = propagateStyles ?? null;
|
||||||
|
|
||||||
const FONTS = [
|
const FONTS = [
|
||||||
["Lexend Deca"],
|
["Lexend Deca", ""],
|
||||||
["Renogare"],
|
["Renogare", "Renogare"],
|
||||||
["OpenDyslexic"],
|
["OpenDyslexic", "OpenDyslexic"],
|
||||||
// ["Mojangles", "Minecraft"],
|
// ["Mojangles", "Minecraft"],
|
||||||
// ["Nintendo DS", "NDS12"],
|
// ["Nintendo DS", "NDS12"],
|
||||||
["System Default", `-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
[
|
||||||
|
"System Default",
|
||||||
|
`-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||||
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
|
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
|
||||||
"Segoe UI Symbol"`],
|
"Segoe UI Symbol"`,
|
||||||
|
],
|
||||||
["Sans-serif", "sans-serif"],
|
["Sans-serif", "sans-serif"],
|
||||||
["Serif", "serif"],
|
["Serif", "serif"],
|
||||||
["Mono", "monospace"]
|
["Mono", "monospace"],
|
||||||
]
|
];
|
||||||
|
|
||||||
function createAccessibilityNodes() {
|
function createAccessibilityNodes() {
|
||||||
document.querySelector("#accessibility").innerHTML = `<details>
|
document.querySelector("#accessibility").innerHTML = `<details>
|
||||||
|
@ -52,7 +55,10 @@ function createAccessibilityNodes() {
|
||||||
</label><br />
|
</label><br />
|
||||||
<label for="acc-font">Page font:
|
<label for="acc-font">Page font:
|
||||||
<select id="acc-font">
|
<select id="acc-font">
|
||||||
${FONTS.map(([name, value]) => `<option value="${value ?? name}" selected>${name}</option>`)}
|
${FONTS.map(
|
||||||
|
([name, value]) =>
|
||||||
|
`<option value="${value}" selected>${name}</option>`
|
||||||
|
)}
|
||||||
</select>
|
</select>
|
||||||
</label><br />
|
</label><br />
|
||||||
<label for="acc-hue">Page hue:
|
<label for="acc-hue">Page hue:
|
||||||
|
@ -119,22 +125,42 @@ function createAccessibilityNodes() {
|
||||||
|
|
||||||
accHueOverride.addEventListener("change", function (e) {
|
accHueOverride.addEventListener("change", function (e) {
|
||||||
window.localStorage.setItem("acc-hue-over", e.target.checked);
|
window.localStorage.setItem("acc-hue-over", e.target.checked);
|
||||||
changeColor(accHue?.value, accSaturation?.value, e.target.checked, accSaturationOverride?.checked);
|
changeColor(
|
||||||
|
accHue?.value,
|
||||||
|
accSaturation?.value,
|
||||||
|
e.target.checked,
|
||||||
|
accSaturationOverride?.checked
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
accHue.addEventListener("input", function (e) {
|
accHue.addEventListener("input", function (e) {
|
||||||
window.localStorage.setItem("acc-hue", e.target.value);
|
window.localStorage.setItem("acc-hue", e.target.value);
|
||||||
changeColor(e.target.value, accSaturation?.value, accHueOverride?.checked, accSaturationOverride?.checked);
|
changeColor(
|
||||||
|
e.target.value,
|
||||||
|
accSaturation?.value,
|
||||||
|
accHueOverride?.checked,
|
||||||
|
accSaturationOverride?.checked
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
accSaturationOverride.addEventListener("change", function (e) {
|
accSaturationOverride.addEventListener("change", function (e) {
|
||||||
window.localStorage.setItem("acc-sat-over", e.target.checked);
|
window.localStorage.setItem("acc-sat-over", e.target.checked);
|
||||||
changeColor(accHue?.value, accSaturation?.value, accHueOverride?.checked, e.target.checked);
|
changeColor(
|
||||||
|
accHue?.value,
|
||||||
|
accSaturation?.value,
|
||||||
|
accHueOverride?.checked,
|
||||||
|
e.target.checked
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
accSaturation.addEventListener("input", function (e) {
|
accSaturation.addEventListener("input", function (e) {
|
||||||
window.localStorage.setItem("acc-sat", e.target.value);
|
window.localStorage.setItem("acc-sat", e.target.value);
|
||||||
changeColor(accHue?.value, e.target.value, accHueOverride?.checked, accSaturationOverride?.checked);
|
changeColor(
|
||||||
|
accHue?.value,
|
||||||
|
e.target.value,
|
||||||
|
accHueOverride?.checked,
|
||||||
|
accSaturationOverride?.checked
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
accBase.addEventListener("change", function (e) {
|
accBase.addEventListener("change", function (e) {
|
||||||
|
@ -143,6 +169,20 @@ function createAccessibilityNodes() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For metered conenctions
|
||||||
|
async function fetch_ask(...args) {
|
||||||
|
// return new Promise(async (resolve, reject) => {
|
||||||
|
// let canFetch = window.sessionStorage.getItem("canFetch");
|
||||||
|
// if (canFetch == null) {
|
||||||
|
// canFetch = confirm("may the site fetch data for this session?");
|
||||||
|
// window.sessionStorage.setItem("canFetch", canFetch);
|
||||||
|
// }
|
||||||
|
// if (canFetch === "true") resolve(await fetch(...args));
|
||||||
|
// else reject(null);
|
||||||
|
// });
|
||||||
|
return await fetch(...args);
|
||||||
|
}
|
||||||
|
|
||||||
window.addEventListener("DOMContentLoaded", (e) => initializeChanges(e, true));
|
window.addEventListener("DOMContentLoaded", (e) => initializeChanges(e, true));
|
||||||
|
|
||||||
// on localStorage change
|
// on localStorage change
|
||||||
|
@ -164,8 +204,8 @@ function initializeChanges(_, loading) {
|
||||||
width = window.localStorage.getItem("acc-width");
|
width = window.localStorage.getItem("acc-width");
|
||||||
}
|
}
|
||||||
let font = window.localStorage.getItem("acc-font");
|
let font = window.localStorage.getItem("acc-font");
|
||||||
if (font == null) {
|
if (font == null || font == "Lexend Deca") {
|
||||||
window.localStorage.setItem("acc-font", "Lexend Deca");
|
window.localStorage.setItem("acc-font", "");
|
||||||
font = window.localStorage.getItem("acc-font");
|
font = window.localStorage.getItem("acc-font");
|
||||||
}
|
}
|
||||||
let hueOver = window.localStorage.getItem("acc-hue-over");
|
let hueOver = window.localStorage.getItem("acc-hue-over");
|
||||||
|
@ -205,9 +245,11 @@ function initializeChanges(_, loading) {
|
||||||
if (width != null && accWidth != null) accWidth.value = width;
|
if (width != null && accWidth != null) accWidth.value = width;
|
||||||
if (font != null && accFont != null) accFont.value = font;
|
if (font != null && accFont != null) accFont.value = font;
|
||||||
|
|
||||||
if (hueOver != null && accHueOverride != null) accHueOverride.checked = hueOver === "true";
|
if (hueOver != null && accHueOverride != null)
|
||||||
|
accHueOverride.checked = hueOver === "true";
|
||||||
if (hue != null && accHue != null) accHue.value = hue;
|
if (hue != null && accHue != null) accHue.value = hue;
|
||||||
if (satOver != null && accSaturationOverride != null) accSaturationOverride.checked = satOver === "true";
|
if (satOver != null && accSaturationOverride != null)
|
||||||
|
accSaturationOverride.checked = satOver === "true";
|
||||||
if (sat != null && accSaturation != null) accSaturation.value = sat;
|
if (sat != null && accSaturation != null) accSaturation.value = sat;
|
||||||
|
|
||||||
if (base != null && accBase != null) accBase.checked = base === "true";
|
if (base != null && accBase != null) accBase.checked = base === "true";
|
||||||
|
@ -223,26 +265,25 @@ function changeWidth(width) {
|
||||||
|
|
||||||
function changeFont(font) {
|
function changeFont(font) {
|
||||||
document.documentElement.style.setProperty("--font-family", font);
|
document.documentElement.style.setProperty("--font-family", font);
|
||||||
|
document.documentElement.style.setProperty("--header-font-family", font);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const baseColor = getComputedStyle(document.documentElement)
|
||||||
|
.getPropertyValue("--base-color")
|
||||||
const baseColor = getComputedStyle(document.documentElement).getPropertyValue("--base-color").split(", ");
|
.split(", ");
|
||||||
function changeColor(hue, sat, hueOver, satOver) {
|
function changeColor(hue, sat, hueOver, satOver) {
|
||||||
if (accHue != null) accHue.disabled = !hueOver;
|
if (accHue != null) accHue.disabled = !hueOver;
|
||||||
if (accSaturation != null) accSaturation.disabled = !satOver;
|
if (accSaturation != null) accSaturation.disabled = !satOver;
|
||||||
|
|
||||||
document.documentElement.style.setProperty("--base-color",
|
document.documentElement.style.setProperty(
|
||||||
(hueOver ? hue : baseColor[0])
|
"--base-color",
|
||||||
+ ", "
|
(hueOver ? hue : baseColor[0]) + ", " + (satOver ? sat + "%" : baseColor[1])
|
||||||
+ (satOver ? (sat + "%") : baseColor[1])
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (propagateStyles != null) propagateStyles(getComputedStyle(document.documentElement));
|
if (propagateStyles != null)
|
||||||
|
propagateStyles(getComputedStyle(document.documentElement));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function changeBase(base) {
|
function changeBase(base) {
|
||||||
if (base) document.documentElement.classList.add("base");
|
if (base) document.documentElement.classList.add("base");
|
||||||
else document.documentElement.classList.remove("base");
|
else document.documentElement.classList.remove("base");
|
||||||
|
|
58
views/scripts/data_get_domain.js
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
const data_get = document.getElementById("data_get");
|
||||||
|
|
||||||
|
function check_uptime(event, url) {
|
||||||
|
const outElement = event.target;
|
||||||
|
const startTime = performance.now();
|
||||||
|
let status, time, timer;
|
||||||
|
outElement.disabled = true;
|
||||||
|
fetch_ask(url, { mode: "no-cors", cache: "no-cache" })
|
||||||
|
.then((res) => {
|
||||||
|
const endTime = performance.now();
|
||||||
|
time = ((endTime - startTime) / 1000).toFixed(2);
|
||||||
|
outElement.innerHTML = `Check Status (${time}s)`;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
const endTime = performance.now();
|
||||||
|
time = ((endTime - startTime) / 1000).toFixed(2);
|
||||||
|
outElement.innerHTML = `Check Status (${time}s - Error)`;
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
window.cancelAnimationFrame(timer);
|
||||||
|
outElement.disabled = false;
|
||||||
|
});
|
||||||
|
function timeCounter() {
|
||||||
|
const curTime = performance.now();
|
||||||
|
time = (curTime - startTime) / 1000;
|
||||||
|
if (time >= 5)
|
||||||
|
outElement.innerHTML = `Check Status (${time.toFixed(
|
||||||
|
2
|
||||||
|
)}s - Taking longer than usual)`;
|
||||||
|
else outElement.innerHTML = `Check Status (${time.toFixed(2)}s - Waiting)`;
|
||||||
|
timer = window.requestAnimationFrame(timeCounter);
|
||||||
|
}
|
||||||
|
timer = window.requestAnimationFrame(timeCounter);
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch_ask("https://blog.abtmtr.link/api/collections/paste/posts/domain")
|
||||||
|
.then((x) => x.json())
|
||||||
|
.then((paste) => {
|
||||||
|
const data = JSON.parse(paste.data.body);
|
||||||
|
data_get.innerHTML = data.reduce((html, subdomain) => {
|
||||||
|
const id = `${subdomain.name.replaceAll(".", "")}-uptime`;
|
||||||
|
return (
|
||||||
|
html +
|
||||||
|
`<h2><a href="${subdomain.url}" target="_blank">${
|
||||||
|
subdomain.name
|
||||||
|
}</a></h2>
|
||||||
|
${subdomain.description.map((x) => `<p>${x}</p>`).join("")}
|
||||||
|
<img src="${subdomain.src}" alt="${subdomain.name}" title="${
|
||||||
|
subdomain.name
|
||||||
|
}" />
|
||||||
|
<p>
|
||||||
|
<button
|
||||||
|
onclick="check_uptime(event, '${subdomain.url}')"
|
||||||
|
>Check Status</button>
|
||||||
|
<span id="${id}"></span></p>`
|
||||||
|
);
|
||||||
|
}, "");
|
||||||
|
});
|
|
@ -1,77 +0,0 @@
|
||||||
const data_whoami = document.getElementById("data_whoami");
|
|
||||||
const time = document.getElementById("time");
|
|
||||||
const weekday = document.getElementById("weekday");
|
|
||||||
const timezone = document.getElementById("timezone");
|
|
||||||
const nofetchy = document.getElementById("no-fetchy");
|
|
||||||
const about = document.getElementById("about");
|
|
||||||
const statusus = document.getElementById("status");
|
|
||||||
const buttonflags = document.getElementById("buttonflags");
|
|
||||||
const fields = document.getElementById("fields");
|
|
||||||
|
|
||||||
const URL_REGEXP =
|
|
||||||
/(([a-z0-9.-]*)(((:\/\/)([a-z0-9.-]*))((\/)([\w;,\/?:@&=+$\-_.!~*'()#]*))?)|(((mailto|tel):)([\w;,\/?:@&=+$\-_.!~*'()#]*)))/g;
|
|
||||||
fetch("https://pronouns.cc/api/v1/users/MeowcaTheoRange")
|
|
||||||
.then((x) => x.json())
|
|
||||||
.then((user) => {
|
|
||||||
data_whoami.innerHTML = `
|
|
||||||
<p>I'm <a href="https://pronouns.cc/@MeowcaTheoRange" target="_blank"><b>${
|
|
||||||
user.names[0].value
|
|
||||||
}</b></a>, also better known online as <b>${
|
|
||||||
user.name
|
|
||||||
}</b>. <small>(${user.pronouns
|
|
||||||
.filter((pronoun) => pronoun.status == "okay")
|
|
||||||
.map((pronoun) => pronoun.pronouns.split("/")[0])
|
|
||||||
.join("/")})</small></p>`;
|
|
||||||
about.innerHTML = `<h2>Bio</h2><p>MeowcaTheoRange<br />${user.bio
|
|
||||||
.replace(URL_REGEXP, (m) => `<a href="${m}" target="_blank">${m}</a>`)
|
|
||||||
.replaceAll("\n", "<br />")}</p>`;
|
|
||||||
const curTime = new Date();
|
|
||||||
timezone.innerHTML = `(UTC${user.utc_offset > 0 ? "+" : "-"}${Math.abs(
|
|
||||||
user.utc_offset / (60 * 60)
|
|
||||||
)})`;
|
|
||||||
buttonflags.onclick = () => {
|
|
||||||
user.flags.forEach((flag) => {
|
|
||||||
const props = flag.description.split(";");
|
|
||||||
initDocument(
|
|
||||||
props[0].split(","),
|
|
||||||
props[1],
|
|
||||||
props[2],
|
|
||||||
props[3],
|
|
||||||
flag.name
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
buttonflags.disabled = false;
|
|
||||||
function updateTime() {
|
|
||||||
curTime.setTime(Date.now());
|
|
||||||
time.innerHTML = curTime.toLocaleTimeString("en-us", {
|
|
||||||
timeZone: "America/Chicago",
|
|
||||||
});
|
|
||||||
weekday.innerHTML = curTime.toLocaleString("en-us", {
|
|
||||||
weekday: "long",
|
|
||||||
timeZone: "America/Chicago",
|
|
||||||
});
|
|
||||||
|
|
||||||
window.requestAnimationFrame(updateTime);
|
|
||||||
}
|
|
||||||
window.requestAnimationFrame(updateTime);
|
|
||||||
nofetchy.style.display = null;
|
|
||||||
fields.innerHTML = user.fields
|
|
||||||
.map(
|
|
||||||
(fieldset) => `
|
|
||||||
<section>
|
|
||||||
<h2>${fieldset.name}</h2>
|
|
||||||
<ul>${fieldset.entries
|
|
||||||
.map((entry) => `<li>${entry.value}</li>`)
|
|
||||||
.join("")}</ul>
|
|
||||||
</section>`
|
|
||||||
)
|
|
||||||
.join("");
|
|
||||||
});
|
|
||||||
|
|
||||||
fetch("https://local.abtmtr.link/api/v1/accounts/stat/statuses")
|
|
||||||
.then((x) => x.json())
|
|
||||||
.then((statuses) => {
|
|
||||||
console.log(statuses);
|
|
||||||
statusus.innerHTML = `<h2><a href="${statuses[0].url}" target="_blank">Current status</a></h2>${statuses[0].content}<p></p>`;
|
|
||||||
});
|
|
141
views/scripts/roll_buttons.js
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
const buttonroll = document.getElementById("buttonroll");
|
||||||
|
const buttons = [
|
||||||
|
{
|
||||||
|
href: "https://jaiden.sh/",
|
||||||
|
img: "/assets/88x31/jaiden_sh.png",
|
||||||
|
alt: "jaiden.sh",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "https://owenzimmerman.com/",
|
||||||
|
img: "/assets/88x31/owenzimmerman_com.png",
|
||||||
|
alt: "owenzimmerman.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "https://acidicalchemist.neocities.org/",
|
||||||
|
img: "/assets/88x31/acidicalchemist_neocities_org.gif",
|
||||||
|
alt: "acidicalchemist.neocities.org",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "https://arimelody.me/",
|
||||||
|
img: "/assets/88x31/arimelody_me.gif",
|
||||||
|
alt: "arimelody.me",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "https://freeplay.floof.company/",
|
||||||
|
img: "/assets/88x31/freeplay_floof_company.png",
|
||||||
|
alt: "freeplay.floof.company",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "https://invoxiplaygames.uk/",
|
||||||
|
img: "/assets/88x31/invoxiplaygames_uk.png",
|
||||||
|
alt: "invoxiplaygames.uk",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "https://ioletsgo.gay/",
|
||||||
|
img: "/assets/88x31/ioletsgo_gay.gif",
|
||||||
|
alt: "ioletsgo.gay",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "https://mae.wtf/",
|
||||||
|
img: "/assets/88x31/mae_wtf.png",
|
||||||
|
alt: "mae.wtf",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "https://micro.pages.gay/",
|
||||||
|
img: "/assets/88x31/micro_pages_gay.png",
|
||||||
|
alt: "micro.pages.gay",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "https://sneexy.pages.gay/",
|
||||||
|
img: "/assets/88x31/sneexy_pages_gay.gif",
|
||||||
|
alt: "sneexy.pages.gay",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "https://whois.slipfox.xyz/",
|
||||||
|
img: "/assets/88x31/whois_slipfox_xyz.png",
|
||||||
|
alt: "whois.slipfox.xyz",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "https://moth.monster/",
|
||||||
|
img: "/assets/88x31/moth_monster.png",
|
||||||
|
alt: "moth.monster",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "https://translunar.academy/",
|
||||||
|
img: "/assets/88x31/translunar_academy.png",
|
||||||
|
alt: "translunar.academy",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "https://ultramarine-linux.org/",
|
||||||
|
img: "/assets/88x31/esoteric/gnu-linux.gif",
|
||||||
|
alt: "Made on GNU/Linux",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "https://abtmtr.link/projects/item/normalize",
|
||||||
|
img: "/assets/88x31/esoteric/html.gif",
|
||||||
|
alt: "<HTML> - Learn it today!",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "https://vivaldi.com",
|
||||||
|
img: "/assets/88x31/esoteric/vivaldi.gif",
|
||||||
|
alt: "I use Vivaldi",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "https://ublockorigin.com",
|
||||||
|
img: "/assets/88x31/esoteric/ublock.png",
|
||||||
|
alt: "uBlock Origin Now!",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "https://channelstore.roku.com/details/7da3fa0c2209746730df8a4e21e83b02",
|
||||||
|
img: "/assets/88x31/esoteric/xkcd.gif",
|
||||||
|
alt: "xkcd",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
function initializeButtons() {
|
||||||
|
buttonroll.innerHTML += buttons.reduce(
|
||||||
|
(pv, cv) =>
|
||||||
|
pv +
|
||||||
|
`<a href="${cv.href}" target="_blank"><img alt="${cv.alt}" title="${cv.alt}" src="${cv.img}"></a>`,
|
||||||
|
""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonroll.hidden = false;
|
||||||
|
overflowButtons();
|
||||||
|
initializeButtons();
|
||||||
|
overflowButtons();
|
||||||
|
overflowButtons();
|
||||||
|
|
||||||
|
function overflowButtons() {
|
||||||
|
buttonroll.innerHTML += buttons.reduce(
|
||||||
|
(pv, cv) =>
|
||||||
|
pv +
|
||||||
|
`<a href="${cv.href}" target="_blank" class="overflow"><img alt="${cv.alt}" title="${cv.alt}" src="${cv.img}"></a>`,
|
||||||
|
""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let isHovering = false;
|
||||||
|
buttonroll.addEventListener("mouseenter", () => (isHovering = true));
|
||||||
|
buttonroll.addEventListener("mouseleave", () => (isHovering = false));
|
||||||
|
|
||||||
|
let curAnim;
|
||||||
|
let endTime = performance.now();
|
||||||
|
let unit = 88;
|
||||||
|
let gap = 8;
|
||||||
|
let scrollX = (unit + gap) * buttons.length * 2;
|
||||||
|
let speed = 25;
|
||||||
|
let max = (unit + gap) * buttons.length;
|
||||||
|
function scrollButtons(startTime) {
|
||||||
|
let deltaTime = (startTime - endTime) / 1000;
|
||||||
|
|
||||||
|
if (!isHovering) {
|
||||||
|
scrollX += speed * deltaTime;
|
||||||
|
} else scrollX = buttonroll.scrollLeft;
|
||||||
|
buttonroll.scrollLeft = (scrollX % max) + max;
|
||||||
|
|
||||||
|
endTime = startTime;
|
||||||
|
curAnim = window.requestAnimationFrame(scrollButtons);
|
||||||
|
}
|
||||||
|
curAnim = window.requestAnimationFrame(scrollButtons);
|
|
@ -1,54 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<title>Site Information - abtmtr.link</title>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<link rel="stylesheet" href="/styles/normal.css" />
|
|
||||||
<link rel="stylesheet" href="/styles/style.css" />
|
|
||||||
<style>
|
|
||||||
:root {
|
|
||||||
--base-color: 125, 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<header>
|
|
||||||
<section>
|
|
||||||
<h1>Site Information</h1>
|
|
||||||
</section>
|
|
||||||
<$ nav.html $>
|
|
||||||
<section id="accessibility" hidden></section>
|
|
||||||
</header>
|
|
||||||
<main>
|
|
||||||
<section>
|
|
||||||
<h2>What happened to the previous site?</h2>
|
|
||||||
<p>
|
|
||||||
The previous site kinda sucked. It depended on client-side React for
|
|
||||||
the most basic of things, and was just overall kind of a mess of TSX
|
|
||||||
everywhere.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
This site is represented semi-statically, which means there's nothing
|
|
||||||
new being generated on the backend.<br />
|
|
||||||
This site does not use React either, so everything the frontend runs
|
|
||||||
is vanilla JavaScript.
|
|
||||||
</p>
|
|
||||||
<h2>
|
|
||||||
What's with the <b>accessibility controls</b> on every page of the
|
|
||||||
site?
|
|
||||||
</h2>
|
|
||||||
<p>
|
|
||||||
Just because. If you want to make the text bigger or get rid of the
|
|
||||||
colors, you have that panel.
|
|
||||||
</p>
|
|
||||||
<h2>What font are you using for this site?</h2>
|
|
||||||
<p>
|
|
||||||
<b>Lexend Deca</b>, or your <b>system's default sans-serif font</b>,
|
|
||||||
depending on if you're using Base style.
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
</main>
|
|
||||||
<script src="/scripts/accessibility.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
34
views/styles/buttonroll.css
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#buttonroll {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
overflow-x: scroll;
|
||||||
|
overflow-y: hidden;
|
||||||
|
gap: 8px;
|
||||||
|
max-width: 50em;
|
||||||
|
margin: auto;
|
||||||
|
padding: 8px 0;
|
||||||
|
}
|
||||||
|
#buttonroll a {
|
||||||
|
display: inline-block;
|
||||||
|
width: 88px;
|
||||||
|
height: 31px;
|
||||||
|
}
|
||||||
|
#buttonroll img {
|
||||||
|
display: inline-block;
|
||||||
|
width: 88px;
|
||||||
|
height: 31px;
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #buttonroll .overflow {
|
||||||
|
opacity: 0.5;
|
||||||
|
} */
|
||||||
|
|
||||||
|
#buttonroll::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#buttonroll {
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
53
views/styles/crt.css
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
body {
|
||||||
|
background-color: black;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.screen {
|
||||||
|
width: 800px;
|
||||||
|
height: 600px;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
translate: -50% -50%;
|
||||||
|
box-shadow: 0 0 64px 4px #fff4;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.screen iframe {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.screen div.crt {
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: repeating-linear-gradient(
|
||||||
|
0deg,
|
||||||
|
#0006 0px,
|
||||||
|
#0006 1px,
|
||||||
|
#0000 1px,
|
||||||
|
#0000 2px
|
||||||
|
);
|
||||||
|
background-repeat: repeat;
|
||||||
|
background-position: 0 0;
|
||||||
|
background-size: 2px;
|
||||||
|
user-select: none;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 9000;
|
||||||
|
}
|
86
views/styles/myapp.css
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
@font-face {
|
||||||
|
font-family: "Lexend Deca";
|
||||||
|
src: url("/assets/fonts/Lexend Deca/Variable.ttf");
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: "Minecraft";
|
||||||
|
src: url("/assets/fonts/Minecraft/Regular.otf");
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: "Renogare";
|
||||||
|
src: url("/assets/fonts/Renogare/Regular.otf");
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: "NDS12";
|
||||||
|
src: url("/assets/fonts/NDS12/Regular.otf");
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: "OpenDyslexic";
|
||||||
|
src: url("/assets/fonts/OpenDyslexic/Regular.otf");
|
||||||
|
}
|
||||||
|
:root {
|
||||||
|
--header-font-family: "Renogare";
|
||||||
|
--header-font-weight: 400;
|
||||||
|
--font-family: "Lexend Deca";
|
||||||
|
--border-width: calc(2rem / 16);
|
||||||
|
--base-color: 325, 50%;
|
||||||
|
--border-radius: calc(4rem / 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
#accessibility {
|
||||||
|
/* position: sticky;
|
||||||
|
bottom: 1em;
|
||||||
|
left: 1em; */
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#accessibility fieldset {
|
||||||
|
margin-block: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* * {
|
||||||
|
font-smooth: never;
|
||||||
|
-webkit-font-smoothing: subpixel-antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
} */
|
||||||
|
|
||||||
|
.nav {
|
||||||
|
max-width: 38em;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav p {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||||
|
gap: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav p * {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.base .nav {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.base .nav p * {
|
||||||
|
text-align: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
border-bottom: var(--border-width) var(--border-style) var(--border-color);
|
||||||
|
padding-bottom: 0em;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
border-bottom: var(--border-width) var(--border-style) var(--border-color);
|
||||||
|
padding-bottom: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 a,
|
||||||
|
h2 a {
|
||||||
|
text-decoration: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rs {
|
||||||
|
float: inline-end;
|
||||||
|
}
|
|
@ -1,63 +1,18 @@
|
||||||
@font-face {
|
@import url("./myapp.css");
|
||||||
font-family: "Lexend Deca";
|
|
||||||
src: url("/assets/fonts/Lexend Deca/Variable.ttf");
|
html:not(.base) {
|
||||||
}
|
background: url("/assets/bg.jpg");
|
||||||
@font-face {
|
background-position: center;
|
||||||
font-family: "Minecraft";
|
background-size: cover;
|
||||||
src: url("/assets/fonts/Minecraft/Regular.otf");
|
background-attachment: fixed;
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: "Renogare";
|
|
||||||
src: url("/assets/fonts/Renogare/Regular.otf");
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: "NDS12";
|
|
||||||
src: url("/assets/fonts/NDS12/Regular.otf");
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: "OpenDyslexic";
|
|
||||||
src: url("/assets/fonts/OpenDyslexic/Regular.otf");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--font-family: "Lexend Deca";
|
--background-color: hsla(var(--base-color), 15%, 0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
#accessibility {
|
@media (prefers-color-scheme: light) {
|
||||||
/* position: sticky;
|
:root {
|
||||||
bottom: 1em;
|
--background-color: hsla(var(--base-color), 80%, 0.9);
|
||||||
left: 1em; */
|
|
||||||
padding: 0.5em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#accessibility fieldset {
|
|
||||||
margin-block: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* * {
|
|
||||||
font-smooth: never;
|
|
||||||
-webkit-font-smoothing: subpixel-antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
} */
|
|
||||||
|
|
||||||
.nav {
|
|
||||||
max-width: 38em;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav p {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr 1fr;
|
|
||||||
gap: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav p a {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
html.base .nav {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
html.base .nav p a {
|
|
||||||
text-align: start;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ div.window-object {
|
||||||
color: var(--accent-color-fg);
|
color: var(--accent-color-fg);
|
||||||
--border-color: var(--color);
|
--border-color: var(--color);
|
||||||
border: var(--border-width) var(--border-style) var(--border-color);
|
border: var(--border-width) var(--border-style) var(--border-color);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
resize: both;
|
resize: both;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 0.25em;
|
padding: 0.25em;
|
||||||
|
@ -47,6 +48,7 @@ html.base div.window-object {
|
||||||
background-color: var(--accent-color);
|
background-color: var(--accent-color);
|
||||||
color: var(--accent-color-fg);
|
color: var(--accent-color-fg);
|
||||||
border: var(--border-width) var(--border-style) var(--border-color);
|
border: var(--border-width) var(--border-style) var(--border-color);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (forced-colors: active) {
|
@media (forced-colors: active) {
|
||||||
|
@ -108,6 +110,7 @@ div.window-object {
|
||||||
background-color: var(--accent-color);
|
background-color: var(--accent-color);
|
||||||
color: var(--accent-color-fg);
|
color: var(--accent-color-fg);
|
||||||
border: var(--border-width) var(--border-style) var(--border-color);
|
border: var(--border-width) var(--border-style) var(--border-color);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,6 +125,7 @@ div.window-object {
|
||||||
background-color: var(--accent-color);
|
background-color: var(--accent-color);
|
||||||
color: var(--accent-color-fg);
|
color: var(--accent-color-fg);
|
||||||
border: var(--border-width) var(--border-style) var(--border-color);
|
border: var(--border-width) var(--border-style) var(--border-color);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,6 +221,7 @@ div.window-object > div.window-manager > div > button {
|
||||||
margin-inline-start: 0.25em;
|
margin-inline-start: 0.25em;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border: var(--border-width) var(--border-style) var(--border-color);
|
border: var(--border-width) var(--border-style) var(--border-color);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
color: currentColor;
|
color: currentColor;
|
||||||
font-family: "Material Symbols Outlined";
|
font-family: "Material Symbols Outlined";
|
||||||
|
@ -231,6 +236,7 @@ div.window-object > iframe.window-content {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: var(--border-width) var(--border-style) var(--border-color);
|
border: var(--border-width) var(--border-style) var(--border-color);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
201
views/tigerrs-minecraft/index.html
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>abtmtr.link</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<link rel="stylesheet" href="/styles/normal.css" />
|
||||||
|
<link rel="stylesheet" href="/styles/myapp.css" />
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--base-color: 128, 50%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1>TIGERRS Minecraft Server</h1>
|
||||||
|
<p>
|
||||||
|
Information regarding the Minecraft server I'm running for the TIGERRS
|
||||||
|
community.
|
||||||
|
</p>
|
||||||
|
<$ nav.html $>
|
||||||
|
<section id="accessibility" hidden></section>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<section>
|
||||||
|
<h1>Rules</h1>
|
||||||
|
<p>These are the rules of the server.</p>
|
||||||
|
<h2>Good Faith</h2>
|
||||||
|
<p>
|
||||||
|
Assume that all players are working in good faith. If someone does
|
||||||
|
something that seems ignorant or rude to you, speak up gently, not
|
||||||
|
harshly.
|
||||||
|
</p>
|
||||||
|
<h2>Sensitive Topics</h2>
|
||||||
|
<p>
|
||||||
|
When discussing sensitive topics, you can use spoiler syntax around
|
||||||
|
your text like this:
|
||||||
|
</p>
|
||||||
|
<pre><spoiler>Test</spoiler></pre>
|
||||||
|
<p>
|
||||||
|
You can also use this shorter syntax to spoiler everything after the
|
||||||
|
tag:
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
This will not be spoilered but <spoiler>all of this will be spoilered</pre
|
||||||
|
>
|
||||||
|
<p>In order to show the spoilers, hover over the text.</p>
|
||||||
|
<h2>Language</h2>
|
||||||
|
<p>
|
||||||
|
Please do not use any slurs, reclaimed or not, as we would like to keep spirits high.
|
||||||
|
</p>
|
||||||
|
<p>Just be silly :3</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h1>Open Hours</h1>
|
||||||
|
<p><i>All times are in Central Time.</i></p>
|
||||||
|
<p><b>Sunday:</b> 9:00 AM–10:00 PM</p>
|
||||||
|
<!-- 0 -->
|
||||||
|
<p><b>Monday:</b> 3:00 PM–10:00 PM</p>
|
||||||
|
<!-- 1 -->
|
||||||
|
<p><b>Tuesday:</b> 3:00 PM–12:00 AM (next day)</p>
|
||||||
|
<!-- 2 -->
|
||||||
|
<p><b>Wednesday:</b> 9:00 AM–10:00 PM</p>
|
||||||
|
<!-- 3 -->
|
||||||
|
<p><b>Thursday:</b> 3:00 PM–10:00 PM</p>
|
||||||
|
<!-- 4 -->
|
||||||
|
<p><b>Friday:</b> 3:00 PM–12:00 AM (next day)</p>
|
||||||
|
<!-- 5 -->
|
||||||
|
<p><b>Saturday:</b> 9:00 AM–12:00 AM (next day)</p>
|
||||||
|
<!-- 6 -->
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h1>Recommended Setup</h1>
|
||||||
|
<p>
|
||||||
|
While the server supports all Minecraft versions since <b>1.19.4</b>,
|
||||||
|
it is recommended that you use version 1.19.4 specifically,
|
||||||
|
<a href="https://fabricmc.net/use/installer/" target="_blank"
|
||||||
|
>especially with the Fabric mod loader</a
|
||||||
|
>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If you're using Fabric, it's also recommended that you install these
|
||||||
|
mods:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="https://modrinth.com/mod/clientsidenoteblocks"
|
||||||
|
target="_blank"
|
||||||
|
>Client Side Noteblocks</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="https://modrinth.com/plugin/invisible-frames"
|
||||||
|
target="_blank"
|
||||||
|
>Invisible Frames</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://modrinth.com/mod/krypton" target="_blank"
|
||||||
|
>Krypton</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://modrinth.com/mod/lambdynamiclights" target="_blank"
|
||||||
|
>LambDynamicLights</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://modrinth.com/mod/serverpingerfixer" target="_blank"
|
||||||
|
>Server Pinger Fixer</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="https://modrinth.com/mod/show-me-what-you-got"
|
||||||
|
target="_blank"
|
||||||
|
>Show Me What You Got</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="https://modrinth.com/plugin/simple-voice-chat"
|
||||||
|
target="_blank"
|
||||||
|
>Simple Voice Chat</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://modrinth.com/mod/zume" target="_blank">Zume</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
Even if you don't have any mods installed, these modded actions will
|
||||||
|
still work:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li><i>EditSign</i> sign editing (especially if you're on 1.20+)</li>
|
||||||
|
<li><i>VeinDigging</i> vein digging</li>
|
||||||
|
<li><i>FallingTree</i> tree cutting</li>
|
||||||
|
<li><i>TabTPS</i> server performance in player menu</li>
|
||||||
|
<li><i>Couplings</i> opening double-doors simultaneously</li>
|
||||||
|
<li>
|
||||||
|
<i>Show Me What You Got</i> item chat (you cannot chat items,
|
||||||
|
however)
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<i>Invisible Frames</i> item frames (you cannot make item frames
|
||||||
|
invisible, however)
|
||||||
|
</li>
|
||||||
|
<li><i>Flan</i> region claiming</li>
|
||||||
|
<li><i>WorldEdit</i> wand usage</li>
|
||||||
|
<li><i>SleepWarp</i> night skipping</li>
|
||||||
|
<li><i>StyledChat</i> chat formatting</li>
|
||||||
|
<li><i>Healthcare</i> health indicators</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h1>Server Address</h1>
|
||||||
|
<p>
|
||||||
|
The server can be found at
|
||||||
|
<b onclick="window.getSelection().selectAllChildren(this);"
|
||||||
|
>tigerrs.abtmtr.link</b
|
||||||
|
>
|
||||||
|
for Minecraft: Java Edition versions <b>1.19.4+</b>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
For Minecraft (Bedrock Edition), you should use version
|
||||||
|
<b>1.20.51</b> (latest).
|
||||||
|
</p>
|
||||||
|
<p>In order to join the server, you have to be whitelisted.</p>
|
||||||
|
<h2>Web map</h2>
|
||||||
|
<p>
|
||||||
|
A web map of the world can be found at
|
||||||
|
<a href="https://tigerrs.abtmtr.link" target="_blank"
|
||||||
|
>the same domain, on HTTPS</a
|
||||||
|
>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If you can't join, you can at least peer inside and see what's
|
||||||
|
happening.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h1>Is this official?</h1>
|
||||||
|
<p>
|
||||||
|
Keep in mind this server is <b>completely unofficial</b>, and is
|
||||||
|
running unaffiliated to the TIGERRS collective.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This means that none of the activities on the server are officially
|
||||||
|
moderated - instead, server rules and regulations are up to the server
|
||||||
|
admins.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
<script src="/scripts/accessibility.js"></script>
|
||||||
|
<script src="./scripts/data_check_uptime.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,34 +1,30 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<title>Domain - abtmtr.link</title>
|
<title>abtmtr.link</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<link rel="stylesheet" href="/styles/normal.css" />
|
<link rel="stylesheet" href="/styles/normal.css" />
|
||||||
<link rel="stylesheet" href="/styles/style.css" />
|
<link rel="stylesheet" href="/styles/style.css" />
|
||||||
<style>
|
|
||||||
:root {
|
|
||||||
--base-color: 15, 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<$ loader.html $>
|
|
||||||
<header>
|
<header>
|
||||||
<section>
|
<h1>Who are we?</h1>
|
||||||
<h1>Domain</h1>
|
|
||||||
<p>What's on this domain.</p>
|
|
||||||
</section>
|
|
||||||
<$ nav.html $>
|
<$ nav.html $>
|
||||||
<section id="accessibility" hidden></section>
|
<section id="accessibility" hidden></section>
|
||||||
|
<div id="buttonroll" hidden></div>
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main>
|
||||||
|
<section>
|
||||||
|
<h1>We're abtmtr.link.</h1>
|
||||||
|
<p>abtmtr.link is an unprofessional consulting-firm/open-source-project-manager ran by one person who is actually more.</p>
|
||||||
|
<p>We're not an actual company. Don't try to call us. <a href="mailto:me@abtmtr.link">You can email us, however.</a></p>
|
||||||
|
</section>
|
||||||
<section id="data_get">
|
<section id="data_get">
|
||||||
<h1>Getting domain indexes...</h1>
|
<h1>Getting member indexes...</h1>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
<section id="accessibility" hidden></section>
|
|
||||||
<script src="/scripts/accessibility.js"></script>
|
<script src="/scripts/accessibility.js"></script>
|
||||||
<script src="./scripts/data_get_domain.js"></script>
|
<script src="./scripts/data_get_members.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
13
views/whois/scripts/data_get_members.js
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
fetch_ask("https://pronouns.cc/api/v1/users/clhd8desmggedm3q1t3g")
|
||||||
|
.then((x) => x.json())
|
||||||
|
.then((data) => {
|
||||||
|
data_get.innerHTML = data.members.reduce((html, member) => (
|
||||||
|
html +
|
||||||
|
`<h2><a href="https://pronouns.cc/@${data.name}/${member.name}" target="_blank">${member.display_name}</a> <small>${member.pronouns.map(x => x.pronouns.split("/")[0]).join("/")}</small></h2>
|
||||||
|
<fieldset>
|
||||||
|
${member.names.map(x => `<p><b>${x.value}</b> (${x.status})</p>`).join("")}
|
||||||
|
</fieldset>
|
||||||
|
<p>${member.bio.replaceAll("\n", "<br />")}</p>
|
||||||
|
<p>Signature: <b>${member.name}</b></p>`
|
||||||
|
), "");
|
||||||
|
});
|