reaper-arcade-hub 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/js/app.js +52 -14
- package/js/firebase-client.js +21 -7
- package/js/moderator.js +51 -3
- package/main/js/app.js +52 -14
- package/main/js/firebase-client.js +21 -7
- package/main/js/moderator.js +51 -3
- package/package.json +5 -3
- package/verify/js/firebase-client.js +21 -7
package/js/app.js
CHANGED
|
@@ -105,14 +105,21 @@ class ReaperHubApp {
|
|
|
105
105
|
window.reaperFirebase.listenBannedUsers((bannedList) => {
|
|
106
106
|
this.bannedUsers = bannedList || [];
|
|
107
107
|
this.renderBannedUsersList();
|
|
108
|
-
|
|
108
|
+
const currentNameLower = (this.currentUser.username || '').toLowerCase();
|
|
109
|
+
const isBannedOnServer = this.bannedUsers.some(u => u.toLowerCase() === currentNameLower);
|
|
110
|
+
|
|
111
|
+
if (this.currentUser.rank !== 'owner' && isBannedOnServer) {
|
|
109
112
|
this.currentUser.isBanned = true;
|
|
110
113
|
localStorage.setItem('reaper_is_banned', 'true');
|
|
111
|
-
localStorage.removeItem('reaper_verified_token');
|
|
112
|
-
localStorage.removeItem('reaper_token_expires');
|
|
113
|
-
localStorage.removeItem('reaper_gateway_verified');
|
|
114
|
-
localStorage.removeItem('reaper_playtime_' + this.currentUser.username);
|
|
115
114
|
this.renderBanScreen("Your account has been permanently blacklisted and all recorded progress has been purged.");
|
|
115
|
+
} else {
|
|
116
|
+
// If unbanned!
|
|
117
|
+
if (this.currentUser.isBanned || document.getElementById('ban-screen-overlay')) {
|
|
118
|
+
this.currentUser.isBanned = false;
|
|
119
|
+
localStorage.removeItem('reaper_is_banned');
|
|
120
|
+
this.removeBanScreen();
|
|
121
|
+
this.showToast("Your account was UNBANNED by an Administrator!");
|
|
122
|
+
}
|
|
116
123
|
}
|
|
117
124
|
});
|
|
118
125
|
window.reaperFirebase.listenShutdownMode((isShutdown) => {
|
|
@@ -1464,14 +1471,16 @@ class ReaperHubApp {
|
|
|
1464
1471
|
if (!check.allowed) {
|
|
1465
1472
|
input.value = '';
|
|
1466
1473
|
this.updateChatStateUI();
|
|
1467
|
-
this.showToast("Message blocked by AI filter.
|
|
1474
|
+
this.showToast(check.reason || "Message blocked by AI filter.");
|
|
1468
1475
|
return;
|
|
1469
1476
|
}
|
|
1470
1477
|
}
|
|
1471
1478
|
|
|
1472
1479
|
input.value = '';
|
|
1473
1480
|
|
|
1481
|
+
const msgId = 'msg_' + Date.now() + '_' + Math.random().toString(36).substring(2, 6);
|
|
1474
1482
|
const msgData = {
|
|
1483
|
+
id: msgId,
|
|
1475
1484
|
username: this.currentUser.username,
|
|
1476
1485
|
rank: this.currentUser.rank,
|
|
1477
1486
|
playtimeStr: this.formatPlaytime(this.playtimeSeconds),
|
|
@@ -1488,6 +1497,7 @@ class ReaperHubApp {
|
|
|
1488
1497
|
}
|
|
1489
1498
|
|
|
1490
1499
|
async deleteMessage(msgId, authorName) {
|
|
1500
|
+
if (!msgId) return;
|
|
1491
1501
|
const isPrivileged = this.currentUser.rank === 'owner' || this.currentUser.rank === 'chat_mod' || this.currentUser.rank === 'mod';
|
|
1492
1502
|
const canDelete = isPrivileged || (authorName === this.currentUser.username);
|
|
1493
1503
|
if (!canDelete) {
|
|
@@ -1495,12 +1505,13 @@ class ReaperHubApp {
|
|
|
1495
1505
|
return;
|
|
1496
1506
|
}
|
|
1497
1507
|
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1508
|
+
this.chatMessages = this.chatMessages.filter(m => m.id !== msgId);
|
|
1509
|
+
localStorage.setItem('reaper_local_chat', JSON.stringify(this.chatMessages));
|
|
1510
|
+
this.renderChatMessages();
|
|
1511
|
+
if (window.reaperFirebase) {
|
|
1501
1512
|
await window.reaperFirebase.deleteChatMessage(msgId);
|
|
1502
|
-
this.showToast("Message deleted.");
|
|
1503
1513
|
}
|
|
1514
|
+
this.showToast("Message deleted globally.");
|
|
1504
1515
|
}
|
|
1505
1516
|
|
|
1506
1517
|
renderChatMessages() {
|
|
@@ -2118,7 +2129,17 @@ class ReaperHubApp {
|
|
|
2118
2129
|
}
|
|
2119
2130
|
|
|
2120
2131
|
renderBanScreen(customReason) {
|
|
2121
|
-
|
|
2132
|
+
let overlay = document.getElementById('ban-screen-overlay');
|
|
2133
|
+
if (!overlay) {
|
|
2134
|
+
overlay = document.createElement('div');
|
|
2135
|
+
overlay.id = 'ban-screen-overlay';
|
|
2136
|
+
overlay.style.position = 'fixed';
|
|
2137
|
+
overlay.style.inset = '0';
|
|
2138
|
+
overlay.style.zIndex = '9999999';
|
|
2139
|
+
overlay.style.background = '#000';
|
|
2140
|
+
document.body.appendChild(overlay);
|
|
2141
|
+
}
|
|
2142
|
+
overlay.innerHTML = `
|
|
2122
2143
|
<div style="display: flex; height: 100vh; width: 100vw; background: #000; color: #ff2a2a; font-family: var(--font-mono); align-items: center; justify-content: center; text-align: center; padding: 2rem;">
|
|
2123
2144
|
<div style="border: 2px solid #ff2a2a; padding: 3rem 2rem; max-width: 540px; background: #0c0202; border-radius: 10px; box-shadow: 0 0 40px rgba(255, 42, 42, 0.4);">
|
|
2124
2145
|
<h1 style="font-size: 2.2rem; margin-bottom: 1rem; color: #ff3333;">[PERMANENT BAN]</h1>
|
|
@@ -2131,6 +2152,14 @@ class ReaperHubApp {
|
|
|
2131
2152
|
</div>
|
|
2132
2153
|
</div>
|
|
2133
2154
|
`;
|
|
2155
|
+
overlay.style.display = 'block';
|
|
2156
|
+
}
|
|
2157
|
+
|
|
2158
|
+
removeBanScreen() {
|
|
2159
|
+
const overlay = document.getElementById('ban-screen-overlay');
|
|
2160
|
+
if (overlay) {
|
|
2161
|
+
overlay.remove();
|
|
2162
|
+
}
|
|
2134
2163
|
}
|
|
2135
2164
|
|
|
2136
2165
|
renderPermanentShutdownScreen() {
|
|
@@ -2341,12 +2370,21 @@ class ReaperHubApp {
|
|
|
2341
2370
|
}
|
|
2342
2371
|
|
|
2343
2372
|
async unbanUser(username) {
|
|
2344
|
-
|
|
2373
|
+
if (!username) return;
|
|
2374
|
+
const cleanUser = username.trim();
|
|
2375
|
+
this.bannedUsers = this.bannedUsers.filter(u => u.toLowerCase() !== cleanUser.toLowerCase());
|
|
2345
2376
|
localStorage.setItem('reaper_banned_users', JSON.stringify(this.bannedUsers));
|
|
2377
|
+
|
|
2378
|
+
if ((this.currentUser.username || '').toLowerCase() === cleanUser.toLowerCase()) {
|
|
2379
|
+
this.currentUser.isBanned = false;
|
|
2380
|
+
localStorage.removeItem('reaper_is_banned');
|
|
2381
|
+
this.removeBanScreen();
|
|
2382
|
+
}
|
|
2383
|
+
|
|
2346
2384
|
if (window.reaperFirebase) {
|
|
2347
|
-
await window.reaperFirebase.unbanUser(
|
|
2385
|
+
await window.reaperFirebase.unbanUser(cleanUser);
|
|
2348
2386
|
}
|
|
2349
|
-
this.showToast(`User ${
|
|
2387
|
+
this.showToast(`User ${cleanUser} UNBANNED.`);
|
|
2350
2388
|
this.renderBannedUsersList();
|
|
2351
2389
|
}
|
|
2352
2390
|
|
package/js/firebase-client.js
CHANGED
|
@@ -257,16 +257,17 @@ class FirebaseService {
|
|
|
257
257
|
|
|
258
258
|
async banUser(username) {
|
|
259
259
|
if (!username || username === 'owner') return;
|
|
260
|
+
const cleanUser = username.trim();
|
|
260
261
|
|
|
261
262
|
if (this.db) {
|
|
262
263
|
try {
|
|
263
|
-
await this.db.ref(`reaperBannedUsers/${
|
|
264
|
-
await this.db.ref(`reaperPlaytime/${
|
|
264
|
+
await this.db.ref(`reaperBannedUsers/${cleanUser}`).set(true);
|
|
265
|
+
await this.db.ref(`reaperPlaytime/${cleanUser}`).remove();
|
|
265
266
|
const chatSnap = await this.db.ref('reaperChat').once('value');
|
|
266
267
|
if (chatSnap.exists()) {
|
|
267
268
|
const chats = chatSnap.val();
|
|
268
269
|
for (const msgId of Object.keys(chats)) {
|
|
269
|
-
if (chats[msgId].username
|
|
270
|
+
if (chats[msgId].username && chats[msgId].username.toLowerCase() === cleanUser.toLowerCase()) {
|
|
270
271
|
await this.db.ref(`reaperChat/${msgId}`).remove();
|
|
271
272
|
}
|
|
272
273
|
}
|
|
@@ -277,21 +278,34 @@ class FirebaseService {
|
|
|
277
278
|
}
|
|
278
279
|
|
|
279
280
|
const localBans = JSON.parse(localStorage.getItem('reaper_banned_users') || '[]');
|
|
280
|
-
if (!localBans.
|
|
281
|
-
localBans.push(
|
|
281
|
+
if (!localBans.some(u => u.toLowerCase() === cleanUser.toLowerCase())) {
|
|
282
|
+
localBans.push(cleanUser);
|
|
282
283
|
localStorage.setItem('reaper_banned_users', JSON.stringify(localBans));
|
|
283
284
|
}
|
|
284
285
|
}
|
|
285
286
|
|
|
286
287
|
async unbanUser(username) {
|
|
288
|
+
if (!username) return;
|
|
289
|
+
const cleanUser = username.trim();
|
|
290
|
+
|
|
287
291
|
if (this.db) {
|
|
288
292
|
try {
|
|
289
|
-
await this.db.ref(`reaperBannedUsers/${
|
|
293
|
+
await this.db.ref(`reaperBannedUsers/${cleanUser}`).remove();
|
|
294
|
+
const snap = await this.db.ref('reaperBannedUsers').once('value');
|
|
295
|
+
if (snap.exists()) {
|
|
296
|
+
const bans = snap.val();
|
|
297
|
+
for (const k of Object.keys(bans)) {
|
|
298
|
+
if (k.toLowerCase() === cleanUser.toLowerCase()) {
|
|
299
|
+
await this.db.ref(`reaperBannedUsers/${k}`).remove();
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
290
303
|
} catch (e) {
|
|
291
304
|
console.warn("Error unbanning user on Firebase:", e);
|
|
292
305
|
}
|
|
293
306
|
}
|
|
294
|
-
|
|
307
|
+
|
|
308
|
+
const localBans = JSON.parse(localStorage.getItem('reaper_banned_users') || '[]').filter(u => u.toLowerCase() !== cleanUser.toLowerCase());
|
|
295
309
|
localStorage.setItem('reaper_banned_users', JSON.stringify(localBans));
|
|
296
310
|
}
|
|
297
311
|
|
package/js/moderator.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
// AI Content Moderator &
|
|
1
|
+
// REAPER HUB - AI Content Moderator & Privacy Name Filter Engine
|
|
2
|
+
// Blocks profanity, slurs, drug references, and real personal names (Male & Female) for user safety and privacy.
|
|
2
3
|
|
|
3
4
|
class AIContentModerator {
|
|
4
5
|
constructor() {
|
|
@@ -19,6 +20,40 @@ class AIContentModerator {
|
|
|
19
20
|
'porn', 'porno', 'xxx', 'hentai', 'rule34', 'xvideos', 'pornhub', 'onlyfans',
|
|
20
21
|
'nsfw', 'sex', 'blowjob', 'handjob', 'dildo'
|
|
21
22
|
];
|
|
23
|
+
|
|
24
|
+
// Real Personal Names Filter (Male & Female Names) for Privacy & Safety
|
|
25
|
+
this.bannedNames = [
|
|
26
|
+
// Specific Requested Names
|
|
27
|
+
'kaidan', 'kaiden', 'kayden', 'caiden', 'kaden', 'loki', 'harry', 'will', 'william',
|
|
28
|
+
|
|
29
|
+
// Male Names
|
|
30
|
+
'liam', 'noah', 'oliver', 'james', 'elijah', 'mateo', 'theodore', 'henry', 'lucas',
|
|
31
|
+
'benjamin', 'levi', 'sebastian', 'jack', 'ezra', 'michael', 'daniel', 'logan', 'jackson',
|
|
32
|
+
'owen', 'samuel', 'alex', 'alexander', 'ryan', 'ethan', 'john', 'david', 'luke', 'mason',
|
|
33
|
+
'connor', 'caleb', 'isaiah', 'anthony', 'charles', 'thomas', 'leo', 'jordan', 'jayden',
|
|
34
|
+
'nathan', 'gabriel', 'carter', 'hunter', 'christian', 'aaron', 'eli', 'colton', 'landon',
|
|
35
|
+
'adrian', 'brayden', 'tyler', 'austin', 'kevin', 'brandon', 'justin', 'george', 'jason',
|
|
36
|
+
'cody', 'travis', 'dylan', 'kyle', 'brian', 'eric', 'steven', 'adam', 'joshua', 'jacob',
|
|
37
|
+
'andrew', 'nicholas', 'zachary', 'zack', 'cameron', 'dominic', 'trevor', 'tristan', 'kobe',
|
|
38
|
+
'brody', 'colin', 'damon', 'declan', 'derek', 'graham', 'ian', 'jasper', 'jonah', 'kai',
|
|
39
|
+
'kieran', 'milo', 'nico', 'rowan', 'silas', 'tanner', 'tucker', 'wesley', 'zane',
|
|
40
|
+
|
|
41
|
+
// Female Names
|
|
42
|
+
'olivia', 'emma', 'charlotte', 'amelia', 'sophia', 'isabella', 'ava', 'mia', 'evelyn',
|
|
43
|
+
'luna', 'harper', 'camila', 'sofia', 'scarlett', 'elizabeth', 'eleanor', 'emily', 'chloe',
|
|
44
|
+
'mila', 'violet', 'penelope', 'gianna', 'aria', 'abigail', 'ella', 'avery', 'hazel',
|
|
45
|
+
'nora', 'layla', 'lily', 'isla', 'elena', 'aurora', 'zoey', 'stella', 'nova', 'hannah',
|
|
46
|
+
'leah', 'maya', 'claire', 'lucy', 'madelyn', 'sarah', 'grace', 'zoe', 'natalie',
|
|
47
|
+
'kinsley', 'audrey', 'riley', 'savannah', 'brooklyn', 'clara', 'genesis', 'piper', 'ivy',
|
|
48
|
+
'sadie', 'delilah', 'serenity', 'autumn', 'ruby', 'alice', 'eva', 'hailey', 'madison',
|
|
49
|
+
'kayla', 'alyssa', 'brianna', 'taylor', 'megan', 'katelyn', 'sydney', 'destiny', 'jessica',
|
|
50
|
+
'ashley', 'amanda', 'brittany', 'stephanie', 'samantha', 'jennifer', 'rachel', 'lauren',
|
|
51
|
+
'morgan', 'kaylee', 'vanessa', 'paige', 'victoria', 'valerie', 'chelsea', 'kaitlyn',
|
|
52
|
+
'melanie', 'amber', 'erica', 'brooke', 'tara', 'courtney', 'holly', 'heather', 'kelsey',
|
|
53
|
+
'shelby', 'leslie', 'shannon', 'whitney', 'dana', 'fiona', 'gemma', 'heidi', 'jenna',
|
|
54
|
+
'kendra', 'kira', 'laura', 'nadia', 'nina', 'poppy', 'rosie', 'sienna', 'skye', 'talia',
|
|
55
|
+
'tessa', 'willa', 'zara'
|
|
56
|
+
];
|
|
22
57
|
}
|
|
23
58
|
|
|
24
59
|
getTimeoutRemaining() {
|
|
@@ -42,15 +77,28 @@ class AIContentModerator {
|
|
|
42
77
|
|
|
43
78
|
const cleanText = text.toLowerCase();
|
|
44
79
|
|
|
80
|
+
// 1. Check Bad Words & Controlled Substances
|
|
45
81
|
for (const term of this.bannedTerms) {
|
|
46
|
-
// Strictly check whole words with boundary regex
|
|
47
82
|
const regex = new RegExp(`(?:^|\\s|[^a-zA-Z0-9])${term}(?:$|\\s|[^a-zA-Z0-9])`, 'i');
|
|
48
83
|
if (regex.test(cleanText)) {
|
|
49
84
|
if (!isAdmin) this.applyTimeout(5);
|
|
50
85
|
return {
|
|
51
86
|
allowed: false,
|
|
52
87
|
flaggedTerm: term,
|
|
53
|
-
reason: `Message
|
|
88
|
+
reason: `Message blocked by AI filter for prohibited language. You are timed out for 5 minutes.`
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// 2. Check Real Personal Names (Male & Female) for Safety & Privacy
|
|
94
|
+
for (const name of this.bannedNames) {
|
|
95
|
+
const regex = new RegExp(`(?:^|\\s|[^a-zA-Z0-9])${name}(?:$|\\s|[^a-zA-Z0-9])`, 'i');
|
|
96
|
+
if (regex.test(cleanText)) {
|
|
97
|
+
if (!isAdmin) this.applyTimeout(2);
|
|
98
|
+
return {
|
|
99
|
+
allowed: false,
|
|
100
|
+
flaggedTerm: name,
|
|
101
|
+
reason: `Privacy Alert: Real personal names (${name}) are strictly prohibited in chat for your safety.`
|
|
54
102
|
};
|
|
55
103
|
}
|
|
56
104
|
}
|
package/main/js/app.js
CHANGED
|
@@ -105,14 +105,21 @@ class ReaperHubApp {
|
|
|
105
105
|
window.reaperFirebase.listenBannedUsers((bannedList) => {
|
|
106
106
|
this.bannedUsers = bannedList || [];
|
|
107
107
|
this.renderBannedUsersList();
|
|
108
|
-
|
|
108
|
+
const currentNameLower = (this.currentUser.username || '').toLowerCase();
|
|
109
|
+
const isBannedOnServer = this.bannedUsers.some(u => u.toLowerCase() === currentNameLower);
|
|
110
|
+
|
|
111
|
+
if (this.currentUser.rank !== 'owner' && isBannedOnServer) {
|
|
109
112
|
this.currentUser.isBanned = true;
|
|
110
113
|
localStorage.setItem('reaper_is_banned', 'true');
|
|
111
|
-
localStorage.removeItem('reaper_verified_token');
|
|
112
|
-
localStorage.removeItem('reaper_token_expires');
|
|
113
|
-
localStorage.removeItem('reaper_gateway_verified');
|
|
114
|
-
localStorage.removeItem('reaper_playtime_' + this.currentUser.username);
|
|
115
114
|
this.renderBanScreen("Your account has been permanently blacklisted and all recorded progress has been purged.");
|
|
115
|
+
} else {
|
|
116
|
+
// If unbanned!
|
|
117
|
+
if (this.currentUser.isBanned || document.getElementById('ban-screen-overlay')) {
|
|
118
|
+
this.currentUser.isBanned = false;
|
|
119
|
+
localStorage.removeItem('reaper_is_banned');
|
|
120
|
+
this.removeBanScreen();
|
|
121
|
+
this.showToast("Your account was UNBANNED by an Administrator!");
|
|
122
|
+
}
|
|
116
123
|
}
|
|
117
124
|
});
|
|
118
125
|
window.reaperFirebase.listenShutdownMode((isShutdown) => {
|
|
@@ -1464,14 +1471,16 @@ class ReaperHubApp {
|
|
|
1464
1471
|
if (!check.allowed) {
|
|
1465
1472
|
input.value = '';
|
|
1466
1473
|
this.updateChatStateUI();
|
|
1467
|
-
this.showToast("Message blocked by AI filter.
|
|
1474
|
+
this.showToast(check.reason || "Message blocked by AI filter.");
|
|
1468
1475
|
return;
|
|
1469
1476
|
}
|
|
1470
1477
|
}
|
|
1471
1478
|
|
|
1472
1479
|
input.value = '';
|
|
1473
1480
|
|
|
1481
|
+
const msgId = 'msg_' + Date.now() + '_' + Math.random().toString(36).substring(2, 6);
|
|
1474
1482
|
const msgData = {
|
|
1483
|
+
id: msgId,
|
|
1475
1484
|
username: this.currentUser.username,
|
|
1476
1485
|
rank: this.currentUser.rank,
|
|
1477
1486
|
playtimeStr: this.formatPlaytime(this.playtimeSeconds),
|
|
@@ -1488,6 +1497,7 @@ class ReaperHubApp {
|
|
|
1488
1497
|
}
|
|
1489
1498
|
|
|
1490
1499
|
async deleteMessage(msgId, authorName) {
|
|
1500
|
+
if (!msgId) return;
|
|
1491
1501
|
const isPrivileged = this.currentUser.rank === 'owner' || this.currentUser.rank === 'chat_mod' || this.currentUser.rank === 'mod';
|
|
1492
1502
|
const canDelete = isPrivileged || (authorName === this.currentUser.username);
|
|
1493
1503
|
if (!canDelete) {
|
|
@@ -1495,12 +1505,13 @@ class ReaperHubApp {
|
|
|
1495
1505
|
return;
|
|
1496
1506
|
}
|
|
1497
1507
|
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1508
|
+
this.chatMessages = this.chatMessages.filter(m => m.id !== msgId);
|
|
1509
|
+
localStorage.setItem('reaper_local_chat', JSON.stringify(this.chatMessages));
|
|
1510
|
+
this.renderChatMessages();
|
|
1511
|
+
if (window.reaperFirebase) {
|
|
1501
1512
|
await window.reaperFirebase.deleteChatMessage(msgId);
|
|
1502
|
-
this.showToast("Message deleted.");
|
|
1503
1513
|
}
|
|
1514
|
+
this.showToast("Message deleted globally.");
|
|
1504
1515
|
}
|
|
1505
1516
|
|
|
1506
1517
|
renderChatMessages() {
|
|
@@ -2118,7 +2129,17 @@ class ReaperHubApp {
|
|
|
2118
2129
|
}
|
|
2119
2130
|
|
|
2120
2131
|
renderBanScreen(customReason) {
|
|
2121
|
-
|
|
2132
|
+
let overlay = document.getElementById('ban-screen-overlay');
|
|
2133
|
+
if (!overlay) {
|
|
2134
|
+
overlay = document.createElement('div');
|
|
2135
|
+
overlay.id = 'ban-screen-overlay';
|
|
2136
|
+
overlay.style.position = 'fixed';
|
|
2137
|
+
overlay.style.inset = '0';
|
|
2138
|
+
overlay.style.zIndex = '9999999';
|
|
2139
|
+
overlay.style.background = '#000';
|
|
2140
|
+
document.body.appendChild(overlay);
|
|
2141
|
+
}
|
|
2142
|
+
overlay.innerHTML = `
|
|
2122
2143
|
<div style="display: flex; height: 100vh; width: 100vw; background: #000; color: #ff2a2a; font-family: var(--font-mono); align-items: center; justify-content: center; text-align: center; padding: 2rem;">
|
|
2123
2144
|
<div style="border: 2px solid #ff2a2a; padding: 3rem 2rem; max-width: 540px; background: #0c0202; border-radius: 10px; box-shadow: 0 0 40px rgba(255, 42, 42, 0.4);">
|
|
2124
2145
|
<h1 style="font-size: 2.2rem; margin-bottom: 1rem; color: #ff3333;">[PERMANENT BAN]</h1>
|
|
@@ -2131,6 +2152,14 @@ class ReaperHubApp {
|
|
|
2131
2152
|
</div>
|
|
2132
2153
|
</div>
|
|
2133
2154
|
`;
|
|
2155
|
+
overlay.style.display = 'block';
|
|
2156
|
+
}
|
|
2157
|
+
|
|
2158
|
+
removeBanScreen() {
|
|
2159
|
+
const overlay = document.getElementById('ban-screen-overlay');
|
|
2160
|
+
if (overlay) {
|
|
2161
|
+
overlay.remove();
|
|
2162
|
+
}
|
|
2134
2163
|
}
|
|
2135
2164
|
|
|
2136
2165
|
renderPermanentShutdownScreen() {
|
|
@@ -2341,12 +2370,21 @@ class ReaperHubApp {
|
|
|
2341
2370
|
}
|
|
2342
2371
|
|
|
2343
2372
|
async unbanUser(username) {
|
|
2344
|
-
|
|
2373
|
+
if (!username) return;
|
|
2374
|
+
const cleanUser = username.trim();
|
|
2375
|
+
this.bannedUsers = this.bannedUsers.filter(u => u.toLowerCase() !== cleanUser.toLowerCase());
|
|
2345
2376
|
localStorage.setItem('reaper_banned_users', JSON.stringify(this.bannedUsers));
|
|
2377
|
+
|
|
2378
|
+
if ((this.currentUser.username || '').toLowerCase() === cleanUser.toLowerCase()) {
|
|
2379
|
+
this.currentUser.isBanned = false;
|
|
2380
|
+
localStorage.removeItem('reaper_is_banned');
|
|
2381
|
+
this.removeBanScreen();
|
|
2382
|
+
}
|
|
2383
|
+
|
|
2346
2384
|
if (window.reaperFirebase) {
|
|
2347
|
-
await window.reaperFirebase.unbanUser(
|
|
2385
|
+
await window.reaperFirebase.unbanUser(cleanUser);
|
|
2348
2386
|
}
|
|
2349
|
-
this.showToast(`User ${
|
|
2387
|
+
this.showToast(`User ${cleanUser} UNBANNED.`);
|
|
2350
2388
|
this.renderBannedUsersList();
|
|
2351
2389
|
}
|
|
2352
2390
|
|
|
@@ -257,16 +257,17 @@ class FirebaseService {
|
|
|
257
257
|
|
|
258
258
|
async banUser(username) {
|
|
259
259
|
if (!username || username === 'owner') return;
|
|
260
|
+
const cleanUser = username.trim();
|
|
260
261
|
|
|
261
262
|
if (this.db) {
|
|
262
263
|
try {
|
|
263
|
-
await this.db.ref(`reaperBannedUsers/${
|
|
264
|
-
await this.db.ref(`reaperPlaytime/${
|
|
264
|
+
await this.db.ref(`reaperBannedUsers/${cleanUser}`).set(true);
|
|
265
|
+
await this.db.ref(`reaperPlaytime/${cleanUser}`).remove();
|
|
265
266
|
const chatSnap = await this.db.ref('reaperChat').once('value');
|
|
266
267
|
if (chatSnap.exists()) {
|
|
267
268
|
const chats = chatSnap.val();
|
|
268
269
|
for (const msgId of Object.keys(chats)) {
|
|
269
|
-
if (chats[msgId].username
|
|
270
|
+
if (chats[msgId].username && chats[msgId].username.toLowerCase() === cleanUser.toLowerCase()) {
|
|
270
271
|
await this.db.ref(`reaperChat/${msgId}`).remove();
|
|
271
272
|
}
|
|
272
273
|
}
|
|
@@ -277,21 +278,34 @@ class FirebaseService {
|
|
|
277
278
|
}
|
|
278
279
|
|
|
279
280
|
const localBans = JSON.parse(localStorage.getItem('reaper_banned_users') || '[]');
|
|
280
|
-
if (!localBans.
|
|
281
|
-
localBans.push(
|
|
281
|
+
if (!localBans.some(u => u.toLowerCase() === cleanUser.toLowerCase())) {
|
|
282
|
+
localBans.push(cleanUser);
|
|
282
283
|
localStorage.setItem('reaper_banned_users', JSON.stringify(localBans));
|
|
283
284
|
}
|
|
284
285
|
}
|
|
285
286
|
|
|
286
287
|
async unbanUser(username) {
|
|
288
|
+
if (!username) return;
|
|
289
|
+
const cleanUser = username.trim();
|
|
290
|
+
|
|
287
291
|
if (this.db) {
|
|
288
292
|
try {
|
|
289
|
-
await this.db.ref(`reaperBannedUsers/${
|
|
293
|
+
await this.db.ref(`reaperBannedUsers/${cleanUser}`).remove();
|
|
294
|
+
const snap = await this.db.ref('reaperBannedUsers').once('value');
|
|
295
|
+
if (snap.exists()) {
|
|
296
|
+
const bans = snap.val();
|
|
297
|
+
for (const k of Object.keys(bans)) {
|
|
298
|
+
if (k.toLowerCase() === cleanUser.toLowerCase()) {
|
|
299
|
+
await this.db.ref(`reaperBannedUsers/${k}`).remove();
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
290
303
|
} catch (e) {
|
|
291
304
|
console.warn("Error unbanning user on Firebase:", e);
|
|
292
305
|
}
|
|
293
306
|
}
|
|
294
|
-
|
|
307
|
+
|
|
308
|
+
const localBans = JSON.parse(localStorage.getItem('reaper_banned_users') || '[]').filter(u => u.toLowerCase() !== cleanUser.toLowerCase());
|
|
295
309
|
localStorage.setItem('reaper_banned_users', JSON.stringify(localBans));
|
|
296
310
|
}
|
|
297
311
|
|
package/main/js/moderator.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
// AI Content Moderator &
|
|
1
|
+
// REAPER HUB - AI Content Moderator & Privacy Name Filter Engine
|
|
2
|
+
// Blocks profanity, slurs, drug references, and real personal names (Male & Female) for user safety and privacy.
|
|
2
3
|
|
|
3
4
|
class AIContentModerator {
|
|
4
5
|
constructor() {
|
|
@@ -19,6 +20,40 @@ class AIContentModerator {
|
|
|
19
20
|
'porn', 'porno', 'xxx', 'hentai', 'rule34', 'xvideos', 'pornhub', 'onlyfans',
|
|
20
21
|
'nsfw', 'sex', 'blowjob', 'handjob', 'dildo'
|
|
21
22
|
];
|
|
23
|
+
|
|
24
|
+
// Real Personal Names Filter (Male & Female Names) for Privacy & Safety
|
|
25
|
+
this.bannedNames = [
|
|
26
|
+
// Specific Requested Names
|
|
27
|
+
'kaidan', 'kaiden', 'kayden', 'caiden', 'kaden', 'loki', 'harry', 'will', 'william',
|
|
28
|
+
|
|
29
|
+
// Male Names
|
|
30
|
+
'liam', 'noah', 'oliver', 'james', 'elijah', 'mateo', 'theodore', 'henry', 'lucas',
|
|
31
|
+
'benjamin', 'levi', 'sebastian', 'jack', 'ezra', 'michael', 'daniel', 'logan', 'jackson',
|
|
32
|
+
'owen', 'samuel', 'alex', 'alexander', 'ryan', 'ethan', 'john', 'david', 'luke', 'mason',
|
|
33
|
+
'connor', 'caleb', 'isaiah', 'anthony', 'charles', 'thomas', 'leo', 'jordan', 'jayden',
|
|
34
|
+
'nathan', 'gabriel', 'carter', 'hunter', 'christian', 'aaron', 'eli', 'colton', 'landon',
|
|
35
|
+
'adrian', 'brayden', 'tyler', 'austin', 'kevin', 'brandon', 'justin', 'george', 'jason',
|
|
36
|
+
'cody', 'travis', 'dylan', 'kyle', 'brian', 'eric', 'steven', 'adam', 'joshua', 'jacob',
|
|
37
|
+
'andrew', 'nicholas', 'zachary', 'zack', 'cameron', 'dominic', 'trevor', 'tristan', 'kobe',
|
|
38
|
+
'brody', 'colin', 'damon', 'declan', 'derek', 'graham', 'ian', 'jasper', 'jonah', 'kai',
|
|
39
|
+
'kieran', 'milo', 'nico', 'rowan', 'silas', 'tanner', 'tucker', 'wesley', 'zane',
|
|
40
|
+
|
|
41
|
+
// Female Names
|
|
42
|
+
'olivia', 'emma', 'charlotte', 'amelia', 'sophia', 'isabella', 'ava', 'mia', 'evelyn',
|
|
43
|
+
'luna', 'harper', 'camila', 'sofia', 'scarlett', 'elizabeth', 'eleanor', 'emily', 'chloe',
|
|
44
|
+
'mila', 'violet', 'penelope', 'gianna', 'aria', 'abigail', 'ella', 'avery', 'hazel',
|
|
45
|
+
'nora', 'layla', 'lily', 'isla', 'elena', 'aurora', 'zoey', 'stella', 'nova', 'hannah',
|
|
46
|
+
'leah', 'maya', 'claire', 'lucy', 'madelyn', 'sarah', 'grace', 'zoe', 'natalie',
|
|
47
|
+
'kinsley', 'audrey', 'riley', 'savannah', 'brooklyn', 'clara', 'genesis', 'piper', 'ivy',
|
|
48
|
+
'sadie', 'delilah', 'serenity', 'autumn', 'ruby', 'alice', 'eva', 'hailey', 'madison',
|
|
49
|
+
'kayla', 'alyssa', 'brianna', 'taylor', 'megan', 'katelyn', 'sydney', 'destiny', 'jessica',
|
|
50
|
+
'ashley', 'amanda', 'brittany', 'stephanie', 'samantha', 'jennifer', 'rachel', 'lauren',
|
|
51
|
+
'morgan', 'kaylee', 'vanessa', 'paige', 'victoria', 'valerie', 'chelsea', 'kaitlyn',
|
|
52
|
+
'melanie', 'amber', 'erica', 'brooke', 'tara', 'courtney', 'holly', 'heather', 'kelsey',
|
|
53
|
+
'shelby', 'leslie', 'shannon', 'whitney', 'dana', 'fiona', 'gemma', 'heidi', 'jenna',
|
|
54
|
+
'kendra', 'kira', 'laura', 'nadia', 'nina', 'poppy', 'rosie', 'sienna', 'skye', 'talia',
|
|
55
|
+
'tessa', 'willa', 'zara'
|
|
56
|
+
];
|
|
22
57
|
}
|
|
23
58
|
|
|
24
59
|
getTimeoutRemaining() {
|
|
@@ -42,15 +77,28 @@ class AIContentModerator {
|
|
|
42
77
|
|
|
43
78
|
const cleanText = text.toLowerCase();
|
|
44
79
|
|
|
80
|
+
// 1. Check Bad Words & Controlled Substances
|
|
45
81
|
for (const term of this.bannedTerms) {
|
|
46
|
-
// Strictly check whole words with boundary regex
|
|
47
82
|
const regex = new RegExp(`(?:^|\\s|[^a-zA-Z0-9])${term}(?:$|\\s|[^a-zA-Z0-9])`, 'i');
|
|
48
83
|
if (regex.test(cleanText)) {
|
|
49
84
|
if (!isAdmin) this.applyTimeout(5);
|
|
50
85
|
return {
|
|
51
86
|
allowed: false,
|
|
52
87
|
flaggedTerm: term,
|
|
53
|
-
reason: `Message
|
|
88
|
+
reason: `Message blocked by AI filter for prohibited language. You are timed out for 5 minutes.`
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// 2. Check Real Personal Names (Male & Female) for Safety & Privacy
|
|
94
|
+
for (const name of this.bannedNames) {
|
|
95
|
+
const regex = new RegExp(`(?:^|\\s|[^a-zA-Z0-9])${name}(?:$|\\s|[^a-zA-Z0-9])`, 'i');
|
|
96
|
+
if (regex.test(cleanText)) {
|
|
97
|
+
if (!isAdmin) this.applyTimeout(2);
|
|
98
|
+
return {
|
|
99
|
+
allowed: false,
|
|
100
|
+
flaggedTerm: name,
|
|
101
|
+
reason: `Privacy Alert: Real personal names (${name}) are strictly prohibited in chat for your safety.`
|
|
54
102
|
};
|
|
55
103
|
}
|
|
56
104
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reaper-arcade-hub",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"description": "Reaper Hub - 788 High-Speed HTML5 Games, Potato PC Performance Mode, Top Plays, Realtime Chat, Private DMs, Playtime Leaderboard & Verification Gateway",
|
|
3
|
+
"version": "1.1.2",
|
|
4
|
+
"description": "Reaper Hub - 788 High-Speed HTML5 Games, Instant Reactive Unban & Ban Engine, AI Name Privacy Filter, Global Chat Deletion, Potato PC Performance Mode, Top Plays, Realtime Chat, Private DMs, Playtime Leaderboard & Verification Gateway",
|
|
5
5
|
"main": "main/index.html",
|
|
6
6
|
"unpkg": "main/index.html",
|
|
7
7
|
"jsdelivr": "main/index.html",
|
|
@@ -14,8 +14,10 @@
|
|
|
14
14
|
"html5",
|
|
15
15
|
"unblocked",
|
|
16
16
|
"arcade",
|
|
17
|
+
"unban",
|
|
18
|
+
"moderation",
|
|
19
|
+
"privacy",
|
|
17
20
|
"performance",
|
|
18
|
-
"potatomode",
|
|
19
21
|
"leaderboard",
|
|
20
22
|
"dms",
|
|
21
23
|
"topplays"
|
|
@@ -257,16 +257,17 @@ class FirebaseService {
|
|
|
257
257
|
|
|
258
258
|
async banUser(username) {
|
|
259
259
|
if (!username || username === 'owner') return;
|
|
260
|
+
const cleanUser = username.trim();
|
|
260
261
|
|
|
261
262
|
if (this.db) {
|
|
262
263
|
try {
|
|
263
|
-
await this.db.ref(`reaperBannedUsers/${
|
|
264
|
-
await this.db.ref(`reaperPlaytime/${
|
|
264
|
+
await this.db.ref(`reaperBannedUsers/${cleanUser}`).set(true);
|
|
265
|
+
await this.db.ref(`reaperPlaytime/${cleanUser}`).remove();
|
|
265
266
|
const chatSnap = await this.db.ref('reaperChat').once('value');
|
|
266
267
|
if (chatSnap.exists()) {
|
|
267
268
|
const chats = chatSnap.val();
|
|
268
269
|
for (const msgId of Object.keys(chats)) {
|
|
269
|
-
if (chats[msgId].username
|
|
270
|
+
if (chats[msgId].username && chats[msgId].username.toLowerCase() === cleanUser.toLowerCase()) {
|
|
270
271
|
await this.db.ref(`reaperChat/${msgId}`).remove();
|
|
271
272
|
}
|
|
272
273
|
}
|
|
@@ -277,21 +278,34 @@ class FirebaseService {
|
|
|
277
278
|
}
|
|
278
279
|
|
|
279
280
|
const localBans = JSON.parse(localStorage.getItem('reaper_banned_users') || '[]');
|
|
280
|
-
if (!localBans.
|
|
281
|
-
localBans.push(
|
|
281
|
+
if (!localBans.some(u => u.toLowerCase() === cleanUser.toLowerCase())) {
|
|
282
|
+
localBans.push(cleanUser);
|
|
282
283
|
localStorage.setItem('reaper_banned_users', JSON.stringify(localBans));
|
|
283
284
|
}
|
|
284
285
|
}
|
|
285
286
|
|
|
286
287
|
async unbanUser(username) {
|
|
288
|
+
if (!username) return;
|
|
289
|
+
const cleanUser = username.trim();
|
|
290
|
+
|
|
287
291
|
if (this.db) {
|
|
288
292
|
try {
|
|
289
|
-
await this.db.ref(`reaperBannedUsers/${
|
|
293
|
+
await this.db.ref(`reaperBannedUsers/${cleanUser}`).remove();
|
|
294
|
+
const snap = await this.db.ref('reaperBannedUsers').once('value');
|
|
295
|
+
if (snap.exists()) {
|
|
296
|
+
const bans = snap.val();
|
|
297
|
+
for (const k of Object.keys(bans)) {
|
|
298
|
+
if (k.toLowerCase() === cleanUser.toLowerCase()) {
|
|
299
|
+
await this.db.ref(`reaperBannedUsers/${k}`).remove();
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
290
303
|
} catch (e) {
|
|
291
304
|
console.warn("Error unbanning user on Firebase:", e);
|
|
292
305
|
}
|
|
293
306
|
}
|
|
294
|
-
|
|
307
|
+
|
|
308
|
+
const localBans = JSON.parse(localStorage.getItem('reaper_banned_users') || '[]').filter(u => u.toLowerCase() !== cleanUser.toLowerCase());
|
|
295
309
|
localStorage.setItem('reaper_banned_users', JSON.stringify(localBans));
|
|
296
310
|
}
|
|
297
311
|
|