reaper-arcade-hub 1.0.2 → 1.0.4
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 +23 -27
- package/js/app.js +86 -74
- package/js/security-shield.js +9 -0
- package/main/index.html +23 -27
- package/main/js/app.js +86 -74
- package/main/js/security-shield.js +9 -0
- package/package.json +1 -1
- package/verify/js/security-shield.js +9 -0
package/index.html
CHANGED
|
@@ -173,20 +173,14 @@
|
|
|
173
173
|
<input type="text" id="opium-search-input" class="opium-search-input" placeholder="Search 780+ games or topics..." autocomplete="off" onkeydown="if(event.key==='Enter') app.handleOpiumSearch()">
|
|
174
174
|
</div>
|
|
175
175
|
|
|
176
|
-
<!-- Quick Navigation Tiles
|
|
177
|
-
<div style="display: flex; gap: 0.85rem; flex-wrap: wrap; justify-content: center; max-width:
|
|
176
|
+
<!-- Quick Navigation Tiles -->
|
|
177
|
+
<div style="display: flex; gap: 0.85rem; flex-wrap: wrap; justify-content: center; max-width: 580px; margin-bottom: 1.25rem;">
|
|
178
178
|
<button class="btn-primary" style="padding: 0.75rem 1.4rem; font-size: 0.88rem;" onclick="app.switchTab('games')">
|
|
179
179
|
BROWSE 788 GAMES
|
|
180
180
|
</button>
|
|
181
181
|
<button class="btn-stealth" style="padding: 0.75rem 1.4rem; font-size: 0.88rem;" onclick="app.switchTab('leaderboard')">
|
|
182
182
|
PLAYTIME LEADERBOARD
|
|
183
183
|
</button>
|
|
184
|
-
<button class="btn-stealth" style="padding: 0.75rem 1.4rem; font-size: 0.88rem; color: #00ffaa; border-color: rgba(0,255,170,0.3);" onclick="app.exportSaveData()" title="Backup your game saves">
|
|
185
|
-
💾 BACKUP SAVES
|
|
186
|
-
</button>
|
|
187
|
-
<button class="btn-stealth" style="padding: 0.75rem 1.4rem; font-size: 0.88rem; color: #ffd700; border-color: rgba(255,215,0,0.3);" onclick="app.importSaveData()" title="Restore game save data">
|
|
188
|
-
📥 RESTORE SAVES
|
|
189
|
-
</button>
|
|
190
184
|
</div>
|
|
191
185
|
</div>
|
|
192
186
|
</section>
|
|
@@ -604,7 +598,6 @@
|
|
|
604
598
|
<div style="display: flex; border-bottom: 1px solid var(--blue-border); background: #030a18; padding: 0.5rem 1.4rem; gap: 0.5rem; overflow-x: auto;">
|
|
605
599
|
<button class="nav-tab-btn active" id="st-tab-btn-shield" onclick="app.switchSettingsTab('shield')" style="padding: 0.45rem 1rem; font-size: 0.82rem;">🛡️ Security Shield</button>
|
|
606
600
|
<button class="nav-tab-btn" id="st-tab-btn-prefs" onclick="app.switchSettingsTab('prefs')" style="padding: 0.45rem 1rem; font-size: 0.82rem;">⚡ Preferences & Audio</button>
|
|
607
|
-
<button class="nav-tab-btn" id="st-tab-btn-saves" onclick="app.switchSettingsTab('saves')" style="padding: 0.45rem 1rem; font-size: 0.82rem;">💾 Game Saves</button>
|
|
608
601
|
<button class="nav-tab-btn" id="st-tab-btn-identity" onclick="app.switchSettingsTab('identity')" style="padding: 0.45rem 1rem; font-size: 0.82rem;">🔑 Device & Rank</button>
|
|
609
602
|
</div>
|
|
610
603
|
|
|
@@ -659,6 +652,26 @@
|
|
|
659
652
|
<!-- SUBTAB 2: PREFERENCES & AUDIO -->
|
|
660
653
|
<div id="st-content-prefs" style="display: none;">
|
|
661
654
|
<div style="display: flex; flex-direction: column; gap: 1.2rem;">
|
|
655
|
+
|
|
656
|
+
<!-- Auto about:blank toggle -->
|
|
657
|
+
<div style="background: #040e1e; border: 1px solid var(--blue-border); padding: 1rem 1.25rem; border-radius: 8px; display: flex; justify-content: space-between; align-items: center;">
|
|
658
|
+
<div>
|
|
659
|
+
<strong style="color: #fff; font-size: 0.95rem;">🌐 Auto-Cloak in about:blank on Visit</strong>
|
|
660
|
+
<p style="color: #88aacc; font-size: 0.8rem;">Automatically opens Reaper Hub in an undetectable about:blank tab every time you visit.</p>
|
|
661
|
+
</div>
|
|
662
|
+
<input type="checkbox" id="auto-aboutblank-toggle" style="width: 22px; height: 22px; cursor: pointer; accent-color: #00d2ff;" onchange="app.toggleAutoAboutBlank(this.checked)">
|
|
663
|
+
</div>
|
|
664
|
+
|
|
665
|
+
<!-- Launch in about:blank button -->
|
|
666
|
+
<div style="background: #040e1e; border: 1px solid var(--blue-border); padding: 1rem 1.25rem; border-radius: 8px; display: flex; justify-content: space-between; align-items: center;">
|
|
667
|
+
<div>
|
|
668
|
+
<strong style="color: #00d2ff; font-size: 0.95rem;">🚀 Launch Site in about:blank Tab</strong>
|
|
669
|
+
<p style="color: #88aacc; font-size: 0.8rem;">Spawn this entire portal inside a clean Google Classroom disguised about:blank window.</p>
|
|
670
|
+
</div>
|
|
671
|
+
<button class="btn-primary" onclick="app.openSiteAboutBlank()" style="font-size: 0.82rem; padding: 0.5rem 1.2rem;">LAUNCH CLOAK</button>
|
|
672
|
+
</div>
|
|
673
|
+
|
|
674
|
+
<!-- SFX toggle -->
|
|
662
675
|
<div style="background: #040e1e; border: 1px solid var(--blue-border); padding: 1rem 1.25rem; border-radius: 8px; display: flex; justify-content: space-between; align-items: center;">
|
|
663
676
|
<div>
|
|
664
677
|
<strong style="color: #fff; font-size: 0.95rem;">🔊 Sci-Fi Synthesizer Sound FX</strong>
|
|
@@ -676,24 +689,7 @@
|
|
|
676
689
|
</div>
|
|
677
690
|
</div>
|
|
678
691
|
|
|
679
|
-
<!-- SUBTAB 3:
|
|
680
|
-
<div id="st-content-saves" style="display: none;">
|
|
681
|
-
<div style="display: flex; flex-direction: column; gap: 1.2rem;">
|
|
682
|
-
<div style="background: #040e1e; border: 1px solid var(--blue-border); padding: 1rem 1.25rem; border-radius: 8px;">
|
|
683
|
-
<strong style="color: #00ffaa; font-size: 0.95rem;">💾 Export & Backup Game Save Data</strong>
|
|
684
|
-
<p style="color: #88aacc; font-size: 0.8rem; margin: 0.4rem 0 0.85rem 0;">Download a single backup file containing all your local progress for Slope, Subway Surfers, BitLife, Retro Bowl, 1v1.LOL, and more.</p>
|
|
685
|
-
<button class="btn-primary" onclick="app.exportSaveData()" style="background: #00ffaa; color: #000; border-color: #00ffaa; font-size: 0.82rem;">💾 DOWNLOAD SAVE BACKUP</button>
|
|
686
|
-
</div>
|
|
687
|
-
|
|
688
|
-
<div style="background: #040e1e; border: 1px solid var(--blue-border); padding: 1rem 1.25rem; border-radius: 8px;">
|
|
689
|
-
<strong style="color: #ffd700; font-size: 0.95rem;">📥 Import & Restore Game Save Data</strong>
|
|
690
|
-
<p style="color: #88aacc; font-size: 0.8rem; margin: 0.4rem 0 0.85rem 0;">Upload a previously downloaded JSON save backup file to restore all your game saves instantly.</p>
|
|
691
|
-
<button class="btn-primary" onclick="app.importSaveData()" style="background: #ffd700; color: #000; border-color: #ffd700; font-size: 0.82rem;">📥 RESTORE SAVE BACKUP</button>
|
|
692
|
-
</div>
|
|
693
|
-
</div>
|
|
694
|
-
</div>
|
|
695
|
-
|
|
696
|
-
<!-- SUBTAB 4: IDENTITY & HWID -->
|
|
692
|
+
<!-- SUBTAB 3: IDENTITY & HWID -->
|
|
697
693
|
<div id="st-content-identity" style="display: none;">
|
|
698
694
|
<div style="display: flex; flex-direction: column; gap: 1rem;">
|
|
699
695
|
<div style="background: #040e1e; border: 1px solid var(--blue-border); padding: 1rem 1.25rem; border-radius: 8px;">
|
package/js/app.js
CHANGED
|
@@ -179,6 +179,18 @@ class ReaperHubApp {
|
|
|
179
179
|
|
|
180
180
|
this.syncPlaytimeToDB();
|
|
181
181
|
|
|
182
|
+
// 10. Auto about:blank Cloak on Visit Check
|
|
183
|
+
const isAutoAboutBlank = localStorage.getItem('reaper_auto_about_blank') === 'true';
|
|
184
|
+
const autoBlankToggle = document.getElementById('auto-aboutblank-toggle');
|
|
185
|
+
if (autoBlankToggle) autoBlankToggle.checked = isAutoAboutBlank;
|
|
186
|
+
|
|
187
|
+
if (isAutoAboutBlank && window.self === window.top && !window.location.protocol.includes('about:')) {
|
|
188
|
+
if (sessionStorage.getItem('reaper_cloaked_session') !== 'true') {
|
|
189
|
+
sessionStorage.setItem('reaper_cloaked_session', 'true');
|
|
190
|
+
this.openSiteAboutBlank();
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
182
194
|
console.log(`[REAPER HUB] System Online. Role: ${this.currentUser.rank.toUpperCase()}`);
|
|
183
195
|
}
|
|
184
196
|
|
|
@@ -949,7 +961,7 @@ class ReaperHubApp {
|
|
|
949
961
|
localStorage.setItem('reaper_playtime_' + this.currentUser.username, this.playtimeSeconds.toString());
|
|
950
962
|
this.updatePlaytimeStatusUI();
|
|
951
963
|
|
|
952
|
-
if (this.playtimeSeconds %
|
|
964
|
+
if (this.playtimeSeconds % 5 === 0) {
|
|
953
965
|
this.syncPlaytimeToDB();
|
|
954
966
|
}
|
|
955
967
|
}
|
|
@@ -1366,47 +1378,6 @@ class ReaperHubApp {
|
|
|
1366
1378
|
this.showToast("Recently played list cleared.");
|
|
1367
1379
|
}
|
|
1368
1380
|
|
|
1369
|
-
exportSaveData() {
|
|
1370
|
-
const backup = {};
|
|
1371
|
-
for (let i = 0; i < localStorage.length; i++) {
|
|
1372
|
-
const key = localStorage.key(i);
|
|
1373
|
-
backup[key] = localStorage.getItem(key);
|
|
1374
|
-
}
|
|
1375
|
-
const blob = new Blob([JSON.stringify(backup, null, 2)], { type: 'application/json' });
|
|
1376
|
-
const url = URL.createObjectURL(blob);
|
|
1377
|
-
const a = document.createElement('a');
|
|
1378
|
-
a.href = url;
|
|
1379
|
-
a.download = `reaper_save_backup_${new Date().toISOString().slice(0,10)}.json`;
|
|
1380
|
-
a.click();
|
|
1381
|
-
URL.revokeObjectURL(url);
|
|
1382
|
-
this.showToast("Game save data downloaded! 💾");
|
|
1383
|
-
}
|
|
1384
|
-
|
|
1385
|
-
importSaveData() {
|
|
1386
|
-
const input = document.createElement('input');
|
|
1387
|
-
input.type = 'file';
|
|
1388
|
-
input.accept = '.json';
|
|
1389
|
-
input.onchange = (e) => {
|
|
1390
|
-
const file = e.target.files[0];
|
|
1391
|
-
if (!file) return;
|
|
1392
|
-
const reader = new FileReader();
|
|
1393
|
-
reader.onload = (event) => {
|
|
1394
|
-
try {
|
|
1395
|
-
const data = JSON.parse(event.target.result);
|
|
1396
|
-
Object.entries(data).forEach(([k, v]) => {
|
|
1397
|
-
localStorage.setItem(k, v);
|
|
1398
|
-
});
|
|
1399
|
-
this.showToast("Save data restored! Reloading...");
|
|
1400
|
-
setTimeout(() => window.location.reload(), 1200);
|
|
1401
|
-
} catch (err) {
|
|
1402
|
-
alert("Invalid backup file.");
|
|
1403
|
-
}
|
|
1404
|
-
};
|
|
1405
|
-
reader.readAsText(file);
|
|
1406
|
-
};
|
|
1407
|
-
input.click();
|
|
1408
|
-
}
|
|
1409
|
-
|
|
1410
1381
|
toggleSoundFX() {
|
|
1411
1382
|
if (window.reaperSFX) {
|
|
1412
1383
|
const enabled = window.reaperSFX.toggleSound();
|
|
@@ -1525,55 +1496,96 @@ class ReaperHubApp {
|
|
|
1525
1496
|
async openGameAboutBlank() {
|
|
1526
1497
|
if (!this.currentGame) return;
|
|
1527
1498
|
const filename = this.currentGame.url.split('/').pop();
|
|
1499
|
+
const gameName = this.currentGame.name;
|
|
1500
|
+
const siteUrl = window.location.href;
|
|
1528
1501
|
const win = window.open('about:blank', '_blank');
|
|
1529
1502
|
if (win) {
|
|
1530
1503
|
const doc = win.document;
|
|
1531
|
-
doc.title = "Google Classroom";
|
|
1532
|
-
const link = doc.createElement('link');
|
|
1533
|
-
link.rel = 'icon';
|
|
1534
|
-
link.href = 'https://ssl.gstatic.com/classroom/favicon.png';
|
|
1535
|
-
doc.head.appendChild(link);
|
|
1536
|
-
|
|
1537
|
-
const frame = doc.createElement('iframe');
|
|
1538
|
-
frame.style.border = 'none';
|
|
1539
|
-
frame.style.width = '100vw';
|
|
1540
|
-
frame.style.height = '100vh';
|
|
1541
|
-
frame.style.margin = '0';
|
|
1542
|
-
frame.style.position = 'fixed';
|
|
1543
|
-
frame.style.top = '0';
|
|
1544
|
-
frame.style.left = '0';
|
|
1545
|
-
frame.allow = 'autoplay; fullscreen; gamepad';
|
|
1504
|
+
doc.title = "Home - Google Classroom";
|
|
1546
1505
|
|
|
1506
|
+
let gameHtml = '';
|
|
1547
1507
|
try {
|
|
1548
1508
|
const res = await fetch(`https://raw.githubusercontent.com/gn-math/html/main/${filename}`);
|
|
1549
1509
|
if (res.ok) {
|
|
1550
|
-
|
|
1551
|
-
if (
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
frame.srcdoc = html;
|
|
1555
|
-
} else {
|
|
1556
|
-
frame.src = `https://fastly.jsdelivr.net/gh/gn-math/html@main/${filename}`;
|
|
1510
|
+
gameHtml = await res.text();
|
|
1511
|
+
if (gameHtml && gameHtml.length > 50) {
|
|
1512
|
+
gameHtml = gameHtml.replace(/https?:\/\/cdn\.jsdelivr\.net\/gh\//g, 'https://fastly.jsdelivr.net/gh/');
|
|
1513
|
+
gameHtml = gameHtml.replace(/https?:\/\/cdn\.jsdelivr\.net\/npm\//g, 'https://fastly.jsdelivr.net/npm/');
|
|
1557
1514
|
}
|
|
1558
|
-
} else {
|
|
1559
|
-
frame.src = `https://fastly.jsdelivr.net/gh/gn-math/html@main/${filename}`;
|
|
1560
1515
|
}
|
|
1561
|
-
} catch (e) {
|
|
1562
|
-
|
|
1516
|
+
} catch (e) {}
|
|
1517
|
+
|
|
1518
|
+
doc.open();
|
|
1519
|
+
doc.write(`
|
|
1520
|
+
<!DOCTYPE html>
|
|
1521
|
+
<html>
|
|
1522
|
+
<head>
|
|
1523
|
+
<title>Home - Google Classroom</title>
|
|
1524
|
+
<link rel="icon" href="https://ssl.gstatic.com/classroom/favicon.png">
|
|
1525
|
+
<style>
|
|
1526
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
1527
|
+
body { background: #000; overflow: hidden; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
|
|
1528
|
+
#game-frame { width: 100vw; height: 100vh; border: none; position: fixed; top: 0; left: 0; z-index: 1; }
|
|
1529
|
+
.reaper-bar {
|
|
1530
|
+
position: fixed; top: 12px; left: 14px; z-index: 9999;
|
|
1531
|
+
display: flex; gap: 8px; align-items: center;
|
|
1532
|
+
background: rgba(3, 8, 18, 0.88); backdrop-filter: blur(8px);
|
|
1533
|
+
border: 1.5px solid rgba(0, 136, 255, 0.4); border-radius: 8px; padding: 6px 12px;
|
|
1534
|
+
box-shadow: 0 4px 20px rgba(0,0,0,0.7);
|
|
1535
|
+
opacity: 0.85; transition: opacity 0.2s ease, border-color 0.2s ease;
|
|
1536
|
+
}
|
|
1537
|
+
.reaper-bar:hover { opacity: 1; border-color: #00d2ff; }
|
|
1538
|
+
.btn-action {
|
|
1539
|
+
background: #041022; color: #00d2ff; border: 1px solid rgba(0, 136, 255, 0.4);
|
|
1540
|
+
padding: 5px 12px; border-radius: 6px; font-size: 11px; font-weight: 800;
|
|
1541
|
+
cursor: pointer; text-decoration: none; display: inline-flex; align-items: center; gap: 4px;
|
|
1542
|
+
transition: all 0.2s ease; font-family: inherit;
|
|
1543
|
+
}
|
|
1544
|
+
.btn-action:hover { background: #0088ff; color: #fff; box-shadow: 0 0 10px rgba(0,136,255,0.6); }
|
|
1545
|
+
.reaper-watermark {
|
|
1546
|
+
position: fixed; bottom: 10px; right: 14px; z-index: 9999;
|
|
1547
|
+
font-family: serif; font-weight: 900; font-size: 13px; letter-spacing: 0.12em;
|
|
1548
|
+
color: rgba(255, 255, 255, 0.35); text-shadow: 0 0 10px rgba(0, 136, 255, 0.6);
|
|
1549
|
+
pointer-events: none; user-select: none;
|
|
1550
|
+
}
|
|
1551
|
+
</style>
|
|
1552
|
+
<script>
|
|
1553
|
+
// Client-Side Ad & Pop-up Blocker
|
|
1554
|
+
window.open = function() { console.log('[REAPER SHIELD] Ad pop-up blocked'); return null; };
|
|
1555
|
+
<\/script>
|
|
1556
|
+
</head>
|
|
1557
|
+
<body>
|
|
1558
|
+
<div class="reaper-bar">
|
|
1559
|
+
<a href="${siteUrl}" class="btn-action" title="Return to Reaper Hub Portal">⚡ BACK TO SITE</a>
|
|
1560
|
+
<button onclick="document.getElementById('game-frame').requestFullscreen()" class="btn-action">⛶ FULLSCREEN</button>
|
|
1561
|
+
<button onclick="document.getElementById('game-frame').contentWindow.location.reload()" class="btn-action">🔄 RELOAD</button>
|
|
1562
|
+
</div>
|
|
1563
|
+
<div class="reaper-watermark">REAPER HUB</div>
|
|
1564
|
+
<iframe id="game-frame" allow="autoplay; fullscreen; gamepad" ${gameHtml ? '' : `src="https://fastly.jsdelivr.net/gh/gn-math/html@main/${filename}"`}></iframe>
|
|
1565
|
+
</body>
|
|
1566
|
+
</html>
|
|
1567
|
+
`);
|
|
1568
|
+
doc.close();
|
|
1569
|
+
|
|
1570
|
+
if (gameHtml) {
|
|
1571
|
+
const f = doc.getElementById('game-frame');
|
|
1572
|
+
if (f) f.srcdoc = gameHtml;
|
|
1563
1573
|
}
|
|
1564
1574
|
|
|
1565
|
-
|
|
1566
|
-
doc.body.style.overflow = 'hidden';
|
|
1567
|
-
doc.body.appendChild(frame);
|
|
1568
|
-
this.showToast("Game launched in about:blank tab.");
|
|
1575
|
+
this.showToast("Game opened in about:blank tab with watermark & return controls.");
|
|
1569
1576
|
}
|
|
1570
1577
|
}
|
|
1571
1578
|
|
|
1579
|
+
toggleAutoAboutBlank(enabled) {
|
|
1580
|
+
localStorage.setItem('reaper_auto_about_blank', enabled ? 'true' : 'false');
|
|
1581
|
+
this.showToast(enabled ? "Auto about:blank cloak enabled on every visit." : "Auto about:blank disabled.");
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1572
1584
|
openSiteAboutBlank() {
|
|
1573
1585
|
const win = window.open('about:blank', '_blank');
|
|
1574
1586
|
if (win) {
|
|
1575
1587
|
const doc = win.document;
|
|
1576
|
-
doc.title = "
|
|
1588
|
+
doc.title = "Home - Google Classroom";
|
|
1577
1589
|
const link = doc.createElement('link');
|
|
1578
1590
|
link.rel = 'icon';
|
|
1579
1591
|
link.href = 'https://ssl.gstatic.com/classroom/favicon.png';
|
|
@@ -1977,7 +1989,7 @@ class ReaperHubApp {
|
|
|
1977
1989
|
}
|
|
1978
1990
|
|
|
1979
1991
|
switchSettingsTab(tabName) {
|
|
1980
|
-
['shield', 'prefs', '
|
|
1992
|
+
['shield', 'prefs', 'identity'].forEach(t => {
|
|
1981
1993
|
const btn = document.getElementById(`st-tab-btn-${t}`);
|
|
1982
1994
|
const content = document.getElementById(`st-content-${t}`);
|
|
1983
1995
|
if (btn) btn.classList.toggle('active', t === tabName);
|
package/js/security-shield.js
CHANGED
|
@@ -217,6 +217,15 @@
|
|
|
217
217
|
count++;
|
|
218
218
|
}
|
|
219
219
|
}
|
|
220
|
+
|
|
221
|
+
// Kill client-side third-party ad script injections & tracking pop-up tags
|
|
222
|
+
const adNodes = document.querySelectorAll('script[src*="googlesyndication"], script[src*="doubleclick"], script[src*="adnxs"], script[src*="monetag"], script[src*="popcash"], script[src*="propellerads"], div[class*="ad-banner" i], div[id*="ad-container" i]');
|
|
223
|
+
for (let i = 0; i < adNodes.length; i++) {
|
|
224
|
+
if (adNodes[i] && adNodes[i].parentNode) {
|
|
225
|
+
adNodes[i].parentNode.removeChild(adNodes[i]);
|
|
226
|
+
count++;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
220
229
|
} catch (e) {}
|
|
221
230
|
|
|
222
231
|
this.blockedCount += count;
|
package/main/index.html
CHANGED
|
@@ -173,20 +173,14 @@
|
|
|
173
173
|
<input type="text" id="opium-search-input" class="opium-search-input" placeholder="Search 780+ games or topics..." autocomplete="off" onkeydown="if(event.key==='Enter') app.handleOpiumSearch()">
|
|
174
174
|
</div>
|
|
175
175
|
|
|
176
|
-
<!-- Quick Navigation Tiles
|
|
177
|
-
<div style="display: flex; gap: 0.85rem; flex-wrap: wrap; justify-content: center; max-width:
|
|
176
|
+
<!-- Quick Navigation Tiles -->
|
|
177
|
+
<div style="display: flex; gap: 0.85rem; flex-wrap: wrap; justify-content: center; max-width: 580px; margin-bottom: 1.25rem;">
|
|
178
178
|
<button class="btn-primary" style="padding: 0.75rem 1.4rem; font-size: 0.88rem;" onclick="app.switchTab('games')">
|
|
179
179
|
BROWSE 788 GAMES
|
|
180
180
|
</button>
|
|
181
181
|
<button class="btn-stealth" style="padding: 0.75rem 1.4rem; font-size: 0.88rem;" onclick="app.switchTab('leaderboard')">
|
|
182
182
|
PLAYTIME LEADERBOARD
|
|
183
183
|
</button>
|
|
184
|
-
<button class="btn-stealth" style="padding: 0.75rem 1.4rem; font-size: 0.88rem; color: #00ffaa; border-color: rgba(0,255,170,0.3);" onclick="app.exportSaveData()" title="Backup your game saves">
|
|
185
|
-
💾 BACKUP SAVES
|
|
186
|
-
</button>
|
|
187
|
-
<button class="btn-stealth" style="padding: 0.75rem 1.4rem; font-size: 0.88rem; color: #ffd700; border-color: rgba(255,215,0,0.3);" onclick="app.importSaveData()" title="Restore game save data">
|
|
188
|
-
📥 RESTORE SAVES
|
|
189
|
-
</button>
|
|
190
184
|
</div>
|
|
191
185
|
</div>
|
|
192
186
|
</section>
|
|
@@ -604,7 +598,6 @@
|
|
|
604
598
|
<div style="display: flex; border-bottom: 1px solid var(--blue-border); background: #030a18; padding: 0.5rem 1.4rem; gap: 0.5rem; overflow-x: auto;">
|
|
605
599
|
<button class="nav-tab-btn active" id="st-tab-btn-shield" onclick="app.switchSettingsTab('shield')" style="padding: 0.45rem 1rem; font-size: 0.82rem;">🛡️ Security Shield</button>
|
|
606
600
|
<button class="nav-tab-btn" id="st-tab-btn-prefs" onclick="app.switchSettingsTab('prefs')" style="padding: 0.45rem 1rem; font-size: 0.82rem;">⚡ Preferences & Audio</button>
|
|
607
|
-
<button class="nav-tab-btn" id="st-tab-btn-saves" onclick="app.switchSettingsTab('saves')" style="padding: 0.45rem 1rem; font-size: 0.82rem;">💾 Game Saves</button>
|
|
608
601
|
<button class="nav-tab-btn" id="st-tab-btn-identity" onclick="app.switchSettingsTab('identity')" style="padding: 0.45rem 1rem; font-size: 0.82rem;">🔑 Device & Rank</button>
|
|
609
602
|
</div>
|
|
610
603
|
|
|
@@ -659,6 +652,26 @@
|
|
|
659
652
|
<!-- SUBTAB 2: PREFERENCES & AUDIO -->
|
|
660
653
|
<div id="st-content-prefs" style="display: none;">
|
|
661
654
|
<div style="display: flex; flex-direction: column; gap: 1.2rem;">
|
|
655
|
+
|
|
656
|
+
<!-- Auto about:blank toggle -->
|
|
657
|
+
<div style="background: #040e1e; border: 1px solid var(--blue-border); padding: 1rem 1.25rem; border-radius: 8px; display: flex; justify-content: space-between; align-items: center;">
|
|
658
|
+
<div>
|
|
659
|
+
<strong style="color: #fff; font-size: 0.95rem;">🌐 Auto-Cloak in about:blank on Visit</strong>
|
|
660
|
+
<p style="color: #88aacc; font-size: 0.8rem;">Automatically opens Reaper Hub in an undetectable about:blank tab every time you visit.</p>
|
|
661
|
+
</div>
|
|
662
|
+
<input type="checkbox" id="auto-aboutblank-toggle" style="width: 22px; height: 22px; cursor: pointer; accent-color: #00d2ff;" onchange="app.toggleAutoAboutBlank(this.checked)">
|
|
663
|
+
</div>
|
|
664
|
+
|
|
665
|
+
<!-- Launch in about:blank button -->
|
|
666
|
+
<div style="background: #040e1e; border: 1px solid var(--blue-border); padding: 1rem 1.25rem; border-radius: 8px; display: flex; justify-content: space-between; align-items: center;">
|
|
667
|
+
<div>
|
|
668
|
+
<strong style="color: #00d2ff; font-size: 0.95rem;">🚀 Launch Site in about:blank Tab</strong>
|
|
669
|
+
<p style="color: #88aacc; font-size: 0.8rem;">Spawn this entire portal inside a clean Google Classroom disguised about:blank window.</p>
|
|
670
|
+
</div>
|
|
671
|
+
<button class="btn-primary" onclick="app.openSiteAboutBlank()" style="font-size: 0.82rem; padding: 0.5rem 1.2rem;">LAUNCH CLOAK</button>
|
|
672
|
+
</div>
|
|
673
|
+
|
|
674
|
+
<!-- SFX toggle -->
|
|
662
675
|
<div style="background: #040e1e; border: 1px solid var(--blue-border); padding: 1rem 1.25rem; border-radius: 8px; display: flex; justify-content: space-between; align-items: center;">
|
|
663
676
|
<div>
|
|
664
677
|
<strong style="color: #fff; font-size: 0.95rem;">🔊 Sci-Fi Synthesizer Sound FX</strong>
|
|
@@ -676,24 +689,7 @@
|
|
|
676
689
|
</div>
|
|
677
690
|
</div>
|
|
678
691
|
|
|
679
|
-
<!-- SUBTAB 3:
|
|
680
|
-
<div id="st-content-saves" style="display: none;">
|
|
681
|
-
<div style="display: flex; flex-direction: column; gap: 1.2rem;">
|
|
682
|
-
<div style="background: #040e1e; border: 1px solid var(--blue-border); padding: 1rem 1.25rem; border-radius: 8px;">
|
|
683
|
-
<strong style="color: #00ffaa; font-size: 0.95rem;">💾 Export & Backup Game Save Data</strong>
|
|
684
|
-
<p style="color: #88aacc; font-size: 0.8rem; margin: 0.4rem 0 0.85rem 0;">Download a single backup file containing all your local progress for Slope, Subway Surfers, BitLife, Retro Bowl, 1v1.LOL, and more.</p>
|
|
685
|
-
<button class="btn-primary" onclick="app.exportSaveData()" style="background: #00ffaa; color: #000; border-color: #00ffaa; font-size: 0.82rem;">💾 DOWNLOAD SAVE BACKUP</button>
|
|
686
|
-
</div>
|
|
687
|
-
|
|
688
|
-
<div style="background: #040e1e; border: 1px solid var(--blue-border); padding: 1rem 1.25rem; border-radius: 8px;">
|
|
689
|
-
<strong style="color: #ffd700; font-size: 0.95rem;">📥 Import & Restore Game Save Data</strong>
|
|
690
|
-
<p style="color: #88aacc; font-size: 0.8rem; margin: 0.4rem 0 0.85rem 0;">Upload a previously downloaded JSON save backup file to restore all your game saves instantly.</p>
|
|
691
|
-
<button class="btn-primary" onclick="app.importSaveData()" style="background: #ffd700; color: #000; border-color: #ffd700; font-size: 0.82rem;">📥 RESTORE SAVE BACKUP</button>
|
|
692
|
-
</div>
|
|
693
|
-
</div>
|
|
694
|
-
</div>
|
|
695
|
-
|
|
696
|
-
<!-- SUBTAB 4: IDENTITY & HWID -->
|
|
692
|
+
<!-- SUBTAB 3: IDENTITY & HWID -->
|
|
697
693
|
<div id="st-content-identity" style="display: none;">
|
|
698
694
|
<div style="display: flex; flex-direction: column; gap: 1rem;">
|
|
699
695
|
<div style="background: #040e1e; border: 1px solid var(--blue-border); padding: 1rem 1.25rem; border-radius: 8px;">
|
package/main/js/app.js
CHANGED
|
@@ -179,6 +179,18 @@ class ReaperHubApp {
|
|
|
179
179
|
|
|
180
180
|
this.syncPlaytimeToDB();
|
|
181
181
|
|
|
182
|
+
// 10. Auto about:blank Cloak on Visit Check
|
|
183
|
+
const isAutoAboutBlank = localStorage.getItem('reaper_auto_about_blank') === 'true';
|
|
184
|
+
const autoBlankToggle = document.getElementById('auto-aboutblank-toggle');
|
|
185
|
+
if (autoBlankToggle) autoBlankToggle.checked = isAutoAboutBlank;
|
|
186
|
+
|
|
187
|
+
if (isAutoAboutBlank && window.self === window.top && !window.location.protocol.includes('about:')) {
|
|
188
|
+
if (sessionStorage.getItem('reaper_cloaked_session') !== 'true') {
|
|
189
|
+
sessionStorage.setItem('reaper_cloaked_session', 'true');
|
|
190
|
+
this.openSiteAboutBlank();
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
182
194
|
console.log(`[REAPER HUB] System Online. Role: ${this.currentUser.rank.toUpperCase()}`);
|
|
183
195
|
}
|
|
184
196
|
|
|
@@ -949,7 +961,7 @@ class ReaperHubApp {
|
|
|
949
961
|
localStorage.setItem('reaper_playtime_' + this.currentUser.username, this.playtimeSeconds.toString());
|
|
950
962
|
this.updatePlaytimeStatusUI();
|
|
951
963
|
|
|
952
|
-
if (this.playtimeSeconds %
|
|
964
|
+
if (this.playtimeSeconds % 5 === 0) {
|
|
953
965
|
this.syncPlaytimeToDB();
|
|
954
966
|
}
|
|
955
967
|
}
|
|
@@ -1366,47 +1378,6 @@ class ReaperHubApp {
|
|
|
1366
1378
|
this.showToast("Recently played list cleared.");
|
|
1367
1379
|
}
|
|
1368
1380
|
|
|
1369
|
-
exportSaveData() {
|
|
1370
|
-
const backup = {};
|
|
1371
|
-
for (let i = 0; i < localStorage.length; i++) {
|
|
1372
|
-
const key = localStorage.key(i);
|
|
1373
|
-
backup[key] = localStorage.getItem(key);
|
|
1374
|
-
}
|
|
1375
|
-
const blob = new Blob([JSON.stringify(backup, null, 2)], { type: 'application/json' });
|
|
1376
|
-
const url = URL.createObjectURL(blob);
|
|
1377
|
-
const a = document.createElement('a');
|
|
1378
|
-
a.href = url;
|
|
1379
|
-
a.download = `reaper_save_backup_${new Date().toISOString().slice(0,10)}.json`;
|
|
1380
|
-
a.click();
|
|
1381
|
-
URL.revokeObjectURL(url);
|
|
1382
|
-
this.showToast("Game save data downloaded! 💾");
|
|
1383
|
-
}
|
|
1384
|
-
|
|
1385
|
-
importSaveData() {
|
|
1386
|
-
const input = document.createElement('input');
|
|
1387
|
-
input.type = 'file';
|
|
1388
|
-
input.accept = '.json';
|
|
1389
|
-
input.onchange = (e) => {
|
|
1390
|
-
const file = e.target.files[0];
|
|
1391
|
-
if (!file) return;
|
|
1392
|
-
const reader = new FileReader();
|
|
1393
|
-
reader.onload = (event) => {
|
|
1394
|
-
try {
|
|
1395
|
-
const data = JSON.parse(event.target.result);
|
|
1396
|
-
Object.entries(data).forEach(([k, v]) => {
|
|
1397
|
-
localStorage.setItem(k, v);
|
|
1398
|
-
});
|
|
1399
|
-
this.showToast("Save data restored! Reloading...");
|
|
1400
|
-
setTimeout(() => window.location.reload(), 1200);
|
|
1401
|
-
} catch (err) {
|
|
1402
|
-
alert("Invalid backup file.");
|
|
1403
|
-
}
|
|
1404
|
-
};
|
|
1405
|
-
reader.readAsText(file);
|
|
1406
|
-
};
|
|
1407
|
-
input.click();
|
|
1408
|
-
}
|
|
1409
|
-
|
|
1410
1381
|
toggleSoundFX() {
|
|
1411
1382
|
if (window.reaperSFX) {
|
|
1412
1383
|
const enabled = window.reaperSFX.toggleSound();
|
|
@@ -1525,55 +1496,96 @@ class ReaperHubApp {
|
|
|
1525
1496
|
async openGameAboutBlank() {
|
|
1526
1497
|
if (!this.currentGame) return;
|
|
1527
1498
|
const filename = this.currentGame.url.split('/').pop();
|
|
1499
|
+
const gameName = this.currentGame.name;
|
|
1500
|
+
const siteUrl = window.location.href;
|
|
1528
1501
|
const win = window.open('about:blank', '_blank');
|
|
1529
1502
|
if (win) {
|
|
1530
1503
|
const doc = win.document;
|
|
1531
|
-
doc.title = "Google Classroom";
|
|
1532
|
-
const link = doc.createElement('link');
|
|
1533
|
-
link.rel = 'icon';
|
|
1534
|
-
link.href = 'https://ssl.gstatic.com/classroom/favicon.png';
|
|
1535
|
-
doc.head.appendChild(link);
|
|
1536
|
-
|
|
1537
|
-
const frame = doc.createElement('iframe');
|
|
1538
|
-
frame.style.border = 'none';
|
|
1539
|
-
frame.style.width = '100vw';
|
|
1540
|
-
frame.style.height = '100vh';
|
|
1541
|
-
frame.style.margin = '0';
|
|
1542
|
-
frame.style.position = 'fixed';
|
|
1543
|
-
frame.style.top = '0';
|
|
1544
|
-
frame.style.left = '0';
|
|
1545
|
-
frame.allow = 'autoplay; fullscreen; gamepad';
|
|
1504
|
+
doc.title = "Home - Google Classroom";
|
|
1546
1505
|
|
|
1506
|
+
let gameHtml = '';
|
|
1547
1507
|
try {
|
|
1548
1508
|
const res = await fetch(`https://raw.githubusercontent.com/gn-math/html/main/${filename}`);
|
|
1549
1509
|
if (res.ok) {
|
|
1550
|
-
|
|
1551
|
-
if (
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
frame.srcdoc = html;
|
|
1555
|
-
} else {
|
|
1556
|
-
frame.src = `https://fastly.jsdelivr.net/gh/gn-math/html@main/${filename}`;
|
|
1510
|
+
gameHtml = await res.text();
|
|
1511
|
+
if (gameHtml && gameHtml.length > 50) {
|
|
1512
|
+
gameHtml = gameHtml.replace(/https?:\/\/cdn\.jsdelivr\.net\/gh\//g, 'https://fastly.jsdelivr.net/gh/');
|
|
1513
|
+
gameHtml = gameHtml.replace(/https?:\/\/cdn\.jsdelivr\.net\/npm\//g, 'https://fastly.jsdelivr.net/npm/');
|
|
1557
1514
|
}
|
|
1558
|
-
} else {
|
|
1559
|
-
frame.src = `https://fastly.jsdelivr.net/gh/gn-math/html@main/${filename}`;
|
|
1560
1515
|
}
|
|
1561
|
-
} catch (e) {
|
|
1562
|
-
|
|
1516
|
+
} catch (e) {}
|
|
1517
|
+
|
|
1518
|
+
doc.open();
|
|
1519
|
+
doc.write(`
|
|
1520
|
+
<!DOCTYPE html>
|
|
1521
|
+
<html>
|
|
1522
|
+
<head>
|
|
1523
|
+
<title>Home - Google Classroom</title>
|
|
1524
|
+
<link rel="icon" href="https://ssl.gstatic.com/classroom/favicon.png">
|
|
1525
|
+
<style>
|
|
1526
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
1527
|
+
body { background: #000; overflow: hidden; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
|
|
1528
|
+
#game-frame { width: 100vw; height: 100vh; border: none; position: fixed; top: 0; left: 0; z-index: 1; }
|
|
1529
|
+
.reaper-bar {
|
|
1530
|
+
position: fixed; top: 12px; left: 14px; z-index: 9999;
|
|
1531
|
+
display: flex; gap: 8px; align-items: center;
|
|
1532
|
+
background: rgba(3, 8, 18, 0.88); backdrop-filter: blur(8px);
|
|
1533
|
+
border: 1.5px solid rgba(0, 136, 255, 0.4); border-radius: 8px; padding: 6px 12px;
|
|
1534
|
+
box-shadow: 0 4px 20px rgba(0,0,0,0.7);
|
|
1535
|
+
opacity: 0.85; transition: opacity 0.2s ease, border-color 0.2s ease;
|
|
1536
|
+
}
|
|
1537
|
+
.reaper-bar:hover { opacity: 1; border-color: #00d2ff; }
|
|
1538
|
+
.btn-action {
|
|
1539
|
+
background: #041022; color: #00d2ff; border: 1px solid rgba(0, 136, 255, 0.4);
|
|
1540
|
+
padding: 5px 12px; border-radius: 6px; font-size: 11px; font-weight: 800;
|
|
1541
|
+
cursor: pointer; text-decoration: none; display: inline-flex; align-items: center; gap: 4px;
|
|
1542
|
+
transition: all 0.2s ease; font-family: inherit;
|
|
1543
|
+
}
|
|
1544
|
+
.btn-action:hover { background: #0088ff; color: #fff; box-shadow: 0 0 10px rgba(0,136,255,0.6); }
|
|
1545
|
+
.reaper-watermark {
|
|
1546
|
+
position: fixed; bottom: 10px; right: 14px; z-index: 9999;
|
|
1547
|
+
font-family: serif; font-weight: 900; font-size: 13px; letter-spacing: 0.12em;
|
|
1548
|
+
color: rgba(255, 255, 255, 0.35); text-shadow: 0 0 10px rgba(0, 136, 255, 0.6);
|
|
1549
|
+
pointer-events: none; user-select: none;
|
|
1550
|
+
}
|
|
1551
|
+
</style>
|
|
1552
|
+
<script>
|
|
1553
|
+
// Client-Side Ad & Pop-up Blocker
|
|
1554
|
+
window.open = function() { console.log('[REAPER SHIELD] Ad pop-up blocked'); return null; };
|
|
1555
|
+
<\/script>
|
|
1556
|
+
</head>
|
|
1557
|
+
<body>
|
|
1558
|
+
<div class="reaper-bar">
|
|
1559
|
+
<a href="${siteUrl}" class="btn-action" title="Return to Reaper Hub Portal">⚡ BACK TO SITE</a>
|
|
1560
|
+
<button onclick="document.getElementById('game-frame').requestFullscreen()" class="btn-action">⛶ FULLSCREEN</button>
|
|
1561
|
+
<button onclick="document.getElementById('game-frame').contentWindow.location.reload()" class="btn-action">🔄 RELOAD</button>
|
|
1562
|
+
</div>
|
|
1563
|
+
<div class="reaper-watermark">REAPER HUB</div>
|
|
1564
|
+
<iframe id="game-frame" allow="autoplay; fullscreen; gamepad" ${gameHtml ? '' : `src="https://fastly.jsdelivr.net/gh/gn-math/html@main/${filename}"`}></iframe>
|
|
1565
|
+
</body>
|
|
1566
|
+
</html>
|
|
1567
|
+
`);
|
|
1568
|
+
doc.close();
|
|
1569
|
+
|
|
1570
|
+
if (gameHtml) {
|
|
1571
|
+
const f = doc.getElementById('game-frame');
|
|
1572
|
+
if (f) f.srcdoc = gameHtml;
|
|
1563
1573
|
}
|
|
1564
1574
|
|
|
1565
|
-
|
|
1566
|
-
doc.body.style.overflow = 'hidden';
|
|
1567
|
-
doc.body.appendChild(frame);
|
|
1568
|
-
this.showToast("Game launched in about:blank tab.");
|
|
1575
|
+
this.showToast("Game opened in about:blank tab with watermark & return controls.");
|
|
1569
1576
|
}
|
|
1570
1577
|
}
|
|
1571
1578
|
|
|
1579
|
+
toggleAutoAboutBlank(enabled) {
|
|
1580
|
+
localStorage.setItem('reaper_auto_about_blank', enabled ? 'true' : 'false');
|
|
1581
|
+
this.showToast(enabled ? "Auto about:blank cloak enabled on every visit." : "Auto about:blank disabled.");
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1572
1584
|
openSiteAboutBlank() {
|
|
1573
1585
|
const win = window.open('about:blank', '_blank');
|
|
1574
1586
|
if (win) {
|
|
1575
1587
|
const doc = win.document;
|
|
1576
|
-
doc.title = "
|
|
1588
|
+
doc.title = "Home - Google Classroom";
|
|
1577
1589
|
const link = doc.createElement('link');
|
|
1578
1590
|
link.rel = 'icon';
|
|
1579
1591
|
link.href = 'https://ssl.gstatic.com/classroom/favicon.png';
|
|
@@ -1977,7 +1989,7 @@ class ReaperHubApp {
|
|
|
1977
1989
|
}
|
|
1978
1990
|
|
|
1979
1991
|
switchSettingsTab(tabName) {
|
|
1980
|
-
['shield', 'prefs', '
|
|
1992
|
+
['shield', 'prefs', 'identity'].forEach(t => {
|
|
1981
1993
|
const btn = document.getElementById(`st-tab-btn-${t}`);
|
|
1982
1994
|
const content = document.getElementById(`st-content-${t}`);
|
|
1983
1995
|
if (btn) btn.classList.toggle('active', t === tabName);
|
|
@@ -217,6 +217,15 @@
|
|
|
217
217
|
count++;
|
|
218
218
|
}
|
|
219
219
|
}
|
|
220
|
+
|
|
221
|
+
// Kill client-side third-party ad script injections & tracking pop-up tags
|
|
222
|
+
const adNodes = document.querySelectorAll('script[src*="googlesyndication"], script[src*="doubleclick"], script[src*="adnxs"], script[src*="monetag"], script[src*="popcash"], script[src*="propellerads"], div[class*="ad-banner" i], div[id*="ad-container" i]');
|
|
223
|
+
for (let i = 0; i < adNodes.length; i++) {
|
|
224
|
+
if (adNodes[i] && adNodes[i].parentNode) {
|
|
225
|
+
adNodes[i].parentNode.removeChild(adNodes[i]);
|
|
226
|
+
count++;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
220
229
|
} catch (e) {}
|
|
221
230
|
|
|
222
231
|
this.blockedCount += count;
|
package/package.json
CHANGED
|
@@ -217,6 +217,15 @@
|
|
|
217
217
|
count++;
|
|
218
218
|
}
|
|
219
219
|
}
|
|
220
|
+
|
|
221
|
+
// Kill client-side third-party ad script injections & tracking pop-up tags
|
|
222
|
+
const adNodes = document.querySelectorAll('script[src*="googlesyndication"], script[src*="doubleclick"], script[src*="adnxs"], script[src*="monetag"], script[src*="popcash"], script[src*="propellerads"], div[class*="ad-banner" i], div[id*="ad-container" i]');
|
|
223
|
+
for (let i = 0; i < adNodes.length; i++) {
|
|
224
|
+
if (adNodes[i] && adNodes[i].parentNode) {
|
|
225
|
+
adNodes[i].parentNode.removeChild(adNodes[i]);
|
|
226
|
+
count++;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
220
229
|
} catch (e) {}
|
|
221
230
|
|
|
222
231
|
this.blockedCount += count;
|