Add cleanup tooling
This commit is contained in:
@@ -20,6 +20,9 @@
|
||||
<li><a href="/admin/memes">Meme Manager</a></li>
|
||||
<li><a href="/admin/halls">Hall Manager</a></li>
|
||||
<li><a href="/admin/motd">MOTD Manager</a></li>
|
||||
@if(enable_cleanup)
|
||||
<li><a href="/admin/cleanup">Cleanup Manager</a></li>
|
||||
@endif
|
||||
<li><a href="/admin/about">About Page</a></li>
|
||||
<li><a href="/admin/rules">Rules Page</a></li>
|
||||
<li><a href="/admin/terms">ToS Page</a></li>
|
||||
@@ -40,26 +43,19 @@
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@if(typeof enable_cleanup_config === "undefined" || enable_cleanup_config !== false)
|
||||
<div class="settings-toggle" style="background: rgba(0,0,0,0.2); padding: 15px; border-radius: 4px; display: flex; align-items: center; justify-content: space-between; margin-top: 10px;">
|
||||
<div>
|
||||
<label style="display: block; font-weight: bold; color: var(--accent);">Log User IPs</label>
|
||||
<p style="margin: 2px 0 0 0; font-size: 0.8em; color: #aaa;">Log all historical IPs for user accounts.</p>
|
||||
<label style="display: block; font-weight: bold; color: var(--accent);">Enable Cleanup Action</label>
|
||||
<p style="margin: 2px 0 0 0; font-size: 0.8em; color: #aaa;">Enable the automated cleanup system and manager.</p>
|
||||
</div>
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="log_user_ips_toggle" {{ log_user_ips ? 'checked' : '' }} onchange="saveAdminSettings()">
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="settings-toggle" style="background: rgba(0,0,0,0.2); padding: 15px; border-radius: 4px; display: flex; align-items: center; justify-content: space-between; margin-top: 10px;">
|
||||
<div>
|
||||
<label style="display: block; font-weight: bold; color: var(--accent);">Hash User IPs</label>
|
||||
<p style="margin: 2px 0 0 0; font-size: 0.8em; color: #aaa;">Anonymize IPs by hashing them (same as failed logins).</p>
|
||||
</div>
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="hash_user_ips_toggle" {{ hash_user_ips ? 'checked' : '' }} onchange="saveAdminSettings()">
|
||||
<input type="checkbox" id="enable_cleanup_toggle" {{ enable_cleanup ? 'checked' : '' }} onchange="saveAdminSettings()">
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if(registration_web_toggle_enabled)
|
||||
<div class="settings-toggle" style="background: rgba(0,0,0,0.2); padding: 15px; border-radius: 4px; display: flex; align-items: center; justify-content: space-between; margin-top: 10px;">
|
||||
@@ -119,8 +115,7 @@
|
||||
const status = document.getElementById('settings-status');
|
||||
const approvalToggle = document.getElementById('manual_approval_toggle');
|
||||
const registrationToggle = document.getElementById('registration_open_toggle');
|
||||
const logIpsToggle = document.getElementById('log_user_ips_toggle');
|
||||
const hashIpsToggle = document.getElementById('hash_user_ips_toggle');
|
||||
const cleanupToggle = document.getElementById('enable_cleanup_toggle');
|
||||
const minTagsInput = document.getElementById('min_tags_input');
|
||||
const trustedUploadsInput = document.getElementById('trusted_uploads_input');
|
||||
|
||||
@@ -136,8 +131,7 @@
|
||||
},
|
||||
body: new URLSearchParams({
|
||||
manual_approval: approvalToggle.checked ? 'on' : 'off',
|
||||
log_user_ips: logIpsToggle.checked ? 'on' : 'off',
|
||||
hash_user_ips: hashIpsToggle.checked ? 'on' : 'off',
|
||||
enable_cleanup: cleanupToggle.checked ? 'on' : 'off',
|
||||
...(registrationToggle ? { registration_open: registrationToggle.checked ? 'on' : 'off' } : {}),
|
||||
min_tags: minTagsInput.value,
|
||||
trusted_uploads: trustedUploadsInput.value,
|
||||
|
||||
155
views/admin/cleanup.html
Normal file
155
views/admin/cleanup.html
Normal file
@@ -0,0 +1,155 @@
|
||||
@include(snippets/header)
|
||||
<div class="pagewrapper">
|
||||
<div id="main" class="admin-container">
|
||||
<div class="container">
|
||||
<h2>Cleanup Manager</h2>
|
||||
<p style="color: #ccc; margin-bottom: 20px;">Delete old posts that have no engagement (no comments, no favorites, and no subscriptions) to regain disk space.</p>
|
||||
|
||||
<div class="admin-cleanup-form" style="background: rgba(0,0,0,0.2); padding: 25px; border-radius: 8px; border: 1px solid rgba(255,255,255,0.05);">
|
||||
<form id="cleanup-form" action="/admin/cleanup" method="POST" onsubmit="event.preventDefault(); saveCleanupSettings(this);">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||||
|
||||
<div class="settings-toggle" style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 25px; padding-bottom: 20px; border-bottom: 1px solid rgba(255,255,255,0.05);">
|
||||
<div>
|
||||
<label style="display: block; font-weight: bold; color: var(--accent); font-size: 1.1em;">Enable Cleanup Action</label>
|
||||
<p style="margin: 5px 0 0 0; font-size: 0.9em; color: #aaa;">This must be enabled to allow running the manual cleanup process.</p>
|
||||
</div>
|
||||
<label class="switch">
|
||||
<input type="checkbox" name="enable_cleanup" id="enable_cleanup_toggle" {{ enable_cleanup ? 'checked' : '' }}>
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="settings-item" style="margin-bottom: 30px;">
|
||||
<label style="display: block; font-weight: bold; color: var(--accent); margin-bottom: 10px;">Cleanup Date Range</label>
|
||||
<div style="display: flex; align-items: center; gap: 15px; flex-wrap: wrap;">
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
<span style="color: #888;">From:</span>
|
||||
<input type="date" id="cleanup_start_date" name="cleanup_start_date" value="{{ cleanup_start_date }}" style="background: rgba(0,0,0,0.3); border: 1px solid rgba(255,255,255,0.1); color: #fff; padding: 10px; border-radius: 4px;">
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
<span style="color: #888;">To:</span>
|
||||
<input type="date" id="cleanup_end_date" name="cleanup_end_date" value="{{ cleanup_end_date }}" style="background: rgba(0,0,0,0.3); border: 1px solid rgba(255,255,255,0.1); color: #fff; padding: 10px; border-radius: 4px;">
|
||||
</div>
|
||||
<span style="color: #888; flex-basis: 100%; margin-top: 5px;">Posts uploaded within this period with no engagement will be targeted.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; gap: 10px; align-items: center;">
|
||||
<button type="submit" class="btn-primary" style="width: auto; padding: 12px 40px; font-weight: bold;">Save Configuration</button>
|
||||
<span id="cleanup-status" style="margin-left: 15px; font-weight: bold; display: none;"></span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="admin-cleanup-run" style="margin-top: 30px; background: rgba(255,255,255,0.02); padding: 25px; border-radius: 8px; border: 1px solid rgba(255,255,255,0.05);">
|
||||
<h3 style="margin-top: 0; color: var(--accent);">Execute Cleanup</h3>
|
||||
<p>Click the button below to start the cleanup process based on the timeframe saved above.</p>
|
||||
|
||||
<div style="display: flex; gap: 20px; align-items: center; margin-top: 20px;">
|
||||
<button onclick="runCleanup()" id="run-cleanup-btn" class="btn-remove" style="width: auto; padding: 15px 40px; font-weight: bold; font-size: 1.1em; background: #c0392b;">RUN CLEANUP NOW</button>
|
||||
<div id="run-status" style="font-weight: bold; font-size: 1.1em;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 40px; padding: 20px; background: rgba(217, 83, 79, 0.1); border-left: 4px solid #d9534f; border-radius: 4px;">
|
||||
<h4 style="color: #d9534f; margin-top: 0;">Danger Zone</h4>
|
||||
<p style="margin-bottom: 0; color: #eee;">Deletions performed by the cleanup manager are <strong>permanent</strong> and cannot be undone. Files will be removed from disk to regain space. Only posts with 0 comments, 0 favorites, and 0 subscriptions are targeted.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.switch { position: relative; display: inline-block; width: 60px; height: 34px; }
|
||||
.switch input { opacity: 0; width: 0; height: 0; }
|
||||
.slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #333; transition: .4s; border-radius: 34px; }
|
||||
.slider:before { position: absolute; content: ""; height: 26px; width: 26px; left: 4px; bottom: 4px; background-color: white; transition: .4s; border-radius: 50%; }
|
||||
input:checked + .slider { background-color: var(--accent); }
|
||||
input:checked + .slider:before { transform: translateX(26px); background-color: #000; }
|
||||
|
||||
.btn-remove:disabled { opacity: 0.5; cursor: not-allowed; }
|
||||
</style>
|
||||
|
||||
<script>
|
||||
async function saveCleanupSettings(form) {
|
||||
const status = document.getElementById('cleanup-status');
|
||||
|
||||
status.textContent = 'Saving...';
|
||||
status.style.color = 'var(--accent)';
|
||||
status.style.display = 'inline';
|
||||
|
||||
try {
|
||||
const formData = new FormData(form);
|
||||
if (!document.getElementById('enable_cleanup_toggle').checked) {
|
||||
formData.delete('enable_cleanup');
|
||||
formData.append('enable_cleanup', 'off');
|
||||
} else {
|
||||
formData.set('enable_cleanup', 'on');
|
||||
}
|
||||
|
||||
const res = await fetch(form.action, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'X-CSRF-Token': window.f0ckSession?.csrf_token || '{{ csrf_token }}'
|
||||
},
|
||||
body: new URLSearchParams(formData)
|
||||
});
|
||||
|
||||
const cleanup_response = await res.json();
|
||||
if (cleanup_response.success) {
|
||||
status.textContent = 'Settings saved!';
|
||||
status.style.color = '#28a745';
|
||||
setTimeout(() => {
|
||||
status.style.display = 'none';
|
||||
}, 3000);
|
||||
} else {
|
||||
throw new Error(cleanup_response.msg || 'Unknown error');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Cleanup Save Error:', err);
|
||||
status.textContent = 'Error: ' + err.message;
|
||||
status.style.color = '#d9534f';
|
||||
}
|
||||
}
|
||||
|
||||
async function runCleanup() {
|
||||
const btn = document.getElementById('run-cleanup-btn');
|
||||
const status = document.getElementById('run-status');
|
||||
|
||||
if (!confirm('Are you absolutely sure? This will PERMANENTLY delete files from disk. This action cannot be undone.')) return;
|
||||
|
||||
btn.disabled = true;
|
||||
btn.textContent = 'CLEANING UP...';
|
||||
status.textContent = 'Processing files, please wait...';
|
||||
status.style.color = 'var(--accent)';
|
||||
|
||||
try {
|
||||
const res = await fetch('/admin/cleanup/run', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
'X-CSRF-Token': window.f0ckSession?.csrf_token || '{{ csrf_token }}'
|
||||
}
|
||||
});
|
||||
|
||||
const cleanup_response = await res.json();
|
||||
if (cleanup_response.success) {
|
||||
status.textContent = 'Success! ' + cleanup_response.msg;
|
||||
status.style.color = '#28a745';
|
||||
} else {
|
||||
throw new Error(cleanup_response.msg || 'Unknown error during cleanup');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Cleanup Run Error:', err);
|
||||
status.textContent = 'Error: ' + err.message;
|
||||
status.style.color = '#d9534f';
|
||||
} finally {
|
||||
btn.disabled = false;
|
||||
btn.textContent = 'RUN CLEANUP NOW';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
@include(snippets/footer)
|
||||
Reference in New Issue
Block a user