Add lookup page

This commit is contained in:
Christopher Cookman 2024-12-23 08:48:40 -07:00
parent a4b7e72452
commit 81504e3107
4 changed files with 151 additions and 1 deletions

View file

@ -1,3 +1,10 @@
fetch('/api/v1/info')
.then(response => response.json())
.then(data => {
window.flags = data.reasonFlags;
})
.catch(error => console.error('Error fetching flags:', error));
/**
* Adds a flag to the current flags.
* @param {number} flags - The current set of flags.
@ -80,4 +87,4 @@ function getSetFlags(flags, flagDefinitions) {
return Object.keys(flagDefinitions).filter(flagName =>
(flags & flagDefinitions[flagName]) !== 0
);
}
}

60
public/lookup/index.html Normal file
View file

@ -0,0 +1,60 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/assets/css/bootstrap.min.css">
<title>UBS Ban Lookup</title>
</head>
<body class="bg-dark text-light">
<div class="container">
<div class="row justify-content-center mt-5">
<div class="col-md-6 col-lg-4">
<div class="card bg-dark text-light shadow">
<div class="card-body p-4">
<h2 class="text-center mb-4">Ban Lookup</h2>
<div class="alert" id="message" style="display: none;"></div>
<form id="lookupForm">
<div class="mb-3">
<label for="lookupType" class="form-label">Lookup Type</label>
<select class="form-select" id="lookupType" name="lookupType">
<option value="id">Ban ID</option>
<option value="discord">Discord ID</option>
<option value="roblox">Roblox ID</option>
</select>
</div>
<div class="mb-3">
<label for="lookupId" class="form-label">ID</label>
<input type="text" class="form-control" id="lookupId" name="lookupId" required>
</div>
<button type="submit" class="btn btn-primary w-100">Lookup</button>
</form>
</div>
</div>
</div>
<h3 class="text-center mb-4">Results</h3>
<table class="table table-dark table-striped" id="resultsTable" style="display: none;">
<thead>
<tr>
<th scope="col">Ban ID</th>
<th scope="col">Roblox ID</th>
<th scope="col">Discord ID</th>
<th scope="col">Roblox Username</th>
<th scope="col">Discord Username</th>
<th scope="col">Reason Short</th>
<th scope="col">Reason Long</th>
<th scope="col">Reason Flags</th>
<th scope="col">Moderator</th>
<th scope="col">Ban Timestamp</th>
<th scope="col">Expires Timestamp</th>
</tr>
</thead>
<tbody>
<!-- Results will be populated here by the script -->
</tbody>
</table>
<script src="/assets/js/bootstrap.bundle.min.js"></script>
<script src="/assets/js/flags.js"></script>
<script src="lookup.js"></script>
</body>
</html>

53
public/lookup/lookup.js Normal file
View file

@ -0,0 +1,53 @@
document.getElementById('lookupForm').addEventListener('submit', async function (event) {
event.preventDefault();
const lookupType = document.getElementById('lookupType').value;
const lookupId = document.getElementById('lookupId').value;
const messageElement = document.getElementById('message');
const resultsTable = document.getElementById('resultsTable');
const resultsTableBody = resultsTable.querySelector('tbody');
resultsTableBody.innerHTML = ''; // Clear previous results
try {
const response = await fetch(`/api/v1/ban/${lookupType}/${lookupId}`);
const data = await response.json();
if (response.ok) {
messageElement.style.display = 'block';
messageElement.className = 'alert alert-success';
messageElement.textContent = "Success!";
resultsTable.style.display = 'table';
data.forEach(result => {
const row = document.createElement('tr');
const banTimestamp = new Date(result.banTimestamp).toLocaleString();
const expiresTimestamp = result.expiresTimestamp ? new Date(result.expiresTimestamp).toLocaleString() : 'Never';
const reasonsFlagNames = getSetFlags(result.reasonsFlag, window.flags).join(', ');
row.innerHTML = `
<td>${result.id}</td>
<td>${result.robloxId || 'N/A'}</td>
<td>${result.discordId || 'N/A'}</td>
<td>${result.robloxUsername || 'N/A'}</td>
<td>${result.discordUsername || 'N/A'}</td>
<td>${result.reasonShort || 'N/A'}</td>
<td>${result.reasonLong || 'N/A'}</td>
<td>${reasonsFlagNames}</td>
<td>${result.moderator || 'N/A'}</td>
<td>${banTimestamp}</td>
<td style="color: ${result.expiresTimestamp && new Date(result.expiresTimestamp) < new Date() ? 'green' : ''};">
${expiresTimestamp}
</td>
`;
resultsTableBody.appendChild(row);
});
} else {
messageElement.style.display = 'block';
messageElement.className = 'alert alert-danger';
messageElement.textContent = data.error || 'An error occurred';
}
} catch (error) {
messageElement.style.display = 'block';
messageElement.className = 'alert alert-danger';
messageElement.textContent = 'An error occurred while fetching the data';
console.error(error)
}
});

View file

@ -120,6 +120,36 @@ router.get("/v1/ban/discord/:uid", async (req, res) => {
}
})
router.get("/v1/ban/id/:id", async (req, res) => {
if (!req.params.id) return res.status(400).json({error: "Specify ban ID!"});
try {
// Get a connection from the pool
const connection = await pool.getConnection();
try {
// Execute the query to fetch all rows from the `bans` table
const rows = await connection.query('SELECT * FROM bans WHERE id = ?', [req.params.id]);
// Convert all timestamps into epoch
rows.forEach(row => {
row.expiresTimestamp = row.expiresTimestamp ? new Date(`${row.expiresTimestamp}Z`).getTime() : null
row.banTimestamp = row.banTimestamp ? new Date(`${row.banTimestamp}`).getTime() : null
row.valid = row.expiresTimestamp ? new Date(row.expiresTimestamp) > new Date() : true
});
// Send the results as a JSON response
res.json(rows);
} finally {
// Release the connection back to the pool
connection.release();
}
} catch (err) {
console.error('Error fetching bans:', err);
// Respond with a 500 Internal Server Error status if something goes wrong
res.status(500).json({ error: 'An error occurred while fetching the bans.' });
}
});
router.get("/v1/info", (req,res) => {
res.json({
commit_hash: execSync('git rev-parse HEAD').toString().trim(),