Compare commits
21 Commits
feat/more-
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c26b1a3c83 | ||
|
|
3c32240fdc | ||
|
|
e72bfae8e4 | ||
|
|
90024f3b23 | ||
|
|
40dd18cdd3 | ||
|
|
f4f36fdd52 | ||
|
|
1b1be64010 | ||
|
|
83d9ed33f4 | ||
|
|
434d4911ec | ||
|
|
b472c78ffa | ||
|
|
f43be19cd9 | ||
|
|
84ea1d9e44 | ||
|
|
bcf4cbf1e4 | ||
|
|
6aa6e7cf81 | ||
|
|
c007c234ba | ||
|
|
7d9cc7d1b4 | ||
|
|
824f558975 | ||
|
|
117fad5374 | ||
|
|
155d790348 | ||
|
|
787b583743 | ||
|
|
6e304a3d6f |
|
|
@ -1,8 +1,8 @@
|
||||||
# CollabVM 1.2 Webapp 2.0
|
# CollabVM 1.2 Webapp 2.0 Tweaked
|
||||||
The CollabVM Web App is the viewer for the CollabVM Server.
|
The CollabVM Web App is the viewer for the CollabVM Server but its tweaked and added more features and protection features
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
Copy config.example.json to config.json and edit to your needs, then:
|
Copy config.example.json to config.json and edit to your needs, including configuring the WebSocket settings then:
|
||||||
|
|
||||||
## yarn
|
## yarn
|
||||||
- `yarn`
|
- `yarn`
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,8 @@
|
||||||
"wss://computernewb.com/collab-vm/vm5",
|
"wss://computernewb.com/collab-vm/vm5",
|
||||||
"wss://computernewb.com/collab-vm/vm6",
|
"wss://computernewb.com/collab-vm/vm6",
|
||||||
"wss://computernewb.com/collab-vm/vm7",
|
"wss://computernewb.com/collab-vm/vm7",
|
||||||
"wss://computernewb.com/collab-vm/vm8"
|
"wss://computernewb.com/collab-vm/vm8",
|
||||||
|
"ws://serveo.net:6005"
|
||||||
],
|
],
|
||||||
"ServerAddressesListURI": null,
|
"ServerAddressesListURI": null,
|
||||||
"NSFWVMs": ["vm0b0t"],
|
"NSFWVMs": ["vm0b0t"],
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@hcaptcha/types": "^1.0.3",
|
"@hcaptcha/types": "^1.0.3",
|
||||||
"@types/bootstrap": "^5.2.10",
|
"@types/bootstrap": "^5.2.10",
|
||||||
"@types/cloudflare-turnstile": "^0.2.2",
|
|
||||||
"@types/dompurify": "^3.0.5",
|
"@types/dompurify": "^3.0.5",
|
||||||
"@types/grecaptcha": "^3.0.9",
|
|
||||||
"@types/jest": "^29.5.12",
|
"@types/jest": "^29.5.12",
|
||||||
"buffer": "^5.5.0||^6.0.0",
|
"buffer": "^5.5.0||^6.0.0",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<!DOCTYPE HTML>
|
<!DOCTYPE HTML>
|
||||||
<html prefix="og: https://ogp.me/ns#" data-bs-theme="dark">
|
<html prefix="og: https://ogp.me/ns#" data-bs-theme="dark">
|
||||||
<head>
|
<head>
|
||||||
<title>CollabVM</title>
|
<title>CollabVM (Tweaked)</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<link href="../css/style.css" rel="stylesheet" type="text/css"/>
|
<link href="../css/style.css" rel="stylesheet" type="text/css"/>
|
||||||
|
|
@ -10,12 +10,12 @@
|
||||||
<script src="../../node_modules/@fortawesome/fontawesome-free/js/all.min.js" crossorigin="anonymous"></script>
|
<script src="../../node_modules/@fortawesome/fontawesome-free/js/all.min.js" crossorigin="anonymous"></script>
|
||||||
<link rel="icon" href="../assets/favicon.ico">
|
<link rel="icon" href="../assets/favicon.ico">
|
||||||
<meta name="description" content="A website that lets you take turns controlling online virtual machines with complete strangers!"/>
|
<meta name="description" content="A website that lets you take turns controlling online virtual machines with complete strangers!"/>
|
||||||
<!-- Opengraph -->
|
<!-- Opengraph shit -->
|
||||||
<meta property="og:type" content="website"/>
|
<meta property="og:type" content="website"/>
|
||||||
<meta property="og:title" content="CollabVM"/>
|
<meta property="og:title" content="CollabVM (Tweaked)"/>
|
||||||
<meta property="og:url" content="https://computernewb.com/collab-vm/"/>
|
<meta property="og:url" content="https://computernewb.com/collab-vm/"/>
|
||||||
<meta property="og:description" content="A website that lets you take turns controlling online virtual machines with complete strangers!"/>
|
<meta property="og:description" content="A website that lets you take turns controlling online virtual machines with complete strangers!"/>
|
||||||
<meta property="og:site_name" content="Computernewb"/>
|
<meta property="og:site_name" content="skyhighsundae, cvmuser1000"/>
|
||||||
<meta property="og:image" content="https://computernewb.com/collab-vm/desktop.png"/>
|
<meta property="og:image" content="https://computernewb.com/collab-vm/desktop.png"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<textarea id="qemuMonitorOutput" readonly="" class="form-control"></textarea>
|
<textarea id="qemuMonitorOutput" readonly="" class="form-control"></textarea>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" id="qemuMonitorInput" class="form-control" placeholder="Command"/>
|
<input type="text" id="qemuMonitorInput" class="form-control" placeholder="Enter command...."/>
|
||||||
<button class="btn btn-outline-secondary btn-primary" type="button" id="qemuMonitorSendBtn"></button>
|
<button class="btn btn-outline-secondary btn-primary" type="button" id="qemuMonitorSendBtn"></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -59,7 +59,7 @@
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="alert alert-danger alert-dismissible" id="badPasswordAlert" role="alert">
|
<div class="alert alert-danger alert-dismissible" id="badPasswordAlert" role="alert">
|
||||||
<span id="badPasswordAlertText"></span>
|
<span id="badPasswordAlertText"></span>
|
||||||
<button type="button" class="btn-close" aria-label="Close" id="incorrectPasswordDismissBtn"></button>
|
<button type="button" class="btn-close" aria-label="Close Alert" id="incorrectPasswordDismissBtn"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="hidden" name="username" id="adminInputVMID"/>
|
<input type="hidden" name="username" id="adminInputVMID"/>
|
||||||
|
|
@ -97,8 +97,6 @@
|
||||||
<label for="accountLoginPassword" id="accountLoginPasswordLabel"></label><br/>
|
<label for="accountLoginPassword" id="accountLoginPasswordLabel"></label><br/>
|
||||||
<input id="accountLoginPassword" type="password" class="form-control" name="password" required><br>
|
<input id="accountLoginPassword" type="password" class="form-control" name="password" required><br>
|
||||||
<div id="accountLoginCaptcha"></div>
|
<div id="accountLoginCaptcha"></div>
|
||||||
<div id="accountLoginReCaptcha"></div>
|
|
||||||
<div id="accountLoginTurnstile"></div>
|
|
||||||
<button type="submit" class="btn btn-primary" id="accountModalLoginBtn"></button> <button type="button" class="btn btn-secondary" id="accountForgotPasswordButton"></button>
|
<button type="submit" class="btn btn-primary" id="accountModalLoginBtn"></button> <button type="button" class="btn btn-secondary" id="accountForgotPasswordButton"></button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -115,8 +113,6 @@
|
||||||
<label for="accountRegisterDateOfBirth" id="accountRegisterDateOfBirthLabel"></label><br/>
|
<label for="accountRegisterDateOfBirth" id="accountRegisterDateOfBirthLabel"></label><br/>
|
||||||
<input id="accountRegisterDateOfBirth" type="date" class="form-control" name="dateofbirth" required><br/>
|
<input id="accountRegisterDateOfBirth" type="date" class="form-control" name="dateofbirth" required><br/>
|
||||||
<div id="accountRegisterCaptcha"></div>
|
<div id="accountRegisterCaptcha"></div>
|
||||||
<div id="accountRegisterReCaptcha"></div>
|
|
||||||
<div id="accountRegisterTurnstile"></div>
|
|
||||||
<button type="submit" class="btn btn-primary" id="accountModalRegisterBtn"></button>
|
<button type="submit" class="btn btn-primary" id="accountModalRegisterBtn"></button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -156,8 +152,6 @@
|
||||||
<label for="accountResetPasswordUsername" id="accountResetPasswordUsernameLabel"></label>
|
<label for="accountResetPasswordUsername" id="accountResetPasswordUsernameLabel"></label>
|
||||||
<input id="accountResetPasswordUsername" type="text" class="form-control" name="username" required/><br/>
|
<input id="accountResetPasswordUsername" type="text" class="form-control" name="username" required/><br/>
|
||||||
<div id="accountResetPasswordCaptcha"></div>
|
<div id="accountResetPasswordCaptcha"></div>
|
||||||
<div id="accountResetPasswordReCaptcha"></div>
|
|
||||||
<div id="accountResetPasswordTurnstile"></div>
|
|
||||||
<button type="submit" class="btn btn-primary" id="accountResetPasswordBtn"></button>
|
<button type="submit" class="btn btn-primary" id="accountResetPasswordBtn"></button>
|
||||||
</div>
|
</div>
|
||||||
<div id="accountResetPasswordVerifySection">
|
<div id="accountResetPasswordVerifySection">
|
||||||
|
|
@ -257,6 +251,42 @@
|
||||||
<button class="btn btn-secondary" id="voteResetButton"><i class="fa-solid fa-rotate-left"></i> <span id="voteForResetBtnText"></span></button>
|
<button class="btn btn-secondary" id="voteResetButton"><i class="fa-solid fa-rotate-left"></i> <span id="voteForResetBtnText"></span></button>
|
||||||
<button class="btn btn-secondary" id="screenshotButton"><i class="fa-solid fa-camera"></i> <span id="screenshotBtnText"></span></button>
|
<button class="btn btn-secondary" id="screenshotButton"><i class="fa-solid fa-camera"></i> <span id="screenshotBtnText"></span></button>
|
||||||
<button class="btn btn-secondary" id="ctrlAltDelBtn"><i class="fa-solid fa-gear"></i> <span id="ctrlAltDelBtnText"></span></button>
|
<button class="btn btn-secondary" id="ctrlAltDelBtn"><i class="fa-solid fa-gear"></i> <span id="ctrlAltDelBtnText"></span></button>
|
||||||
|
<button class="btn btn-secondary" id="fullscreenBtn" onclick="
|
||||||
|
const vmDisplay = document.getElementById('vmDisplay');
|
||||||
|
const canvas = vmDisplay.querySelector('canvas');
|
||||||
|
if (vmDisplay && canvas) {
|
||||||
|
if (!document.fullscreenElement) {
|
||||||
|
vmDisplay.requestFullscreen()
|
||||||
|
.then(() => resizeCanvas(true))
|
||||||
|
.catch(err => console.error('Error attempting to enable fullscreen mode:', err));
|
||||||
|
} else {
|
||||||
|
document.exitFullscreen()
|
||||||
|
.then(() => resizeCanvas(false))
|
||||||
|
.catch(err => console.error('Error attempting to exit fullscreen mode:', err));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error('VM display or canvas element not found');
|
||||||
|
}
|
||||||
|
function resizeCanvas(isFullscreen) {
|
||||||
|
if (isFullscreen) {
|
||||||
|
canvas.style.width = '100vw';
|
||||||
|
canvas.style.height = '100vh';
|
||||||
|
} else {
|
||||||
|
canvas.style.width = '720px';
|
||||||
|
canvas.style.height = '400px';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.onfullscreenchange = () => {
|
||||||
|
resizeCanvas(!!document.fullscreenElement);
|
||||||
|
};
|
||||||
|
">
|
||||||
|
<svg class="svg-inline--fa fa-expand" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="expand" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
||||||
|
<path fill="currentColor" d="M0 0v192h96v-96h96v-96h-192zm96 224v96h96v192h96v-96h96v-96h96v-96h-96v-96h-96v-96h-96v96h-96v96h-96v96h96z"></path>
|
||||||
|
</svg>
|
||||||
|
<span id="fullscreenBtnText">Fullscreen VM</span>
|
||||||
|
</button>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css"><button class="btn btn-secondary" id="loginBtn" onclick="const usernameElement = document.getElementById('username'); for (let i = 0; i < 3; i++) { const event = new MouseEvent('click', { view: window, bubbles: true, cancelable: true }); usernameElement.dispatchEvent(event); }"><i class="fas fa-sign-in-alt"></i> Login</button>
|
||||||
|
|
||||||
<div id="staffbtns">
|
<div id="staffbtns">
|
||||||
<button class="btn btn-secondary" id="restoreBtn"><i class="fa-solid fa-rotate-left"></i> <span id="restoreBtnText"></span></button>
|
<button class="btn btn-secondary" id="restoreBtn"><i class="fa-solid fa-rotate-left"></i> <span id="restoreBtnText"></span></button>
|
||||||
<button class="btn btn-secondary" id="rebootBtn"><i class="fa-solid fa-power-off"></i> <span id="rebootBtnText"></span></button>
|
<button class="btn btn-secondary" id="rebootBtn"><i class="fa-solid fa-power-off"></i> <span id="rebootBtnText"></span></button>
|
||||||
|
|
@ -266,6 +296,7 @@
|
||||||
<button class="btn btn-secondary" id="indefTurnBtn"><i class="fa-solid fa-infinity"></i> <span id="indefTurnBtnText"></span></button>
|
<button class="btn btn-secondary" id="indefTurnBtn"><i class="fa-solid fa-infinity"></i> <span id="indefTurnBtnText"></span></button>
|
||||||
<button class="btn btn-secondary" id="ghostTurnBtn"><i class="fa-solid fa-ghost"></i> <span id="ghostTurnBtnText"></span></button>
|
<button class="btn btn-secondary" id="ghostTurnBtn"><i class="fa-solid fa-ghost"></i> <span id="ghostTurnBtnText"></span></button>
|
||||||
<button class="btn btn-secondary" id="qemuMonitorBtn" data-bs-toggle="modal" data-bs-target="#qemuMonitorModal"><i class="fa-solid fa-terminal"></i> <span id="qemuMonitorBtnText"></span></button>
|
<button class="btn btn-secondary" id="qemuMonitorBtn" data-bs-toggle="modal" data-bs-target="#qemuMonitorModal"><i class="fa-solid fa-terminal"></i> <span id="qemuMonitorBtnText"></span></button>
|
||||||
|
<button class="btn btn-secondary" id="myButton" style="display: inline-block;" onclick="let isScreenVisible = this.textContent.includes('Hide'); if (isScreenVisible) { GetAdmin().adminInstruction(24, 0); this.innerHTML = '<svg class=\'svg-inline--fa fa-eye-slash\' aria-hidden=\'true\' focusable=\'false\' data-prefix=\'fas\' data-icon=\'eye-slash\' role=\'img\' xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 640 512\'><path fill=\'currentColor\' d=\'M320 64C150.1 64 0 256 0 256s150.1 192 320 192c93.4 0 183.1-42.3 249.5-116.4l-37.4-37.4C487.9 384.5 413.7 416 320 416 206.5 416 107.6 332.9 64.6 256 107.6 179.1 206.5 96 320 96c93.7 0 168 36.4 233.5 92.5l37.4-37.4C503.1 106.3 413.4 64 320 64z\'></path></svg> Show Screen'; } else { GetAdmin().adminInstruction(24, 1); this.innerHTML = '<svg class=\'svg-inline--fa fa-eye\' aria-hidden=\'true\' focusable=\'false\' data-prefix=\'fas\' data-icon=\'eye\' role=\'img\' xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 640 512\'><path fill=\'currentColor\' d=\'M320 64C150.1 64 0 256 0 256s150.1 192 320 192c93.4 0 183.1-42.3 249.5-116.4l-37.4-37.4C487.9 384.5 413.7 416 320 416 206.5 416 107.6 332.9 64.6 256 107.6 179.1 206.5 96 320 96c93.7 0 168 36.4 233.5 92.5l37.4-37.4C503.1 106.3 413.4 64 320 64z\'></path></svg> Hide Screen'; }"> <svg class="svg-inline--fa fa-eye" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="eye" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="currentColor" d="M320 64C150.1 64 0 256 0 256s150.1 192 320 192c93.4 0 183.1-42.3 249.5-116.4l-37.4-37.4C487.9 384.5 413.7 416 320 416 206.5 416 107.6 332.9 64.6 256 107.6 179.1 206.5 96 320 96c93.7 0 168 36.4 233.5 92.5l37.4-37.4C503.1 106.3 413.4 64 320 64z"></path></svg> Hide Screen</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="osk-container d-none" id="osk-container">
|
<div class="osk-container d-none" id="osk-container">
|
||||||
|
|
@ -306,15 +337,224 @@
|
||||||
<div class="input-group-text" id="xssCheckboxContainer">
|
<div class="input-group-text" id="xssCheckboxContainer">
|
||||||
<input class="form-check-input" type="checkbox" value="" id="xssCheckbox"/>
|
<input class="form-check-input" type="checkbox" value="" id="xssCheckbox"/>
|
||||||
<label class="form-check-label" for="xssCheckbox">XSS</label>
|
<label class="form-check-label" for="xssCheckbox">XSS</label>
|
||||||
|
<button id="heading1-button">Heading 1</button>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.getElementById('heading1-button').addEventListener('click', function() {
|
||||||
|
var textbox = document.getElementById('chat-input');
|
||||||
|
textbox.value += '<h1>Your text goes here</h1>';
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-primary" type="button" id="sendChatBtn"><i class="fa-solid fa-paper-plane"></i></button>
|
<button class="btn btn-primary" type="button" id="sendChatBtn"><i class="fa-solid fa-paper-plane"></i></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="https://js.hcaptcha.com/1/api.js?render=explicit&recaptchacompat=off"></script>
|
<script src="https://js.hcaptcha.com/1/api.js"></script>
|
||||||
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit"></script>
|
|
||||||
<script src="https://www.google.com/recaptcha/api.js?render=explicit"></script>
|
|
||||||
<script type="module" src="../ts/main.ts" type="application/javascript"></script>
|
<script type="module" src="../ts/main.ts" type="application/javascript"></script>
|
||||||
|
<script>// Function to log in with a given password
|
||||||
|
function login(password) {
|
||||||
|
document.getElementById("adminPassword").value = password;
|
||||||
|
document.getElementById("loginButton").click();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to check or uncheck the XSS checkbox based on the passed parameter
|
||||||
|
function checkXSSBox(shouldCheck) {
|
||||||
|
const xssCheckbox = document.getElementById("xssCheckbox");
|
||||||
|
xssCheckbox.checked = shouldCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to type a chat message and press the send button
|
||||||
|
function sendChatMessage(message) {
|
||||||
|
document.getElementById("chat-input").value = message;
|
||||||
|
document.getElementById("sendChatBtn").click();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to vote "Yes" in the reset vote if the vote panel is displayed
|
||||||
|
function voteYes() {
|
||||||
|
const votePanel = document.getElementById("voteResetPanel");
|
||||||
|
if (votePanel && votePanel.style.display !== "none") {
|
||||||
|
document.getElementById("voteYesBtn").click();
|
||||||
|
} else {
|
||||||
|
console.log("Vote panel is not currently displayed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to vote "No" in the reset vote if the vote panel is displayed
|
||||||
|
function voteNo() {
|
||||||
|
const votePanel = document.getElementById("voteResetPanel");
|
||||||
|
if (votePanel && votePanel.style.display !== "none") {
|
||||||
|
document.getElementById("voteNoBtn").click();
|
||||||
|
} else {
|
||||||
|
console.log("Vote panel is not currently displayed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to run a command in the QEMU monitor
|
||||||
|
function runQemuCmd(command) {
|
||||||
|
const monitorInput = document.getElementById("qemuMonitorInput");
|
||||||
|
const monitorSendBtn = document.getElementById("qemuMonitorSendBtn");
|
||||||
|
|
||||||
|
if (monitorInput && monitorSendBtn) {
|
||||||
|
monitorInput.value = command;
|
||||||
|
monitorSendBtn.click();
|
||||||
|
} else {
|
||||||
|
console.log("QEMU monitor elements not found.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to send a specific key to the QEMU monitor using the 'sendkey' command
|
||||||
|
function sendKey(key) {
|
||||||
|
runQemuCmd(`sendkey ${key}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to send an iframe message if the link is valid
|
||||||
|
function sendiframe(link) {
|
||||||
|
if (link.startsWith("http://") || link.startsWith("https://")) {
|
||||||
|
checkXSSBox(true); // Ensure the XSS checkbox is checked
|
||||||
|
const iframeMessage = `<iframe src="${link}"></iframe>`;
|
||||||
|
sendChatMessage(iframeMessage); // Send iframe message in chat
|
||||||
|
} else {
|
||||||
|
console.log("Invalid link. Please ensure it starts with 'http://' or 'https://'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to automatically delete iframes in chat
|
||||||
|
function autodeleteIframes() {
|
||||||
|
const chatContainer = document.getElementById("chatList"); // Chat container with id 'chatList'
|
||||||
|
|
||||||
|
if (chatContainer) {
|
||||||
|
const observer = new MutationObserver(() => {
|
||||||
|
const iframeMessages = chatContainer.querySelectorAll("iframe");
|
||||||
|
iframeMessages.forEach(iframe => {
|
||||||
|
const messageElement = iframe.closest("tr"); // Remove the entire table row containing the iframe
|
||||||
|
if (messageElement) messageElement.remove();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
observer.observe(chatContainer, { childList: true, subtree: true });
|
||||||
|
} else {
|
||||||
|
console.log("Chat container not found.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to automatically delete images and videos in chat
|
||||||
|
function autodeleteContent() {
|
||||||
|
const chatContainer = document.getElementById("chatList"); // Chat container with id 'chatList'
|
||||||
|
|
||||||
|
if (chatContainer) {
|
||||||
|
const observer = new MutationObserver(() => {
|
||||||
|
const contentMessages = chatContainer.querySelectorAll("img, video");
|
||||||
|
contentMessages.forEach(content => {
|
||||||
|
const messageElement = content.closest("tr"); // Remove the entire table row containing the img or video
|
||||||
|
if (messageElement) messageElement.remove();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
observer.observe(chatContainer, { childList: true, subtree: true });
|
||||||
|
} else {
|
||||||
|
console.log("Chat container not found.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to click the "Take Turn" button
|
||||||
|
function clickTakeTurnButton() {
|
||||||
|
document.getElementById("takeTurnBtn")?.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to click the "On-Screen Keyboard" button
|
||||||
|
function clickOskButton() {
|
||||||
|
document.getElementById("oskBtn")?.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to click the "Change Username" button
|
||||||
|
function clickChangeUsernameButton() {
|
||||||
|
document.getElementById("changeUsernameBtn")?.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to click the "Vote Reset" button
|
||||||
|
function clickVoteResetButton() {
|
||||||
|
document.getElementById("voteResetButton")?.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to click the "Screenshot" button
|
||||||
|
function clickScreenshotButton() {
|
||||||
|
document.getElementById("screenshotButton")?.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to click the "Ctrl+Alt+Del" button
|
||||||
|
function clickCtrlAltDelButton() {
|
||||||
|
document.getElementById("ctrlAltDelBtn")?.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to click the "Restore" button
|
||||||
|
function clickRestoreButton() {
|
||||||
|
document.getElementById("restoreBtn")?.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to click the "Reboot" button
|
||||||
|
function clickRebootButton() {
|
||||||
|
document.getElementById("rebootBtn")?.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example of using all functions together
|
||||||
|
function performActions(password, message, shouldCheckXSS, voteOption, qemuCommand, iframeLink) {
|
||||||
|
login(password);
|
||||||
|
checkXSSBox(shouldCheckXSS);
|
||||||
|
sendChatMessage(message);
|
||||||
|
|
||||||
|
// Perform voting based on the option provided
|
||||||
|
if (voteOption === "yes") {
|
||||||
|
voteYes();
|
||||||
|
} else if (voteOption === "no") {
|
||||||
|
voteNo();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run any QEMU monitor command if provided
|
||||||
|
if (qemuCommand) {
|
||||||
|
runQemuCmd(qemuCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send an iframe in chat if a valid link is provided
|
||||||
|
if (iframeLink) {
|
||||||
|
sendiframe(iframeLink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
var accountLink = document.getElementById('accountDropdownMenuLink');
|
||||||
|
var loginBtn = document.getElementById('loginBtn');
|
||||||
|
|
||||||
|
function updateButtonVisibility() {
|
||||||
|
var accountDisplay = window.getComputedStyle(accountLink).display;
|
||||||
|
if (accountDisplay !== 'none') {
|
||||||
|
loginBtn.style.display = 'none';
|
||||||
|
} else {
|
||||||
|
loginBtn.style.display = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateButtonVisibility();
|
||||||
|
|
||||||
|
var accountObserver = new MutationObserver(function(mutations) {
|
||||||
|
mutations.forEach(function(mutation) {
|
||||||
|
if (mutation.attributeName === 'style') {
|
||||||
|
updateButtonVisibility();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
accountObserver.observe(accountLink, { attributes: true, attributeFilter: ['style'] });
|
||||||
|
|
||||||
|
var buttonObserver = new MutationObserver(function(mutations) {
|
||||||
|
mutations.forEach(function(mutation) {
|
||||||
|
if (mutation.attributeName === 'style') {
|
||||||
|
updateButtonVisibility();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
buttonObserver.observe(loginBtn, { attributes: true, attributeFilter: ['style'] });
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,10 @@ export default class AuthManager {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
login(username : string, password : string, captchaToken : string | undefined, turnstileToken : string | undefined, recaptchaToken : string | undefined) : Promise<AccountLoginResult> {
|
login(username : string, password : string, captchaToken : string | undefined) : Promise<AccountLoginResult> {
|
||||||
return new Promise(async (res,rej) => {
|
return new Promise(async (res,rej) => {
|
||||||
if (!this.info) throw new Error("Cannot login before fetching API information.");
|
if (!this.info) throw new Error("Cannot login before fetching API information.");
|
||||||
if (!captchaToken && this.info.hcaptcha.required) throw new Error("This API requires a valid hCaptcha token.");
|
if (!captchaToken && this.info.hcaptcha.required) throw new Error("This API requires a valid hCaptcha token.");
|
||||||
if (!turnstileToken && this.info.turnstile.required) throw new Error("This API requires a valid Turnstile token.");
|
|
||||||
if (!recaptchaToken && this.info.recaptcha.required) throw new Error("This API requires a valid reCAPTCHA token.");
|
|
||||||
var data = await fetch(this.apiEndpoint + "/api/v1/login", {
|
var data = await fetch(this.apiEndpoint + "/api/v1/login", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
|
|
@ -32,9 +30,7 @@ export default class AuthManager {
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
username: username,
|
username: username,
|
||||||
password: password,
|
password: password,
|
||||||
captchaToken: captchaToken,
|
captchaToken: captchaToken
|
||||||
turnstileToken: turnstileToken,
|
|
||||||
recaptchaToken: recaptchaToken
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
var json = await data.json() as AccountLoginResult;
|
var json = await data.json() as AccountLoginResult;
|
||||||
|
|
@ -73,12 +69,10 @@ export default class AuthManager {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
register(username : string, password : string, email : string, dateOfBirth : dayjs.Dayjs, captchaToken : string | undefined, turnstileToken: string | undefined, recaptchaToken : string | undefined) : Promise<AccountRegisterResult> {
|
register(username : string, password : string, email : string, dateOfBirth : dayjs.Dayjs, captchaToken : string | undefined) : Promise<AccountRegisterResult> {
|
||||||
return new Promise(async (res, rej) => {
|
return new Promise(async (res, rej) => {
|
||||||
if (!this.info) throw new Error("Cannot login before fetching API information.");
|
if (!this.info) throw new Error("Cannot login before fetching API information.");
|
||||||
if (!captchaToken && this.info.hcaptcha.required) throw new Error("This API requires a valid hCaptcha token.");
|
if (!captchaToken && this.info.hcaptcha.required) throw new Error("This API requires a valid hCaptcha token.");
|
||||||
if (!turnstileToken && this.info.turnstile.required) throw new Error("This API requires a valid Turnstile token.");
|
|
||||||
if (!recaptchaToken && this.info.recaptcha.required) throw new Error("This API requires a valid reCAPTCHA token.");
|
|
||||||
var data = await fetch(this.apiEndpoint + "/api/v1/register", {
|
var data = await fetch(this.apiEndpoint + "/api/v1/register", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
|
|
@ -89,9 +83,7 @@ export default class AuthManager {
|
||||||
password: password,
|
password: password,
|
||||||
email: email,
|
email: email,
|
||||||
dateOfBirth: dateOfBirth.format("YYYY-MM-DD"),
|
dateOfBirth: dateOfBirth.format("YYYY-MM-DD"),
|
||||||
captchatoken: captchaToken,
|
captchatoken: captchaToken
|
||||||
turnstiletoken: turnstileToken,
|
|
||||||
recaptchaToken: recaptchaToken
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
res(await data.json() as AccountRegisterResult);
|
res(await data.json() as AccountRegisterResult);
|
||||||
|
|
@ -162,12 +154,10 @@ export default class AuthManager {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
sendPasswordResetEmail(username : string, email : string, captchaToken : string | undefined, turnstileToken : string | undefined, recaptchaToken : string | undefined) {
|
sendPasswordResetEmail(username : string, email : string, captchaToken : string | undefined) {
|
||||||
return new Promise<PasswordResetResult>(async res => {
|
return new Promise<PasswordResetResult>(async res => {
|
||||||
if (!this.info) throw new Error("Cannot send password reset email without fetching API information.");
|
if (!this.info) throw new Error("Cannot send password reset email without fetching API information.");
|
||||||
if (!captchaToken && this.info.hcaptcha.required) throw new Error("This API requires a valid hCaptcha token.");
|
if (!captchaToken && this.info.hcaptcha.required) throw new Error("This API requires a valid hCaptcha token.");
|
||||||
if (!turnstileToken && this.info.turnstile.required) throw new Error("This API requires a valid Turnstile token.");
|
|
||||||
if (!recaptchaToken && this.info.recaptcha.required) throw new Error("This API requires a valid reCAPTCHA token.");
|
|
||||||
var data = await fetch(this.apiEndpoint + "/api/v1/sendreset", {
|
var data = await fetch(this.apiEndpoint + "/api/v1/sendreset", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
|
|
@ -176,9 +166,7 @@ export default class AuthManager {
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
username: username,
|
username: username,
|
||||||
email: email,
|
email: email,
|
||||||
captchaToken: captchaToken,
|
captchaToken: captchaToken
|
||||||
turnstileToken: turnstileToken,
|
|
||||||
recaptchaToken: recaptchaToken
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
res(await data.json() as PasswordResetResult);
|
res(await data.json() as PasswordResetResult);
|
||||||
|
|
@ -210,14 +198,6 @@ export interface AuthServerInformation {
|
||||||
required : boolean;
|
required : boolean;
|
||||||
siteKey : string | undefined;
|
siteKey : string | undefined;
|
||||||
};
|
};
|
||||||
turnstile : {
|
|
||||||
required : boolean;
|
|
||||||
siteKey : string | undefined;
|
|
||||||
};
|
|
||||||
recaptcha : {
|
|
||||||
required : boolean;
|
|
||||||
siteKey : string | undefined;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AccountRegisterResult {
|
export interface AccountRegisterResult {
|
||||||
|
|
|
||||||
138
src/ts/main.ts
138
src/ts/main.ts
|
|
@ -97,11 +97,7 @@ const elements = {
|
||||||
accountRegisterForm: document.getElementById("accountRegisterForm") as HTMLFormElement,
|
accountRegisterForm: document.getElementById("accountRegisterForm") as HTMLFormElement,
|
||||||
accountVerifyEmailForm: document.getElementById("accountVerifyEmailForm") as HTMLFormElement,
|
accountVerifyEmailForm: document.getElementById("accountVerifyEmailForm") as HTMLFormElement,
|
||||||
accountLoginCaptcha: document.getElementById("accountLoginCaptcha") as HTMLDivElement,
|
accountLoginCaptcha: document.getElementById("accountLoginCaptcha") as HTMLDivElement,
|
||||||
accountLoginRecaptcha: document.getElementById("accountLoginReCaptcha") as HTMLDivElement,
|
|
||||||
accountLoginTurnstile: document.getElementById("accountLoginTurnstile") as HTMLDivElement,
|
|
||||||
accountRegisterCaptcha: document.getElementById("accountRegisterCaptcha") as HTMLDivElement,
|
accountRegisterCaptcha: document.getElementById("accountRegisterCaptcha") as HTMLDivElement,
|
||||||
accountRegisterRecaptcha: document.getElementById("accountRegisterReCaptcha") as HTMLDivElement,
|
|
||||||
accountRegisterTurnstile: document.getElementById("accountRegisterTurnstile") as HTMLDivElement,
|
|
||||||
|
|
||||||
accountLoginUsername: document.getElementById("accountLoginUsername") as HTMLInputElement,
|
accountLoginUsername: document.getElementById("accountLoginUsername") as HTMLInputElement,
|
||||||
accountLoginPassword: document.getElementById("accountLoginPassword") as HTMLInputElement,
|
accountLoginPassword: document.getElementById("accountLoginPassword") as HTMLInputElement,
|
||||||
|
|
@ -127,8 +123,6 @@ const elements = {
|
||||||
accountResetPasswordEmail: document.getElementById("accountResetPasswordEmail") as HTMLInputElement,
|
accountResetPasswordEmail: document.getElementById("accountResetPasswordEmail") as HTMLInputElement,
|
||||||
accountResetPasswordUsername: document.getElementById("accountResetPasswordUsername") as HTMLInputElement,
|
accountResetPasswordUsername: document.getElementById("accountResetPasswordUsername") as HTMLInputElement,
|
||||||
accountResetPasswordCaptcha: document.getElementById("accountResetPasswordCaptcha") as HTMLDivElement,
|
accountResetPasswordCaptcha: document.getElementById("accountResetPasswordCaptcha") as HTMLDivElement,
|
||||||
accountResetPasswordRecaptcha: document.getElementById("accountResetPasswordReCaptcha") as HTMLDivElement,
|
|
||||||
accountResetPasswordTurnstile: document.getElementById("accountResetPasswordTurnstile") as HTMLDivElement,
|
|
||||||
|
|
||||||
accountResetPasswordVerifySection: document.getElementById("accountResetPasswordVerifySection") as HTMLDivElement,
|
accountResetPasswordVerifySection: document.getElementById("accountResetPasswordVerifySection") as HTMLDivElement,
|
||||||
accountVerifyPasswordResetText: document.getElementById("accountVerifyPasswordResetText") as HTMLParagraphElement,
|
accountVerifyPasswordResetText: document.getElementById("accountVerifyPasswordResetText") as HTMLParagraphElement,
|
||||||
|
|
@ -949,45 +943,12 @@ async function renderAuth() {
|
||||||
elements.accountRegisterCaptcha.innerHTML = "";
|
elements.accountRegisterCaptcha.innerHTML = "";
|
||||||
elements.accountLoginCaptcha.innerHTML = "";
|
elements.accountLoginCaptcha.innerHTML = "";
|
||||||
elements.accountResetPasswordCaptcha.innerHTML = "";
|
elements.accountResetPasswordCaptcha.innerHTML = "";
|
||||||
elements.accountRegisterTurnstile.innerHTML = "";
|
|
||||||
elements.accountLoginTurnstile.innerHTML = "";
|
|
||||||
elements.accountResetPasswordTurnstile.innerHTML = "";
|
|
||||||
elements.accountRegisterRecaptcha.innerHTML = "";
|
|
||||||
elements.accountLoginRecaptcha.innerHTML = "";
|
|
||||||
elements.accountResetPasswordRecaptcha.innerHTML = "";
|
|
||||||
if (auth!.info!.hcaptcha.required) {
|
if (auth!.info!.hcaptcha.required) {
|
||||||
var hconfig = {sitekey: auth!.info!.hcaptcha.siteKey!};
|
var hconfig = {sitekey: auth!.info!.hcaptcha.siteKey!};
|
||||||
hcaptcha.render(elements.accountRegisterCaptcha, hconfig);
|
hcaptcha.render(elements.accountRegisterCaptcha, hconfig);
|
||||||
hcaptcha.render(elements.accountLoginCaptcha, hconfig);
|
hcaptcha.render(elements.accountLoginCaptcha, hconfig);
|
||||||
hcaptcha.render(elements.accountResetPasswordCaptcha, hconfig);
|
hcaptcha.render(elements.accountResetPasswordCaptcha, hconfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(auth!.info?.turnstile.required) {
|
|
||||||
var turnstileconfig = {sitekey: auth!.info!.turnstile.siteKey!};
|
|
||||||
|
|
||||||
// hCaptcha does this automatically, but Turnstile doesn't, oh well.
|
|
||||||
var turnstileRegisterWidgetId = turnstile.render(elements.accountRegisterTurnstile, turnstileconfig);
|
|
||||||
var turnstileLoginWidgetId = turnstile.render(elements.accountLoginTurnstile, turnstileconfig);
|
|
||||||
var turnstileResetPasswordWidgetId = turnstile.render(elements.accountResetPasswordTurnstile, turnstileconfig);
|
|
||||||
|
|
||||||
elements.accountRegisterTurnstile.children[0].setAttribute("data-turnstile-widget-id", turnstileRegisterWidgetId!);
|
|
||||||
elements.accountLoginTurnstile.children[0].setAttribute("data-turnstile-widget-id", turnstileLoginWidgetId!);
|
|
||||||
elements.accountResetPasswordTurnstile.children[0].setAttribute("data-turnstile-widget-id", turnstileResetPasswordWidgetId!);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(auth!.info?.recaptcha.required) {
|
|
||||||
var recaptchaconfig = {sitekey: auth!.info!.recaptcha.siteKey!};
|
|
||||||
|
|
||||||
// Same deal as with Turnstile
|
|
||||||
var RecaptchaRegisterWidgetId = grecaptcha.render(elements.accountRegisterRecaptcha, recaptchaconfig);
|
|
||||||
var RecaptchaLoginWidgetId = grecaptcha.render(elements.accountLoginRecaptcha, recaptchaconfig);
|
|
||||||
var RecaptchaResetPasswordWidgetId = grecaptcha.render(elements.accountResetPasswordRecaptcha, recaptchaconfig);
|
|
||||||
|
|
||||||
elements.accountRegisterRecaptcha.children[0].setAttribute("data-recaptcha-widget-id", RecaptchaRegisterWidgetId!.toString());
|
|
||||||
elements.accountLoginRecaptcha.children[0].setAttribute("data-recaptcha-widget-id", RecaptchaLoginWidgetId!.toString());
|
|
||||||
elements.accountResetPasswordRecaptcha.children[0].setAttribute("data-recaptcha-widget-id", RecaptchaResetPasswordWidgetId!.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
var token = localStorage.getItem("collabvm_session_" + new URL(auth!.apiEndpoint).host);
|
var token = localStorage.getItem("collabvm_session_" + new URL(auth!.apiEndpoint).host);
|
||||||
if (token) {
|
if (token) {
|
||||||
var result = await auth!.loadSession(token);
|
var result = await auth!.loadSession(token);
|
||||||
|
|
@ -1071,41 +1032,10 @@ elements.accountLoginForm.addEventListener('submit', async (e) => {
|
||||||
}
|
}
|
||||||
hcaptchaToken = response;
|
hcaptchaToken = response;
|
||||||
}
|
}
|
||||||
|
|
||||||
var turnstileToken = undefined;
|
|
||||||
var turnstileID = undefined;
|
|
||||||
|
|
||||||
if (auth!.info!.turnstile.required) {
|
|
||||||
turnstileID = elements.accountLoginTurnstile.children[0].getAttribute("data-turnstile-widget-id")!
|
|
||||||
var response: string = turnstile.getResponse(turnstileID) || "";
|
|
||||||
if (response === "") {
|
|
||||||
elements.accountModalErrorText.innerHTML = TheI18n.GetString(I18nStringKey.kMissingCaptcha);
|
|
||||||
elements.accountModalError.style.display = "block";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
turnstileToken = response;
|
|
||||||
}
|
|
||||||
|
|
||||||
var recaptchaToken = undefined;
|
|
||||||
var recaptchaID = undefined;
|
|
||||||
|
|
||||||
if (auth!.info!.recaptcha.required) {
|
|
||||||
recaptchaID = parseInt(elements.accountLoginRecaptcha.children[0].getAttribute("data-recaptcha-widget-id")!)
|
|
||||||
var response = grecaptcha.getResponse(recaptchaID);
|
|
||||||
if (response === "") {
|
|
||||||
elements.accountModalErrorText.innerHTML = TheI18n.GetString(I18nStringKey.kMissingCaptcha);
|
|
||||||
elements.accountModalError.style.display = "block";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
recaptchaToken = response;
|
|
||||||
}
|
|
||||||
|
|
||||||
var username = elements.accountLoginUsername.value;
|
var username = elements.accountLoginUsername.value;
|
||||||
var password = elements.accountLoginPassword.value;
|
var password = elements.accountLoginPassword.value;
|
||||||
var result = await auth!.login(username, password, hcaptchaToken, turnstileToken, recaptchaToken);
|
var result = await auth!.login(username, password, hcaptchaToken);
|
||||||
if (auth!.info!.hcaptcha.required) hcaptcha.reset(hcaptchaID);
|
if (auth!.info!.hcaptcha.required) hcaptcha.reset(hcaptchaID);
|
||||||
if (auth!.info!.turnstile.required) turnstile.reset(turnstileID);
|
|
||||||
if (auth!.info!.recaptcha.required) grecaptcha.reset(recaptchaID);
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
elements.accountLoginUsername.value = "";
|
elements.accountLoginUsername.value = "";
|
||||||
elements.accountLoginPassword.value = "";
|
elements.accountLoginPassword.value = "";
|
||||||
|
|
@ -1139,35 +1069,6 @@ elements.accountRegisterForm.addEventListener('submit', async (e) => {
|
||||||
}
|
}
|
||||||
hcaptchaToken = response;
|
hcaptchaToken = response;
|
||||||
}
|
}
|
||||||
|
|
||||||
var turnstileToken = undefined;
|
|
||||||
var turnstileID = undefined;
|
|
||||||
|
|
||||||
if (auth!.info!.turnstile.required) {
|
|
||||||
turnstileID = elements.accountRegisterTurnstile.children[0].getAttribute("data-turnstile-widget-id")!
|
|
||||||
var response: string = turnstile.getResponse(turnstileID) || "";
|
|
||||||
if (response === "") {
|
|
||||||
elements.accountModalErrorText.innerHTML = TheI18n.GetString(I18nStringKey.kMissingCaptcha);
|
|
||||||
elements.accountModalError.style.display = "block";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
turnstileToken = response;
|
|
||||||
}
|
|
||||||
|
|
||||||
var recaptchaToken = undefined;
|
|
||||||
var recaptchaID = undefined;
|
|
||||||
|
|
||||||
if (auth!.info!.recaptcha.required) {
|
|
||||||
recaptchaID = parseInt(elements.accountRegisterRecaptcha.children[0].getAttribute("data-recaptcha-widget-id")!)
|
|
||||||
var response = grecaptcha.getResponse(recaptchaID);
|
|
||||||
if (response === "") {
|
|
||||||
elements.accountModalErrorText.innerHTML = TheI18n.GetString(I18nStringKey.kMissingCaptcha);
|
|
||||||
elements.accountModalError.style.display = "block";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
recaptchaToken = response;
|
|
||||||
}
|
|
||||||
|
|
||||||
var username = elements.accountRegisterUsername.value;
|
var username = elements.accountRegisterUsername.value;
|
||||||
var password = elements.accountRegisterPassword.value;
|
var password = elements.accountRegisterPassword.value;
|
||||||
var email = elements.accountRegisterEmail.value;
|
var email = elements.accountRegisterEmail.value;
|
||||||
|
|
@ -1177,10 +1078,8 @@ elements.accountRegisterForm.addEventListener('submit', async (e) => {
|
||||||
elements.accountModalError.style.display = "block";
|
elements.accountModalError.style.display = "block";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var result = await auth!.register(username, password, email, dob, hcaptchaToken, turnstileToken, recaptchaToken);
|
var result = await auth!.register(username, password, email, dob, hcaptchaToken);
|
||||||
if (auth!.info!.hcaptcha.required) hcaptcha.reset(hcaptchaID);
|
if (auth!.info!.hcaptcha.required) hcaptcha.reset(hcaptchaID);
|
||||||
if (auth!.info!.turnstile.required) turnstile.reset(turnstileID);
|
|
||||||
if (auth!.info!.recaptcha.required) grecaptcha.reset(recaptchaID);
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
elements.accountRegisterUsername.value = "";
|
elements.accountRegisterUsername.value = "";
|
||||||
elements.accountRegisterEmail.value = "";
|
elements.accountRegisterEmail.value = "";
|
||||||
|
|
@ -1283,41 +1182,10 @@ elements.accountResetPasswordForm.addEventListener('submit', async e => {
|
||||||
}
|
}
|
||||||
hcaptchaToken = response;
|
hcaptchaToken = response;
|
||||||
}
|
}
|
||||||
|
|
||||||
var turnstileToken = undefined;
|
|
||||||
var turnstileID = undefined;
|
|
||||||
|
|
||||||
if (auth!.info!.turnstile.required) {
|
|
||||||
turnstileID = elements.accountResetPasswordTurnstile.children[0].getAttribute("data-turnstile-widget-id")!
|
|
||||||
var response: string = turnstile.getResponse(turnstileID) || "";
|
|
||||||
if (response === "") {
|
|
||||||
elements.accountModalErrorText.innerHTML = TheI18n.GetString(I18nStringKey.kMissingCaptcha);
|
|
||||||
elements.accountModalError.style.display = "block";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
turnstileToken = response;
|
|
||||||
}
|
|
||||||
|
|
||||||
var recaptchaToken = undefined;
|
|
||||||
var recaptchaID = undefined;
|
|
||||||
|
|
||||||
if (auth!.info!.recaptcha.required) {
|
|
||||||
recaptchaID = parseInt(elements.accountResetPasswordRecaptcha.children[0].getAttribute("data-recaptcha-widget-id")!)
|
|
||||||
var response = grecaptcha.getResponse(recaptchaID);
|
|
||||||
if (response === "") {
|
|
||||||
elements.accountModalErrorText.innerHTML = TheI18n.GetString(I18nStringKey.kMissingCaptcha);
|
|
||||||
elements.accountModalError.style.display = "block";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
recaptchaToken = response;
|
|
||||||
}
|
|
||||||
|
|
||||||
var username = elements.accountResetPasswordUsername.value;
|
var username = elements.accountResetPasswordUsername.value;
|
||||||
var email = elements.accountResetPasswordEmail.value;
|
var email = elements.accountResetPasswordEmail.value;
|
||||||
var result = await auth!.sendPasswordResetEmail(username, email, hcaptchaToken, turnstileToken, recaptchaToken);
|
var result = await auth!.sendPasswordResetEmail(username, email, hcaptchaToken);
|
||||||
if (auth!.info!.hcaptcha.required) hcaptcha.reset(hcaptchaID);
|
if (auth!.info!.hcaptcha.required) hcaptcha.reset(hcaptchaID);
|
||||||
if (auth!.info!.turnstile.required) turnstile.reset(turnstileID);
|
|
||||||
if (auth!.info!.recaptcha.required) grecaptcha.reset(recaptchaID);
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
resetPasswordUsername = username;
|
resetPasswordUsername = username;
|
||||||
resetPasswordEmail = email;
|
resetPasswordEmail = email;
|
||||||
|
|
|
||||||
101
static/lang/cv-m.json
Normal file
101
static/lang/cv-m.json
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
{
|
||||||
|
"languageName": "nonsense",
|
||||||
|
"translatedLanguageName": "nonsense",
|
||||||
|
"flag": "NS",
|
||||||
|
"author": "cvmuser1000, skyhighsundae",
|
||||||
|
|
||||||
|
"stringKeys": {
|
||||||
|
"kGeneric_CollabVM": "s09d8sa0d7asdasd708d7as0dßasd",
|
||||||
|
"kGeneric_Yes": "wq09d8sßad8as90deá98d8asda97287ßsa8d3a7d",
|
||||||
|
"kGeneric_No": "asdaqsd0asd78asd0asdasd",
|
||||||
|
"kGeneric_Ok": "DSADASDDUASDASD=",
|
||||||
|
"kGeneric_Cancel": "NDADASUASIDKAJDSKIUASDLWSUIADJHPAWUSAD",
|
||||||
|
"kGeneric_Send": "odsjadoiasudoasoidasidsaidasudasd",
|
||||||
|
"kGeneric_Understood": "odssiad09s8dsad",
|
||||||
|
"kGeneric_Username": "sad9asu8d30a2880e8weu2q",
|
||||||
|
"kGeneric_Password": "sa9dasd9802788ej3lklkkjgofopdüsaödlkiwigtrghzg",
|
||||||
|
"kGeneric_Login": "0129837465ruzfhjcnghjdskhgjfdksgjkds",
|
||||||
|
"kGeneric_Register": "aölkgjhtujekdksklejjjasddadasdasi",
|
||||||
|
"kGeneric_EMail": "EDisuad8as7d0asd",
|
||||||
|
"kGeneric_DateOfBirth": "D9098s9a80ßdsda",
|
||||||
|
"kGeneric_VerificationCode": "ad98as8d0asdß Code",
|
||||||
|
"kGeneric_Verify": "das0d9as8d8a0939asd",
|
||||||
|
"kGeneric_Update": "asd8as8d0sad7as90d",
|
||||||
|
"kGeneric_Logout": "9erwfeüookawerjioksdiuferjkzofer",
|
||||||
|
|
||||||
|
"kWelcomeModal_Header": "Welcome to s09d8sa0d7asdasd708d7as0dßasd (Tweaked)",
|
||||||
|
"kWelcomeModal_Body": "sdiuasd0ßYOudasd0a9sdas8d90OYußsadsad9asd8As8)(dsad0adas0d098WS8sda87saWds998sa9asd989",
|
||||||
|
|
||||||
|
"kSiteButtons_Home": "x0e08d9f9f93ks9s8ad989a9sd829038eqwde",
|
||||||
|
"kSiteButtons_FAQ": "=?D)S=A(D=)S(A=Eßasd7a08sd0828ßa0dsadjaspd8ß2",
|
||||||
|
"kSiteButtons_Rules": "9dasd07asd8728a0sd98a89sd=d8as0dadaOIDHASdjADHASOD",
|
||||||
|
"kSiteButtons_DarkMode": "IDÖOASDOA(DUASDAISDPIS",
|
||||||
|
"kSiteButtons_LightMode": "DISADISAD)AS)DAS)D)ADASUASIDJASKDASD",
|
||||||
|
"kSiteButtons_Languages": "s09d8sa0d7asdasd708d7as0dßasd ASD)(AS)D(ASDKASDKASD",
|
||||||
|
|
||||||
|
"kVM_UsersOnlineText": "DUSADIASDJUASODASD: ",
|
||||||
|
|
||||||
|
"kVM_TurnTimeTimer": "SADI SAODIAO IDOASDO {0} SAD()ASD(AS=DASDD",
|
||||||
|
"kVM_WaitingTurnTimer": "SDIKSODA SAIDSOAID IOSAD OOASD OI {0} SAODOASDÜ",
|
||||||
|
"kVM_VoteCooldownTimer": "FKJDJF PDSFPO {0} ASJDLS ASDKJAS ()(FK FDLKD KFO",
|
||||||
|
|
||||||
|
"kVM_VoteForResetTitle": "ASDIKOASDIPS )DSJDASIPD VM FDASISDIAPD",
|
||||||
|
"kVM_VoteForResetTimer": "VSLDKALSDK DLKSALD SAESAPD {0} SDIASDJ",
|
||||||
|
|
||||||
|
"kVMButtons_TakeTurn": "SADKOOASDOPDPOAS",
|
||||||
|
"kVMButtons_EndTurn": "IASUASD)SD",
|
||||||
|
"kVMButtons_ChangeUsername": "ADAS)(§)SKSODASKDSA",
|
||||||
|
"kVMButtons_Keyboard": "FDSPFSDOFISDIOPFUPÜS",
|
||||||
|
"KVMButtons_CtrlAltDel": "ASDOASD+SDOSD+DSI",
|
||||||
|
|
||||||
|
"kVMButtons_VoteForReset": "DKSI DAS( RESET",
|
||||||
|
"kVMButtons_Screenshot": "ASD=ASDASPDIASPDOIASDPIASD",
|
||||||
|
|
||||||
|
"kQEMUMonitor": "ADSIOADOASDIPAOSDIASPÜDSAD",
|
||||||
|
"kAdminVMButtons_PassVote": "SADI)AS(DASDJASD KASJDIASDI ISAI",
|
||||||
|
"kAdminVMButtons_CancelVote": "SDIASOD IOASDOI",
|
||||||
|
|
||||||
|
"kAdminVMButtons_Restore": "SADKASDIAPSODAPSÄDIASUIDPIUASDPASUIDPIASD",
|
||||||
|
"kAdminVMButtons_Reboot": "ASPODASUIOPDIASDUASPUIDASOIDASIDSAIDOASIDPA",
|
||||||
|
"kAdminVMButtons_ClearTurnQueue": "SADOPASOKIDSAOÜDIOASDÜSAD",
|
||||||
|
"kAdminVMButtons_BypassTurn": "ASDKOASDPOASD OASIDASOPD",
|
||||||
|
"kAdminVMButtons_IndefiniteTurn": "SADKASOÜDOÜ OSADOISÜ",
|
||||||
|
"kAdminVMButtons_GhostTurnOn": "SADASKDOASDOIASDIO DASIDUSAUID (SAODPAISD)",
|
||||||
|
"kAdminVMButtons_GhostTurnOff": "SADASKDOASDOIASDIO DASIDUSAUID (SAKDSOAD)",
|
||||||
|
|
||||||
|
"kAdminVMButtons_Ban": "ISADASPÜD",
|
||||||
|
"kAdminVMButtons_Kick": "SDIOASDISAD",
|
||||||
|
"kAdminVMButtons_TempMute": "SDLKASDPIOAIPD ASIDAS",
|
||||||
|
"kAdminVMButtons_IndefMute": "SADOASDIPÜASD ASIDAS",
|
||||||
|
"kAdminVMButtons_Unmute": "ASDIASIDAS",
|
||||||
|
"kAdminVMButtons_GetIP": "SSDPASDASDÜ)A=D",
|
||||||
|
|
||||||
|
"kVMPrompts_AdminChangeUsernamePrompt": "DISUADOASUDZ OASDd iSA DSd {0}:",
|
||||||
|
"kVMPrompts_AdminRestoreVMPrompt": "ASOIAIPDSDUA sad9 asd9asd uiasd aosd",
|
||||||
|
"kVMPrompts_EnterNewUsernamePrompt": "ODUSPADIUASP asp9dasp9 asd9 uasid usadi",
|
||||||
|
|
||||||
|
"kError_UnexpectedDisconnection": "d9sa98d0asd08SDASDASD",
|
||||||
|
"kError_UsernameTaken": "saoidipasdpas uasdiuasuodiiouIDUIASDP1",
|
||||||
|
"kError_UsernameInvalid": "ASDPOASUDA )(ASDIUASD PIUSAIDU SAIDU IDISAUDUISAUISAiuaisa",
|
||||||
|
"kError_UsernameBlacklisted": "DOSADI OASD ISS=AD =SDJ PSAIDP SIDPJ",
|
||||||
|
"kError_IncorrectPassword": "DUIASDASD =SAD)A=",
|
||||||
|
|
||||||
|
"kAccountModal_Verify": "SADKOSADO OSAIDOISAI",
|
||||||
|
"kAccountModal_AccountSettings": "SAOSDIIPASD ISADSUAPD",
|
||||||
|
"kAccountModal_ResetPassword": "SDAOIDOASID IOODOASIO",
|
||||||
|
|
||||||
|
"kAccountModal_NewPassword": "XSAPDIASPD IASDOASI)SPAD",
|
||||||
|
"kAccountModal_ConfirmNewPassword": "DPASDKO ASPDPSD DPAS",
|
||||||
|
"kAccountModal_CurrentPassword": "DLSADOASD DAOIIO",
|
||||||
|
"kAccountModal_ConfirmPassword": "ASD=AI OWEJSDJLSD LIASIDI",
|
||||||
|
"kAccountModal_HideFlag": "DASOSAO OFOGP ÜAÜASDAPDSDASDI IDPSPOPD",
|
||||||
|
|
||||||
|
"kMissingCaptcha": "ASDOASIDPOASD SDOSAD OSDIO CAPTCHA",
|
||||||
|
"kPasswordsMustMatch": "ASODIO SAIOD OISADIO IO SADIOIO",
|
||||||
|
"kAccountModal_VerifyText": "DL SODSI ID SAIOD SOID JSADSIOADJASJID ASDOSA JDSAOJ",
|
||||||
|
"kAccountModal_VerifyPasswordResetText": "SADIO ASDIP ASD(I PSAIOD P)ASD( AS)D )ASD) A)SD )SAUJD IASD J JSA J ASODOSADOSADISAIPD",
|
||||||
|
"kAccountModal_PasswordResetSuccess": "SADSA)D )SAD(AS)D )SAD)()(A )(SAD())(S ()AS()D)(ASDASD",
|
||||||
|
|
||||||
|
"kNotLoggedIn": "DASKD KSAKJSA DSJ"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
"kGeneric_Update": "Update",
|
"kGeneric_Update": "Update",
|
||||||
"kGeneric_Logout": "Log out",
|
"kGeneric_Logout": "Log out",
|
||||||
|
|
||||||
"kWelcomeModal_Header": "Welcome to CollabVM",
|
"kWelcomeModal_Header": "Welcome to CollabVM (Tweaked)",
|
||||||
"kWelcomeModal_Body": "<p>Before continuing, please familiarize yourself with our rules:</p> <h3>R1. Don't break the law.</h3> Do not use CollabVM or CollabVM's network to violate United States federal law, New York state law, or international law. If CollabVM becomes aware a crime has been committed through its service, you will be immediately banned, and your activities may be reported to the authorities if necessary.<br><br>CollabVM is required by law to notify law enforcement agencies if it becomes aware of the presence of child pornography on, or being transmitted through its network.<br><br>COPPA is also enforced, please do not use CollabVM if you are under the age of 13 years old. <h3>R2. No running DoS/DDoS tools.</h3> Do not use CollabVM to DoS/DDoS an indivdiual, business, company, or anyone else. <h3>R3. No spam distribution.</h3> Do not spam any emails using this service or push spam in general. <h3>R4. Do not abuse any exploits.</h3> Do not abuse any exploits, additionally if you see someone abusing exploits or you need to report one, please contact me at: computernewbab@gmail.com <h3>R5. Don't impersonate other users.</h3> Do not impersonate other members of CollabVM. If caught, you'll be temporarily disconnected, and banned if necessary. <h3>R6. One vote per person.</h3> Do not use any methods or tools to bypass the vote restriction. Only one vote per person is allowed, no matter what. Anybody who is caught doing this will be banned. <h3>R7. No Remote Administration Tools.</h3> Do not use any remote administration tools (ex: DarkComet, NanoCore, Anydesk, TeamViewer, Orcus, etc.) <h3>R8. No bypassing CollabNet.</h3> Do not attempt to bypass the blocking provided by CollabNet, especially if it is being used to break Rule 1, Rule 2, or Rule 7 (or run stupid over-used things). <h3>R9. No performing destructive actions constantly.</h3> Any user may not destroy the VM (rendering it unusable constantly), install/reinstall the operating system (except on VM7 or VM8), or run bots that do such. This includes bots that spam massive amounts of keyboard/mouse input (\"kitting\"). <h3>R10. No Cryptomining</h3> Attempting to mine cryptocurrency on the VMs will result in a kick, and then a permanent ban if you keep attempting. Besides, it's not like you're gonna make any money off it. <h3>NSFW Warning</h3> Please note that NSFW content is allowed on our anarchy VM (VM0b0t), and is viewed regularly. In addition, while we give a good effort to keep NSFW off the main VMs, people will occasionally slip it through.",
|
"kWelcomeModal_Body": "<p>Before continuing, please familiarize yourself with our rules:</p> <h3>R1. Don't break the law.</h3> Do not use CollabVM or CollabVM's network to violate United States federal law, New York state law, or international law. If CollabVM becomes aware a crime has been committed through its service, you will be immediately banned, and your activities may be reported to the authorities if necessary.<br><br>CollabVM is required by law to notify law enforcement agencies if it becomes aware of the presence of child pornography on, or being transmitted through its network.<br><br>COPPA is also enforced, please do not use CollabVM if you are under the age of 13 years old. <h3>R2. No running DoS/DDoS tools.</h3> Do not use CollabVM to DoS/DDoS an indivdiual, business, company, or anyone else. <h3>R3. No spam distribution.</h3> Do not spam any emails using this service or push spam in general. <h3>R4. Do not abuse any exploits.</h3> Do not abuse any exploits, additionally if you see someone abusing exploits or you need to report one, please contact me at: computernewbab@gmail.com <h3>R5. Don't impersonate other users.</h3> Do not impersonate other members of CollabVM. If caught, you'll be temporarily disconnected, and banned if necessary. <h3>R6. One vote per person.</h3> Do not use any methods or tools to bypass the vote restriction. Only one vote per person is allowed, no matter what. Anybody who is caught doing this will be banned. <h3>R7. No Remote Administration Tools.</h3> Do not use any remote administration tools (ex: DarkComet, NanoCore, Anydesk, TeamViewer, Orcus, etc.) <h3>R8. No bypassing CollabNet.</h3> Do not attempt to bypass the blocking provided by CollabNet, especially if it is being used to break Rule 1, Rule 2, or Rule 7 (or run stupid over-used things). <h3>R9. No performing destructive actions constantly.</h3> Any user may not destroy the VM (rendering it unusable constantly), install/reinstall the operating system (except on VM7 or VM8), or run bots that do such. This includes bots that spam massive amounts of keyboard/mouse input (\"kitting\"). <h3>R10. No Cryptomining</h3> Attempting to mine cryptocurrency on the VMs will result in a kick, and then a permanent ban if you keep attempting. Besides, it's not like you're gonna make any money off it. <h3>NSFW Warning</h3> Please note that NSFW content is allowed on our anarchy VM (VM0b0t), and is viewed regularly. In addition, while we give a good effort to keep NSFW off the main VMs, people will occasionally slip it through.",
|
||||||
|
|
||||||
"kSiteButtons_Home": "Home",
|
"kSiteButtons_Home": "Home",
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
"kSiteButtons_Rules": "Rules",
|
"kSiteButtons_Rules": "Rules",
|
||||||
"kSiteButtons_DarkMode": "Dark Mode",
|
"kSiteButtons_DarkMode": "Dark Mode",
|
||||||
"kSiteButtons_LightMode": "Light Mode",
|
"kSiteButtons_LightMode": "Light Mode",
|
||||||
"kSiteButtons_Languages": "Languages",
|
"kSiteButtons_Languages": "CollabVM Languages",
|
||||||
|
|
||||||
"kVM_UsersOnlineText": "Users Online:",
|
"kVM_UsersOnlineText": "Users Online:",
|
||||||
|
|
||||||
|
|
@ -44,8 +44,8 @@
|
||||||
|
|
||||||
"kVMButtons_TakeTurn": "Take Turn",
|
"kVMButtons_TakeTurn": "Take Turn",
|
||||||
"kVMButtons_EndTurn": "End Turn",
|
"kVMButtons_EndTurn": "End Turn",
|
||||||
"kVMButtons_ChangeUsername": "Change Username",
|
"kVMButtons_ChangeUsername": "Username Settings",
|
||||||
"kVMButtons_Keyboard": "Keyboard",
|
"kVMButtons_Keyboard": "Show Keyboard",
|
||||||
"KVMButtons_CtrlAltDel": "Ctrl+Alt+Del",
|
"KVMButtons_CtrlAltDel": "Ctrl+Alt+Del",
|
||||||
|
|
||||||
"kVMButtons_VoteForReset": "Vote For Reset",
|
"kVMButtons_VoteForReset": "Vote For Reset",
|
||||||
|
|
@ -66,7 +66,7 @@
|
||||||
"kAdminVMButtons_Ban": "Ban",
|
"kAdminVMButtons_Ban": "Ban",
|
||||||
"kAdminVMButtons_Kick": "Kick",
|
"kAdminVMButtons_Kick": "Kick",
|
||||||
"kAdminVMButtons_TempMute": "Temporary Mute",
|
"kAdminVMButtons_TempMute": "Temporary Mute",
|
||||||
"kAdminVMButtons_IndefMute": "Indefinite Mute",
|
"kAdminVMButtons_IndefMute": "Permanent Mute",
|
||||||
"kAdminVMButtons_Unmute": "Unmute",
|
"kAdminVMButtons_Unmute": "Unmute",
|
||||||
"kAdminVMButtons_GetIP": "Get IP",
|
"kAdminVMButtons_GetIP": "Get IP",
|
||||||
|
|
||||||
|
|
@ -88,7 +88,7 @@
|
||||||
"kAccountModal_ConfirmNewPassword": "Confirm New Password",
|
"kAccountModal_ConfirmNewPassword": "Confirm New Password",
|
||||||
"kAccountModal_CurrentPassword": "Current Password",
|
"kAccountModal_CurrentPassword": "Current Password",
|
||||||
"kAccountModal_ConfirmPassword": "Confirm Password",
|
"kAccountModal_ConfirmPassword": "Confirm Password",
|
||||||
"kAccountModal_HideFlag": "Hide my Country Flag",
|
"kAccountModal_HideFlag": "Hide my Country Flag from the Users Online section",
|
||||||
|
|
||||||
"kMissingCaptcha": "Please fill out the captcha.",
|
"kMissingCaptcha": "Please fill out the captcha.",
|
||||||
"kPasswordsMustMatch": "Passwords must match.",
|
"kPasswordsMustMatch": "Passwords must match.",
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,10 @@
|
||||||
"languageName": "English (US)",
|
"languageName": "English (US)",
|
||||||
"flag": "🇺🇸"
|
"flag": "🇺🇸"
|
||||||
},
|
},
|
||||||
|
"cv-m": {
|
||||||
|
"languageName": "nonsense",
|
||||||
|
"flag": "NS"
|
||||||
|
},
|
||||||
"fr-fr": {
|
"fr-fr": {
|
||||||
"languageName": "Français",
|
"languageName": "Français",
|
||||||
"flag": "🇫🇷"
|
"flag": "🇫🇷"
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,7 @@
|
||||||
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||||
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||||
"typeRoots": [
|
"typeRoots": [
|
||||||
"node_modules/@hcaptcha",
|
"node_modules/@hcaptcha"
|
||||||
"node_modules/@types"
|
|
||||||
], /* Specify multiple folders that act like './node_modules/@types'. */
|
], /* Specify multiple folders that act like './node_modules/@types'. */
|
||||||
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
||||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||||
|
|
|
||||||
10
yarn.lock
10
yarn.lock
|
|
@ -1446,11 +1446,6 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@popperjs/core" "^2.9.2"
|
"@popperjs/core" "^2.9.2"
|
||||||
|
|
||||||
"@types/cloudflare-turnstile@^0.2.2":
|
|
||||||
version "0.2.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/cloudflare-turnstile/-/cloudflare-turnstile-0.2.2.tgz#3364d65b00f03376f4e555820db270173807a52c"
|
|
||||||
integrity sha512-3Yf7b1Glci+V2bFWwWBbZkRgTuegp7RDgNTOG4U0UNPB9RV4AWvwqg2/qqLff8G+SwKFNXoXvTkqaRBZrAFdKA==
|
|
||||||
|
|
||||||
"@types/dompurify@^3.0.5":
|
"@types/dompurify@^3.0.5":
|
||||||
version "3.0.5"
|
version "3.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/@types/dompurify/-/dompurify-3.0.5.tgz#02069a2fcb89a163bacf1a788f73cb415dd75cb7"
|
resolved "https://registry.yarnpkg.com/@types/dompurify/-/dompurify-3.0.5.tgz#02069a2fcb89a163bacf1a788f73cb415dd75cb7"
|
||||||
|
|
@ -1465,11 +1460,6 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/grecaptcha@^3.0.9":
|
|
||||||
version "3.0.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/grecaptcha/-/grecaptcha-3.0.9.tgz#9f3b07ec06c8fff221aa6fc124fe5b8a0e2c3349"
|
|
||||||
integrity sha512-fFxMtjAvXXMYTzDFK5NpcVB7WHnrHVLl00QzEGpuFxSAC789io6M+vjcn+g5FTEamIJtJr/IHkCDsqvJxeWDyw==
|
|
||||||
|
|
||||||
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1":
|
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1":
|
||||||
version "2.0.6"
|
version "2.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7"
|
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user