」 feat: tournament done, added env vars

This commit is contained in:
y-syo
2025-10-24 11:24:26 +02:00
parent 808228a32a
commit e8177cc8d9
13 changed files with 193 additions and 92 deletions

View File

@ -29,3 +29,6 @@ EMAIL_TO=<mail to send to>
USER_URL=<the url to the user api> USER_URL=<the url to the user api>
AUTH_URL=<the url to the auth api> AUTH_URL=<the url to the auth api>
CORS_ORIGIN=<the url of origin for cors> CORS_ORIGIN=<the url of origin for cors>
VITE_USER_API=<the external url of the user api>
VITE_AUTH_API=<the external url of the auth api>

View File

@ -4,8 +4,11 @@ import FriendsMenu from "./views/Friends.ts";
let profile_view = new ProfileMenu; let profile_view = new ProfileMenu;
let friends_view = new FriendsMenu; let friends_view = new FriendsMenu;
export const user_api = import.meta.env.VITE_USER_API as String;
export const auth_api = import.meta.env.VITE_AUTH_API as String;
export async function isLogged(): Promise<boolean> { export async function isLogged(): Promise<boolean> {
let uuid_req = await fetch("http://localhost:3001/me", { let uuid_req = await fetch(auth_api + "/me", {
method: "GET", method: "GET",
credentials: "include", credentials: "include",
}); });
@ -129,7 +132,7 @@ function updateClock()
async function pingClock() { async function pingClock() {
if (await isLogged()) { if (await isLogged()) {
fetch(`http://localhost:3002/ping`, { fetch(user_api + "/ping", {
method: "POST", method: "POST",
credentials: "include" credentials: "include"
}); });

View File

@ -1,7 +1,7 @@
import Aview from "./Aview.ts" import Aview from "./Aview.ts"
import { setOnekoState } from "../oneko.ts"
import { dragElement } from "./drag.ts"; import { dragElement } from "./drag.ts";
import { isLogged, navigationManager } from "../main.ts" import { setOnekoState } from "../oneko.ts"
import { isLogged, navigationManager, user_api, auth_api } from "../main.ts"
export default class extends Aview { export default class extends Aview {
@ -58,7 +58,7 @@ export default class extends Aview {
const add_friend_msg = (document.getElementById("add-friend-msg") as HTMLParagraphElement); const add_friend_msg = (document.getElementById("add-friend-msg") as HTMLParagraphElement);
async function removeFriend(name: String) { async function removeFriend(name: String) {
const data_req = await fetch("http://localhost:3002/users/" + uuid + "/friends/" + name, { const data_req = await fetch(user_api + "/users/" + uuid + "/friends/" + name, {
method: "DELETE", method: "DELETE",
credentials: "include", credentials: "include",
}); });
@ -76,7 +76,7 @@ export default class extends Aview {
} }
async function isFriendLogged(name: string): Promise<Boolean> { async function isFriendLogged(name: string): Promise<Boolean> {
const data_req = await fetch("http://localhost:3002/ping/" + name, { const data_req = await fetch(user_api + "/ping/" + name, {
method: "GET", method: "GET",
credentials: "include", credentials: "include",
}); });
@ -88,7 +88,7 @@ export default class extends Aview {
} }
const list_friends = async () => { const list_friends = async () => {
const data_req = await fetch("http://localhost:3002/users/" + uuid + "/friends/count", { const data_req = await fetch(user_api + "/users/" + uuid + "/friends/count", {
method: "GET", method: "GET",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
@ -103,7 +103,7 @@ export default class extends Aview {
} }
if (data.n_friends > 0) { if (data.n_friends > 0) {
const list_req = await fetch("http://localhost:3002/users/" + uuid + "/friends?iStart=0&iEnd=2147483647", { const list_req = await fetch(user_api + "/users/" + uuid + "/friends?iStart=0&iEnd=2147483647", {
method: "GET", method: "GET",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
@ -156,7 +156,7 @@ export default class extends Aview {
} }
const add_friend = async () => { const add_friend = async () => {
const data_req = await fetch("http://localhost:3002/users/" + uuid + "/friends/" + new_friend.value, { const data_req = await fetch(user_api + "/users/" + uuid + "/friends/" + new_friend.value, {
method: "POST", method: "POST",
credentials: "include", credentials: "include",
}); });
@ -179,7 +179,7 @@ export default class extends Aview {
} }
try { try {
const data_req = await fetch("http://localhost:3002/users/" + uuid + "/friends/count", { const data_req = await fetch(user_api + "/users/" + uuid + "/friends/count", {
method: "GET", method: "GET",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",

View File

@ -1,7 +1,7 @@
import Aview from "./Aview.ts" import Aview from "./Aview.ts"
import { dragElement } from "./drag.ts" import { dragElement } from "./drag.ts"
import { setOnekoState } from "../oneko.ts" import { setOnekoState } from "../oneko.ts"
import { isLogged, navigationManager } from "../main.ts" import { isLogged, navigationManager, user_api, auth_api } from "../main.ts"
export default class extends Aview { export default class extends Aview {
@ -39,13 +39,13 @@ export default class extends Aview {
<hr class="my-4 w-64 reverse-border"> <hr class="my-4 w-64 reverse-border">
<div class="flex flex-col space-y-4 w-full"> <div class="flex flex-col space-y-4 w-full">
<a target="_blank" href="http://localhost:3001/login/google" class="default-button inline-flex items-center justify-center w-full"> <a target="_blank" id="login-google" class="default-button inline-flex items-center justify-center w-full">
<img src="https://upload.wikimedia.org/wikipedia/commons/c/c1/Google_%22G%22_logo.svg" height=20 width=20 class="mr-2 justify-self-start" /> <img src="https://upload.wikimedia.org/wikipedia/commons/c/c1/Google_%22G%22_logo.svg" height=20 width=20 class="mr-2 justify-self-start" />
login with John Google login with google
</a> </a>
<a target="_blank" href="https://rusty.42angouleme.fr/issues/all" class="default-button inline-flex items-center justify-center w-full"> <a target="_blank" href="https://rusty.42angouleme.fr/issues/all" class="default-button inline-flex items-center justify-center w-full">
<img src="https://rusty.42angouleme.fr/assets/favicon-bb06adc80c8495db.ico" height=20 width=20 class="mr-2 justify-self-start" /> <img src="https://rusty.42angouleme.fr/assets/favicon-bb06adc80c8495db.ico" height=20 width=20 class="mr-2 justify-self-start" />
login with Rusty login with rusty
</a> </a>
</div> </div>
</div> </div>
@ -55,6 +55,7 @@ export default class extends Aview {
} }
async run() { async run() {
document.getElementById("login-google").href = `${auth_api}/login/google`;
dragElement(document.getElementById("window")); dragElement(document.getElementById("window"));
const totpVerify = async () => { const totpVerify = async () => {
@ -63,7 +64,7 @@ export default class extends Aview {
const totpPin = (document.getElementById('totpPin') as HTMLInputElement).value; const totpPin = (document.getElementById('totpPin') as HTMLInputElement).value;
const idWindow = (document.getElementById('2fa-popup-content') as HTMLInputElement); const idWindow = (document.getElementById('2fa-popup-content') as HTMLInputElement);
try { try {
const data_req = await fetch("http://localhost:3001/login", { const data_req = await fetch(auth_api + "/login", {
method: "POST", method: "POST",
headers: { "Content-Type": "application/json", }, headers: { "Content-Type": "application/json", },
credentials: "include", credentials: "include",
@ -101,7 +102,7 @@ export default class extends Aview {
const password = (document.getElementById("password") as HTMLInputElement).value; const password = (document.getElementById("password") as HTMLInputElement).value;
try { try {
const data_req = await fetch("http://localhost:3001/login", { const data_req = await fetch(auth_api + "/login", {
method: "POST", method: "POST",
headers: { "Content-Type": "application/json", }, headers: { "Content-Type": "application/json", },
credentials: "include", credentials: "include",

View File

@ -1,7 +1,7 @@
import Aview from "./Aview.ts" import Aview from "./Aview.ts"
import { isLogged } from "../main.js" import { isLogged } from "../main.js"
import { dragElement } from "./drag.js" import { dragElement } from "./drag.js"
import { setOnekoState, setBallPos, setOnekoOffset } from "../oneko.ts" import { setOnekoState, setBallPos, setOnekoOffset , user_api, auth_api } from "../oneko.ts"
export default class extends Aview { export default class extends Aview {
@ -151,7 +151,7 @@ export default class extends Aview {
if (await isLogged()) if (await isLogged())
{ {
let uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2]; let uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
fetch(`http://localhost:3002/users/${uuid}/matchHistory?game=pong`, { fetch(user_api + "/users/" + uuid + "/matchHistory?game=pong", {
method: "POST", method: "POST",
headers: { "Content-Type": "application/json", }, headers: { "Content-Type": "application/json", },
credentials: "include", credentials: "include",
@ -287,11 +287,11 @@ export default class extends Aview {
let p1_isvalid = true; let p1_isvalid = true;
let p2_isvalid = true; let p2_isvalid = true;
if (await isLogged()) { if (await isLogged()) {
const p1_req = await fetch(`http://localhost:3002/users/${p1_input.value}`, { const p1_req = await fetch(`${user_api}/users/${p1_input.value}`, {
method: "GET", method: "GET",
credentials: "include", credentials: "include",
}); });
const p2_req = await fetch(`http://localhost:3002/users/${p2_input.value}`, { const p2_req = await fetch(`${user_api}/users/${p2_input.value}`, {
method: "GET", method: "GET",
credentials: "include", credentials: "include",
}); });

View File

@ -1,7 +1,7 @@
import Aview from "./Aview.ts" import Aview from "./Aview.ts"
import { dragElement } from "./drag.ts"; import { dragElement } from "./drag.ts";
import { setOnekoState } from "../oneko.ts" import { setOnekoState } from "../oneko.ts"
import { isLogged, navigationManager } from "../main.ts" import { isLogged, navigationManager, user_api, auth_api } from "../main.ts"
export default class extends Aview { export default class extends Aview {
@ -49,7 +49,7 @@ export default class extends Aview {
let uuid: String; let uuid: String;
uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2]; uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
const userdata_req = await fetch(`http://localhost:3002/users/${uuid}`, { const userdata_req = await fetch(`${user_api}/users/${uuid}`, {
method: "GET", method: "GET",
credentials: "include", credentials: "include",
}); });
@ -59,14 +59,14 @@ export default class extends Aview {
} }
let userdata = await userdata_req.json(); let userdata = await userdata_req.json();
let matchCount_req = await fetch(`http://localhost:3002/users/${uuid}/matchHistory/count?game=pong`, { let matchCount_req = await fetch(`${user_api}/users/${uuid}/matchHistory/count?game=pong`, {
method: "GET", method: "GET",
credentials: "include", credentials: "include",
}); });
let matchCount = await matchCount_req.json(); let matchCount = await matchCount_req.json();
pc += matchCount.n_matches; pc += matchCount.n_matches;
let matches_req = await fetch(`http://localhost:3002/users/${uuid}/matchHistory?game=pong&iStart=0&iEnd=${matchCount.n_matches}`, { let matches_req = await fetch(`${user_api}/users/${uuid}/matchHistory?game=pong&iStart=0&iEnd=${matchCount.n_matches}`, {
method: "GET", method: "GET",
credentials: "include", credentials: "include",
}); });
@ -78,7 +78,7 @@ export default class extends Aview {
if (matches.matchHistory) { if (matches.matchHistory) {
for (let match of matches.matchHistory) { for (let match of matches.matchHistory) {
const p2_req = await fetch(`http://localhost:3002/users/${match.score.p2}`, { const p2_req = await fetch(`${user_api}/users/${match.score.p2}`, {
method: "GET", method: "GET",
credentials: "include", credentials: "include",
}); });
@ -121,14 +121,14 @@ export default class extends Aview {
} }
} }
matchCount_req = await fetch(`http://localhost:3002/users/${uuid}/matchHistory/count?game=tetris`, { matchCount_req = await fetch(`${user_api}/users/${uuid}/matchHistory/count?game=tetris`, {
method: "GET", method: "GET",
credentials: "include", credentials: "include",
}); });
matchCount = await matchCount_req.json(); matchCount = await matchCount_req.json();
pc += matchCount.n_matches; pc += matchCount.n_matches;
matches_req = await fetch(`http://localhost:3002/users/${uuid}/matchHistory?game=tetris&iStart=0&iEnd=${matchCount.n_matches}`, { matches_req = await fetch(`${user_api}/users/${uuid}/matchHistory?game=tetris&iStart=0&iEnd=${matchCount.n_matches}`, {
method: "GET", method: "GET",
credentials: "include", credentials: "include",
}); });
@ -143,7 +143,7 @@ export default class extends Aview {
for (let match of matches.matchHistory) { for (let match of matches.matchHistory) {
if (match.score.p2 != undefined) if (match.score.p2 != undefined)
{ {
const p2_req = await fetch(`http://localhost:3002/users/${match.score.p2}`, { const p2_req = await fetch(`${user_api}/users/${match.score.p2}`, {
method: "GET", method: "GET",
credentials: "include", credentials: "include",
}); });
@ -199,12 +199,12 @@ export default class extends Aview {
if (!profile) return; if (!profile) return;
const picture = profile.appendChild(document.createElement("img")); const picture = profile.appendChild(document.createElement("img"));
const a = await fetch(`http://localhost:3002/users/${uuid}/avatar`, { const a = await fetch(`${user_api}/users/${uuid}/avatar`, {
method: "GET", method: "GET",
credentials: "include", credentials: "include",
}); });
picture.src = a.status === 200 picture.src = a.status === 200
? `http://localhost:3002/users/${uuid}/avatar?t=${Date.now()}` ? `${user_api}/users/${uuid}/avatar?t=${Date.now()}`
: "https://api.kanel.ovh/pp"; : "https://api.kanel.ovh/pp";
picture.classList.add("text-neutral-900", "dark:text-white", "center", "h-18", "w-18", "mx-3", "reverse-border"); picture.classList.add("text-neutral-900", "dark:text-white", "center", "h-18", "w-18", "mx-3", "reverse-border");

View File

@ -1,5 +1,5 @@
import Aview from "./Aview.ts" import Aview from "./Aview.ts"
import { isLogged, navigationManager } from "../main.ts" import { isLogged, user_api, auth_api } from "../main.ts"
export default class extends Aview { export default class extends Aview {
async getHTML() { async getHTML() {
@ -7,8 +7,7 @@ export default class extends Aview {
<div id="main-window" class="default-border shadow-2x1 bg-neutral-200 dark:bg-neutral-800"> <div id="main-window" class="default-border shadow-2x1 bg-neutral-200 dark:bg-neutral-800">
<div class="flex flex-row items-stretch"> <div class="flex flex-row items-stretch">
<div class="inline-block bg-linear-to-b from-orange-200 to-orange-300 min-h-84 w-6 relative"> <div class="inline-block bg-linear-to-b from-orange-200 to-orange-300 min-h-84 w-6 relative">
<!--div class="absolute bottom-1 left-full whitespace-nowrap origin-bottom-left -rotate-90 font-bold">knl_meowscendence</div--> <div class="absolute bottom-1 left-full whitespace-nowrap origin-bottom-left -rotate-90 font-bold">knl_meowscendence</div>
<div class="absolute bottom-1 left-full whitespace-nowrap origin-bottom-left -rotate-90 font-bold">girls kissing :3</div>
</div> </div>
<div class="flex flex-col items-center"> <div class="flex flex-col items-center">
@ -49,7 +48,7 @@ export default class extends Aview {
document.getElementById("menu-bottom-div")?.classList.remove("hidden"); document.getElementById("menu-bottom-div")?.classList.remove("hidden");
uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2]; uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
const userdata_req = await fetch(`http://localhost:3002/users/${uuid}`, { const userdata_req = await fetch(`${user_api}/users/${uuid}`, {
method: "GET", method: "GET",
credentials: "include", credentials: "include",
}); });
@ -68,20 +67,21 @@ export default class extends Aview {
`; `;
} }
requestAnimationFrame(async () => {
document.getElementById("profile-items").innerHTML = await getMainHTML(); document.getElementById("profile-items").innerHTML = await getMainHTML();
requestAnimationFrame(() => {
document.getElementById("menu-logout").addEventListener("click", async () => { document.getElementById("menu-logout").addEventListener("click", async () => {
let req = await fetch("http://localhost:3001/logout", { let req = fetch(`${auth_api}/logout`, {
method: "GET", method: "GET",
credentials: "include", credentials: "include",
}); });
req.then((res) => {
isLogged(); isLogged();
if (req.status === 200) if (res.status === 200)
this.run(); this.run();
else else
console.error("logout failed"); console.error("logout failed");
}); });
document.getElementById("profile-items").innerHTML = await getMainHTML(); });
});
} }
} }

View File

@ -1,7 +1,7 @@
import Aview from "./Aview.ts" import Aview from "./Aview.ts"
import { dragElement } from "./drag.ts"; import { dragElement } from "./drag.ts";
import { setOnekoState } from "../oneko.ts" import { setOnekoState } from "../oneko.ts"
import { isLogged, navigationManager } from "../main.ts" import { isLogged, navigationManager, user_api, auth_api } from "../main.ts"
export default class extends Aview { export default class extends Aview {
@ -38,13 +38,13 @@ export default class extends Aview {
<hr class="my-4 w-64 reverse-border"> <hr class="my-4 w-64 reverse-border">
<div class="flex flex-col space-y-4 w-full"> <div class="flex flex-col space-y-4 w-full">
<a target="_blank" href="http://localhost:3001/register/google" class="default-button inline-flex items-center justify-center w-full"> <a target="_blank" id="register-google" class="default-button inline-flex items-center justify-center w-full">
<img src="https://upload.wikimedia.org/wikipedia/commons/c/c1/Google_%22G%22_logo.svg" height=20 width=20 class="mr-2 justify-self-start" /> <img src="https://upload.wikimedia.org/wikipedia/commons/c/c1/Google_%22G%22_logo.svg" height=20 width=20 class="mr-2 justify-self-start" />
register with John Google register with google
</a> </a>
<a target="_blank" href="https://rusty.42angouleme.fr/issues/all" class="default-button inline-flex items-center justify-center w-full"> <a target="_blank" href="https://rusty.42angouleme.fr/issues/all" class="default-button inline-flex items-center justify-center w-full">
<img src="https://rusty.42angouleme.fr/assets/favicon-bb06adc80c8495db.ico" height=20 width=20 class="mr-2 justify-self-start" /> <img src="https://rusty.42angouleme.fr/assets/favicon-bb06adc80c8495db.ico" height=20 width=20 class="mr-2 justify-self-start" />
register with Rusty register with rusty
</a> </a>
</div> </div>
</div> </div>
@ -54,13 +54,14 @@ export default class extends Aview {
} }
async run() { async run() {
document.getElementById("register-google").href = `${auth_api}/register/google`;
dragElement(document.getElementById("window")); dragElement(document.getElementById("window"));
const login = async () => { const login = async () => {
const username = (document.getElementById("username") as HTMLInputElement).value; const username = (document.getElementById("username") as HTMLInputElement).value;
const password = (document.getElementById("password") as HTMLInputElement).value; const password = (document.getElementById("password") as HTMLInputElement).value;
try { try {
const data_req = await fetch("http://localhost:3001/register", { const data_req = await fetch(auth_api + "/register", {
method: "POST", method: "POST",
headers: { "Content-Type": "application/json", }, headers: { "Content-Type": "application/json", },
credentials: "include", credentials: "include",
@ -69,12 +70,12 @@ export default class extends Aview {
const data = await data_req.json(); const data = await data_req.json();
if (data_req.status === 200) { if (data_req.status === 200) {
let uuid_req = await fetch("http://localhost:3001/me", { let uuid_req = await fetch(auth_api + "/me", {
method: "GET", method: "GET",
credentials: "include", credentials: "include",
}); });
let uuid = await uuid_req.json(); let uuid = await uuid_req.json();
document.cookie = `uuid=${uuid.user};max-ages=${60*60*24*7}`; document.cookie = `uuid=${uuid.user};max-ages=${60 * 60 * 24 * 7}`;
isLogged(); isLogged();
navigationManager("/"); navigationManager("/");
} }

View File

@ -1,9 +1,9 @@
import Aview from "./Aview.ts" import Aview from "./Aview.ts"
import { dragElement } from "./drag.ts"; import { dragElement } from "./drag.ts";
import { setOnekoState } from "../oneko.ts" import { setOnekoState } from "../oneko.ts"
import { isLogged, navigationManager } from "../main.ts"
import { totpEnablePopup } from "./TotpEnable.ts"; import { totpEnablePopup } from "./TotpEnable.ts";
import { totpVerify } from "../../../../api/auth/totpVerify.js"; import { totpVerify } from "../../../../api/auth/totpVerify.js";
import { isLogged, navigationManager, user_api, auth_api } from "../main.ts"
export default class extends Aview { export default class extends Aview {
@ -53,7 +53,7 @@ export default class extends Aview {
dragElement(document.getElementById("window")); dragElement(document.getElementById("window"));
const isTOTPEnabled = async () => { const isTOTPEnabled = async () => {
const totpVerify_req = await fetch('http://localhost:3001/2fa', { const totpVerify_req = await fetch(auth_api + '/2fa', {
method: "GET", method: "GET",
credentials: "include" credentials: "include"
}) })
@ -69,7 +69,7 @@ export default class extends Aview {
let uuid: String; let uuid: String;
uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2]; uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
const userdata_req = await fetch(`http://localhost:3002/users/${uuid}`, { const userdata_req = await fetch(`${user_api}/users/${uuid}`, {
method: "GET", method: "GET",
credentials: "include", credentials: "include",
}); });
@ -83,7 +83,7 @@ export default class extends Aview {
(document.getElementById("displayName-input") as HTMLInputElement).value = userdata.displayName; (document.getElementById("displayName-input") as HTMLInputElement).value = userdata.displayName;
document.getElementById("displayName-button")?.addEventListener("click", async () => { document.getElementById("displayName-button")?.addEventListener("click", async () => {
const changeDisplayName_req = await fetch(`http://localhost:3002/users/${uuid}/displayName`, { const changeDisplayName_req = await fetch(`${user_api}/users/${uuid}/displayName`, {
method: "PATCH", method: "PATCH",
headers: { "Content-Type": "application/json", }, headers: { "Content-Type": "application/json", },
credentials: "include", credentials: "include",
@ -98,7 +98,7 @@ export default class extends Aview {
}); });
document.getElementById("deleteAccount-button")?.addEventListener("click", async () => { document.getElementById("deleteAccount-button")?.addEventListener("click", async () => {
const delete_req = await fetch(`http://localhost:3001/`, { const delete_req = await fetch(auth_api + "/", {
method: "DELETE", method: "DELETE",
credentials: "include", credentials: "include",
}); });
@ -134,7 +134,7 @@ export default class extends Aview {
}); });
(document.getElementById("upload-submit") as HTMLButtonElement).onclick = async () => { (document.getElementById("upload-submit") as HTMLButtonElement).onclick = async () => {
const up_req = await fetch(`http://localhost:3002/users/${uuid}/avatar`, { const up_req = await fetch(`${user_api}/users/${uuid}/avatar`, {
method: "POST", method: "POST",
headers: { "Content-Type": upload.files[0].type } , headers: { "Content-Type": upload.files[0].type } ,
credentials: "include", credentials: "include",
@ -149,7 +149,7 @@ export default class extends Aview {
totpButton.innerHTML = "disable 2fa"; totpButton.innerHTML = "disable 2fa";
document.getElementById("2fa-button")?.addEventListener("click", async () => { document.getElementById("2fa-button")?.addEventListener("click", async () => {
const totp_req = await fetch(`http://localhost:3001/2fa`, { const totp_req = await fetch(`${user_api}/2fa`, {
method: "DELETE", method: "DELETE",
credentials: "include" credentials: "include"
}) })
@ -164,7 +164,7 @@ export default class extends Aview {
totpButton.innerHTML = "enable 2fa"; totpButton.innerHTML = "enable 2fa";
document.getElementById("2fa-button")?.addEventListener("click", async () => { document.getElementById("2fa-button")?.addEventListener("click", async () => {
const totp_req = await fetch(`http://localhost:3001/2fa`, { const totp_req = await fetch(`${user_api}/2fa`, {
method: "POST", method: "POST",
credentials: "include" credentials: "include"
}) })

View File

@ -1,6 +1,6 @@
import Aview from "./Aview.ts"; import Aview from "./Aview.ts";
import { isLogged } from "../main.js";
import { dragElement } from "./drag.js"; import { dragElement } from "./drag.js";
import { isLogged , user_api, auth_api } from "../main.js";
import { setOnekoState, setBallPos, setOnekoOffset } from "../oneko.ts"; import { setOnekoState, setBallPos, setOnekoOffset } from "../oneko.ts";
export default class extends Aview { export default class extends Aview {
@ -629,7 +629,7 @@ export default class extends Aview {
if (await isLogged()) if (await isLogged())
{ {
let uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2]; let uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
fetch(`http://localhost:3002/users/${uuid}/matchHistory?game=tetris`, { fetch(`${user_api}/users/${uuid}/matchHistory?game=tetris`, {
method: "POST", method: "POST",
headers: { "Content-Type": "application/json", }, headers: { "Content-Type": "application/json", },
credentials: "include", credentials: "include",

View File

@ -1,5 +1,5 @@
import Aview from "./Aview.ts"; import Aview from "./Aview.ts";
import { isLogged } from "../main.js"; import { isLogged, user_api, auth_api } from "../main.js";
import { dragElement } from "./drag.js"; import { dragElement } from "./drag.js";
import { setOnekoState, setBallPos, setOnekoOffset } from "../oneko.ts"; import { setOnekoState, setBallPos, setOnekoOffset } from "../oneko.ts";
@ -668,7 +668,7 @@ export default class extends Aview {
if (await isLogged() && this.id == 0) if (await isLogged() && this.id == 0)
{ {
let uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2]; let uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
fetch(`http://localhost:3002/users/${uuid}/matchHistory?game=tetris`, { fetch(`${user_api}/users/${uuid}/matchHistory?game=tetris`, {
method: "POST", method: "POST",
headers: { "Content-Type": "application/json", }, headers: { "Content-Type": "application/json", },
credentials: "include", credentials: "include",
@ -944,11 +944,11 @@ export default class extends Aview {
let p1_isvalid = true; let p1_isvalid = true;
let p2_isvalid = true; let p2_isvalid = true;
if (await isLogged()) { if (await isLogged()) {
const p1_req = await fetch(`http://localhost:3002/users/${p1_input.value}`, { const p1_req = await fetch(`${user_api}/users/${p1_input.value}`, {
method: "GET", method: "GET",
credentials: "include", credentials: "include",
}); });
const p2_req = await fetch(`http://localhost:3002/users/${p2_input.value}`, { const p2_req = await fetch(`${user_api}/users/${p2_input.value}`, {
method: "GET", method: "GET",
credentials: "include", credentials: "include",
}); });

View File

@ -1,9 +1,9 @@
import { navigationManager } from "../main.ts"; import { navigationManager, user_api, auth_api } from "../main.ts";
import { dragElement } from "./drag.ts"; import { dragElement } from "./drag.ts";
async function totpVerify() { async function totpVerify() {
const code = (document.getElementById("totpPin") as HTMLInputElement).value; const code = (document.getElementById("totpPin") as HTMLInputElement).value;
const data_req = await fetch('http://localhost:3001/2fa/verify', { const data_req = await fetch(auth_api + '/2fa/verify', {
method: "POST", method: "POST",
credentials: "include", credentials: "include",
headers: { headers: {

View File

@ -1,5 +1,5 @@
import Aview from "./Aview.ts" import Aview from "./Aview.ts"
import { isLogged } from "../main.js" import { isLogged, user_api } from "../main.js"
import { dragElement } from "./drag.ts"; import { dragElement } from "./drag.ts";
import { setOnekoState, setBallPos, setOnekoOffset } from "../oneko.ts" import { setOnekoState, setBallPos, setOnekoOffset } from "../oneko.ts"
@ -42,6 +42,18 @@ export default class extends Aview {
<div id="bracket" class="flex flex-col space-y-6 items-center"></div> <div id="bracket" class="flex flex-col space-y-6 items-center"></div>
</div> </div>
</div> </div>
<div id="announcement" class="hidden flex flex-col space-y-8">
<div id="bracket-announcement" class="flex flex-col space-y-6 items-center">
</div>
<span id="announcement-text" class="text-lg font-bold text-neutral-900 dark:text-white"></span>
<button type="submit" id="tournament-continue" class="default-button">let's go</button>
</div>
<div id="winner-div" class="hidden flex flex-col items-center space-y-8">
<img src="https://api.kanel.ovh/pp?id=3" class="w-25 h-25 default-border" \>
<span id="winner-text" class="text-2x1 text-neutral-900 dark:text-white"></span>
</div>
</div> </div>
</div> </div>
`; `;
@ -49,9 +61,10 @@ export default class extends Aview {
async runGame(p1_id: number, p2_id: number, players: string[]): Promise<number> { async runGame(p1_id: number, p2_id: number, players: string[]): Promise<number> {
return new Promise<number>(async (resolve) => { return new Promise<number>(async (resolve) => {
console.log(p1_id, p2_id, players, players[p1_id], players[p2_id]); //console.log(p1_id, p2_id, players, players[p1_id], players[p2_id]);
let p1_name = players[p1_id]; let p1_name = players[p1_id];
let p2_name = players[p2_id]; let p2_name = players[p2_id];
let uuid: string; let uuid: string;
let start: number = 0; let start: number = 0;
let elapsed: number; let elapsed: number;
@ -146,7 +159,7 @@ export default class extends Aview {
if (p1_score === 3 || p2_score === 3) { if (p1_score === 3 || p2_score === 3) {
if (await isLogged()) { if (await isLogged()) {
let uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2]; let uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
fetch(`http://localhost:3002/users/${uuid}/matchHistory?game=pong`, { fetch(`${user_api}/users/${uuid}/matchHistory?game=pong`, {
method: "POST", method: "POST",
headers: { "Content-Type": "application/json", }, headers: { "Content-Type": "application/json", },
credentials: "include", credentials: "include",
@ -158,9 +171,9 @@ export default class extends Aview {
"date": Date.now(), "date": Date.now(),
}), }),
}); });
resolve(p1_score == 3 ? p1_id : p2_id);
} }
match_over = true; match_over = true;
resolve(p1_score == 3 ? p1_id : p2_id);
} }
else { else {
countdown = 3; countdown = 3;
@ -262,24 +275,29 @@ export default class extends Aview {
let p1_isvalid = true; let p1_isvalid = true;
let p2_isvalid = true; let p2_isvalid = true;
if (await isLogged()) { if (await isLogged()) {
const p1_req = await fetch(`http://localhost:3002/users/${p1_name}`, { const p1_req = await fetch(`${user_api}/users/${p1_name}`, {
method: "GET", method: "GET",
credentials: "include", credentials: "include",
}); });
const p2_req = await fetch(`http://localhost:3002/users/${p2_name}`, { const p2_req = await fetch(`${user_api}/users/${p2_name}`, {
method: "GET", method: "GET",
credentials: "include", credentials: "include",
}); });
if (p1_req.status != 200) if (p1_req.status == 200)
p1_displayName = p1_name;
else
p1_displayName = (await p1_req.json()).displayName; p1_displayName = (await p1_req.json()).displayName;
if (p2_req.status != 200)
p2_displayName = p2_name;
else else
p1_displayName = p1_name;
if (p2_req.status == 200)
p2_displayName = (await p2_req.json()).displayName; p2_displayName = (await p2_req.json()).displayName;
else
p2_displayName = p2_name;
}
else
{
p1_displayName = p1_name;
p2_displayName = p2_name;
} }
p1_displayName = p1_displayName.length > 16 ? p1_displayName.substring(0, 16) + "." : p1_displayName; p1_displayName = p1_displayName.length > 16 ? p1_displayName.substring(0, 16) + "." : p1_displayName;
@ -309,9 +327,77 @@ export default class extends Aview {
}); });
} }
waitForUserClick(buttonId: string): Promise<void> {
return new Promise((resolve) => {
const button = document.getElementById(buttonId);
if (!button) return resolve(); // failsafe if no button
const handler = () => {
button.removeEventListener("click", handler);
resolve();
};
button.addEventListener("click", handler);
});
}
tournament_state: number[][];
i: number = 0;
space: number;
updateBracketDisplay(tournament: number[][], players: string[]) {
for (let i of Array(tournament[0].length).keys())
this.tournament_state[this.i][i] = tournament[0][i];
for (let i of Array(tournament[1].length).keys())
{
console.log(this.tournament_state, this.i, i);
this.tournament_state[this.i + 1][i] = tournament[1][i];
}
this.i++;
const container = document.getElementById("bracket-announcement");
if (!container) return;
container.innerHTML = ""; // clear old bracket
const bracketWrapper = document.createElement("div");
bracketWrapper.className = "flex space-x-8 overflow-x-auto";
// replicate generateBracket() spacing logic
let previousPadding = 4;
for (let round = 0; round < this.tournament_state.length; round++) {
const roundColumn = document.createElement("div");
if (round === 0) {
roundColumn.className = `flex flex-col mt-${this.space} space-y-4`;
} else {
previousPadding = previousPadding * 2 + 10;
roundColumn.className = `flex flex-col justify-center space-y-${previousPadding}`;
}
// each player slot or winner
for (let i = 0; i < this.tournament_state[round].length; i++) {
const playerIndex = this.tournament_state[round][i];
const name =
playerIndex !== undefined && playerIndex !== null
? players[playerIndex]
: "";
const cell = document.createElement("div");
cell.className =
"w-32 h-10 flex items-center justify-center bg-white text-center text-sm input-border";
cell.textContent = name || "";
roundColumn.appendChild(cell);
}
bracketWrapper.appendChild(roundColumn);
}
container.appendChild(bracketWrapper);
}
async run() { async run() {
dragElement(document.getElementById("window")); dragElement(document.getElementById("window"));
const generateBracket = async (playerCount: number) => { const generateBracket = async (playerCount: number) => {
this.tournament_state = [];
let initPlayerCount = playerCount; let initPlayerCount = playerCount;
document.getElementById("bracket").innerHTML = ""; document.getElementById("bracket").innerHTML = "";
@ -333,9 +419,11 @@ export default class extends Aview {
// Round 0: Player input column // Round 0: Player input column
const playerInputColumn = document.createElement("div"); const playerInputColumn = document.createElement("div");
this.space = (notPowPlayersCount + odd) * 28;
playerInputColumn.className = `flex flex-col mt-${(notPowPlayersCount + odd) * 28} space-y-4`; playerInputColumn.className = `flex flex-col mt-${(notPowPlayersCount + odd) * 28} space-y-4`;
tournament.push([]); tournament.push([]);
this.tournament_state.push([]);
initialPlayers.forEach((name, i) => { initialPlayers.forEach((name, i) => {
const input = document.createElement("input"); const input = document.createElement("input");
input.type = "text"; input.type = "text";
@ -355,6 +443,7 @@ export default class extends Aview {
input.className = "w-32 h-10 p-2 text-sm bg-white disabled:bg-gray-200 input-border"; input.className = "w-32 h-10 p-2 text-sm bg-white disabled:bg-gray-200 input-border";
playerInputColumn.appendChild(input); playerInputColumn.appendChild(input);
tournament[0].push(i); tournament[0].push(i);
this.tournament_state[0].push(-1);
}); });
bracketWrapper.appendChild(playerInputColumn); bracketWrapper.appendChild(playerInputColumn);
@ -364,6 +453,7 @@ export default class extends Aview {
tournament.push([]); tournament.push([]);
for (let round = 1; round <= rounds; round++) for (let round = 1; round <= rounds; round++)
{ {
this.tournament_state.push([]);
const roundColumn = document.createElement("div"); const roundColumn = document.createElement("div");
previousPadding = previousPadding * 2 + 10 previousPadding = previousPadding * 2 + 10
roundColumn.className = `flex flex-col justify-center space-y-${previousPadding}`; roundColumn.className = `flex flex-col justify-center space-y-${previousPadding}`;
@ -372,6 +462,7 @@ export default class extends Aview {
while (notPowPlayersCount) { while (notPowPlayersCount) {
tournament[1].push(playerCount); tournament[1].push(playerCount);
this.tournament_state[1].push(-1);
const input = document.createElement("input"); const input = document.createElement("input");
input.type = "text"; input.type = "text";
input.id = `playerName${playerCount}`; input.id = `playerName${playerCount}`;
@ -397,6 +488,7 @@ export default class extends Aview {
nextRound.push(""); nextRound.push("");
roundColumn.appendChild(matchDiv); roundColumn.appendChild(matchDiv);
this.tournament_state[round].push(-1);
} }
bracketWrapper.appendChild(roundColumn); bracketWrapper.appendChild(roundColumn);
@ -410,7 +502,7 @@ export default class extends Aview {
btn.classList.add("default-button", "w-full"); btn.classList.add("default-button", "w-full");
btn.id = "tournament-play"; btn.id = "tournament-play";
btn.onclick = async () => { btn.onclick = async () => {
document.getElementById("tournament-id")?.classList.add("hidden");
let players: string[] = []; let players: string[] = [];
for (let i of Array(initPlayerCount).keys()) { for (let i of Array(initPlayerCount).keys()) {
players.push((document.getElementById(`playerName${i}`) as HTMLInputElement).value); players.push((document.getElementById(`playerName${i}`) as HTMLInputElement).value);
@ -418,22 +510,25 @@ export default class extends Aview {
while (tournament[0].length > 1) while (tournament[0].length > 1)
{ {
this.updateBracketDisplay(tournament, players);
while(tournament[0].length > 0) while(tournament[0].length > 0)
{ {
console.log(tournament[0]);
const p1 = tournament[0].shift() as number; const p1 = tournament[0].shift() as number;
const p2 = tournament[0].shift() as number; const p2 = tournament[0].shift() as number;
document.getElementById("tournament-id")?.classList.add("hidden"); document.getElementById("announcement-text").innerText = `${players[p1]} vs ${players[p2]}`;
document.getElementById("announcement")?.classList.remove("hidden");
await this.waitForUserClick("tournament-continue");
document.getElementById("announcement")?.classList.add("hidden");
const result = await this.runGame(p1, p2, players); const result = await this.runGame(p1, p2, players);
document.getElementById("gameCanvas").remove(); document.getElementById("gameCanvas")?.remove();
document.getElementById("tournament-id")?.classList.remove("hidden");
tournament[1].push(result); tournament[1].push(result);
} }
tournament[0] = tournament[1]; tournament[0] = tournament[1];
tournament[1] = []; tournament[1] = [];
} }
console.log(`winner: ${tournament[0][0]}`); document.getElementById("winner-div")?.classList.remove("hidden");
document.getElementById("winner-text").innerText = `${players[tournament[0][0]]} won the tournament !! ggs :D`;
}; };
btn.innerText = "start tournament !!"; btn.innerText = "start tournament !!";
@ -445,7 +540,5 @@ export default class extends Aview {
return; return;
generateBracket(+input.value); generateBracket(+input.value);
}); });
} }
} }