Skip to content

Commit 1741a8e

Browse files
committed
2.8.4
1 parent f1214a3 commit 1741a8e

26 files changed

+1487
-918
lines changed

.github/workflows/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"version": "2.8.3"}
1+
{"version": "2.8.4"}

api/linkvertise.js

Lines changed: 47 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,62 @@
11
const settings = require('../settings.json')
2+
const axios = require('axios');
3+
24

35
module.exports.load = async function (app, db) {
46

57
const lvcodes = {}
68
const cooldowns = {}
79

8-
app.get(`/lv/gen`, async (req, res) => {
10+
app.get('/lv/gen', async (req, res) => {
11+
const captcha = req.query['g-recaptcha-response'];
12+
if (!captcha) return res.send("Please complete the CAPTCHA first.");
13+
14+
const verifyURL = `https://www.google.com/recaptcha/api/siteverify?secret=${settings.recaptcha.secret}&response=${captcha}`;
15+
const { data } = await axios.post(verifyURL);
16+
17+
if (!data.success) {
18+
return res.send("CAPTCHA verification failed. Try again.");
19+
}
920
if (!req.session.pterodactyl) return res.redirect("/login");
10-
11-
if (cooldowns[req.session.userinfo.id] && cooldowns[req.session.userinfo.id] > Date.now()) {
12-
return res.redirect(`/lv`)
13-
} else if (cooldowns[req.session.userinfo.id]) {
14-
delete cooldowns[req.session.userinfo.id]
21+
22+
const userId = req.session.userinfo.id;
23+
const now = Date.now();
24+
25+
// Check if cooldown is still active
26+
if (cooldowns[userId] && cooldowns[userId] > now) {
27+
return res.redirect(`/lv`);
28+
} else {
29+
delete cooldowns[userId];
1530
}
16-
17-
const dailyTotal = await db.get(`dailylinkvertise-${req.session.userinfo.id}`)
31+
32+
// Check if daily limit has been reached
33+
const dailyTotal = await db.get(`dailylinkvertise-${userId}`);
1834
if (dailyTotal && dailyTotal >= settings.linkvertise.dailyLimit) {
19-
return res.redirect(`/lv?err=REACHEDDAILYLIMIT`)
35+
return res.redirect(`/lv?err=REACHEDDAILYLIMIT`);
2036
}
21-
22-
let referer = req.headers.referer
23-
if (!referer) return res.send('An error occured with your browser!')
24-
referer = referer.toLowerCase()
25-
if (referer.includes('?')) referer = referer.split('?')[0]
26-
if (!referer.endsWith(`/lv`) && !referer.endsWith(`/lv/`)) return res.send('An error occured with your browser!')
27-
if (!referer.endsWith(`/`)) referer += `/`
28-
29-
const code = makeid(12)
30-
const lvurl = linkvertise(settings.linkvertise.userid, referer + `redeem/${code}`)
31-
32-
lvcodes[req.session.userinfo.id] = {
33-
code: code,
34-
user: req.session.userinfo.id,
35-
generated: Date.now()
37+
38+
// Validate referer
39+
let referer = req.headers.referer;
40+
if (!referer) return res.send('An error occurred with your browser!');
41+
referer = referer.toLowerCase().split('?')[0];
42+
if (!referer.endsWith('/lv') && !referer.endsWith('/lv/')) {
43+
return res.send('An error occurred with your browser!');
3644
}
37-
38-
res.redirect(lvurl)
39-
})
45+
if (!referer.endsWith('/')) referer += '/';
46+
47+
// Generate link and store session code
48+
const code = makeid(12);
49+
const lvurl = linkvertise(settings.linkvertise.userid, referer + `redeem/${code}`);
50+
51+
lvcodes[userId] = {
52+
code,
53+
user: userId,
54+
generated: now
55+
};
56+
57+
return res.redirect(lvurl);
58+
});
59+
4060

4161
app.get(`/lv/redeem/:code`, async (req, res) => {
4262
if (!req.session.pterodactyl) return res.redirect("/");

api/store.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,17 @@ module.exports.load = async function(app, db) {
1010
let maxcpu = null;
1111
let maxservers = null;
1212
let maxdisk = null;
13-
app.get("/buyram", async (req, res) => {
13+
14+
// Middleware to check if user is logged in
15+
function requireLogin(req, res, next) {
16+
if (!req.session.userinfo || !req.session.userinfo.id) {
17+
let theme = indexjs.get(req);
18+
return res.redirect(theme.settings.redirect.notloggedin || "/login");
19+
}
20+
next();
21+
}
22+
23+
app.get("/buyram", requireLogin, async (req, res) => {
1424
let newsettings = await enabledCheck(req, res);
1525
if (newsettings) {
1626
let amount = req.query.amount;
@@ -74,7 +84,7 @@ module.exports.load = async function(app, db) {
7484
}
7585
});
7686

77-
app.get("/buydisk", async (req, res) => {
87+
app.get("/buydisk", requireLogin, async (req, res) => {
7888
let newsettings = await enabledCheck(req, res);
7989
if (newsettings) {
8090
let amount = req.query.amount;
@@ -138,7 +148,7 @@ module.exports.load = async function(app, db) {
138148
}
139149
});
140150

141-
app.get("/buycpu", async (req, res) => {
151+
app.get("/buycpu", requireLogin, async (req, res) => {
142152
let newsettings = await enabledCheck(req, res);
143153
if (newsettings) {
144154
let amount = req.query.amount;
@@ -202,7 +212,7 @@ module.exports.load = async function(app, db) {
202212
}
203213
});
204214

205-
app.get("/buyservers", async (req, res) => {
215+
app.get("/buyservers", requireLogin, async (req, res) => {
206216
let newsettings = await enabledCheck(req, res);
207217
if (newsettings) {
208218
let amount = req.query.amount;
@@ -286,4 +296,4 @@ module.exports.load = async function(app, db) {
286296
});
287297
return null;
288298
}
289-
}
299+
}

exec/node.js

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
const fs = require('fs');
2+
const readline = require('readline');
3+
const chalk = require('chalk');
4+
const path = require('path');
5+
6+
function setupNode() {
7+
const rl = readline.createInterface({
8+
input: process.stdin,
9+
output: process.stdout
10+
});
11+
12+
console.log(chalk.green('\nLapsus Node Configuration\n'));
13+
console.log(chalk.yellow('This will configure node settings at line 146 in settings.json\n'));
14+
15+
const settingsPath = path.join(__dirname, '../settings.json');
16+
17+
// Read the entire file as lines
18+
let settingsLines;
19+
try {
20+
settingsLines = fs.readFileSync(settingsPath, 'utf8').split('\n');
21+
} catch (err) {
22+
console.error(chalk.red('Error reading settings.json:'), err);
23+
process.exit(1);
24+
}
25+
26+
// Find the locations line (around line 146)
27+
let locationsIndex = -1;
28+
for (let i = 0; i < settingsLines.length; i++) {
29+
if (settingsLines[i].includes('"locations":')) {
30+
locationsIndex = i;
31+
break;
32+
}
33+
}
34+
35+
// If locations not found, create it at line 146 (145 in 0-based index)
36+
if (locationsIndex === -1) {
37+
locationsIndex = 145;
38+
// Ensure we have enough lines (pad if necessary)
39+
while (settingsLines.length <= locationsIndex) {
40+
settingsLines.push('');
41+
}
42+
settingsLines.splice(locationsIndex, 0, ' "locations": {},');
43+
}
44+
45+
// Extract the current locations content
46+
let locations = {};
47+
try {
48+
const lineContent = settingsLines[locationsIndex];
49+
const match = lineContent.match(/"locations":\s*({[^}]*})/);
50+
if (match && match[1]) {
51+
locations = JSON.parse(match[1]);
52+
}
53+
} catch (err) {
54+
console.log(chalk.yellow('Starting with empty locations (could not parse existing)'));
55+
}
56+
57+
const askQuestions = async () => {
58+
const nodeId = await new Promise(resolve => {
59+
rl.question(chalk.blue('\nEnter Node ID (e.g., "2"): '), (input) => {
60+
resolve(input.trim());
61+
});
62+
});
63+
64+
const nodeName = await new Promise(resolve => {
65+
rl.question(chalk.blue('Enter Node Name (e.g., "Germany"): '), (input) => {
66+
resolve(input.trim());
67+
});
68+
});
69+
70+
const city = await new Promise(resolve => {
71+
rl.question(chalk.blue('Enter City (e.g., "Berlin"): '), (input) => {
72+
resolve(input.trim());
73+
});
74+
});
75+
76+
console.log(chalk.yellow('\nISO Code is a 2-letter country code (e.g., "de" for Germany)'));
77+
const iso = await new Promise(resolve => {
78+
rl.question(chalk.blue('Enter ISO Country Code: '), (input) => {
79+
resolve(input.trim().toLowerCase());
80+
});
81+
});
82+
83+
const pkg = await new Promise(resolve => {
84+
rl.question(chalk.blue('Enter Package (leave empty for null): '), (input) => {
85+
resolve(input.trim() || null);
86+
});
87+
});
88+
89+
// Update locations
90+
locations[nodeId] = {
91+
name: nodeName,
92+
city: city,
93+
ISO: iso,
94+
package: pkg
95+
};
96+
97+
// Create the new locations line with proper indentation
98+
const locationsString = JSON.stringify(locations, null, 4)
99+
.split('\n')
100+
.map((line, i) => i === 0 ? line : ' ' + line)
101+
.join('\n');
102+
103+
// Update the specific line while preserving the original indentation
104+
const originalIndent = settingsLines[locationsIndex].match(/^\s*/)[0];
105+
settingsLines[locationsIndex] = originalIndent + '"locations": ' + locationsString + ',';
106+
107+
// Write back to file
108+
try {
109+
fs.writeFileSync(settingsPath, settingsLines.join('\n'), 'utf8');
110+
console.log(chalk.green('\nSuccessfully updated node at line ' + (locationsIndex + 1) + ' in settings.json!'));
111+
console.log(chalk.gray('\nCurrent node configuration:'));
112+
console.log(chalk.gray(JSON.stringify(locations, null, 2)));
113+
} catch (err) {
114+
console.error(chalk.red('Error writing settings.json:'), err);
115+
process.exit(1);
116+
}
117+
118+
rl.close();
119+
};
120+
121+
askQuestions();
122+
}
123+
124+
setupNode();

0 commit comments

Comments
 (0)