- Integrate github.com/TwiN/go-away for content filtering - Check subdomains for inappropriate content during validation - Update frontend to display 'inappropriate content' message - Blocks profane subdomains from being claimed Uses go-away's built-in profanity dictionary to detect: - Leet speak substitutions (e.g., @73447h013) - Obfuscated profanity - Common inappropriate terms
140 lines
5.2 KiB
JavaScript
140 lines
5.2 KiB
JavaScript
document.addEventListener('DOMContentLoaded', function() {
|
|
const claimForm = document.getElementById('claim-form');
|
|
const subdomainInput = document.getElementById('subdomain');
|
|
const availabilityStatus = document.getElementById('availability-status');
|
|
const claimBtn = document.getElementById('claim-btn');
|
|
const claimSection = document.getElementById('claim-section');
|
|
const successSection = document.getElementById('success-section');
|
|
const errorSection = document.getElementById('error-section');
|
|
const routerConfig = document.getElementById('router-config');
|
|
|
|
let checkTimeout = null;
|
|
|
|
subdomainInput.addEventListener('input', function() {
|
|
const value = this.value.toLowerCase().replace(/[^a-z0-9-]/g, '');
|
|
this.value = value;
|
|
|
|
clearTimeout(checkTimeout);
|
|
availabilityStatus.textContent = '';
|
|
availabilityStatus.className = 'status';
|
|
claimBtn.disabled = true;
|
|
|
|
if (value.length >= 3) {
|
|
checkTimeout = setTimeout(() => checkAvailability(value), 300);
|
|
}
|
|
});
|
|
|
|
async function checkAvailability(subdomain) {
|
|
try {
|
|
const response = await fetch(`/api/check?subdomain=${encodeURIComponent(subdomain)}`);
|
|
const data = await response.json();
|
|
|
|
if (data.available) {
|
|
availabilityStatus.textContent = '✓ Available';
|
|
availabilityStatus.className = 'status available';
|
|
claimBtn.disabled = false;
|
|
} else if (data.reason === 'inappropriate') {
|
|
availabilityStatus.textContent = '✗ Contains inappropriate content';
|
|
availabilityStatus.className = 'status taken';
|
|
claimBtn.disabled = true;
|
|
} else {
|
|
availabilityStatus.textContent = '✗ Already taken';
|
|
availabilityStatus.className = 'status taken';
|
|
claimBtn.disabled = true;
|
|
}
|
|
} catch (error) {
|
|
console.error('Error checking availability:', error);
|
|
}
|
|
}
|
|
|
|
claimForm.addEventListener('submit', async function(e) {
|
|
e.preventDefault();
|
|
const subdomain = subdomainInput.value;
|
|
|
|
claimBtn.disabled = true;
|
|
claimBtn.textContent = 'Claiming...';
|
|
|
|
try {
|
|
const response = await fetch('/api/claim', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({ subdomain: subdomain }),
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (response.ok) {
|
|
showSuccess(data);
|
|
} else {
|
|
showError(data.error || 'Failed to claim space');
|
|
}
|
|
} catch (error) {
|
|
showError('Network error. Please try again.');
|
|
}
|
|
|
|
claimBtn.disabled = false;
|
|
claimBtn.textContent = 'Claim Space';
|
|
});
|
|
|
|
function showSuccess(data) {
|
|
claimSection.classList.add('hidden');
|
|
successSection.classList.remove('hidden');
|
|
routerConfig.classList.remove('hidden');
|
|
|
|
document.getElementById('token-value').textContent = data.token;
|
|
document.getElementById('fqdn-value').textContent = data.fqdn;
|
|
|
|
const updateUrl = `https://dyn.${data.fqdn.split('.').slice(-2).join('.')}/api/nic/update?hostname=%h&myip=%i`;
|
|
document.getElementById('update-url').textContent = updateUrl;
|
|
|
|
document.querySelectorAll('.hostname-placeholder').forEach(el => {
|
|
el.textContent = data.fqdn;
|
|
});
|
|
|
|
document.querySelectorAll('.update-url-placeholder').forEach(el => {
|
|
el.textContent = updateUrl;
|
|
});
|
|
|
|
const curlCmd = `curl -u "none:${data.token}" "https://dyn.${data.fqdn.split('.').slice(-2).join('.')}/api/nic/update?hostname=${data.fqdn}"`;
|
|
document.getElementById('curl-example').textContent = curlCmd;
|
|
|
|
document.getElementById('copy-token').addEventListener('click', function() {
|
|
copyToClipboard(data.token);
|
|
this.textContent = 'Copied!';
|
|
setTimeout(() => this.textContent = 'Copy Token', 2000);
|
|
});
|
|
|
|
document.getElementById('copy-curl').addEventListener('click', function() {
|
|
copyToClipboard(curlCmd);
|
|
this.textContent = 'Copied!';
|
|
setTimeout(() => this.textContent = 'Copy', 2000);
|
|
});
|
|
}
|
|
|
|
function showError(message) {
|
|
claimSection.classList.add('hidden');
|
|
errorSection.classList.remove('hidden');
|
|
document.getElementById('error-message').textContent = message;
|
|
}
|
|
|
|
document.getElementById('try-again').addEventListener('click', function() {
|
|
errorSection.classList.add('hidden');
|
|
claimSection.classList.remove('hidden');
|
|
subdomainInput.value = '';
|
|
subdomainInput.focus();
|
|
});
|
|
|
|
function copyToClipboard(text) {
|
|
navigator.clipboard.writeText(text).catch(function() {
|
|
const textarea = document.createElement('textarea');
|
|
textarea.value = text;
|
|
document.body.appendChild(textarea);
|
|
textarea.select();
|
|
document.execCommand('copy');
|
|
document.body.removeChild(textarea);
|
|
});
|
|
}
|
|
});
|