2019-10-15 23:42:47 -03:00
const express = require ( 'express' ) ;
const fs = require ( "fs" )
const timeout = require ( 'connect-timeout' )
2019-11-07 01:07:31 -03:00
const compression = require ( 'compression' ) ;
2020-09-10 10:02:40 -03:00
const rateLimit = require ( "express-rate-limit" ) ;
// set to false if you're using gdbrowser locally, for obvious reasons
2020-09-27 23:22:47 -03:00
let useRateLimiting = true
2020-09-10 10:02:40 -03:00
const app = express ( ) ;
app . offline = false // set to true to go into "offline" mode (in case of ip ban from rob)
2020-09-29 22:42:18 -03:00
app . secret = "Wmfd2893gb7" // lol
2020-10-13 11:25:07 -03:00
app . config = require ( './gdpsConfig' ) // tweak settings in this file if you're using a GDPS
2020-09-29 22:42:18 -03:00
app . endpoint = app . config . endpoint // boomlings.com/database/
app . gdParams = function ( obj = { } ) {
Object . keys ( app . config . params ) . forEach ( x => { if ( ! obj [ x ] ) obj [ x ] = app . config . params [ x ] } )
return obj
}
2020-09-10 10:02:40 -03:00
const RL = rateLimit ( {
windowMs : useRateLimiting ? 5 * 60 * 1000 : 0 ,
max : useRateLimiting ? 100 : 0 , // max requests per 5 minutes
message : "Rate limited ¯\\_(ツ)_/¯" ,
keyGenerator : function ( req ) { return req . headers [ 'x-real-ip' ] } ,
skip : function ( req ) { return ( ( req . url . includes ( "api/level" ) && ! req . query . hasOwnProperty ( "download" ) ) ? true : false ) }
} )
2019-11-07 01:07:31 -03:00
2019-10-15 23:42:47 -03:00
let api = true ;
2020-09-24 23:07:53 -03:00
let gdIcons = fs . readdirSync ( './icons/iconkit' )
let sampleIcons = require ( './misc/sampleIcons.json' )
2019-10-21 12:20:25 -03:00
app . use ( compression ( ) ) ;
2019-10-15 23:42:47 -03:00
app . use ( express . json ( ) ) ;
app . use ( express . urlencoded ( { extended : true } ) ) ;
2019-12-25 18:20:32 -03:00
app . use ( timeout ( '30s' ) ) ;
2019-10-15 23:42:47 -03:00
app . use ( haltOnTimedout )
app . set ( 'json spaces' , 2 )
2019-12-25 18:20:32 -03:00
let directories = [ "" , "post" , "messages" ] //this can probably be automated but i'm lazy
app . run = { }
directories . forEach ( d => {
fs . readdirSync ( './api/' + d ) . forEach ( x => { if ( x . includes ( '.' ) ) app . run [ x . split ( '.' ) [ 0 ] ] = require ( './api/' + d + "/" + x ) } )
2019-10-16 19:47:53 -03:00
} )
2019-10-15 23:42:47 -03:00
2019-12-22 00:52:09 -03:00
function haltOnTimedout ( req , res , next ) {
if ( ! req . timedout ) next ( )
}
try {
const secrets = require ( "./misc/secretStuff.json" )
app . id = secrets . id
app . gjp = secrets . gjp
2020-04-24 15:26:29 -04:00
app . sheetsKey = secrets . sheetsKey
2020-02-20 22:09:40 -03:00
if ( app . id == "account id goes here" || app . gjp == "account gjp goes here" ) console . warn ( "Warning: No account ID and/or GJP has been provided in secretStuff.json! These are required for level leaderboards to work." )
2020-04-24 15:26:29 -04:00
if ( app . sheetsKey . startsWith ( "google sheets api key" ) ) app . sheetsKey = undefined
2019-12-22 00:52:09 -03:00
}
2019-10-15 23:42:47 -03:00
2019-12-25 18:20:32 -03:00
catch ( e ) {
2019-12-22 00:52:09 -03:00
app . id = 0
app . gjp = 0
2020-02-20 22:09:40 -03:00
console . warn ( "Warning: secretStuff.json has not been created! These are required for level leaderboards to work." )
2019-10-15 23:42:47 -03:00
}
app . parseResponse = function ( responseBody , splitter ) {
2019-10-23 18:48:01 -03:00
if ( ! responseBody || responseBody == "-1" ) return { } ;
2019-10-15 23:42:47 -03:00
let response = responseBody . split ( '#' ) [ 0 ] . split ( splitter || ':' ) ;
let res = { } ;
for ( let i = 0 ; i < response . length ; i += 2 ) {
res [ response [ i ] ] = response [ i + 1 ] }
return res }
2019-10-16 19:47:53 -03:00
//xss bad
2019-10-25 18:22:29 -03:00
app . clean = function ( text ) { if ( ! text || typeof text != "string" ) return text ; else return text . replace ( /&/g , "&" ) . replace ( /</g , "<" ) . replace ( />/g , ">" ) . replace ( /=/g , "=" ) . replace ( /"/g , """ ) . replace ( /'/g , "'" ) }
2019-10-15 23:42:47 -03:00
2019-12-16 10:48:05 -03:00
// ASSETS
2019-12-21 16:33:32 -03:00
let assets = [ 'css' , 'assets' , 'blocks' , 'deatheffects' , 'difficulty' , 'gauntlets' , 'gdicon' , 'iconkitbuttons' , 'levelstyle' , 'objects' ]
2019-10-19 01:27:17 -03:00
app . use ( '/css' , express . static ( _ _dirname + '/assets/css' ) ) ;
2019-12-16 10:48:05 -03:00
app . use ( '/assets' , express . static ( _ _dirname + '/assets' , { maxAge : "7d" } ) ) ;
2019-10-18 17:48:33 -03:00
app . use ( '/blocks' , express . static ( _ _dirname + '/assets/blocks' , { maxAge : "7d" } ) ) ;
2019-12-21 16:33:32 -03:00
app . use ( '/deatheffects' , express . static ( _ _dirname + '/assets/deatheffects' , { maxAge : "7d" } ) ) ;
2019-10-18 17:48:33 -03:00
app . use ( '/difficulty' , express . static ( _ _dirname + '/assets/gdfaces' , { maxAge : "7d" } ) ) ;
2019-12-16 10:48:05 -03:00
app . use ( '/gauntlets' , express . static ( _ _dirname + '/assets/gauntlets' , { maxAge : "7d" } ) ) ;
2019-10-18 17:48:33 -03:00
app . use ( '/gdicon' , express . static ( _ _dirname + '/icons/iconkit' , { maxAge : "7d" } ) ) ;
2019-12-16 10:48:05 -03:00
app . use ( '/iconkitbuttons' , express . static ( _ _dirname + '/assets/iconkitbuttons' , { maxAge : "7d" } ) ) ;
app . use ( '/levelstyle' , express . static ( _ _dirname + '/assets/initial' , { maxAge : "7d" } ) ) ;
app . use ( '/objects' , express . static ( _ _dirname + '/assets/objects' , { maxAge : "7d" } ) ) ;
2019-10-15 23:42:47 -03:00
2019-12-16 10:48:05 -03:00
// POST REQUESTS
2019-10-15 23:42:47 -03:00
2020-09-10 10:02:40 -03:00
app . post ( "/like" , RL , function ( req , res ) { app . run . like ( app , req , res ) } )
app . post ( "/postComment" , RL , function ( req , res ) { app . run . postComment ( app , req , res ) } )
app . post ( "/postProfileComment" , RL , function ( req , res ) { app . run . postProfileComment ( app , req , res ) } )
2019-12-25 18:20:32 -03:00
2020-09-10 10:02:40 -03:00
app . post ( "/messages" , RL , async function ( req , res ) { app . run . getMessages ( app , req , res ) } )
app . post ( "/messages/:id" , RL , async function ( req , res ) { app . run . fetchMessage ( app , req , res ) } )
app . post ( "/deleteMessage" , RL , function ( req , res ) { app . run . deleteMessage ( app , req , res ) } )
app . post ( "/sendMessage" , RL , function ( req , res ) { app . run . sendMessage ( app , req , res ) } )
2019-10-15 23:42:47 -03:00
2020-10-02 15:33:24 -03:00
app . post ( "/accurateLeaderboard" , function ( req , res ) { app . run . accurateLeaderboard ( app , req , res , true ) } )
2019-10-15 23:42:47 -03:00
2019-12-16 10:48:05 -03:00
// HTML
2019-10-15 23:42:47 -03:00
2020-09-10 10:02:40 -03:00
app . get ( "/" , function ( req , res ) {
if ( app . offline && ! req . query . hasOwnProperty ( "home" ) ) res . sendFile ( _ _dirname + "/html/offline.html" )
else res . sendFile ( _ _dirname + "/html/home.html" )
} )
2019-12-16 10:48:05 -03:00
app . get ( "/analyze/:id" , async function ( req , res ) { res . sendFile ( _ _dirname + "/html/analyze.html" ) } )
app . get ( "/api" , function ( req , res ) { res . sendFile ( _ _dirname + "/html/api.html" ) } )
app . get ( "/comments/:id" , function ( req , res ) { res . sendFile ( _ _dirname + "/html/comments.html" ) } )
app . get ( "/gauntlets" , function ( req , res ) { res . sendFile ( _ _dirname + "/html/gauntlets.html" ) } )
2019-12-16 17:01:46 -03:00
app . get ( "/iconkit" , function ( req , res ) { res . sendFile ( _ _dirname + "/html/iconkit.html" ) } )
2019-12-16 10:48:05 -03:00
app . get ( "/leaderboard" , function ( req , res ) { res . sendFile ( _ _dirname + "/html/leaderboard.html" ) } )
app . get ( "/leaderboard/:text" , function ( req , res ) { res . sendFile ( _ _dirname + "/html/levelboard.html" ) } )
app . get ( "/mappacks" , function ( req , res ) { res . sendFile ( _ _dirname + "/html/mappacks.html" ) } )
2019-12-29 20:59:29 -03:00
app . get ( "/messages" , function ( req , res ) { res . sendFile ( _ _dirname + "/html/messages.html" ) } )
2019-12-16 10:48:05 -03:00
app . get ( "/search" , function ( req , res ) { res . sendFile ( _ _dirname + "/html/filters.html" ) } )
app . get ( "/search/:text" , function ( req , res ) { res . sendFile ( _ _dirname + "/html/search.html" ) } )
2019-10-15 23:42:47 -03:00
2019-12-16 10:48:05 -03:00
// API
2019-10-21 00:33:01 -03:00
2020-09-10 10:02:40 -03:00
app . get ( "/api/analyze/:id" , RL , async function ( req , res ) { app . run . level ( app , req , res , api , true ) } )
2020-09-28 14:05:59 -03:00
app . get ( "/api/comments/:id" , function ( req , res ) { app . run . comments ( app , req , res ) } )
2019-12-16 10:48:05 -03:00
app . get ( "/api/credits" , function ( req , res ) { res . send ( require ( './misc/credits.json' ) ) } )
2020-09-28 14:05:59 -03:00
app . get ( "/api/leaderboard" , function ( req , res ) { app . run [ req . query . hasOwnProperty ( "accurate" ) ? "accurateLeaderboard" : "leaderboard" ] ( app , req , res ) } )
app . get ( "/api/leaderboardLevel/:id" , RL , function ( req , res ) { app . run . leaderboardLevel ( app , req , res ) } )
2020-09-10 10:02:40 -03:00
app . get ( "/api/level/:id" , RL , async function ( req , res ) { app . run . level ( app , req , res , api ) } )
2019-12-16 10:48:05 -03:00
app . get ( "/api/mappacks" , async function ( req , res ) { res . send ( require ( './misc/mapPacks.json' ) ) } )
2019-12-25 18:20:32 -03:00
app . get ( "/api/profile/:id" , function ( req , res ) { app . run . profile ( app , req , res , api ) } )
2020-09-28 14:05:59 -03:00
app . get ( "/api/search/:text" , function ( req , res ) { app . run . search ( app , req , res ) } )
2019-12-16 10:48:05 -03:00
2019-10-15 23:42:47 -03:00
2019-12-16 10:48:05 -03:00
// REDIRECTS
2019-10-15 23:42:47 -03:00
2019-12-16 10:48:05 -03:00
app . get ( "/icon" , function ( req , res ) { res . redirect ( '/iconkit' ) } )
app . get ( "/iconkit/:text" , function ( req , res ) { res . redirect ( '/icon/' + req . params . text ) } )
2020-10-13 11:25:07 -03:00
app . get ( "/obj/:text" , function ( req , res ) { res . redirect ( '/obj/' + req . params . text ) } )
2019-12-16 10:48:05 -03:00
app . get ( "/leaderboards/:id" , function ( req , res ) { res . redirect ( '/leaderboard/' + req . params . id ) } )
2020-09-29 22:42:18 -03:00
app . get ( "/profile/:id" , function ( req , res ) { res . redirect ( '/u/' + req . params . id ) } )
app . get ( "/p/:id" , function ( req , res ) { res . redirect ( '/u/' + req . params . id ) } )
2019-12-16 10:48:05 -03:00
app . get ( "/l/:id" , function ( req , res ) { res . redirect ( '/leaderboard/' + req . params . id ) } )
app . get ( "/a/:id" , function ( req , res ) { res . redirect ( '/analyze/' + req . params . id ) } )
app . get ( "/c/:id" , function ( req , res ) { res . redirect ( '/comments/' + req . params . id ) } )
2019-10-15 23:42:47 -03:00
2020-09-24 23:07:53 -03:00
// API AND HTML
2020-09-29 22:42:18 -03:00
app . get ( "/u/:id" , function ( req , res ) { app . run . profile ( app , req , res ) } )
2020-09-24 23:07:53 -03:00
app . get ( "/:id" , function ( req , res ) { app . run . level ( app , req , res ) } )
2019-12-16 10:48:05 -03:00
// MISC
2019-10-15 23:42:47 -03:00
2019-12-16 10:48:05 -03:00
app . get ( "/assets/sizecheck.js" , function ( req , res ) { res . sendFile ( _ _dirname + "/misc/sizecheck.js" ) } )
2019-12-25 18:20:32 -03:00
app . get ( "/icon/:text" , function ( req , res ) { app . run . icon ( app , req , res ) } )
2020-10-13 11:25:07 -03:00
app . get ( "/object/:text" , function ( req , res ) { app . run . object ( app , req , res ) } )
2020-09-24 23:07:53 -03:00
app . get ( '/api/icons' , function ( req , res ) {
let sample = [ JSON . stringify ( sampleIcons [ Math . floor ( Math . random ( ) * sampleIcons . length ) ] . slice ( 1 ) ) ]
res . send ( gdIcons . concat ( sample ) ) ;
} ) ;
2019-10-15 23:42:47 -03:00
app . get ( '*' , function ( req , res ) {
2019-12-16 10:48:05 -03:00
if ( req . path . startsWith ( '/api' ) ) res . send ( '-1' )
2019-12-21 16:33:32 -03:00
if ( assets . some ( x => req . path . startsWith ( "/" + x ) ) ) res . send ( "Looks like this file doesn't exist ¯\\_(ツ)_/¯<br>You can check out all of the assets on <a target='_blank' href='https://github.com/GDColon/GDBrowser/tree/master/assets'>GitHub</a>" )
2019-12-15 21:11:35 -03:00
else res . redirect ( '/search/404%20' )
2019-10-15 23:42:47 -03:00
} ) ;
2020-04-09 10:42:08 -04:00
app . listen ( 2000 , ( ) => console . log ( "Site online!" ) )