mirror of
https://github.com/SrIzan10/vdo.ninja.git
synced 2026-05-01 11:05:24 +00:00
349 lines
11 KiB
HTML
349 lines
11 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>VDO.Ninja Hash Generator</title>
|
|
<meta charset="utf8" />
|
|
<style>
|
|
:root {
|
|
--primary: #00ff00;
|
|
--primary-dark: #00cc00;
|
|
--bg-dark: #141926;
|
|
--bg-darker: #0d1117;
|
|
--bg-card: #1e2738;
|
|
--bg-input: #2a364d;
|
|
--border: #3a465d;
|
|
--text: #ffffff;
|
|
--text-muted: #8b949e;
|
|
}
|
|
|
|
* {
|
|
box-sizing: border-box;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
body {
|
|
background: var(--bg-dark);
|
|
color: var(--text);
|
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
|
line-height: 1.6;
|
|
min-height: 100vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.container {
|
|
max-width: 800px;
|
|
margin: 0 auto;
|
|
padding: 2rem;
|
|
width: 100%;
|
|
}
|
|
|
|
.header {
|
|
text-align: center;
|
|
margin-bottom: 2rem;
|
|
padding: 2rem 0;
|
|
background: var(--bg-darker);
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
|
|
h1 {
|
|
color: var(--primary);
|
|
margin-bottom: 1rem;
|
|
font-size: 2.5rem;
|
|
}
|
|
|
|
.subtitle {
|
|
color: var(--text-muted);
|
|
font-size: 1.1rem;
|
|
}
|
|
|
|
.card {
|
|
background: var(--bg-card);
|
|
padding: 1.5rem;
|
|
border-radius: 8px;
|
|
margin-bottom: 1.5rem;
|
|
border: 1px solid var(--border);
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.input-group {
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
label {
|
|
display: block;
|
|
margin-bottom: 0.5rem;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.input-wrapper {
|
|
position: relative;
|
|
display: flex;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
input {
|
|
flex: 1;
|
|
padding: 0.75rem;
|
|
background: var(--bg-input);
|
|
border: 1px solid var(--border);
|
|
color: var(--text);
|
|
border-radius: 4px;
|
|
font-size: 1rem;
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
input:focus {
|
|
outline: none;
|
|
border-color: var(--primary);
|
|
box-shadow: 0 0 0 2px rgba(0, 255, 0, 0.1);
|
|
}
|
|
|
|
button {
|
|
background: var(--primary);
|
|
color: var(--bg-dark);
|
|
border: none;
|
|
padding: 0.75rem 1.5rem;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
font-weight: 600;
|
|
font-size: 1rem;
|
|
transition: all 0.2s ease;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
button:hover {
|
|
background: var(--primary-dark);
|
|
transform: translateY(-1px);
|
|
}
|
|
|
|
button:active {
|
|
transform: translateY(0);
|
|
}
|
|
|
|
.result {
|
|
display: none;
|
|
animation: fadeIn 0.3s ease;
|
|
}
|
|
|
|
.result.visible {
|
|
display: block;
|
|
}
|
|
|
|
.hash-display {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 1rem;
|
|
background: var(--bg-input);
|
|
padding: 1rem;
|
|
border-radius: 4px;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.hash-value {
|
|
font-family: monospace;
|
|
font-size: 1.2rem;
|
|
color: var(--primary);
|
|
}
|
|
|
|
.url-preview {
|
|
font-family: monospace;
|
|
background: var(--bg-input);
|
|
padding: 1rem;
|
|
border-radius: 4px;
|
|
word-break: break-all;
|
|
}
|
|
|
|
.info {
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.info h3 {
|
|
color: var(--text);
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.info p {
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
code {
|
|
background: var(--bg-input);
|
|
padding: 0.2rem 0.4rem;
|
|
border-radius: 3px;
|
|
font-family: monospace;
|
|
}
|
|
|
|
@keyframes fadeIn {
|
|
from { opacity: 0; transform: translateY(-10px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
|
|
.toggle-password {
|
|
position: absolute;
|
|
right: 0.5rem;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
background: none;
|
|
border: none;
|
|
color: var(--text-muted);
|
|
cursor: pointer;
|
|
padding: 0.5rem;
|
|
}
|
|
|
|
.copy-notification {
|
|
position: fixed;
|
|
top: 1rem;
|
|
right: 1rem;
|
|
background: var(--primary);
|
|
color: var(--bg-dark);
|
|
padding: 0.75rem 1.5rem;
|
|
border-radius: 4px;
|
|
display: none;
|
|
animation: slideIn 0.3s ease;
|
|
}
|
|
|
|
@keyframes slideIn {
|
|
from { transform: translateX(100%); opacity: 0; }
|
|
to { transform: translateX(0); opacity: 1; }
|
|
}
|
|
|
|
@media (max-width: 600px) {
|
|
.container {
|
|
padding: 1rem;
|
|
}
|
|
|
|
h1 {
|
|
font-size: 2rem;
|
|
}
|
|
|
|
.input-wrapper {
|
|
flex-direction: column;
|
|
}
|
|
|
|
button {
|
|
width: 100%;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="header">
|
|
<h1>VDO.Ninja Hash Generator</h1>
|
|
<p class="subtitle">Generate secure hash values for your VDO.Ninja rooms and streams</p>
|
|
</div>
|
|
|
|
<div class="container">
|
|
<div class="card">
|
|
<div class="input-group">
|
|
<label for="passwordInput">VDO.Ninja Password</label>
|
|
<div class="input-wrapper">
|
|
<input type="password" id="passwordInput" placeholder="Enter your VDO.Ninja password" autocomplete="off">
|
|
<button onclick="togglePassword()">Show</button>
|
|
<button onclick="generateHashFromInput()">Generate Hash</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="result" id="resultDiv">
|
|
<div class="hash-display">
|
|
<span>Hash:</span>
|
|
<span class="hash-value" id="hashResult"></span>
|
|
<button onclick="copyHash()">Copy Hash</button>
|
|
</div>
|
|
<div class="url-preview" id="urlPreview"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card info">
|
|
<h3>About Hash Generation</h3>
|
|
<p>This tool generates a hash value that can be used with VDO.Ninja's <code>&hash</code> parameter instead of using <code>&password</code>. The hash provides a secure way to verify passwords without exposing the actual password in the URL.</p>
|
|
<p>Using a hash instead of a password in your URL:</p>
|
|
<p>❌ Instead of: <code>vdo.ninja/?room=yourroom&password=yourpassword</code></p>
|
|
<p>✅ Use: <code>vdo.ninja/?room=yourroom&hash=99e5</code></p>
|
|
<p>The hash value is derived from your password but doesn't contain the actual password, making it safer to share URLs while maintaining security.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="copy-notification" id="copyNotification">Hash copied to clipboard!</div>
|
|
|
|
<script>
|
|
function generateHash(str, length=false) {
|
|
var buffer = new TextEncoder("utf-8").encode(str);
|
|
return crypto.subtle.digest("SHA-256", buffer).then(
|
|
function(hash) {
|
|
hash = new Uint8Array(hash);
|
|
if (length) {
|
|
hash = hash.slice(0, parseInt(parseInt(length)/2));
|
|
}
|
|
return toHexString(hash);
|
|
}
|
|
);
|
|
}
|
|
|
|
function toHexString(byteArray) {
|
|
return Array.prototype.map.call(byteArray, function(byte) {
|
|
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
|
|
}).join('');
|
|
}
|
|
|
|
function generateHashFromInput() {
|
|
var password = document.getElementById('passwordInput').value;
|
|
if (!password) {
|
|
alert('Please enter a password');
|
|
return;
|
|
}
|
|
|
|
password = password.trim();
|
|
password = encodeURIComponent(password);
|
|
|
|
var salt = location.hostname;
|
|
if (location.hostname == "steveseguin.github.io") {
|
|
salt = "vdo.ninja";
|
|
} else if (["vdo.ninja","rtc.ninja","versus.cam","socialstream.ninja"].includes(location.hostname.split(".").slice(-2).join("."))) {
|
|
salt = location.hostname.split(".").slice(-2).join(".");
|
|
}
|
|
|
|
generateHash(password + salt, 4).then(function(hash) {
|
|
document.getElementById('hashResult').textContent = hash;
|
|
document.getElementById('urlPreview').textContent = `vdo.ninja/?room=yourroom&hash=${hash}`;
|
|
document.getElementById('resultDiv').classList.add('visible');
|
|
});
|
|
}
|
|
|
|
function copyHash() {
|
|
const hash = document.getElementById('hashResult').textContent;
|
|
navigator.clipboard.writeText(hash).then(function() {
|
|
showNotification();
|
|
});
|
|
}
|
|
|
|
function togglePassword() {
|
|
const input = document.getElementById('passwordInput');
|
|
const button = input.nextElementSibling;
|
|
if (input.type === 'password') {
|
|
input.type = 'text';
|
|
button.textContent = 'Hide';
|
|
} else {
|
|
input.type = 'password';
|
|
button.textContent = 'Show';
|
|
}
|
|
}
|
|
|
|
function showNotification() {
|
|
const notification = document.getElementById('copyNotification');
|
|
notification.style.display = 'block';
|
|
setTimeout(() => {
|
|
notification.style.display = 'none';
|
|
}, 2000);
|
|
}
|
|
|
|
// Enable Enter key to generate hash
|
|
document.getElementById('passwordInput').addEventListener('keypress', function(e) {
|
|
if (e.key === 'Enter') {
|
|
generateHashFromInput();
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |