reaper-arcade-hub 2.0.8 → 2.1.0
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/index.html +2 -2
- package/js/app.js +74 -31
- package/main/index.html +2 -2
- package/main/js/app.js +74 -31
- package/package.json +6 -27
package/index.html
CHANGED
|
@@ -58,8 +58,8 @@
|
|
|
58
58
|
</div>
|
|
59
59
|
</div>
|
|
60
60
|
|
|
61
|
-
<!-- Key Gatekeeper Modal (
|
|
62
|
-
<div id="key-gate-modal"
|
|
61
|
+
<!-- Key Gatekeeper Modal (Hard Wall - Blocks All Interaction) -->
|
|
62
|
+
<div id="key-gate-modal" style="display: none; position: fixed; inset: 0; width: 100vw; height: 100vh; background: #02050a; z-index: 999999999; align-items: center; justify-content: center; padding: 1.5rem; flex-direction: column; pointer-events: all; user-select: none;">
|
|
63
63
|
<div class="admin-window" style="max-width: 480px; text-align: center; border-color: var(--blue-primary); box-shadow: 0 0 45px var(--blue-glow); padding: 2.5rem 2rem;">
|
|
64
64
|
<div style="font-family: var(--font-logo); font-size: 3.5rem; color: #fff; font-weight: 900; margin-bottom: 0.25rem; letter-spacing: 0.1em;">reaper</div>
|
|
65
65
|
<div style="color: #00d2ff; font-family: var(--font-heading); font-size: 0.8rem; font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase; margin-bottom: 1.25rem;">AUTHENTICATION REQUIRED</div>
|
package/js/app.js
CHANGED
|
@@ -43,32 +43,40 @@ class ReaperHubApp {
|
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
// 3. Process URL Master Token from Gateway if present
|
|
46
|
+
// 3. Process URL Master Token from Gateway if present (BEFORE gate check)
|
|
47
47
|
this.processUrlToken();
|
|
48
48
|
|
|
49
|
-
// 4. Validate Gateway Key Verification Session
|
|
49
|
+
// 4. HARD GATE: Validate Gateway Key Verification Session
|
|
50
50
|
const isAuthed = this.checkGatewayAuthentication();
|
|
51
51
|
const gateModal = document.getElementById('key-gate-modal');
|
|
52
|
+
|
|
52
53
|
if (!isAuthed) {
|
|
53
|
-
|
|
54
|
+
// Block everything - show gate and stop all init dead here
|
|
55
|
+
if (gateModal) {
|
|
56
|
+
gateModal.style.display = 'flex';
|
|
57
|
+
gateModal.style.pointerEvents = 'all';
|
|
58
|
+
}
|
|
59
|
+
document.body.style.overflow = 'hidden';
|
|
54
60
|
this.currentUser.isGuest = true;
|
|
55
61
|
this.currentUser.username = "";
|
|
56
62
|
this.currentUser.rank = "guest";
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
63
|
+
return; // <<< HARD STOP - no games, no firebase, no UI
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Authenticated - hide gate and proceed
|
|
67
|
+
if (gateModal) gateModal.style.display = 'none';
|
|
68
|
+
this.currentUser.isGuest = false;
|
|
69
|
+
if (!this.currentUser.username) {
|
|
70
|
+
const stored = localStorage.getItem('reaper_username');
|
|
71
|
+
if (stored) {
|
|
72
|
+
this.currentUser.username = stored;
|
|
73
|
+
} else {
|
|
74
|
+
const newName = typeof getRandomUsername === 'function' ? getRandomUsername() : "Reaper_" + Math.floor(Math.random() * 9999);
|
|
75
|
+
this.currentUser.username = newName;
|
|
76
|
+
localStorage.setItem('reaper_username', newName);
|
|
69
77
|
}
|
|
70
|
-
this.playtimeSeconds = parseInt(localStorage.getItem('reaper_playtime_' + this.currentUser.username) || '0', 10);
|
|
71
78
|
}
|
|
79
|
+
this.playtimeSeconds = parseInt(localStorage.getItem('reaper_playtime_' + this.currentUser.username) || '0', 10);
|
|
72
80
|
|
|
73
81
|
// 6. Role check
|
|
74
82
|
if (this.currentUser.rank === 'owner') {
|
|
@@ -461,15 +469,8 @@ class ReaperHubApp {
|
|
|
461
469
|
localStorage.setItem('reaper_token_expires', expiresAt.toString());
|
|
462
470
|
localStorage.setItem('reaper_gateway_verified', 'true');
|
|
463
471
|
localStorage.setItem('reaper_rank', rank);
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
this.isAdmin = true;
|
|
467
|
-
localStorage.setItem('reaper_admin_auth', 'true');
|
|
468
|
-
}
|
|
469
|
-
const gateModal = document.getElementById('key-gate-modal');
|
|
470
|
-
if (gateModal) gateModal.style.display = 'none';
|
|
471
|
-
this.updateUserUI();
|
|
472
|
-
this.showToast(`Access Granted: ${rank.toUpperCase()}`);
|
|
472
|
+
// Full page reload to properly initialize all systems after auth
|
|
473
|
+
window.location.reload();
|
|
473
474
|
return;
|
|
474
475
|
}
|
|
475
476
|
}
|
|
@@ -1654,20 +1655,20 @@ class ReaperHubApp {
|
|
|
1654
1655
|
const coverUrl = game.cover || `https://placehold.co/400x250/041022/ffffff?text=${encodeURIComponent(game.name)}`;
|
|
1655
1656
|
|
|
1656
1657
|
return `
|
|
1657
|
-
<div class="game-card" onclick="app.launchGame('${game.id}')">
|
|
1658
|
+
<div class="game-card" data-id="${game.id}" onclick="app.launchGame('${game.id}')">
|
|
1658
1659
|
<div class="game-thumb-container">
|
|
1659
|
-
<img class="game-thumb" src="${coverUrl}" alt="${game.name}" loading="lazy" onerror="this.onerror=null; this.src='https://placehold.co/400x250/041022/ffffff?text=${encodeURIComponent(game.name)}';" />
|
|
1660
|
+
<img class="game-thumb" src="${coverUrl}" alt="${this.escapeHtml(game.name)}" loading="lazy" onerror="this.onerror=null; this.src='https://placehold.co/400x250/041022/ffffff?text=${encodeURIComponent(game.name)}';" />
|
|
1660
1661
|
${game.featured ? '<span class="game-badge-featured">FEATURED</span>' : ''}
|
|
1661
1662
|
</div>
|
|
1662
1663
|
<div class="game-info">
|
|
1663
|
-
<div class="game-title" title="${game.name}">${game.name}</div>
|
|
1664
|
+
<div class="game-title" title="${this.escapeHtml(game.name)}">${this.escapeHtml(game.name)}</div>
|
|
1664
1665
|
<div class="game-meta">
|
|
1665
|
-
<span class="game-author">${game.author || 'GN-Math'}</span>
|
|
1666
|
-
<button class="btn-fav ${isFav ? 'active' : ''}" onclick="event.stopPropagation(); app.toggleFavorite('${game.id}')" title="${isFav ? 'Remove from favorites' : 'Add to favorites'}">
|
|
1666
|
+
<span class="game-author">${this.escapeHtml(game.author || 'GN-Math')}</span>
|
|
1667
|
+
<button class="btn-fav ${isFav ? 'active' : ''}" data-id="${game.id}" onclick="event.stopPropagation(); app.toggleFavorite('${game.id}')" title="${isFav ? 'Remove from favorites' : 'Add to favorites'}">
|
|
1667
1668
|
${isFav ? '★ SAVED' : '☆ FAV'}
|
|
1668
1669
|
</button>
|
|
1669
1670
|
</div>
|
|
1670
|
-
<button class="btn-card-play" onclick="event.stopPropagation(); app.launchGame('${game.id}')">PLAY GAME</button>
|
|
1671
|
+
<button class="btn-card-play" data-id="${game.id}" onclick="event.stopPropagation(); app.launchGame('${game.id}')">PLAY GAME</button>
|
|
1671
1672
|
</div>
|
|
1672
1673
|
</div>
|
|
1673
1674
|
`;
|
|
@@ -2509,6 +2510,48 @@ class ReaperHubApp {
|
|
|
2509
2510
|
}
|
|
2510
2511
|
}
|
|
2511
2512
|
});
|
|
2513
|
+
|
|
2514
|
+
// Guaranteed Click Delegation for Games Grid & Recent Games Grid
|
|
2515
|
+
const gamesGrid = document.getElementById('games-grid');
|
|
2516
|
+
if (gamesGrid) {
|
|
2517
|
+
gamesGrid.addEventListener('click', (e) => {
|
|
2518
|
+
const favBtn = e.target.closest('.btn-fav');
|
|
2519
|
+
if (favBtn) {
|
|
2520
|
+
e.preventDefault();
|
|
2521
|
+
e.stopPropagation();
|
|
2522
|
+
const id = favBtn.getAttribute('data-id');
|
|
2523
|
+
if (id !== null) this.toggleFavorite(id);
|
|
2524
|
+
return;
|
|
2525
|
+
}
|
|
2526
|
+
|
|
2527
|
+
const card = e.target.closest('.game-card');
|
|
2528
|
+
const playBtn = e.target.closest('.btn-card-play');
|
|
2529
|
+
if (card || playBtn) {
|
|
2530
|
+
e.preventDefault();
|
|
2531
|
+
e.stopPropagation();
|
|
2532
|
+
const target = playBtn || card;
|
|
2533
|
+
const id = target.getAttribute('data-id') || (card ? card.getAttribute('data-id') : null);
|
|
2534
|
+
if (id !== null) {
|
|
2535
|
+
this.launchGame(id);
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
});
|
|
2539
|
+
}
|
|
2540
|
+
|
|
2541
|
+
const recentGrid = document.getElementById('recent-games-grid');
|
|
2542
|
+
if (recentGrid) {
|
|
2543
|
+
recentGrid.addEventListener('click', (e) => {
|
|
2544
|
+
const card = e.target.closest('.recent-card');
|
|
2545
|
+
if (card) {
|
|
2546
|
+
e.preventDefault();
|
|
2547
|
+
e.stopPropagation();
|
|
2548
|
+
const id = card.getAttribute('data-id');
|
|
2549
|
+
if (id !== null) {
|
|
2550
|
+
this.launchGame(id);
|
|
2551
|
+
}
|
|
2552
|
+
}
|
|
2553
|
+
});
|
|
2554
|
+
}
|
|
2512
2555
|
}
|
|
2513
2556
|
|
|
2514
2557
|
openSettingsModal() {
|
package/main/index.html
CHANGED
|
@@ -58,8 +58,8 @@
|
|
|
58
58
|
</div>
|
|
59
59
|
</div>
|
|
60
60
|
|
|
61
|
-
<!-- Key Gatekeeper Modal (
|
|
62
|
-
<div id="key-gate-modal"
|
|
61
|
+
<!-- Key Gatekeeper Modal (Hard Wall - Blocks All Interaction) -->
|
|
62
|
+
<div id="key-gate-modal" style="display: none; position: fixed; inset: 0; width: 100vw; height: 100vh; background: #02050a; z-index: 999999999; align-items: center; justify-content: center; padding: 1.5rem; flex-direction: column; pointer-events: all; user-select: none;">
|
|
63
63
|
<div class="admin-window" style="max-width: 480px; text-align: center; border-color: var(--blue-primary); box-shadow: 0 0 45px var(--blue-glow); padding: 2.5rem 2rem;">
|
|
64
64
|
<div style="font-family: var(--font-logo); font-size: 3.5rem; color: #fff; font-weight: 900; margin-bottom: 0.25rem; letter-spacing: 0.1em;">reaper</div>
|
|
65
65
|
<div style="color: #00d2ff; font-family: var(--font-heading); font-size: 0.8rem; font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase; margin-bottom: 1.25rem;">AUTHENTICATION REQUIRED</div>
|
package/main/js/app.js
CHANGED
|
@@ -43,32 +43,40 @@ class ReaperHubApp {
|
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
// 3. Process URL Master Token from Gateway if present
|
|
46
|
+
// 3. Process URL Master Token from Gateway if present (BEFORE gate check)
|
|
47
47
|
this.processUrlToken();
|
|
48
48
|
|
|
49
|
-
// 4. Validate Gateway Key Verification Session
|
|
49
|
+
// 4. HARD GATE: Validate Gateway Key Verification Session
|
|
50
50
|
const isAuthed = this.checkGatewayAuthentication();
|
|
51
51
|
const gateModal = document.getElementById('key-gate-modal');
|
|
52
|
+
|
|
52
53
|
if (!isAuthed) {
|
|
53
|
-
|
|
54
|
+
// Block everything - show gate and stop all init dead here
|
|
55
|
+
if (gateModal) {
|
|
56
|
+
gateModal.style.display = 'flex';
|
|
57
|
+
gateModal.style.pointerEvents = 'all';
|
|
58
|
+
}
|
|
59
|
+
document.body.style.overflow = 'hidden';
|
|
54
60
|
this.currentUser.isGuest = true;
|
|
55
61
|
this.currentUser.username = "";
|
|
56
62
|
this.currentUser.rank = "guest";
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
63
|
+
return; // <<< HARD STOP - no games, no firebase, no UI
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Authenticated - hide gate and proceed
|
|
67
|
+
if (gateModal) gateModal.style.display = 'none';
|
|
68
|
+
this.currentUser.isGuest = false;
|
|
69
|
+
if (!this.currentUser.username) {
|
|
70
|
+
const stored = localStorage.getItem('reaper_username');
|
|
71
|
+
if (stored) {
|
|
72
|
+
this.currentUser.username = stored;
|
|
73
|
+
} else {
|
|
74
|
+
const newName = typeof getRandomUsername === 'function' ? getRandomUsername() : "Reaper_" + Math.floor(Math.random() * 9999);
|
|
75
|
+
this.currentUser.username = newName;
|
|
76
|
+
localStorage.setItem('reaper_username', newName);
|
|
69
77
|
}
|
|
70
|
-
this.playtimeSeconds = parseInt(localStorage.getItem('reaper_playtime_' + this.currentUser.username) || '0', 10);
|
|
71
78
|
}
|
|
79
|
+
this.playtimeSeconds = parseInt(localStorage.getItem('reaper_playtime_' + this.currentUser.username) || '0', 10);
|
|
72
80
|
|
|
73
81
|
// 6. Role check
|
|
74
82
|
if (this.currentUser.rank === 'owner') {
|
|
@@ -461,15 +469,8 @@ class ReaperHubApp {
|
|
|
461
469
|
localStorage.setItem('reaper_token_expires', expiresAt.toString());
|
|
462
470
|
localStorage.setItem('reaper_gateway_verified', 'true');
|
|
463
471
|
localStorage.setItem('reaper_rank', rank);
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
this.isAdmin = true;
|
|
467
|
-
localStorage.setItem('reaper_admin_auth', 'true');
|
|
468
|
-
}
|
|
469
|
-
const gateModal = document.getElementById('key-gate-modal');
|
|
470
|
-
if (gateModal) gateModal.style.display = 'none';
|
|
471
|
-
this.updateUserUI();
|
|
472
|
-
this.showToast(`Access Granted: ${rank.toUpperCase()}`);
|
|
472
|
+
// Full page reload to properly initialize all systems after auth
|
|
473
|
+
window.location.reload();
|
|
473
474
|
return;
|
|
474
475
|
}
|
|
475
476
|
}
|
|
@@ -1654,20 +1655,20 @@ class ReaperHubApp {
|
|
|
1654
1655
|
const coverUrl = game.cover || `https://placehold.co/400x250/041022/ffffff?text=${encodeURIComponent(game.name)}`;
|
|
1655
1656
|
|
|
1656
1657
|
return `
|
|
1657
|
-
<div class="game-card" onclick="app.launchGame('${game.id}')">
|
|
1658
|
+
<div class="game-card" data-id="${game.id}" onclick="app.launchGame('${game.id}')">
|
|
1658
1659
|
<div class="game-thumb-container">
|
|
1659
|
-
<img class="game-thumb" src="${coverUrl}" alt="${game.name}" loading="lazy" onerror="this.onerror=null; this.src='https://placehold.co/400x250/041022/ffffff?text=${encodeURIComponent(game.name)}';" />
|
|
1660
|
+
<img class="game-thumb" src="${coverUrl}" alt="${this.escapeHtml(game.name)}" loading="lazy" onerror="this.onerror=null; this.src='https://placehold.co/400x250/041022/ffffff?text=${encodeURIComponent(game.name)}';" />
|
|
1660
1661
|
${game.featured ? '<span class="game-badge-featured">FEATURED</span>' : ''}
|
|
1661
1662
|
</div>
|
|
1662
1663
|
<div class="game-info">
|
|
1663
|
-
<div class="game-title" title="${game.name}">${game.name}</div>
|
|
1664
|
+
<div class="game-title" title="${this.escapeHtml(game.name)}">${this.escapeHtml(game.name)}</div>
|
|
1664
1665
|
<div class="game-meta">
|
|
1665
|
-
<span class="game-author">${game.author || 'GN-Math'}</span>
|
|
1666
|
-
<button class="btn-fav ${isFav ? 'active' : ''}" onclick="event.stopPropagation(); app.toggleFavorite('${game.id}')" title="${isFav ? 'Remove from favorites' : 'Add to favorites'}">
|
|
1666
|
+
<span class="game-author">${this.escapeHtml(game.author || 'GN-Math')}</span>
|
|
1667
|
+
<button class="btn-fav ${isFav ? 'active' : ''}" data-id="${game.id}" onclick="event.stopPropagation(); app.toggleFavorite('${game.id}')" title="${isFav ? 'Remove from favorites' : 'Add to favorites'}">
|
|
1667
1668
|
${isFav ? '★ SAVED' : '☆ FAV'}
|
|
1668
1669
|
</button>
|
|
1669
1670
|
</div>
|
|
1670
|
-
<button class="btn-card-play" onclick="event.stopPropagation(); app.launchGame('${game.id}')">PLAY GAME</button>
|
|
1671
|
+
<button class="btn-card-play" data-id="${game.id}" onclick="event.stopPropagation(); app.launchGame('${game.id}')">PLAY GAME</button>
|
|
1671
1672
|
</div>
|
|
1672
1673
|
</div>
|
|
1673
1674
|
`;
|
|
@@ -2509,6 +2510,48 @@ class ReaperHubApp {
|
|
|
2509
2510
|
}
|
|
2510
2511
|
}
|
|
2511
2512
|
});
|
|
2513
|
+
|
|
2514
|
+
// Guaranteed Click Delegation for Games Grid & Recent Games Grid
|
|
2515
|
+
const gamesGrid = document.getElementById('games-grid');
|
|
2516
|
+
if (gamesGrid) {
|
|
2517
|
+
gamesGrid.addEventListener('click', (e) => {
|
|
2518
|
+
const favBtn = e.target.closest('.btn-fav');
|
|
2519
|
+
if (favBtn) {
|
|
2520
|
+
e.preventDefault();
|
|
2521
|
+
e.stopPropagation();
|
|
2522
|
+
const id = favBtn.getAttribute('data-id');
|
|
2523
|
+
if (id !== null) this.toggleFavorite(id);
|
|
2524
|
+
return;
|
|
2525
|
+
}
|
|
2526
|
+
|
|
2527
|
+
const card = e.target.closest('.game-card');
|
|
2528
|
+
const playBtn = e.target.closest('.btn-card-play');
|
|
2529
|
+
if (card || playBtn) {
|
|
2530
|
+
e.preventDefault();
|
|
2531
|
+
e.stopPropagation();
|
|
2532
|
+
const target = playBtn || card;
|
|
2533
|
+
const id = target.getAttribute('data-id') || (card ? card.getAttribute('data-id') : null);
|
|
2534
|
+
if (id !== null) {
|
|
2535
|
+
this.launchGame(id);
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
});
|
|
2539
|
+
}
|
|
2540
|
+
|
|
2541
|
+
const recentGrid = document.getElementById('recent-games-grid');
|
|
2542
|
+
if (recentGrid) {
|
|
2543
|
+
recentGrid.addEventListener('click', (e) => {
|
|
2544
|
+
const card = e.target.closest('.recent-card');
|
|
2545
|
+
if (card) {
|
|
2546
|
+
e.preventDefault();
|
|
2547
|
+
e.stopPropagation();
|
|
2548
|
+
const id = card.getAttribute('data-id');
|
|
2549
|
+
if (id !== null) {
|
|
2550
|
+
this.launchGame(id);
|
|
2551
|
+
}
|
|
2552
|
+
}
|
|
2553
|
+
});
|
|
2554
|
+
}
|
|
2512
2555
|
}
|
|
2513
2556
|
|
|
2514
2557
|
openSettingsModal() {
|
package/package.json
CHANGED
|
@@ -1,35 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reaper-arcade-hub",
|
|
3
|
-
"version": "2.0
|
|
4
|
-
"description": "Reaper Hub -
|
|
3
|
+
"version": "2.1.0",
|
|
4
|
+
"description": "Reaper Hub - Hard Key Gate (No Bypass), Full Click Delegation, Direct GitHub Pages CDN, Strict HWID Auth, Realtime Chat & 788 Games",
|
|
5
5
|
"main": "main/index.html",
|
|
6
6
|
"unpkg": "main/index.html",
|
|
7
7
|
"jsdelivr": "main/index.html",
|
|
8
|
-
"scripts": {
|
|
9
|
-
|
|
10
|
-
},
|
|
11
|
-
"keywords": [
|
|
12
|
-
"reaper",
|
|
13
|
-
"games",
|
|
14
|
-
"html5",
|
|
15
|
-
"unblocked",
|
|
16
|
-
"arcade",
|
|
17
|
-
"keysystem",
|
|
18
|
-
"performance",
|
|
19
|
-
"leaderboard",
|
|
20
|
-
"dms"
|
|
21
|
-
],
|
|
8
|
+
"scripts": { "test": "node js/security-shield.js" },
|
|
9
|
+
"keywords": ["reaper","games","html5","unblocked","arcade","keysystem"],
|
|
22
10
|
"author": "asfsaf",
|
|
23
11
|
"license": "MIT",
|
|
24
|
-
"publishConfig": {
|
|
25
|
-
|
|
26
|
-
},
|
|
27
|
-
"files": [
|
|
28
|
-
"main",
|
|
29
|
-
"verify",
|
|
30
|
-
"css",
|
|
31
|
-
"js",
|
|
32
|
-
"index.html",
|
|
33
|
-
"games.json"
|
|
34
|
-
]
|
|
12
|
+
"publishConfig": { "access": "public" },
|
|
13
|
+
"files": ["main","verify","css","js","index.html","games.json"]
|
|
35
14
|
}
|