const express = require('express'); const Discord = require("discord.js"); require("dotenv").config(); let hook; if (process.env.DISCORD_WEBHOOK) {hook = new Discord.WebhookClient({ url: process.env.DISCORD_WEBHOOK })} const app = express(); const port = process.env.SERVER_PORT || 3000; const path = require('path'); const fs = require('fs'); const logFile = path.join(__dirname, process.env.LOG_FILE || 'server.log'); var known = []; const reloadKnown = () => { if (!fs.existsSync(path.join(__dirname, process.env.KNOWN_FILE || 'known.json'))) { fs.writeFileSync(path.join(__dirname, process.env.KNOWN_FILE || 'known.json'), JSON.stringify([]), 'utf8'); } try { const data = fs.readFileSync(path.join(__dirname, process.env.KNOWN_FILE || 'known.json'), 'utf8'); known = JSON.parse(data); } catch (err) { console.error('Error reading known file:', err); } } reloadKnown(); const checkKnown = (id) => { reloadKnown(); if (known.includes(id)) { return true; } else { known.push(id); console.log(`New ID added! ${id}`); if (process.env.DISCORD_WEBHOOK) { hook.send(`[New Game ID! ${id}](https://www.roblox.com/games/${id})`); } fs.writeFileSync(path.join(__dirname, process.env.KNOWN_FILE || 'known.json'), JSON.stringify(known), 'utf8'); return false; } }; app.use(express.static(path.join(__dirname, 'public'))); app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use((req, res, next) => { //Logger // [timestamp] method - url; UA; IP; roblox-id header if it exists const timestamp = new Date().toISOString(); const method = req.method; const url = req.originalUrl; const userAgent = req.headers['user-agent'] || 'unknown'; const ip = req.headers['x-forwarded-for'] || req.remoteAddress || 'unknown'; const robloxId = req.headers['roblox-id'] || 'none'; const logEntry = `[${timestamp}] ${method} - ${url}; UA: ${userAgent}; IP: ${ip}; Roblox-ID: ${robloxId}\n`; fs.appendFileSync(logFile, logEntry, 'utf8', (err) => { if (err) { console.error('Error writing to log file:', err); } }); if (userAgent.includes('Roblox')) { checkKnown(robloxId); console.log(logEntry.trim()); } next(); }); app.get('/', (req, res) => { res.sendFile(path.join(__dirname, 'msg.html')); }); app.get('/time.php', (req, res) => { // This endpoint returns the current time in a specific format based on the timezone provided const tz = req.query.zone || 'UTC'; const date = new Date(); try { const options = { timeZone: tz, hour12: false }; const formatter = new Intl.DateTimeFormat('en-GB', { ...options, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' }); /* { ...options, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' } // Old format */ // Example output with space-padded single digits instead of zero-padded const spacePad = n => n.toString().padStart(2, ' '); const parts = formatter.formatToParts(date); const get = type => parts.find(p => p.type === type).value; //const formatted = `${get('day')}${get('month')}${get('year')}${get('hour')}${get('minute')}${get('second')}`; const singleDigit = n => ' ' + (n.startsWith('0') ? n.slice(1) : n); const formatted = `${singleDigit(get('day'))}${singleDigit(get('month'))}${singleDigit(get('year'))}${singleDigit(get('hour'))}${singleDigit(get('minute'))}${singleDigit(get('second'))}`; const msg = fs.readFileSync(path.join(__dirname, 'msg.html'), 'utf8'); res.send(`${formatted}

${msg}`); } catch (e) { res.status(400).send('Invalid timezone'); } }); app.listen(port, () => { console.log(`Server is running on port ${port}`); });