Install dependencies with pnpm and format files with Prettier

This commit is contained in:
Lewin Kelly 2023-09-10 02:02:20 +01:00
parent 24e44a3b50
commit e61816bd6d
No known key found for this signature in database
GPG Key ID: C103AD9C84014FD7
144 changed files with 40063 additions and 20038 deletions

9
.prettierrc Normal file
View File

@ -0,0 +1,9 @@
{
"semi": false,
"arrowParens": "avoid",
"printWidth": 80,
"tabWidth": 4,
"useTabs": true,
"bracketSameLine": true,
"htmlWhitespaceSensitivity": "ignore"
}

View File

@ -1,4 +1,5 @@
# SushiBlox-Website
Website for sushiblox I guess.
~~Private for now might open source.~~
@ -8,13 +9,15 @@ The setup is ~~easy install required node modules and setup a nginx reverse prox
Uses MongoDB for datastorage. Redis for special things
# Advice
~~This uses hardcoded domain names in the code~~ and relies on cloudflare headers for IP configs. so yeahhhhhhhhhhhhhhhhhhhhhhhhhh
# Redis
idk set it up nerd
# setup
easy enough
# Example

View File

@ -1,24 +1,29 @@
const jwt = require('jsonwebtoken')
require('dotenv').config()
const jwt = require("jsonwebtoken")
require("dotenv").config()
const JWT_SECRET = process.env.JWT_SECRET
const atob = require("atob");
const atob = require("atob")
const model = require("./../model/user.js")
const requireAuth = (req, res, next) => {
if (!req.cookies && req.headers['authorization']) {
if (!req.cookies && req.headers["authorization"]) {
return res.json({ status: "error", error: "Unauthorized" })
}
let token = req.cookies.jwt??req.cookies['.ROBLOSECURITY']??req.headers['authorization']??req.headers['roblox-session-id']
let token =
req.cookies.jwt ??
req.cookies[".ROBLOSECURITY"] ??
req.headers["authorization"] ??
req.headers["roblox-session-id"]
if (!token) {
return res.status(401).json({ status: "error", error: "Unauthorized" })
}
jwt.verify(token, JWT_SECRET, (err, decodedtoken) => {
if (err) {
res.cookie('jwt', "", {SameSite: "Strict",maxAge: 1 })
return res.status(401).json({status: "error", error: "Unauthorized"})
res.cookie("jwt", "", { SameSite: "Strict", maxAge: 1 })
return res
.status(401)
.json({ status: "error", error: "Unauthorized" })
} else {
var tokendata = decodedtoken
var name = tokendata.userid
@ -29,26 +34,42 @@ const requireAuth = (req,res,next) => {
req.userdocument = doc
moderationstatus = JSON.parse(doc.moderation)
const actualTimeMilliseconds = new Date().getTime()
if (actualTimeMilliseconds - doc.timesincelastrequest >= 60000 * 1 || !doc.timesincelastrequest /*2 minutes make sure to update*/){
if (
actualTimeMilliseconds - doc.timesincelastrequest >=
60000 * 1 ||
!doc.timesincelastrequest /*2 minutes make sure to update*/
) {
doc.timesincelastrequest = actualTimeMilliseconds
doc.markModified('timesincelastrequest')
doc.markModified("timesincelastrequest")
await doc.save()
}
// check if they are eligble for daily login reward
if (actualTimeMilliseconds - req.userdocument.lastclaimofcurrency > 86400000){ // 24 hours
req.userdocument.lastclaimofcurrency = actualTimeMilliseconds
if (req.userdocument.membership === "TurboBuildersClub"){
if (
actualTimeMilliseconds -
req.userdocument.lastclaimofcurrency >
86400000
) {
// 24 hours
req.userdocument.lastclaimofcurrency =
actualTimeMilliseconds
if (
req.userdocument.membership === "TurboBuildersClub"
) {
req.userdocument.coins += 90
}else if (req.userdocument.membership === "BuildersClub"){
} else if (
req.userdocument.membership === "BuildersClub"
) {
req.userdocument.coins += 60
}else if (req.userdocument.membership === "OutrageousBuildersClub"){
} else if (
req.userdocument.membership ===
"OutrageousBuildersClub"
) {
req.userdocument.coins += 150
}
else{
} else {
req.userdocument.coins += 35
}
req.userdocument.markModified('coins')
req.userdocument.markModified('lastclaimofcurrency')
req.userdocument.markModified("coins")
req.userdocument.markModified("lastclaimofcurrency")
await req.userdocument.save()
}
@ -57,7 +78,7 @@ const requireAuth = (req,res,next) => {
//res.cookie('jwt', "", {SameSite: "Strict",maxAge: 1 })
//return res.send("You have been moderated for "+moderationstatus.Reason+" expires at"+moderationstatus.ExpiresIn+" Moderated by "+moderationstatus.BannedBy )
var date = Date.parse(moderationstatus.ExpiresIn)
var datetime = new Date();
var datetime = new Date()
var datetime2 = Date.parse(datetime)
/*if (date <= datetime2){
// they have served there time
@ -73,16 +94,18 @@ const requireAuth = (req,res,next) => {
return next()
}*/
return res.json({status: "error", error:"Moderated", moderationstatus})
return res.json({
status: "error",
error: "Moderated",
moderationstatus,
})
}
next()
})/*.lean() rip*/}
catch (error) {
console.error(error);
}) /*.lean() rip*/
} catch (error) {
console.error(error)
}
}
})
}

View File

@ -1,37 +1,37 @@
const jwt = require('jsonwebtoken')
require('dotenv').config()
const jwt = require("jsonwebtoken")
require("dotenv").config()
const JWT_SECRET = process.env.JWT_SECRET
const atob = require("atob");
const atob = require("atob")
const model = require("./../model/user.js")
// exactly the same as normal authimddleware but uses req.query instead of cookies for our client
const requireAuth = (req, res, next) => {
let token = req.query.auth
if (req.cookies && req.headers?.['user-agent'] != "Roblox/WinInet") { // Mobile
if (req.cookies && req.headers?.["user-agent"] != "Roblox/WinInet") {
// Mobile
if (req.cookies.jwt) {
token = req.cookies.jwt
}
}
if (req.headers['roblox-session-id']) { // TeleportService
token = req.headers['roblox-session-id']
if (req.headers["roblox-session-id"]) {
// TeleportService
token = req.headers["roblox-session-id"]
}
if (req.headers?.['user-agent']?.includes("Android") === true || req.headers?.['user-agent']?.includes("iPhone") === true){
if (
req.headers?.["user-agent"]?.includes("Android") === true ||
req.headers?.["user-agent"]?.includes("iPhone") === true
) {
console.log(token)
console.log(req.headers)
}
//console.log(req.headers)
if (!token) {
return res.status(405).end()
}
jwt.verify(token, JWT_SECRET, (err, decodedtoken) => {
if (err) {
res.cookie('jwt', "", {SameSite: "Strict",maxAge: 1 })
res.cookie("jwt", "", { SameSite: "Strict", maxAge: 1 })
return res.status(405)
} else {
var tokendata = decodedtoken
@ -47,7 +47,7 @@ const requireAuth = (req,res,next) => {
//res.cookie('jwt', "", {SameSite: "Strict",maxAge: 1 })
//return res.send("You have been moderated for "+moderationstatus.Reason+" expires at"+moderationstatus.ExpiresIn+" Moderated by "+moderationstatus.BannedBy )
var date = Date.parse(moderationstatus.ExpiresIn)
var datetime = new Date();
var datetime = new Date()
var datetime2 = Date.parse(datetime)
/*if (date <= datetime2){
// they have served there time
@ -63,16 +63,18 @@ const requireAuth = (req,res,next) => {
}*/
return res.json({status: "error", error:"Moderated", moderationstatus})
return res.json({
status: "error",
error: "Moderated",
moderationstatus,
})
}
next()
})/*.lean() rip*/}
catch (error) {
console.error(error);
}) /*.lean() rip*/
} catch (error) {
console.error(error)
}
}
})
}

View File

@ -1,14 +1,17 @@
const jwt = require('jsonwebtoken')
require('dotenv').config()
const jwt = require("jsonwebtoken")
require("dotenv").config()
const JWT_SECRET = process.env.JWT_SECRET
const atob = require("atob");
const atob = require("atob")
const model = require("./../model/user.js")
const grabAuth = (req, res, next) => {
if (!req.cookies && req.headers['authorization']) {
if (!req.cookies && req.headers["authorization"]) {
return next()
}
const token = req.cookies.jwt??req.cookies['.ROBLOSECURITY']??req.headers['authorization']
const token =
req.cookies.jwt ??
req.cookies[".ROBLOSECURITY"] ??
req.headers["authorization"]
if (!token) {
return next()
@ -21,7 +24,9 @@ const grabAuth = (req,res,next) => {
var tokendata = decodedtoken
var name = tokendata.username
try {
model.findOne({username: new RegExp('^'+name+'$', "i")}, function(err, doc) {
model.findOne(
{ username: new RegExp("^" + name + "$", "i") },
function (err, doc) {
req.numberofcoins = doc.coins
req.admin = doc.admin
req.tokenData = tokendata
@ -32,32 +37,41 @@ const grabAuth = (req,res,next) => {
//res.cookie('jwt', "", {SameSite: "Strict",maxAge: 1 })
//return res.send("You have been moderated for "+moderationstatus.Reason+" expires at"+moderationstatus.ExpiresIn+" Moderated by "+moderationstatus.BannedBy )
var date = Date.parse(moderationstatus.ExpiresIn)
var datetime = new Date();
var datetime = new Date()
var datetime2 = Date.parse(datetime)
if (date <= datetime2) {
// they have served there time
model.updateOne({userid: doc.userid}, {
model.updateOne(
{ userid: doc.userid },
{
$set: {
moderation: JSON.stringify({"status":"ok","Reason":"none","ExpiresIn":"none", "BannedBy": "none"})
}
moderation: JSON.stringify({
status: "ok",
Reason: "none",
ExpiresIn: "none",
BannedBy: "none",
}),
},
},
function (err, doc) {
//console.log(err)
})
},
)
}
return res.json({status: "error", error:"Moderated", moderationstatus})
return res.json({
status: "error",
error: "Moderated",
moderationstatus,
})
}
next()
})/*.lean() rip*/}
catch (error) {
console.error(error);
},
) /*.lean() rip*/
} catch (error) {
console.error(error)
}
}
})
}

View File

@ -1,11 +1,13 @@
const requirediscord = (req, res, next) => {
const discordid = req.userdocument.discordid
if (!discordid) {
return res.json({status: "error", error: "Discord link required for develop. Link your discord in the settings panel."})
return res.json({
status: "error",
error: "Discord link required for develop. Link your discord in the settings panel.",
})
} else {
next();
next()
}
}
};
module.exports = { requirediscord }

View File

@ -1,9 +1,10 @@
const mongoose = require('mongoose')
const bankSchema = new mongoose.Schema({
const mongoose = require("mongoose")
const bankSchema = new mongoose.Schema(
{
balance: { type: Number, required: true },
},
{collection: 'bank'}
{ collection: "bank" },
)
const model = mongoose.model('bank', bankSchema)
const model = mongoose.model("bank", bankSchema)
module.exports = model

View File

@ -1,22 +1,23 @@
const mongoose = require('mongoose')
const CommentSchema = new mongoose.Schema({
const mongoose = require("mongoose")
const CommentSchema = new mongoose.Schema(
{
associatedassetid: { type: Number, required: true, index: true },
associatedassettype: { type: String, required: true, index: true },
posterid: { type: Number, required: true },
content: { type: String, required: true },
date: { type: Number, required: true },
moderated: {type: Boolean, required: true}
moderated: { type: Boolean, required: true },
},
{collection: 'comments'}
{ collection: "comments" },
)
CommentSchema.virtual('poster', {
ref: 'UserSchema',
localField: 'posterid',
foreignField: 'userid',
justOne: true
CommentSchema.virtual("poster", {
ref: "UserSchema",
localField: "posterid",
foreignField: "userid",
justOne: true,
})
const model = mongoose.model('CommentSchema', CommentSchema)
const model = mongoose.model("CommentSchema", CommentSchema)
module.exports = model

View File

@ -1,13 +1,14 @@
const mongoose = require('mongoose')
const ConfigSchema = new mongoose.Schema({
const mongoose = require("mongoose")
const ConfigSchema = new mongoose.Schema(
{
RegistrationEnabled: { type: Boolean, required: true },
MaintenanceEnabled: { type: Boolean, required: true },
KeysEnabled: { type: Boolean, required: true },
GamesEnabled: {type: Boolean, required: true}
GamesEnabled: { type: Boolean, required: true },
},
{collection: 'config'}
{ collection: "config" },
)
const model = mongoose.model('ConfigSchema', ConfigSchema)
const model = mongoose.model("ConfigSchema", ConfigSchema)
module.exports = model

View File

@ -1,5 +1,6 @@
const mongoose = require('mongoose')
const GamesSchema = new mongoose.Schema({
const mongoose = require("mongoose")
const GamesSchema = new mongoose.Schema(
{
useridofowner: { type: Number, required: true },
idofgame: { type: Number, required: true, index: true },
nameofgame: { type: String, required: true },
@ -12,18 +13,18 @@ const GamesSchema = new mongoose.Schema({
players: { type: Object, required: false },
avatartype: { type: Object, required: false },
gearallowed: { type: Boolean, required: false },
comments: {type: Object, required: false}
comments: { type: Object, required: false },
},
{collection: 'games'}
{ collection: "games" },
)
GamesSchema.virtual('owner', {
ref: 'UserSchema',
localField: 'useridofowner',
foreignField: 'userid',
justOne: true
GamesSchema.virtual("owner", {
ref: "UserSchema",
localField: "useridofowner",
foreignField: "userid",
justOne: true,
})
const model = mongoose.model('GamesSchema', GamesSchema)
const model = mongoose.model("GamesSchema", GamesSchema)
module.exports = model

View File

@ -1,5 +1,6 @@
const mongoose = require('mongoose')
const GroupSchema = new mongoose.Schema({
const mongoose = require("mongoose")
const GroupSchema = new mongoose.Schema(
{
Name: { type: String, required: true },
Description: { type: String, required: true },
Public: { type: Boolean, required: true },
@ -10,24 +11,43 @@ const GroupSchema = new mongoose.Schema({
ownerid: { type: Number, required: true },
memberscount: { type: Number, required: true },
members: { type: [{ userId: Number, rank: Number }], required: true },
currentshout: {type: {content: String, shouter: Number}, required: false},
Roles: {type: [{RoleName: String, Permissions: {Shout: Boolean, Kick: Boolean, ChangeRoles: Boolean, ModerateWall: Boolean, ManageAllies: Boolean, All: Boolean}, Rank: Number}], required: true}, // default {}
currentshout: {
type: { content: String, shouter: Number },
required: false,
},
{collection: 'groups'}
Roles: {
type: [
{
RoleName: String,
Permissions: {
Shout: Boolean,
Kick: Boolean,
ChangeRoles: Boolean,
ModerateWall: Boolean,
ManageAllies: Boolean,
All: Boolean,
},
Rank: Number,
},
],
required: true,
}, // default {}
},
{ collection: "groups" },
)
const model = mongoose.model('GroupSchema', GroupSchema)
const model = mongoose.model("GroupSchema", GroupSchema)
GroupSchema.virtual('owner', {
ref: 'UserSchema',
localField: 'ownerid',
foreignField: 'userid',
justOne: true
GroupSchema.virtual("owner", {
ref: "UserSchema",
localField: "ownerid",
foreignField: "userid",
justOne: true,
})
GroupSchema.virtual('memberspoly', {
ref: 'UserSchema',
localField: 'members.userId',
foreignField: 'userid'
GroupSchema.virtual("memberspoly", {
ref: "UserSchema",
localField: "members.userId",
foreignField: "userid",
})
module.exports = model

View File

@ -1,7 +1,7 @@
import { Schema } from 'redis-om'
import { Schema } from "redis-om"
const ipWhiteListSchema = new Schema('ipWhiteListSchema', {
ip: { type: 'string' },
const ipWhiteListSchema = new Schema("ipWhiteListSchema", {
ip: { type: "string" },
})
export default ipWhiteListSchema

View File

@ -1,5 +1,6 @@
const mongoose = require('mongoose')
const CatalogSchema = new mongoose.Schema({
const mongoose = require("mongoose")
const CatalogSchema = new mongoose.Schema(
{
Name: { type: String, required: true },
Description: { type: String, required: false },
Price: { type: String, required: true },
@ -16,8 +17,8 @@ const CatalogSchema = new mongoose.Schema({
denied: { type: Boolean, required: false },
associatedgameid: { type: Number, required: false },
},
{collection: 'catalog'}
{ collection: "catalog" },
)
const model = mongoose.model('CatalogSchema', CatalogSchema)
const model = mongoose.model("CatalogSchema", CatalogSchema)
module.exports = model

View File

@ -1,13 +1,14 @@
const mongoose = require('mongoose')
const KeysSchema = new mongoose.Schema({
const mongoose = require("mongoose")
const KeysSchema = new mongoose.Schema(
{
Creator: { type: String, required: true },
Key: { type: String, required: true },
Used: { type: Boolean, required: true },
UsedBy: {type: String, required: false}
UsedBy: { type: String, required: false },
},
{collection: 'keys'}
{ collection: "keys" },
)
const model = mongoose.model('KeysSchema', KeysSchema)
const model = mongoose.model("KeysSchema", KeysSchema)
module.exports = model

View File

@ -1,11 +1,12 @@
const mongoose = require('mongoose')
const RccSchema = new mongoose.Schema({
const mongoose = require("mongoose")
const RccSchema = new mongoose.Schema(
{
PlaceId: { type: Number, required: true },
Port: { type: Number, required: true },
Status: { type: Number, required: true },
},
{collection: 'RCC'}
{ collection: "RCC" },
)
const model = mongoose.model('RccSchema', RccSchema)
const model = mongoose.model("RccSchema", RccSchema)
module.exports = model

View File

@ -1,10 +1,11 @@
const mongoose = require('mongoose')
const Rcc2014Schema = new mongoose.Schema({
const mongoose = require("mongoose")
const Rcc2014Schema = new mongoose.Schema(
{
PlaceId: { type: Number, required: true },
Port: {type: Number, required: true}
Port: { type: Number, required: true },
},
{collection: 'RCC2014'}
{ collection: "RCC2014" },
)
const model = mongoose.model('Rcc2014Schema', Rcc2014Schema)
const model = mongoose.model("Rcc2014Schema", Rcc2014Schema)
module.exports = model

View File

@ -1,11 +1,12 @@
const mongoose = require('mongoose')
const Rcc2018Schema = new mongoose.Schema({
const mongoose = require("mongoose")
const Rcc2018Schema = new mongoose.Schema(
{
PlaceId: { type: Number, required: true },
Port: { type: Number, required: true },
Status: { type: Number, required: true },
},
{collection: 'RCC2018'}
{ collection: "RCC2018" },
)
const model = mongoose.model('Rcc2018Schema', Rcc2018Schema)
const model = mongoose.model("Rcc2018Schema", Rcc2018Schema)
module.exports = model

View File

@ -1,11 +1,12 @@
const mongoose = require('mongoose')
const Rcc2020Schema = new mongoose.Schema({
const mongoose = require("mongoose")
const Rcc2020Schema = new mongoose.Schema(
{
PlaceId: { type: Number, required: true },
Port: { type: Number, required: true },
Status: { type: Number, required: true },
},
{collection: 'RCC2020'}
{ collection: "RCC2020" },
)
const model = mongoose.model('Rcc2020Schema', Rcc2020Schema)
const model = mongoose.model("Rcc2020Schema", Rcc2020Schema)
module.exports = model

View File

@ -1,7 +1,13 @@
const mongoose = require('mongoose')
var uniqueValidator = require('mongoose-unique-validator');
const UserSchema = new mongoose.Schema({
username: {type: String, required: true, unique: true,uniqueCaseInsensitive: true},
const mongoose = require("mongoose")
var uniqueValidator = require("mongoose-unique-validator")
const UserSchema = new mongoose.Schema(
{
username: {
type: String,
required: true,
unique: true,
uniqueCaseInsensitive: true,
},
password: { type: String, required: true },
coins: { type: Number, required: true },
admin: { type: Boolean, required: true },
@ -31,32 +37,40 @@ const UserSchema = new mongoose.Schema({
css: { type: String, required: false },
aboutme: { type: String, required: false },
lastfeedsharetime: { type: Number, required: false },
feed: [{posterid: Number, content: String, date: Number, moderated: Boolean}], required: false},
feed: [
{
posterid: Number,
content: String,
date: Number,
moderated: Boolean,
},
],
required: false,
},
{collection: 'users'}
{ collection: "users" },
)
UserSchema.plugin(uniqueValidator)
UserSchema.virtual('recentlyplayedgames', {
ref: 'GamesSchema',
localField: 'recentlyplayed.id',
foreignField: 'idofgame'
UserSchema.virtual("recentlyplayedgames", {
ref: "GamesSchema",
localField: "recentlyplayed.id",
foreignField: "idofgame",
})
UserSchema.virtual('friendsdata', {
ref: 'UserSchema',
localField: 'friends.userid',
foreignField: 'userid'
UserSchema.virtual("friendsdata", {
ref: "UserSchema",
localField: "friends.userid",
foreignField: "userid",
})
UserSchema.virtual('feed.userdata', {
ref: 'UserSchema',
localField: 'feed.posterid',
foreignField: 'userid',
justOne: true
UserSchema.virtual("feed.userdata", {
ref: "UserSchema",
localField: "feed.posterid",
foreignField: "userid",
justOne: true,
})
const model = mongoose.model('UserSchema', UserSchema)
const model = mongoose.model("UserSchema", UserSchema)
module.exports = model

View File

@ -51,6 +51,7 @@
},
"devDependencies": {
"cross-env": "^7.0.3",
"nodemon": "^2.0.19"
"nodemon": "^2.0.19",
"prettier": "^3.0.3"
}
}

5145
Back/pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,61 +1,72 @@
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
let controller = new AbortController();
require('dotenv').config()
const fetch = (...args) =>
import("node-fetch").then(({ default: fetch }) => fetch(...args))
let controller = new AbortController()
require("dotenv").config()
const RCC_HOST = process.env.RCC_HOST
const url = 'http://'+RCC_HOST+':64989'; // change this to rcc soap
const url = "http://" + RCC_HOST + ":64989" // change this to rcc soap
var convert = require('xml-js');
var convert = require("xml-js")
const sampleHeaders = {
'Content-Type': 'text/xml;charset=UTF-8',
};
"Content-Type": "text/xml;charset=UTF-8",
}
async function OpenJob(jobid, script, expiration) {
return new Promise(async (resolve, reject) => {
// this is all boilerplate because soap sucks
var xml = {
_declaration: { _attributes: { version: '1.0', encoding: 'UTF-8' } },
'SOAP-ENV:Envelope': {
_declaration: {
_attributes: { version: "1.0", encoding: "UTF-8" },
},
"SOAP-ENV:Envelope": {
_attributes: {
'xmlns:SOAP-ENV': 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:ns1': 'http://roblox.com/'
"xmlns:SOAP-ENV":
"http://schemas.xmlsoap.org/soap/envelope/",
"xmlns:ns1": "http://roblox.com/",
},
"SOAP-ENV:Body": {
"ns1:OpenJobEx": {
"ns1:job": {
"ns1:id": { _text: "StringTest11" },
"ns1:expirationInSeconds": { _text: "10" },
"ns1:category": { _text: "0" },
"ns1:cores": { _text: "1" },
},
"ns1:script": {
"ns1:name": { _text: "StringTest11-Script" },
"ns1:script": {
_text: 'print("Recieved job with ID " .. game.JobId)\r\n',
},
"ns1:arguments": {},
},
},
'SOAP-ENV:Body': {
'ns1:OpenJobEx': {
'ns1:job': {
'ns1:id': { _text: 'StringTest11' },
'ns1:expirationInSeconds': { _text: '10' },
'ns1:category': { _text: '0' },
'ns1:cores': { _text: '1' }
},
'ns1:script': {
'ns1:name': { _text: 'StringTest11-Script' },
'ns1:script': {
_text: 'print("Recieved job with ID " .. game.JobId)\r\n'
},
'ns1:arguments': {}
}
}
}
}
}
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:OpenJobEx']['ns1:job']['ns1:id']._text = jobid
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:OpenJobEx']['ns1:job']['ns1:expirationInSeconds']._text = expiration
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:OpenJobEx"]["ns1:job"][
"ns1:id"
]._text = jobid
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:OpenJobEx"]["ns1:job"][
"ns1:expirationInSeconds"
]._text = expiration
if (!expiration) {
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:OpenJobEx']['ns1:job']['ns1:expirationInSeconds']._text = "60"
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:OpenJobEx"][
"ns1:job"
]["ns1:expirationInSeconds"]._text = "60"
}
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:OpenJobEx']['ns1:script']['ns1:script']._text = script
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:OpenJobEx"][
"ns1:script"
]["ns1:script"]._text = script
const body = convert.js2xml(xml, { compact: true, spaces: 4 })
try {
const result = await fetch(url, { method: 'POST', body })
const result = await fetch(url, { method: "POST", body })
const data = await result.text()
const convertedData = convert.xml2js(data, { compact: true, spaces: 4 })
return resolve(
convertedData
)
const convertedData = convert.xml2js(data, {
compact: true,
spaces: 4,
})
return resolve(convertedData)
} catch (error) {
return reject(error)
}
@ -66,30 +77,37 @@ async function GetAllJobs() {
return new Promise(async (resolve, reject) => {
const xmlData = (xml = {
_declaration: {
_attributes: { version: '1.0', encoding: 'UTF - 8' },
_attributes: { version: "1.0", encoding: "UTF - 8" },
},
'SOAP-ENV:Envelope': {
"SOAP-ENV:Envelope": {
_attributes: {
'xmlns:SOAP-ENV': 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:SOAP-ENC': 'http://schemas.xmlsoap.org/soap/encoding/',
'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
'xmlns:xsd': 'http://www.w3.org/2001/XMLSchema',
'xmlns:ns2': 'http://roblox.com/RCCServiceSoap',
'xmlns:ns1': 'http://roblox.com/',
'xmlns:ns3': 'http://roblox.com/RCCServiceSoap12',
"xmlns:SOAP-ENV":
"http://schemas.xmlsoap.org/soap/envelope/",
"xmlns:SOAP-ENC":
"http://schemas.xmlsoap.org/soap/encoding/",
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"xmlns:xsd": "http://www.w3.org/2001/XMLSchema",
"xmlns:ns2": "http://roblox.com/RCCServiceSoap",
"xmlns:ns1": "http://roblox.com/",
"xmlns:ns3": "http://roblox.com/RCCServiceSoap12",
},
'SOAP-ENV:Body': { 'ns1:GetAllJobsEx': {} },
"SOAP-ENV:Body": { "ns1:GetAllJobsEx": {} },
},
})
const body = convert.js2xml(xmlData, { compact: true, spaces: 4 })
try {
const result = await fetch(url, { method: 'POST', body })
const result = await fetch(url, { method: "POST", body })
const data = await result.text()
const convertedData = convert.xml2js(data, { compact: true, spaces: 4 })
const convertedData = convert.xml2js(data, {
compact: true,
spaces: 4,
})
return resolve(
convertedData['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:GetAllJobsExResponse']['ns1:GetAllJobsExResult']
convertedData["SOAP-ENV:Envelope"]["SOAP-ENV:Body"][
"ns1:GetAllJobsExResponse"
]["ns1:GetAllJobsExResult"],
)
} catch (error) {
return reject(error)
@ -97,124 +115,144 @@ async function GetAllJobs() {
})
}
async function Execute(jobid, script) {
return new Promise(async (resolve, reject) => {
var xml = {
_declaration: { _attributes: { version: '1.0', encoding: 'UTF - 8' } },
'SOAP-ENV:Envelope': {
_attributes: {
'xmlns:SOAP-ENV': 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:SOAP-ENC': 'http://schemas.xmlsoap.org/soap/encoding/',
'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
'xmlns:xsd': 'http://www.w3.org/2001/XMLSchema',
'xmlns:ns2': 'http://roblox.com/RCCServiceSoap',
'xmlns:ns1': 'http://roblox.com/',
'xmlns:ns3': 'http://roblox.com/RCCServiceSoap12'
_declaration: {
_attributes: { version: "1.0", encoding: "UTF - 8" },
},
"SOAP-ENV:Envelope": {
_attributes: {
"xmlns:SOAP-ENV":
"http://schemas.xmlsoap.org/soap/envelope/",
"xmlns:SOAP-ENC":
"http://schemas.xmlsoap.org/soap/encoding/",
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"xmlns:xsd": "http://www.w3.org/2001/XMLSchema",
"xmlns:ns2": "http://roblox.com/RCCServiceSoap",
"xmlns:ns1": "http://roblox.com/",
"xmlns:ns3": "http://roblox.com/RCCServiceSoap12",
},
"SOAP-ENV:Body": {
"ns1:ExecuteEx": {
"ns1:jobID": { _text: "Test" },
"ns1:script": {
"ns1:name": { _text: "Script" },
"ns1:script": { _text: 'print("no")' },
"ns1:arguments": { _text: "" },
},
},
},
},
'SOAP-ENV:Body': {
'ns1:ExecuteEx': {
'ns1:jobID': { _text: 'Test' },
'ns1:script': {
'ns1:name': { _text: 'Script' },
'ns1:script': { _text: 'print("no")' },
'ns1:arguments': { _text: '' }
}
}
}
}
}
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:ExecuteEx']['ns1:jobID']._text = jobid
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:ExecuteEx']['ns1:script']['ns1:script']._text = script
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:ExecuteEx"][
"ns1:jobID"
]._text = jobid
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:ExecuteEx"][
"ns1:script"
]["ns1:script"]._text = script
const body = convert.js2xml(xml, { compact: true, spaces: 4 })
try {
const result = await fetch(url, { method: 'POST', body })
const result = await fetch(url, { method: "POST", body })
const data = await result.text()
const convertedData = convert.xml2js(data, { compact: true, spaces: 4 })
return resolve(
convertedData
)
const convertedData = convert.xml2js(data, {
compact: true,
spaces: 4,
})
return resolve(convertedData)
} catch (error) {
return reject(error)
}
})
}
async function CloseJob(jobid) {
return new Promise(async (resolve, reject) => {
var xml = {
_declaration: { _attributes: { version: '1.0', encoding: 'UTF - 8' } },
'SOAP-ENV:Envelope': {
_attributes: {
'xmlns:SOAP-ENV': 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:SOAP-ENC': 'http://schemas.xmlsoap.org/soap/encoding/',
'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
'xmlns:xsd': 'http://www.w3.org/2001/XMLSchema',
'xmlns:ns2': 'http://roblox.com/RCCServiceSoap',
'xmlns:ns1': 'http://roblox.com/',
'xmlns:ns3': 'http://roblox.com/RCCServiceSoap12'
_declaration: {
_attributes: { version: "1.0", encoding: "UTF - 8" },
},
"SOAP-ENV:Envelope": {
_attributes: {
"xmlns:SOAP-ENV":
"http://schemas.xmlsoap.org/soap/envelope/",
"xmlns:SOAP-ENC":
"http://schemas.xmlsoap.org/soap/encoding/",
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"xmlns:xsd": "http://www.w3.org/2001/XMLSchema",
"xmlns:ns2": "http://roblox.com/RCCServiceSoap",
"xmlns:ns1": "http://roblox.com/",
"xmlns:ns3": "http://roblox.com/RCCServiceSoap12",
},
"SOAP-ENV:Body": {
"ns1:CloseJob": {
"ns1:jobID": { _text: "Test" },
},
},
},
'SOAP-ENV:Body': {
'ns1:CloseJob': {
'ns1:jobID': { _text: 'Test' }
}
}
}
}
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:CloseJob']['ns1:jobID']._text = jobid
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:CloseJob"][
"ns1:jobID"
]._text = jobid
const body = convert.js2xml(xml, { compact: true, spaces: 4 })
try {
const result = await fetch(url, { method: 'POST', body })
const result = await fetch(url, { method: "POST", body })
const data = await result.text()
const convertedData = convert.xml2js(data, { compact: true, spaces: 4 })
return resolve(
convertedData
)
const convertedData = convert.xml2js(data, {
compact: true,
spaces: 4,
})
return resolve(convertedData)
} catch (error) {
return reject(error)
}
})
}
async function RenewLease(jobid, expiration) {
return new Promise(async (resolve, reject) => {
var xml = {
_declaration: { _attributes: { version: '1.0', encoding: 'UTF-8' } },
'SOAP-ENV:Envelope': {
_declaration: {
_attributes: { version: "1.0", encoding: "UTF-8" },
},
"SOAP-ENV:Envelope": {
_attributes: {
'xmlns:SOAP-ENV': 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:ns1': 'http://roblox.com/',
'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance'
"xmlns:SOAP-ENV":
"http://schemas.xmlsoap.org/soap/envelope/",
"xmlns:ns1": "http://roblox.com/",
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
},
"SOAP-ENV:Body": {
"ns1:RenewLease": {
"ns1:jobID": {
_attributes: { "xsi:type": "ns1:Job" },
"ns1:id": { _text: "StringTest11" },
"ns1:expirationInSeconds": { _text: "10" },
"ns1:category": { _text: "0" },
"ns1:cores": { _text: "1" },
},
"ns1:expirationInSeconds": { _text: "100" },
},
},
'SOAP-ENV:Body': {
'ns1:RenewLease': {
'ns1:jobID': {
_attributes: { 'xsi:type': 'ns1:Job' },
'ns1:id': { _text: 'StringTest11' },
'ns1:expirationInSeconds': { _text: '10' },
'ns1:category': { _text: '0' },
'ns1:cores': { _text: '1' }
},
'ns1:expirationInSeconds': { _text: '100' }
}
}
}
}
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:RenewLease']['ns1:jobID']['ns1:id']._text = jobid
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:RenewLease']['ns1:expirationInSeconds']._text = expiration
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:RenewLease"][
"ns1:jobID"
]["ns1:id"]._text = jobid
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:RenewLease"][
"ns1:expirationInSeconds"
]._text = expiration
const body = convert.js2xml(xml, { compact: true, spaces: 4 })
try {
const result = await fetch(url, { method: 'POST', body })
const result = await fetch(url, { method: "POST", body })
const data = await result.text()
const convertedData = convert.xml2js(data, { compact: true, spaces: 4 })
return resolve(
convertedData
)
const convertedData = convert.xml2js(data, {
compact: true,
spaces: 4,
})
return resolve(convertedData)
} catch (error) {
return reject(error)
}
@ -224,25 +262,33 @@ async function RenewLease(jobid,expiration) {
async function GetExpiration(jobid) {
return new Promise(async (resolve, reject) => {
var xml = {
_declaration: { _attributes: { version: '1.0', encoding: 'UTF-8' } },
'SOAP-ENV:Envelope': {
_attributes: {
'xmlns:SOAP-ENV': 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:ns1': 'http://roblox.com/'
_declaration: {
_attributes: { version: "1.0", encoding: "UTF-8" },
},
"SOAP-ENV:Envelope": {
_attributes: {
"xmlns:SOAP-ENV":
"http://schemas.xmlsoap.org/soap/envelope/",
"xmlns:ns1": "http://roblox.com/",
},
"SOAP-ENV:Body": {
"ns1:GetExpiration": { "ns1:jobID": { _text: "Test" } },
},
},
'SOAP-ENV:Body': { 'ns1:GetExpiration': { 'ns1:jobID': { _text: 'Test' } } }
}
}
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:GetExpiration']['ns1:jobID']._text = jobid
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:GetExpiration"][
"ns1:jobID"
]._text = jobid
const body = convert.js2xml(xml, { compact: true, spaces: 4 })
try {
const result = await fetch(url, { method: 'POST', body })
const result = await fetch(url, { method: "POST", body })
const data = await result.text()
const convertedData = convert.xml2js(data, { compact: true, spaces: 4 })
return resolve(
convertedData
)
const convertedData = convert.xml2js(data, {
compact: true,
spaces: 4,
})
return resolve(convertedData)
} catch (error) {
return reject(error)
}
@ -253,26 +299,30 @@ async function GetExpiration(jobid){
async function CloseExpiredJobs() {
return new Promise(async (resolve, reject) => {
var xml = xml = {
_declaration: { _attributes: { version: '1.0', encoding: 'UTF-8' } },
'SOAP-ENV:Envelope': {
_attributes: {
'xmlns:SOAP-ENV': 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:ns1': 'http://roblox.com/'
var xml = (xml = {
_declaration: {
_attributes: { version: "1.0", encoding: "UTF-8" },
},
'SOAP-ENV:Body': { 'ns1:CloseExpiredJobs': {} }
}
}
"SOAP-ENV:Envelope": {
_attributes: {
"xmlns:SOAP-ENV":
"http://schemas.xmlsoap.org/soap/envelope/",
"xmlns:ns1": "http://roblox.com/",
},
"SOAP-ENV:Body": { "ns1:CloseExpiredJobs": {} },
},
})
const body = convert.js2xml(xml, { compact: true, spaces: 4 })
try {
const result = await fetch(url, { method: 'POST', body })
const result = await fetch(url, { method: "POST", body })
const data = await result.text()
const convertedData = convert.xml2js(data, { compact: true, spaces: 4 })
return resolve(
convertedData
)
const convertedData = convert.xml2js(data, {
compact: true,
spaces: 4,
})
return resolve(convertedData)
} catch (error) {
return reject(error)
}
@ -281,40 +331,43 @@ async function CloseExpiredJobs(){
async function CloseAllJobs() {
return new Promise(async (resolve, reject) => {
var xml = xml = {
_declaration: { _attributes: { version: '1.0', encoding: 'UTF-8' } },
'SOAP-ENV:Envelope': {
_attributes: {
'xmlns:SOAP-ENV': 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:ns1': 'http://roblox.com/'
var xml = (xml = {
_declaration: {
_attributes: { version: "1.0", encoding: "UTF-8" },
},
'SOAP-ENV:Body': { 'ns1:CloseAllJobs': {} }
}
}
"SOAP-ENV:Envelope": {
_attributes: {
"xmlns:SOAP-ENV":
"http://schemas.xmlsoap.org/soap/envelope/",
"xmlns:ns1": "http://roblox.com/",
},
"SOAP-ENV:Body": { "ns1:CloseAllJobs": {} },
},
})
const body = convert.js2xml(xml, { compact: true, spaces: 4 })
try {
const result = await fetch(url, { method: 'POST', body })
const result = await fetch(url, { method: "POST", body })
const data = await result.text()
const convertedData = convert.xml2js(data, { compact: true, spaces: 4 })
return resolve(
convertedData
)
const convertedData = convert.xml2js(data, {
compact: true,
spaces: 4,
})
return resolve(convertedData)
} catch (error) {
return reject(error)
}
})
}
module.exports = {OpenJob, GetAllJobs,Execute,CloseJob,RenewLease,GetExpiration,CloseExpiredJobs,CloseAllJobs}
module.exports = {
OpenJob,
GetAllJobs,
Execute,
CloseJob,
RenewLease,
GetExpiration,
CloseExpiredJobs,
CloseAllJobs,
}

View File

@ -1,14 +1,41 @@
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
let controller = new AbortController();
require('dotenv').config()
const fetch = (...args) =>
import("node-fetch").then(({ default: fetch }) => fetch(...args))
let controller = new AbortController()
require("dotenv").config()
const RCC_HOST = process.env.RCC_HOST
var convert = require('xml-js');
var convert = require("xml-js")
let url = 'http://'+RCC_HOST+':8000'; // change this to rcc soap
let url = "http://" + RCC_HOST + ":8000" // change this to rcc soap
async function OpenGame(jobid, port, ip, placeid, creatorid) {
return new Promise(async (resolve, reject) => {
let json = {"Mode":"GameServer","GameId":"game1","Settings":{"IsRobloxPlace":false,"PlaceId":1,"CreatorId":1,"GameId":"00000000-0000-0000-0000-000000000132","GsmInterval":50,"MaxPlayers":100,"MaxGameInstances":52,"ApiKey":"egg","GameCode":"AAAAAAAAAAAAAA-a","PreferredPlayerCapacity":10,"DatacenterId":1,"PlaceVisitAccessKey":"rbx_evt_ftp","UniverseId":13058,"PlaceFetchUrl":"https://mete0r.xyz/asset?id=11","MatchmakingContextId":1,"CreatorType":"User","PlaceVersion":123,"BaseUrl":"mete0r.xyz","MachineAddress":"localhost","JobId":"game1","PreferredPort":53640}}
let json = {
Mode: "GameServer",
GameId: "game1",
Settings: {
IsRobloxPlace: false,
PlaceId: 1,
CreatorId: 1,
GameId: "00000000-0000-0000-0000-000000000132",
GsmInterval: 50,
MaxPlayers: 100,
MaxGameInstances: 52,
ApiKey: "egg",
GameCode: "AAAAAAAAAAAAAA-a",
PreferredPlayerCapacity: 10,
DatacenterId: 1,
PlaceVisitAccessKey: "rbx_evt_ftp",
UniverseId: 13058,
PlaceFetchUrl: "https://mete0r.xyz/asset?id=11",
MatchmakingContextId: 1,
CreatorType: "User",
PlaceVersion: 123,
BaseUrl: "mete0r.xyz",
MachineAddress: "localhost",
JobId: "game1",
PreferredPort: 53640,
},
}
json.GameId = jobid
json.Settings.PreferredPort = port
json.Settings.MachineAddress = ip
@ -36,14 +63,17 @@ async function OpenGame(jobid,port,ip,placeid,creatorid){
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>`
//console.log(encodeURIComponent(JSON.stringify(json)))
try {
const result = await fetch(url+"/opengame/"+jobid+"/"+encodeURIComponent(JSON.stringify(json)))
const data = await result.text()
return resolve(
data
const result = await fetch(
url +
"/opengame/" +
jobid +
"/" +
encodeURIComponent(JSON.stringify(json)),
)
const data = await result.text()
return resolve(data)
} catch (error) {
return reject(error)
}
@ -52,7 +82,33 @@ async function OpenGame(jobid,port,ip,placeid,creatorid){
async function OpenGame2020(jobid, port, ip, placeid, creatorid) {
return new Promise(async (resolve, reject) => {
let json = {"Mode":"GameServer","GameId":"game1","Settings":{"IsRobloxPlace":false,"PlaceId":1,"CreatorId":1,"GameId":"00000000-0000-0000-0000-000000000132","GsmInterval":50,"MaxPlayers":100,"MaxGameInstances":52,"ApiKey":"egg","GameCode":"AAAAAAAAAAAAAA-a","PreferredPlayerCapacity":10,"DatacenterId":1,"PlaceVisitAccessKey":"rbx_evt_ftp","UniverseId":13058,"PlaceFetchUrl":"https://mete0r.xyz/asset?id=11","MatchmakingContextId":1,"CreatorType":"User","PlaceVersion":123,"BaseUrl":"mete0r.xyz","MachineAddress":"localhost","JobId":"game1","PreferredPort":53640}}
let json = {
Mode: "GameServer",
GameId: "game1",
Settings: {
IsRobloxPlace: false,
PlaceId: 1,
CreatorId: 1,
GameId: "00000000-0000-0000-0000-000000000132",
GsmInterval: 50,
MaxPlayers: 100,
MaxGameInstances: 52,
ApiKey: "egg",
GameCode: "AAAAAAAAAAAAAA-a",
PreferredPlayerCapacity: 10,
DatacenterId: 1,
PlaceVisitAccessKey: "rbx_evt_ftp",
UniverseId: 13058,
PlaceFetchUrl: "https://mete0r.xyz/asset?id=11",
MatchmakingContextId: 1,
CreatorType: "User",
PlaceVersion: 123,
BaseUrl: "mete0r.xyz",
MachineAddress: "localhost",
JobId: "game1",
PreferredPort: 53640,
},
}
json.GameId = jobid
json.Settings.PreferredPort = port
json.Settings.MachineAddress = ip
@ -61,7 +117,8 @@ let json = {"Mode":"GameServer","GameId":"game1","Settings":{"IsRobloxPlace":fa
json.Settings.UniverseId = json.Settings.PlaceId
json.Settings.CreatorId = creatorid
json.Settings.GameId = jobid
json.Settings.PlaceFetchUrl = "https://mete0r.xyz/asset?id="+parseFloat(placeid)
json.Settings.PlaceFetchUrl =
"https://mete0r.xyz/asset?id=" + parseFloat(placeid)
let xml = `<?xml version = "1.0" encoding = "UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns2="http://roblox.com/RCCServiceSoap" xmlns:ns1="http://roblox.com/" xmlns:ns3="http://roblox.com/RCCServiceSoap12">
@ -81,14 +138,17 @@ let json = {"Mode":"GameServer","GameId":"game1","Settings":{"IsRobloxPlace":fa
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>`
//console.log(encodeURIComponent(JSON.stringify(json)))
try {
const result = await fetch(url+"/opengame2020/"+jobid+"/"+encodeURIComponent(JSON.stringify(json)))
const data = await result.text()
return resolve(
data
const result = await fetch(
url +
"/opengame2020/" +
jobid +
"/" +
encodeURIComponent(JSON.stringify(json)),
)
const data = await result.text()
return resolve(data)
} catch (error) {
return reject(error)
}
@ -98,33 +158,37 @@ let json = {"Mode":"GameServer","GameId":"game1","Settings":{"IsRobloxPlace":fa
async function CloseJob(jobid) {
return new Promise(async (resolve, reject) => {
var xml = {
_declaration: { _attributes: { version: '1.0', encoding: 'UTF - 8' } },
'SOAP-ENV:Envelope': {
_attributes: {
'xmlns:SOAP-ENV': 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:SOAP-ENC': 'http://schemas.xmlsoap.org/soap/encoding/',
'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
'xmlns:xsd': 'http://www.w3.org/2001/XMLSchema',
'xmlns:ns2': 'http://roblox.com/RCCServiceSoap',
'xmlns:ns1': 'http://roblox.com/',
'xmlns:ns3': 'http://roblox.com/RCCServiceSoap12'
_declaration: {
_attributes: { version: "1.0", encoding: "UTF - 8" },
},
"SOAP-ENV:Envelope": {
_attributes: {
"xmlns:SOAP-ENV":
"http://schemas.xmlsoap.org/soap/envelope/",
"xmlns:SOAP-ENC":
"http://schemas.xmlsoap.org/soap/encoding/",
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"xmlns:xsd": "http://www.w3.org/2001/XMLSchema",
"xmlns:ns2": "http://roblox.com/RCCServiceSoap",
"xmlns:ns1": "http://roblox.com/",
"xmlns:ns3": "http://roblox.com/RCCServiceSoap12",
},
"SOAP-ENV:Body": {
"ns1:CloseJob": {
"ns1:jobID": { _text: "Test" },
},
},
},
'SOAP-ENV:Body': {
'ns1:CloseJob': {
'ns1:jobID': { _text: 'Test' }
}
}
}
}
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:CloseJob']['ns1:jobID']._text = jobid
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:CloseJob"][
"ns1:jobID"
]._text = jobid
const body = convert.js2xml(xml, { compact: true, spaces: 4 })
try {
const result = await fetch(url + "/closejob/" + jobid)
const data = await result.text()
return resolve(
data
)
return resolve(data)
} catch (error) {
return reject(error)
}
@ -134,18 +198,19 @@ async function CloseJob(jobid) {
async function OpenRender(userid, closeup) {
return new Promise(async (resolve, reject) => {
try {
const result = await fetch(url+"/openrender/"+userid+"/"+closeup)
const result = await fetch(
url + "/openrender/" + userid + "/" + closeup,
)
const data = await result.text()
//console.log(data)
if (data === '{"status": "error","error":"Already started"}') {
return resolve(
JSON.parse(data)
)
return resolve(JSON.parse(data))
}
const convertedData = convert.xml2js(data, { compact: true, spaces: 4 })
return resolve(
convertedData
)
const convertedData = convert.xml2js(data, {
compact: true,
spaces: 4,
})
return resolve(convertedData)
} catch (error) {
return reject(error)
}
@ -155,18 +220,19 @@ async function OpenRender(userid,closeup) {
async function OpenRenderAsset(assetid, type) {
return new Promise(async (resolve, reject) => {
try {
const result = await fetch(url+"/openrenderasset/"+assetid+"/"+type)
const result = await fetch(
url + "/openrenderasset/" + assetid + "/" + type,
)
const data = await result.text()
//console.log(data)
if (data === '{"status": "error","error":"Already started"}') {
return resolve(
JSON.parse(data)
)
return resolve(JSON.parse(data))
}
const convertedData = convert.xml2js(data, { compact: true, spaces: 4 })
return resolve(
convertedData
)
const convertedData = convert.xml2js(data, {
compact: true,
spaces: 4,
})
return resolve(convertedData)
} catch (error) {
return reject(error)
}
@ -175,37 +241,48 @@ async function OpenRenderAsset(assetid,type) {
async function lol2() {
const lol = await OpenRender(0)
console.log(lol['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:OpenJobResponse']['ns1:OpenJobResult'][0]['ns1:value']._text)
console.log(
lol["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:OpenJobResponse"][
"ns1:OpenJobResult"
][0]["ns1:value"]._text,
)
}
async function RenewLease(jobid, expiration) {
return new Promise(async (resolve, reject) => {
var xml = {
_declaration: { _attributes: { version: '1.0', encoding: 'UTF-8' } },
'SOAP-ENV:Envelope': {
_attributes: {
'xmlns:SOAP-ENV': 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:ns1': 'http://roblox.com/',
'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance'
_declaration: {
_attributes: { version: "1.0", encoding: "UTF-8" },
},
"SOAP-ENV:Envelope": {
_attributes: {
"xmlns:SOAP-ENV":
"http://schemas.xmlsoap.org/soap/envelope/",
"xmlns:ns1": "http://roblox.com/",
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
},
"SOAP-ENV:Body": {
"ns1:RenewLease": {
"ns1:jobID": { _text: "Test" },
"ns1:expirationInSeconds": { _text: "100" },
},
},
},
'SOAP-ENV:Body': {
'ns1:RenewLease': {
'ns1:jobID': { _text: 'Test' },
'ns1:expirationInSeconds': { _text: '100' }
}
}
}
}
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:RenewLease']['ns1:jobID']._text = jobid
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:RenewLease']['ns1:expirationInSeconds']._text = expiration
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:RenewLease"][
"ns1:jobID"
]._text = jobid
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:RenewLease"][
"ns1:expirationInSeconds"
]._text = expiration
const body = convert.js2xml(xml, { compact: true, spaces: 4 })
try {
const result = await fetch(url+"/renewlease/"+jobid+"/"+expiration)
const data = await result.text()
return resolve(
data
const result = await fetch(
url + "/renewlease/" + jobid + "/" + expiration,
)
const data = await result.text()
return resolve(data)
} catch (error) {
return reject(error)
}
@ -215,11 +292,15 @@ async function RenewLease(jobid,expiration) {
async function Execute(jobid, json) {
return new Promise(async (resolve, reject) => {
try {
const result = await fetch(url+"/executejson/"+jobid+"/"+encodeURIComponent(JSON.stringify(json)))
const data = await result.text()
return resolve(
data
const result = await fetch(
url +
"/executejson/" +
jobid +
"/" +
encodeURIComponent(JSON.stringify(json)),
)
const data = await result.text()
return resolve(data)
} catch (error) {
return reject(error)
}
@ -230,30 +311,37 @@ async function GetAllJobs() {
return new Promise(async (resolve, reject) => {
const xmlData = (xml = {
_declaration: {
_attributes: { version: '1.0', encoding: 'UTF - 8' },
_attributes: { version: "1.0", encoding: "UTF - 8" },
},
'SOAP-ENV:Envelope': {
"SOAP-ENV:Envelope": {
_attributes: {
'xmlns:SOAP-ENV': 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:SOAP-ENC': 'http://schemas.xmlsoap.org/soap/encoding/',
'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
'xmlns:xsd': 'http://www.w3.org/2001/XMLSchema',
'xmlns:ns2': 'http://roblox.com/RCCServiceSoap',
'xmlns:ns1': 'http://roblox.com/',
'xmlns:ns3': 'http://roblox.com/RCCServiceSoap12',
"xmlns:SOAP-ENV":
"http://schemas.xmlsoap.org/soap/envelope/",
"xmlns:SOAP-ENC":
"http://schemas.xmlsoap.org/soap/encoding/",
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"xmlns:xsd": "http://www.w3.org/2001/XMLSchema",
"xmlns:ns2": "http://roblox.com/RCCServiceSoap",
"xmlns:ns1": "http://roblox.com/",
"xmlns:ns3": "http://roblox.com/RCCServiceSoap12",
},
'SOAP-ENV:Body': { 'ns1:GetAllJobsEx': {} },
"SOAP-ENV:Body": { "ns1:GetAllJobsEx": {} },
},
})
const body = convert.js2xml(xmlData, { compact: true, spaces: 4 })
try {
const result = await fetch(url, { method: 'POST', body })
const result = await fetch(url, { method: "POST", body })
const data = await result.text()
const convertedData = convert.xml2js(data, { compact: true, spaces: 4 })
const convertedData = convert.xml2js(data, {
compact: true,
spaces: 4,
})
return resolve(
convertedData['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:GetAllJobsExResponse']['ns1:GetAllJobsExResult']
convertedData["SOAP-ENV:Envelope"]["SOAP-ENV:Body"][
"ns1:GetAllJobsExResponse"
]["ns1:GetAllJobsExResult"],
)
} catch (error) {
return reject(error)
@ -267,34 +355,32 @@ let res = await GetAllJobs()
//console.dir(res,{ depth: null })
let exists = false
if (res != "{}") {
if (Array.isArray(res['ns1:Job']) === false){
console.log('asd')
if (Array.isArray(res["ns1:Job"]) === false) {
console.log("asd")
//console.log(res['ns1:Job']['ns1:id']._text)
if (res['ns1:Job']['ns1:id']._text === 'game2'){
if (res["ns1:Job"]["ns1:id"]._text === "game2") {
exists = true
}
} else {
res['ns1:Job'].forEach(element => {
if (element['ns1:id']?._text === 'game2'){
res["ns1:Job"].forEach(element => {
if (element["ns1:id"]?._text === "game2") {
exists = true
}
})
}
}
console.log(exists)
}
//lol()
//GetAllJobs()
//OpenGame('game2','3333','127.0.0.1','2')
module.exports = {OpenGame,CloseJob,RenewLease,GetAllJobs,OpenRender,OpenRenderAsset,OpenGame2020,Execute}
module.exports = {
OpenGame,
CloseJob,
RenewLease,
GetAllJobs,
OpenRender,
OpenRenderAsset,
OpenGame2020,
Execute,
}

View File

@ -1,36 +1,95 @@
const express = require("express")
const router = express.Router()
const { requireAuth } = require('../../middleware/authmiddlewaregame')
const crypto = require('crypto');
const fs = require('fs')
const key = fs.readFileSync('DefaultPrivateKey.pem')
const { getPort, checkPort, getRandomPort, waitForPort } = require('get-port-please')
const { requireAuth } = require("../../middleware/authmiddlewaregame")
const crypto = require("crypto")
const fs = require("fs")
const key = fs.readFileSync("DefaultPrivateKey.pem")
const {
getPort,
checkPort,
getRandomPort,
waitForPort,
} = require("get-port-please")
const RCC_HOST = process.env.RCC_HOST
var sanitize = require('mongo-sanitize');
const games = require('./../../model/games.js')
var sanitize = require("mongo-sanitize")
const games = require("./../../model/games.js")
const signatures = require("./../signatures.js")
const rcc = require('../../model/rcc2018.js')
const rcctalk = require('../../rcctalk2018')
const User = require('../../model/user.js')
const rcc = require("../../model/rcc2018.js")
const rcctalk = require("../../rcctalk2018")
const User = require("../../model/user.js")
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
return new Promise(resolve => {
setTimeout(resolve, ms)
})
}
const _2018placelauncher = async (req, res, next) => {
var enabled = req.config
if (enabled.GamesEnabled === false) {
return res.json({status:"error",error:"Games are disabled bad boy"})
return res.json({
status: "error",
error: "Games are disabled bad boy",
})
}
var joinJson = {
ClientPort: 0,
MachineAddress: "localhost",
ServerPort: 25564,
PingUrl: "",
PingInterval: 120,
UserName: "default",
SeleniumTestMode: false,
UserId: 0,
SuperSafeChat: false,
CharacterAppearance: "http://shitncumblox.gq/game/charapp?name=default",
ClientTicket: "",
GameId: 1,
PlaceId: 1818,
MeasurementUrl: "",
WaitingForCharacterGuid: "cad99b30-7983-434b-b24c-eac12595e5fd",
BaseUrl: "http://www.mete0r.xyz/",
ChatStyle: "ClassicAndBubble",
VendorId: 0,
ScreenShotInfo: "",
VideoInfo:
'<?xml version="1.0"?><entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007"><media:group><media:title type="plain"><![CDATA[ROBLOX Place]]></media:title><media:description type="plain"><![CDATA[ For more games visit http://www.roblox.com]]></media:description><media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">Games</media:category><media:keywords>ROBLOX, video, free game, online virtual world</media:keywords></media:group></entry>',
CreatorId: 0,
CreatorTypeEnum: "User",
MembershipType: "None",
AccountAge: 365,
CookieStoreFirstTimePlayKey: "rbx_evt_ftp",
CookieStoreFiveMinutePlayKey: "rbx_evt_fmp",
CookieStoreEnabled: true,
IsRobloxPlace: false,
GenerateTeleportJoin: false,
IsUnknownOrUnder13: false,
SessionId:
"c25fd620-bbaa-4fb2-b022-3f053cdd1abd|00000000-0000-0000-0000-000000000000|0|204.236.226.210|8|2016-08-17T01:05:05.7115837Z|0|null|null|null|null",
DataCenterId: 0,
UniverseId: 0,
BrowserTrackerId: 0,
UsePortraitMode: false,
FollowUserId: 0,
CharacterAppearanceId: 1,
}
var joinJson = {"ClientPort":0,"MachineAddress":"localhost","ServerPort":25564,"PingUrl":"","PingInterval":120,"UserName":"default","SeleniumTestMode":false,"UserId":0,"SuperSafeChat":false,"CharacterAppearance":"http://shitncumblox.gq/game/charapp?name=default","ClientTicket":"","GameId":1,"PlaceId":1818,"MeasurementUrl":"","WaitingForCharacterGuid":"cad99b30-7983-434b-b24c-eac12595e5fd","BaseUrl":"http://www.mete0r.xyz/","ChatStyle":"ClassicAndBubble","VendorId":0,"ScreenShotInfo":"","VideoInfo":"<?xml version=\"1.0\"?><entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:media=\"http://search.yahoo.com/mrss/\" xmlns:yt=\"http://gdata.youtube.com/schemas/2007\"><media:group><media:title type=\"plain\"><![CDATA[ROBLOX Place]]></media:title><media:description type=\"plain\"><![CDATA[ For more games visit http://www.roblox.com]]></media:description><media:category scheme=\"http://gdata.youtube.com/schemas/2007/categories.cat\">Games</media:category><media:keywords>ROBLOX, video, free game, online virtual world</media:keywords></media:group></entry>","CreatorId":0,"CreatorTypeEnum":"User","MembershipType":"None","AccountAge":365,"CookieStoreFirstTimePlayKey":"rbx_evt_ftp","CookieStoreFiveMinutePlayKey":"rbx_evt_fmp","CookieStoreEnabled":true,"IsRobloxPlace":false,"GenerateTeleportJoin":false,"IsUnknownOrUnder13":false,"SessionId":"c25fd620-bbaa-4fb2-b022-3f053cdd1abd|00000000-0000-0000-0000-000000000000|0|204.236.226.210|8|2016-08-17T01:05:05.7115837Z|0|null|null|null|null","DataCenterId":0,"UniverseId":0,"BrowserTrackerId":0,"UsePortraitMode":false,"FollowUserId":0,"CharacterAppearanceId":1}
if (!req.query.name && !req.query.placeId && !req.query.placeid) {
return res.json({ status: "error", error: "no placeid bad" })
}
if (req.userdocument.gamejoin2018) {
return res.json({"jobId":"Test","status":2,"joinScriptUrl":"http://mete0r.xyz/game/join.ashx?ver=2018&auth="+req.query.auth??req.cookies.jwt,"authenticationUrl":"http://mete0r.xyz/Login/Negotiate.ashx","authenticationTicket":"SomeTicketThatDosentCrash","message":""})
return res.json({
jobId: "Test",
status: 2,
joinScriptUrl:
"http://mete0r.xyz/game/join.ashx?ver=2018&auth=" +
req.query.auth ?? req.cookies.jwt,
authenticationUrl: "http://mete0r.xyz/Login/Negotiate.ashx",
authenticationTicket: "SomeTicketThatDosentCrash",
message: "",
})
}
var sanitizedplaceid = sanitize(req.query.name??req.query.placeId??req.query.placeid)
var sanitizedplaceid = sanitize(
req.query.name ?? req.query.placeId ?? req.query.placeid,
)
const game = await games.findOne({ idofgame: sanitizedplaceid }).lean()
if (!game) {
return res.json({ status: "error", error: "that game doesn't exist!" })
@ -40,12 +99,12 @@ function sleep(ms) {
}
let instance = await rcc.findOne({ PlaceId: sanitizedplaceid }).lean()
if (instance && instance.Status === 2) {
// if an rcc instance already exists we don't need to create a new one so we will just drag them into the existing game
joinJson.UserName = req.userdocument.username
joinJson.UserId = req.userdocument.userid
joinJson.CharacterAppearance = "http://mete0r.xyz/v1.1/avatar-fetch?userId" + req.userdocument.userid
joinJson.CharacterAppearance =
"http://mete0r.xyz/v1.1/avatar-fetch?userId" +
req.userdocument.userid
joinJson.MachineAddress = RCC_HOST // need to put rcc host here lol
joinJson.ServerPort = instance.Port
joinJson.PlaceId = instance.PlaceId
@ -58,52 +117,95 @@ function sleep(ms) {
const timestamp = Date.now()
joinJson.ClientTicket = timestamp + ";" // timestamp
//create signature 1
const sign1 = crypto.createSign('SHA1');
sign1.update(`${req.userdocument.userid}\n`/*userid*/+`${req.userdocument.username}\n`/*username*/+`http://mete0r.xyz/v1.1/avatar-fetch?userId=${req.userdocument.userid}\n`/*charapp*/+`game${sanitizedplaceid}\n`/*jobid*/+ timestamp/*timestamp*/)
const sign1 = crypto.createSign("SHA1")
sign1.update(
`${req.userdocument.userid}\n` /*userid*/ +
`${req.userdocument.username}\n` /*username*/ +
`http://mete0r.xyz/v1.1/avatar-fetch?userId=${req.userdocument.userid}\n` /*charapp*/ +
`game${sanitizedplaceid}\n` /*jobid*/ +
timestamp /*timestamp*/,
)
var signature1 = sign1.sign(key, "base64")
joinJson.ClientTicket += signature1 + ";"
//create signature 2
const sign2 = crypto.createSign('SHA1');
sign2.update(`${req.userdocument.userid}\n`/*userid*/+`game${sanitizedplaceid}\n`/*jobid*/+ timestamp/*timestamp*/)
const sign2 = crypto.createSign("SHA1")
sign2.update(
`${req.userdocument.userid}\n` /*userid*/ +
`game${sanitizedplaceid}\n` /*jobid*/ +
timestamp /*timestamp*/,
)
var signature2 = sign2.sign(key, "base64")
joinJson.ClientTicket += signature2
req.userdocument.gamejoin2018 = JSON.stringify(joinJson)
req.userdocument.markModified('gamejoin2018')
req.userdocument.markModified("gamejoin2018")
await req.userdocument.save()
var joinScriptJson = {"jobId":"Test","status":2,"joinScriptUrl":"http://mete0r.xyz/game/join.ashx?ver=2018&auth="+joinJson.SessionId,"authenticationUrl":"http://mete0r.xyz/Login/Negotiate.ashx","authenticationTicket":"SomeTicketThatDosentCrash","message":""}
var joinScriptJson = {
jobId: "Test",
status: 2,
joinScriptUrl:
"http://mete0r.xyz/game/join.ashx?ver=2018&auth=" +
joinJson.SessionId,
authenticationUrl: "http://mete0r.xyz/Login/Negotiate.ashx",
authenticationTicket: "SomeTicketThatDosentCrash",
message: "",
}
return res.send(JSON.stringify(joinScriptJson))
}
if (instance && instance.Status === 1) {
var joinScriptJson = {"jobId":"Test","status":1,"joinScriptUrl":"http://mete0r.xyz/game/join.ashx?ver=2018&auth="+joinJson.SessionId,"authenticationUrl":"http://mete0r.xyz/Login/Negotiate.ashx","authenticationTicket":"SomeTicketThatDosentCrash","message":""}
var joinScriptJson = {
jobId: "Test",
status: 1,
joinScriptUrl:
"http://mete0r.xyz/game/join.ashx?ver=2018&auth=" +
joinJson.SessionId,
authenticationUrl: "http://mete0r.xyz/Login/Negotiate.ashx",
authenticationTicket: "SomeTicketThatDosentCrash",
message: "",
}
return res.send(JSON.stringify(joinScriptJson))
}
var port = await getPort({ random: true })
// launch job
rcctalk.OpenGame("game"+sanitizedplaceid,port,RCC_HOST,sanitizedplaceid,game.useridofowner)
rcctalk.OpenGame(
"game" + sanitizedplaceid,
port,
RCC_HOST,
sanitizedplaceid,
game.useridofowner,
)
//console.dir(response,{ depth: null })
//console.dir(response,{ depth: null })
await rcc.create({
PlaceId: sanitizedplaceid,
Port: port,
Status: 1 // 1 means loading
Status: 1, // 1 means loading
})
//console.log(newrenderscript)
var joinScriptJson = {"jobId":"Test","status":1,"joinScriptUrl":"http://mete0r.xyz/game/join.ashx?ver=2020&auth="+joinJson.SessionId,"authenticationUrl":"http://mete0r.xyz/Login/Negotiate.ashx","authenticationTicket":"SomeTicketThatDosentCrash","message":""}
var joinScriptJson = {
jobId: "Test",
status: 1,
joinScriptUrl:
"http://mete0r.xyz/game/join.ashx?ver=2020&auth=" +
joinJson.SessionId,
authenticationUrl: "http://mete0r.xyz/Login/Negotiate.ashx",
authenticationTicket: "SomeTicketThatDosentCrash",
message: "",
}
return res.send(JSON.stringify(joinScriptJson))
}
router.all("/2018/join", requireAuth, _2018placelauncher, async (req, res) => {
return res.json({status:"error",error:"Version different than client requested."})
return res.json({
status: "error",
error: "Version different than client requested.",
})
})
//rcctalk.CloseJob('game2')

View File

@ -1,47 +1,110 @@
const express = require("express")
const router = express.Router()
const { requireAuth } = require('../../middleware/authmiddlewaregame')
const crypto = require('crypto');
const fs = require('fs')
const key = fs.readFileSync('PrivateKey2020.txt')
const { getPort, checkPort, getRandomPort, waitForPort } = require('get-port-please')
const { requireAuth } = require("../../middleware/authmiddlewaregame")
const crypto = require("crypto")
const fs = require("fs")
const key = fs.readFileSync("PrivateKey2020.txt")
const {
getPort,
checkPort,
getRandomPort,
waitForPort,
} = require("get-port-please")
const RCC_HOST = process.env.RCC_HOST
var sanitize = require('mongo-sanitize');
const games = require('./../../model/games.js')
var sanitize = require("mongo-sanitize")
const games = require("./../../model/games.js")
const signatures = require("./../signatures.js")
const rcc = require('../../model/rcc2020.js')
const rcctalk = require('../../rcctalk2018')
const User = require('../../model/user.js')
const bodyParser = require('body-parser')
const rcc = require("../../model/rcc2020.js")
const rcctalk = require("../../rcctalk2018")
const User = require("../../model/user.js")
const bodyParser = require("body-parser")
router.use(bodyParser.json())
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
return new Promise(resolve => {
setTimeout(resolve, ms)
})
}
const _2020placelauncher = async (req, res, next) => {
var enabled = req.config
if (enabled.GamesEnabled === false) {
return res.json({status:"error",error:"Games are disabled bad boy"})
return res.json({
status: "error",
error: "Games are disabled bad boy",
})
}
if (req.headers?.['user-agent']?.includes("Android") === true || req.headers?.['user-agent']?.includes("iPhone") === true){
if (
req.headers?.["user-agent"]?.includes("Android") === true ||
req.headers?.["user-agent"]?.includes("iPhone") === true
) {
console.log(req.headers)
console.log(req.userdocument.username)
}
if (req.method === "POST"){ // mobile join-game
if (req.method === "POST") {
// mobile join-game
req.query.name = req.body.placeId
}
var joinJson = {"ClientPort":0,"MachineAddress":"localhost","ServerPort":25564,"PingUrl":"","PingInterval":120,"UserName":"default","SeleniumTestMode":false,"UserId":0,"SuperSafeChat":false,"CharacterAppearance":"http://shitncumblox.gq/game/charapp?name=default","ClientTicket":"","GameId":1,"PlaceId":1818,"MeasurementUrl":"","WaitingForCharacterGuid":"cad99b30-7983-434b-b24c-eac12595e5fd","BaseUrl":"http://www.mete0r.xyz/","ChatStyle":"ClassicAndBubble","VendorId":0,"ScreenShotInfo":"","VideoInfo":"<?xml version=\"1.0\"?><entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:media=\"http://search.yahoo.com/mrss/\" xmlns:yt=\"http://gdata.youtube.com/schemas/2007\"><media:group><media:title type=\"plain\"><![CDATA[ROBLOX Place]]></media:title><media:description type=\"plain\"><![CDATA[ For more games visit http://www.roblox.com]]></media:description><media:category scheme=\"http://gdata.youtube.com/schemas/2007/categories.cat\">Games</media:category><media:keywords>ROBLOX, video, free game, online virtual world</media:keywords></media:group></entry>","CreatorId":0,"CreatorTypeEnum":"User","MembershipType":"None","AccountAge":365,"CookieStoreFirstTimePlayKey":"rbx_evt_ftp","CookieStoreFiveMinutePlayKey":"rbx_evt_fmp","CookieStoreEnabled":true,"IsRobloxPlace":false,"GenerateTeleportJoin":false,"IsUnknownOrUnder13":false,"SessionId":"c25fd620-bbaa-4fb2-b022-3f053cdd1abd|00000000-0000-0000-0000-000000000000|0|204.236.226.210|8|2016-08-17T01:05:05.7115837Z|0|null|null|null|null","DataCenterId":0,"UniverseId":0,"BrowserTrackerId":0,"UsePortraitMode":false,"FollowUserId":0,"CharacterAppearanceId":1}
var joinJson = {
ClientPort: 0,
MachineAddress: "localhost",
ServerPort: 25564,
PingUrl: "",
PingInterval: 120,
UserName: "default",
SeleniumTestMode: false,
UserId: 0,
SuperSafeChat: false,
CharacterAppearance: "http://shitncumblox.gq/game/charapp?name=default",
ClientTicket: "",
GameId: 1,
PlaceId: 1818,
MeasurementUrl: "",
WaitingForCharacterGuid: "cad99b30-7983-434b-b24c-eac12595e5fd",
BaseUrl: "http://www.mete0r.xyz/",
ChatStyle: "ClassicAndBubble",
VendorId: 0,
ScreenShotInfo: "",
VideoInfo:
'<?xml version="1.0"?><entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007"><media:group><media:title type="plain"><![CDATA[ROBLOX Place]]></media:title><media:description type="plain"><![CDATA[ For more games visit http://www.roblox.com]]></media:description><media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">Games</media:category><media:keywords>ROBLOX, video, free game, online virtual world</media:keywords></media:group></entry>',
CreatorId: 0,
CreatorTypeEnum: "User",
MembershipType: "None",
AccountAge: 365,
CookieStoreFirstTimePlayKey: "rbx_evt_ftp",
CookieStoreFiveMinutePlayKey: "rbx_evt_fmp",
CookieStoreEnabled: true,
IsRobloxPlace: false,
GenerateTeleportJoin: false,
IsUnknownOrUnder13: false,
SessionId:
"c25fd620-bbaa-4fb2-b022-3f053cdd1abd|00000000-0000-0000-0000-000000000000|0|204.236.226.210|8|2016-08-17T01:05:05.7115837Z|0|null|null|null|null",
DataCenterId: 0,
UniverseId: 0,
BrowserTrackerId: 0,
UsePortraitMode: false,
FollowUserId: 0,
CharacterAppearanceId: 1,
}
if (!req.query.name && !req.query.placeId && !req.query.placeid) {
return res.json({ status: "error", error: "no placeid bad" })
}
if (req.userdocument.gamejoin2020) {
return res.json({"jobId":"Test","status":2,"joinScriptUrl":"http://mete0r.xyz/game/join.ashx?ver=2020&auth="+req.query.auth??req.cookies.jwt,"authenticationUrl":"http://mete0r.xyz/Login/Negotiate.ashx","authenticationTicket":"SomeTicketThatDosentCrash","message":""})
return res.json({
jobId: "Test",
status: 2,
joinScriptUrl:
"http://mete0r.xyz/game/join.ashx?ver=2020&auth=" +
req.query.auth ?? req.cookies.jwt,
authenticationUrl: "http://mete0r.xyz/Login/Negotiate.ashx",
authenticationTicket: "SomeTicketThatDosentCrash",
message: "",
})
}
var sanitizedplaceid = sanitize(req.query.name??req.query.placeId??req.query.placeid)
var sanitizedplaceid = sanitize(
req.query.name ?? req.query.placeId ?? req.query.placeid,
)
const game = await games.findOne({ idofgame: sanitizedplaceid }).lean()
if (!game) {
return res.json({ status: "error", error: "that game doesn't exist!" })
@ -51,12 +114,12 @@ const _2020placelauncher = async(req,res,next) => {
}
let instance = await rcc.findOne({ PlaceId: sanitizedplaceid }).lean()
if (instance && instance.Status === 2) {
// if an rcc instance already exists we don't need to create a new one so we will just drag them into the existing game
joinJson.UserName = req.userdocument.username
joinJson.UserId = req.userdocument.userid
joinJson.CharacterAppearance = "http://mete0r.xyz/v1.1/avatar-fetch?userId=" + req.userdocument.userid
joinJson.CharacterAppearance =
"http://mete0r.xyz/v1.1/avatar-fetch?userId=" +
req.userdocument.userid
joinJson.MachineAddress = RCC_HOST // need to put rcc host here lol
joinJson.ServerPort = instance.Port
joinJson.PlaceId = instance.PlaceId
@ -69,139 +132,196 @@ const _2020placelauncher = async(req,res,next) => {
const timestamp = Date.now()
joinJson.ClientTicket = timestamp + ";" // timestamp
//create signature 1
const sign1 = crypto.createSign('SHA1');
sign1.update(`${req.userdocument.userid}\n`/*userid*/+`${req.userdocument.username}\n`/*username*/+`${"0"}\n`/*userid 2 that 0k wants for some reason what a retard*/+`game${sanitizedplaceid}\n`/*jobid*/+ timestamp/*timestamp*/)
const sign1 = crypto.createSign("SHA1")
sign1.update(
`${req.userdocument.userid}\n` /*userid*/ +
`${req.userdocument.username}\n` /*username*/ +
`${"0"}\n` /*userid 2 that 0k wants for some reason what a retard*/ +
`game${sanitizedplaceid}\n` /*jobid*/ +
timestamp /*timestamp*/,
)
var signature1 = sign1.sign(key, "base64")
joinJson.ClientTicket += signature1 + ";"
//create signature 2
const sign2 = crypto.createSign('SHA1');
sign2.update(`${req.userdocument.userid}\n`/*userid*/+`game${sanitizedplaceid}\n`/*jobid*/+ timestamp/*timestamp*/)
const sign2 = crypto.createSign("SHA1")
sign2.update(
`${req.userdocument.userid}\n` /*userid*/ +
`game${sanitizedplaceid}\n` /*jobid*/ +
timestamp /*timestamp*/,
)
var signature2 = sign2.sign(key, "base64")
joinJson.ClientTicket += signature2 + ";4"
if (req.method === "POST" && req.body.isTeleport){ // mobile join-game
const mobileJoin =
if (req.method === "POST" && req.body.isTeleport) {
// mobile join-game
const mobileJoin = {
ClientPort: 0,
MachineAddress: RCC_HOST,
ServerPort: instance.Port,
ServerConnections: [
{
"ClientPort": 0,
"MachineAddress": RCC_HOST,
"ServerPort": instance.Port,
"ServerConnections": [
{
"Address": RCC_HOST,
"Port": instance.Port
}
Address: RCC_HOST,
Port: instance.Port,
},
],
"DirectServerReturn": true,
"TokenGenAlgorithm": 0,
"PepperId": 0,
"TokenValue": "vg",
"PingUrl": "",
"PingInterval": 0,
"UserName": req.userdocument.username,
"SeleniumTestMode": false,
"UserId": req.userdocument.userid,
"RobloxLocale": "",
"GameLocale": "",
"SuperSafeChat": false,
"CharacterAppearance": "http://mete0r.xyz/v1.1/avatar-fetch?userId=" + req.userdocument.userid,
"ClientTicket": joinJson.ClientTicket,
"GameId": ""+sanitizedplaceid,
"PlaceId": sanitizedplaceid,
"BaseUrl": "http://www.mete0r.xyz/",
"ChatStyle": "ClassicAndBubble",
"CreatorId": game.useridofowner,
"CreatorTypeEnum": "User",
"MembershipType": req.userdocument.membership,
"AccountAge": 365,
"CookieStoreFirstTimePlayKey": "rbx_evt_ftp",
"CookieStoreFiveMinutePlayKey": "rbx_evt_fmp",
"CookieStoreEnabled": false,
"IsUnknownOrUnder13": false,
"GameChatType": "AllUsers",
"SessionId": req.query.auth??req.cookies.jwt,
"AnalyticsSessionId": "",
"DataCenterId": 0,
"UniverseId": sanitizedplaceid,
"FollowUserId": 0,
"characterAppearanceId": req.userdocument.userid,
"CountryCode": "US",
"AlternateName": "",
"RandomSeed1": "57575745353",
"ClientPublicKeyData": ""
DirectServerReturn: true,
TokenGenAlgorithm: 0,
PepperId: 0,
TokenValue: "vg",
PingUrl: "",
PingInterval: 0,
UserName: req.userdocument.username,
SeleniumTestMode: false,
UserId: req.userdocument.userid,
RobloxLocale: "",
GameLocale: "",
SuperSafeChat: false,
CharacterAppearance:
"http://mete0r.xyz/v1.1/avatar-fetch?userId=" +
req.userdocument.userid,
ClientTicket: joinJson.ClientTicket,
GameId: "" + sanitizedplaceid,
PlaceId: sanitizedplaceid,
BaseUrl: "http://www.mete0r.xyz/",
ChatStyle: "ClassicAndBubble",
CreatorId: game.useridofowner,
CreatorTypeEnum: "User",
MembershipType: req.userdocument.membership,
AccountAge: 365,
CookieStoreFirstTimePlayKey: "rbx_evt_ftp",
CookieStoreFiveMinutePlayKey: "rbx_evt_fmp",
CookieStoreEnabled: false,
IsUnknownOrUnder13: false,
GameChatType: "AllUsers",
SessionId: req.query.auth ?? req.cookies.jwt,
AnalyticsSessionId: "",
DataCenterId: 0,
UniverseId: sanitizedplaceid,
FollowUserId: 0,
characterAppearanceId: req.userdocument.userid,
CountryCode: "US",
AlternateName: "",
RandomSeed1: "57575745353",
ClientPublicKeyData: "",
}
console.log(mobileJoin)
return res.json({
"jobId": "Test",
"status": 2,
"joinScriptUrl": `http://mete0r.xyz/game/join.ashx?ver=2020&auth=${req.query.auth??req.cookies.jwt}`,
"authenticationUrl": "http://mete0r.xyz/Login/Negotiate.ashx",
"authenticationTicket": "SomeTicketThatDosentCrash",
"message": "",
"joinScript": mobileJoin
jobId: "Test",
status: 2,
joinScriptUrl: `http://mete0r.xyz/game/join.ashx?ver=2020&auth=${
req.query.auth ?? req.cookies.jwt
}`,
authenticationUrl: "http://mete0r.xyz/Login/Negotiate.ashx",
authenticationTicket: "SomeTicketThatDosentCrash",
message: "",
joinScript: mobileJoin,
})
}
req.userdocument.gamejoin2020 = JSON.stringify(joinJson)
req.userdocument.markModified('gamejoin2020')
req.userdocument.markModified("gamejoin2020")
await req.userdocument.save()
var joinScriptJson = {"jobId":"Test","status":2,"joinScriptUrl":"http://mete0r.xyz/game/join.ashx?ver=2020&auth="+joinJson.SessionId,"authenticationUrl":"http://mete0r.xyz/Login/Negotiate.ashx","authenticationTicket":"SomeTicketThatDosentCrash","message":""}
var joinScriptJson = {
jobId: "Test",
status: 2,
joinScriptUrl:
"http://mete0r.xyz/game/join.ashx?ver=2020&auth=" +
joinJson.SessionId,
authenticationUrl: "http://mete0r.xyz/Login/Negotiate.ashx",
authenticationTicket: "SomeTicketThatDosentCrash",
message: "",
}
return res.send(JSON.stringify(joinScriptJson))
}
if (instance && instance.Status === 1) {
var joinScriptJson = {"jobId":"Test","status":1,"joinScriptUrl":"http://mete0r.xyz/game/join.ashx?ver=2020&auth="+joinJson.SessionId,"authenticationUrl":"http://mete0r.xyz/Login/Negotiate.ashx","authenticationTicket":"SomeTicketThatDosentCrash","message":""}
var joinScriptJson = {
jobId: "Test",
status: 1,
joinScriptUrl:
"http://mete0r.xyz/game/join.ashx?ver=2020&auth=" +
joinJson.SessionId,
authenticationUrl: "http://mete0r.xyz/Login/Negotiate.ashx",
authenticationTicket: "SomeTicketThatDosentCrash",
message: "",
}
if (req.method === "POST" && req.body.isTeleport){ // mobile join-game
if (req.method === "POST" && req.body.isTeleport) {
// mobile join-game
return res.json({
"jobId": "Test",
"status": 0,
"joinScriptUrl": "http://mete0r.xyz/game/join.ashx?ver=2020&auth="+req.query.auth??req.cookies.jwt,
"authenticationUrl": "http://mete0r.xyz/Login/Negotiate.ashx",
"authenticationTicket": "SomeTicketThatDosentCrash",
"message": ""
jobId: "Test",
status: 0,
joinScriptUrl:
"http://mete0r.xyz/game/join.ashx?ver=2020&auth=" +
req.query.auth ?? req.cookies.jwt,
authenticationUrl: "http://mete0r.xyz/Login/Negotiate.ashx",
authenticationTicket: "SomeTicketThatDosentCrash",
message: "",
})
}
return res.send(JSON.stringify(joinScriptJson))
}
var port = 53640 + Math.floor(Math.random() * 100)
// launch job
rcctalk.OpenGame2020("game"+sanitizedplaceid,port,RCC_HOST,sanitizedplaceid,game.useridofowner)
rcctalk.OpenGame2020(
"game" + sanitizedplaceid,
port,
RCC_HOST,
sanitizedplaceid,
game.useridofowner,
)
//console.dir(response,{ depth: null })
await rcc.create({
PlaceId: sanitizedplaceid,
Port: port,
Status: 1 // 1 means loading
Status: 1, // 1 means loading
})
//console.log(newrenderscript)
var joinScriptJson = {"jobId":"Test","status":1,"joinScriptUrl":"http://mete0r.xyz/game/join.ashx?ver=2020&auth="+joinJson.SessionId,"authenticationUrl":"http://mete0r.xyz/Login/Negotiate.ashx","authenticationTicket":"SomeTicketThatDosentCrash","message":""}
var joinScriptJson = {
jobId: "Test",
status: 1,
joinScriptUrl:
"http://mete0r.xyz/game/join.ashx?ver=2020&auth=" +
joinJson.SessionId,
authenticationUrl: "http://mete0r.xyz/Login/Negotiate.ashx",
authenticationTicket: "SomeTicketThatDosentCrash",
message: "",
}
if (req.method === "POST" && req.body.isTeleport){ // mobile join-game
if (req.method === "POST" && req.body.isTeleport) {
// mobile join-game
return res.json({
"jobId": "Test",
"status": 0,
"joinScriptUrl": "http://mete0r.xyz/game/join.ashx?ver=2020&auth="+req.query.auth??req.cookies.jwt,
"authenticationUrl": "http://mete0r.xyz/Login/Negotiate.ashx",
"authenticationTicket": "SomeTicketThatDosentCrash",
"message": ""
jobId: "Test",
status: 0,
joinScriptUrl:
"http://mete0r.xyz/game/join.ashx?ver=2020&auth=" +
req.query.auth ?? req.cookies.jwt,
authenticationUrl: "http://mete0r.xyz/Login/Negotiate.ashx",
authenticationTicket: "SomeTicketThatDosentCrash",
message: "",
})
}
return res.send(JSON.stringify(joinScriptJson))
}
router.all(["/MTwentyTwenty.ashx","/2020/join","/join-game"],requireAuth,_2020placelauncher,async (req, res) => {
return res.json({status:"error",error:"Version different than client requested."})
router.all(
["/MTwentyTwenty.ashx", "/2020/join", "/join-game"],
requireAuth,
_2020placelauncher,
async (req, res) => {
return res.json({
status: "error",
error: "Version different than client requested.",
})
},
)
//rcctalk.CloseJob('game2')
module.exports = { router: router, _2020placelauncher: _2020placelauncher }

View File

@ -1,18 +1,18 @@
const express = require("express")
const router = express.Router()
var path = require('path')
const { requireAuth } = require('./../middleware/authmiddleware')
var multer = require('multer');
const bodyParser = require('body-parser')
var path = require("path")
const { requireAuth } = require("./../middleware/authmiddleware")
var multer = require("multer")
const bodyParser = require("body-parser")
router.use(bodyParser.json())
const User = require('./../model/games.js')
const ActualUser = require('./../model/user.js')
const catalog = require('./../model/item.js')
const games = require('./../model/games.js')
const rcc = require('./../model/rcc.js')
var numbtest = /^\d+\.?\d*$/;
const rcctalk = require('./../rcctalk')
require('dotenv').config()
const User = require("./../model/games.js")
const ActualUser = require("./../model/user.js")
const catalog = require("./../model/item.js")
const games = require("./../model/games.js")
const rcc = require("./../model/rcc.js")
var numbtest = /^\d+\.?\d*$/
const rcctalk = require("./../rcctalk")
require("dotenv").config()
const RCCDIR = process.env.RCC_Content
var thisistheplaceid = "1"
@ -24,60 +24,83 @@ var storage = multer.diskStorage({
} else {
cb(null, "./assets/ugc")
}
},
filename: async function (req, file, cb) {
if (path.extname(file.originalname) === ".rbxl") {
const placeid = await User.countDocuments();
cb(null, file.fieldname + "-" + placeid +path.extname(file.originalname))
const placeid = await User.countDocuments()
cb(
null,
file.fieldname +
"-" +
placeid +
path.extname(file.originalname),
)
} else if (file.mimetype == "image/png") {
const placeid = await User.countDocuments();
cb(null, file.fieldname + "-" + placeid +path.extname(file.originalname))
const placeid = await User.countDocuments()
cb(
null,
file.fieldname +
"-" +
placeid +
path.extname(file.originalname),
)
} else if (file.mimetype == "application/octet-stream") {
const itemid = await catalog.countDocuments();
cb(null, file.fieldname + "-" + itemid +path.extname(file.originalname))
}
const itemid = await catalog.countDocuments()
cb(
null,
file.fieldname + "-" + itemid + path.extname(file.originalname),
)
}
},
})
const upload = multer({storage: storage,
const upload = multer({
storage: storage,
fileFilter: function (req, file, callback) {
var ext = path.extname(file.originalname);
if(ext !== '.png' && ext !== '.png' && ext !== '.rbxl') {
return callback('Only pngs and rbxl are allowed')
var ext = path.extname(file.originalname)
if (ext !== ".png" && ext !== ".png" && ext !== ".rbxl") {
return callback("Only pngs and rbxl are allowed")
}
callback(null, true)
},
})
const itemupload = multer({storage: storage,
const itemupload = multer({
storage: storage,
fileFilter: function (req, file, callback) {
var ext = path.extname(file.originalname);
var ext = path.extname(file.originalname)
if (req.userdocument.admin === "false") {
return callback('LEAVE')
return callback("LEAVE")
}
if(ext !== '.png' && ext !== '.png' && ext !== '.rbxm') {
return callback('Only pngs and rbxm are allowed')
if (ext !== ".png" && ext !== ".png" && ext !== ".rbxm") {
return callback("Only pngs and rbxm are allowed")
}
callback(null, true)
},
})
router.post("/uploaditem", requireAuth,itemupload.single("itemfile"),async (req, res) => {
if (req.userdocument.admin == false && req.userdocument?.ugcpermission == false) {
return res.redirect('/')
router.post(
"/uploaditem",
requireAuth,
itemupload.single("itemfile"),
async (req, res) => {
if (
req.userdocument.admin == false &&
req.userdocument?.ugcpermission == false
) {
return res.redirect("/")
}
const xss = require('xss')
const xss = require("xss")
//console.log(req.body)
const { itemname, description, price, Type } = req.body
if (numbtest.test(price) == false) {
return res.json({status: 'error', error: 'Price can only be a number!'})
return res.json({
status: "error",
error: "Price can only be a number!",
})
}
try {
const itemid = await catalog.countDocuments();
const itemid = await catalog.countDocuments()
const response = await catalog.create({
Name: xss(itemname),
Description: xss(description),
@ -85,23 +108,26 @@ router.post("/uploaditem", requireAuth,itemupload.single("itemfile"),async (req,
Type: Type,
Creator: req.userdocument.userid,
ItemId: itemid,
approved: true
approved: true,
})
} catch (error) {
throw error
}
return res.json({ status: "success", message: "Action completed." })
})
},
)
router.post("/moderateuser", requireAuth, async (req, res) => {
if (req.userdocument.admin == false) {
return res.redirect('/')
return res.redirect("/")
}
let { userid, reason, unbantime, Type } = req.body
if (numbtest.test(userid) == false) {
return res.json({status: "error", error: "Userid can only be a number!"})
return res.json({
status: "error",
error: "Userid can only be a number!",
})
}
const lookupuser = await ActualUser.findOne({ userid: userid }).lean()
@ -119,38 +145,77 @@ router.post("/moderateuser", requireAuth,async (req, res) => {
//console.log(unbantime)
// if all above checks have passed lets set their moderation status and also log this entry for later lookup
var datetime = new Date();
ActualUser.updateOne({userid: userid}, {
var datetime = new Date()
ActualUser.updateOne(
{ userid: userid },
{
$set: {
moderation: JSON.stringify({"status":Type,"Reason":reason,"ExpiresIn":unbantime, "BannedBy": req.userdocument.username})
moderation: JSON.stringify({
status: Type,
Reason: reason,
ExpiresIn: unbantime,
BannedBy: req.userdocument.username,
}),
},
$push: {
moderationhistory: {"status":Type,"Reason":reason, "BannedBy": req.userdocument.username, "Date": datetime.toISOString().slice(0,10)}
}
moderationhistory: {
status: Type,
Reason: reason,
BannedBy: req.userdocument.username,
Date: datetime.toISOString().slice(0, 10),
},
},
},
function (err, doc) {
//console.log(err)
})
},
)
return res.json({ status: "success", message: "Action completed." })
})
router.post("/moderateuserlookup", requireAuth, async (req, res) => {
if (req.userdocument.admin == false) {
return res.redirect('/')
return res.redirect("/")
}
const { userid, username } = req.body
const whitelist = ["username","coins","userid","admin","moderation","colors","inventory","joindate","lastclaimofcurrency","membership","friendrequests","friends","badges","status","timesincelastrequest","avatartype","discordid","moderationhistory"]
const whitelist = [
"username",
"coins",
"userid",
"admin",
"moderation",
"colors",
"inventory",
"joindate",
"lastclaimofcurrency",
"membership",
"friendrequests",
"friends",
"badges",
"status",
"timesincelastrequest",
"avatartype",
"discordid",
"moderationhistory",
]
if (numbtest.test(userid) == false && !username) {
return res.json({status: "error", error: "Userid can only be a number!"})
return res.json({
status: "error",
error: "Userid can only be a number!",
})
}
let lookupuser
if (userid != "") {
lookupuser = await ActualUser.findOne({userid: userid}).lean().select(whitelist)
lookupuser = await ActualUser.findOne({ userid: userid })
.lean()
.select(whitelist)
} else if (username) {
lookupuser = await ActualUser.findOne({username: username}).lean().select(whitelist)
lookupuser = await ActualUser.findOne({ username: username })
.lean()
.select(whitelist)
}
if (!lookupuser) {
@ -161,7 +226,7 @@ router.post("/moderateuserlookup", requireAuth,async (req, res) => {
router.post("/queue", requireAuth, async (req, res) => {
if (req.userdocument.admin == false) {
return res.redirect('/')
return res.redirect("/")
}
const resultsPerPage = 30
let page = req.body.page ?? 0
@ -173,16 +238,47 @@ router.post("/queue", requireAuth,async (req, res) => {
let responsecount
if (sort != "All") {
response = await catalog.find({Type: sort, approved: false, Type: {$ne: "Image"}, denied: {$exists:false}}).limit(resultsPerPage).skip(0+parseFloat(page)*resultsPerPage).lean().select(['-_id'])
responsecount = await catalog.countDocuments({Type: sort, approved: false, Type: {$ne: "Image"}, denied: {$exists:false}})
response = await catalog
.find({
Type: sort,
approved: false,
Type: { $ne: "Image" },
denied: { $exists: false },
})
.limit(resultsPerPage)
.skip(0 + parseFloat(page) * resultsPerPage)
.lean()
.select(["-_id"])
responsecount = await catalog.countDocuments({
Type: sort,
approved: false,
Type: { $ne: "Image" },
denied: { $exists: false },
})
}
if (sort === "All") {
response = await catalog.find({approved: false, Type: {$ne: "Image"}, denied: {$exists:false}}).limit(resultsPerPage).skip(0+parseFloat(page)*resultsPerPage).lean().select(['-_id'])
responsecount = await catalog.countDocuments({approved: false, Type: {$ne: "Image"}, denied: {$exists:false}})
response = await catalog
.find({
approved: false,
Type: { $ne: "Image" },
denied: { $exists: false },
})
.limit(resultsPerPage)
.skip(0 + parseFloat(page) * resultsPerPage)
.lean()
.select(["-_id"])
responsecount = await catalog.countDocuments({
approved: false,
Type: { $ne: "Image" },
denied: { $exists: false },
})
}
return res.json({data: response, pages: Math.ceil(Math.max(responsecount/resultsPerPage, 1)), count: responsecount })
return res.json({
data: response,
pages: Math.ceil(Math.max(responsecount / resultsPerPage, 1)),
count: responsecount,
})
})
module.exports = router

View File

@ -1,10 +1,10 @@
const express = require("express")
const router = express.Router()
const { requireAuth } = require('./../../middleware/authmiddleware')
const bodyParser = require('body-parser')
const User = require('./../../model/user.js')
const catalog = require('./../../model/item.js')
const games = require('./../../model/games.js')
const { requireAuth } = require("./../../middleware/authmiddleware")
const bodyParser = require("body-parser")
const User = require("./../../model/user.js")
const catalog = require("./../../model/item.js")
const games = require("./../../model/games.js")
router.use(bodyParser.json())
router.post("/", requireAuth, async (req, res) => {
@ -23,7 +23,10 @@ router.post("/",requireAuth,async (req, res) => {
}
if (req.userdocument.coins < 10) {
return res.json({status: "error", error: "You don't have enough Rocks!"})
return res.json({
status: "error",
error: "You don't have enough Rocks!",
})
}
const Addoc = await catalog.findOne({ ItemId: AdId })
@ -36,8 +39,12 @@ router.post("/",requireAuth,async (req, res) => {
return res.json({ status: "error", error: "Not Authorized" }) // tried to use someone elses ad
}
if (Addoc.ActiveAd === true){ // ad is already running
return res.json({status: "error", error: "You are already running this ad!"})
if (Addoc.ActiveAd === true) {
// ad is already running
return res.json({
status: "error",
error: "You are already running this ad!",
})
}
if (Addoc.Hidden) {
@ -48,7 +55,6 @@ router.post("/",requireAuth,async (req, res) => {
return res.json({ status: "error", error: "Ad is pending approval!" })
}
let itemdoc
if (type === "game") {
@ -60,23 +66,21 @@ router.post("/",requireAuth,async (req, res) => {
}
if (type === "game") {
if (itemdoc.useridofowner != req.userdocument.userid){ // make sure we only let game owners advertise there game
if (itemdoc.useridofowner != req.userdocument.userid) {
// make sure we only let game owners advertise there game
return res.json({ status: "error", error: "Not Authorized" })
}
}
if (type === "item") {
if (itemdoc.Creator != req.userdocument.userid){ // make sure we only let item owners advertise there item
if (itemdoc.Creator != req.userdocument.userid) {
// make sure we only let item owners advertise there item
return res.json({ status: "error", error: "Not Authorized" })
}
}
req.userdocument.coins -= 10
req.userdocument.markModified('coins')
req.userdocument.markModified("coins")
await req.userdocument.save()
Addoc.adtype = type
@ -84,18 +88,13 @@ router.post("/",requireAuth,async (req, res) => {
Addoc.ActiveAd = true
Addoc.adstartedtime = Date.now()
Addoc.markModified('adtype')
Addoc.markModified('adredirectid')
Addoc.markModified('ActiveAd')
Addoc.markModified('adstartedtime')
Addoc.markModified("adtype")
Addoc.markModified("adredirectid")
Addoc.markModified("ActiveAd")
Addoc.markModified("adstartedtime")
await Addoc.save()
return res.json({ status: "success", message: "Done!" })
})
module.exports = router

View File

@ -1,22 +1,44 @@
const express = require("express")
const router = express.Router()
const { requireAuth } = require('./../../middleware/authmiddleware')
const bodyParser = require('body-parser')
const User = require('./../../model/user.js')
const { requireAuth } = require("./../../middleware/authmiddleware")
const bodyParser = require("body-parser")
const User = require("./../../model/user.js")
router.use(bodyParser.json())
function selectKeys(obj, keysArray) {
let result = {};
let result = {}
for (let i = 0; i < keysArray.length; i++) {
if (keysArray[i] in obj === true) {
result[keysArray[i]] = obj[keysArray[i]];
result[keysArray[i]] = obj[keysArray[i]]
}
}
return result;
return result
}
router.get("/", requireAuth, async (req, res) => {
const filtered = selectKeys(req.userdocument,["username","coins","userid","admin","ugcpermission","moderation","colors","inventory","joindate","lastclaimofcurrency","membership","friendrequests","friends","badges","status","timesincelastrequest","avatartype","discordid","bio","recentlyplayed","css"])
const filtered = selectKeys(req.userdocument, [
"username",
"coins",
"userid",
"admin",
"ugcpermission",
"moderation",
"colors",
"inventory",
"joindate",
"lastclaimofcurrency",
"membership",
"friendrequests",
"friends",
"badges",
"status",
"timesincelastrequest",
"avatartype",
"discordid",
"bio",
"recentlyplayed",
"css",
])
//console.log(filtered.recentlyplayedgames)
filtered._2faenabled = false
if (req.userdocument?.twofasecrets) {
@ -26,16 +48,34 @@ router.get("/",requireAuth,async (req, res) => {
}
}
return res.json(filtered)
})
router.post("/recentgames", requireAuth, async (req, res) => {
const response = await User.findOne({userid: req.userdocument.userid}).lean().populate({path: "recentlyplayedgames",select: ["useridofowner","nameofgame","numberofplayers","version","visits"] , populate: {path: "owner", select: ["username"]}}).select("recentlyplayed")
const response = await User.findOne({ userid: req.userdocument.userid })
.lean()
.populate({
path: "recentlyplayedgames",
select: [
"useridofowner",
"nameofgame",
"numberofplayers",
"version",
"visits",
],
populate: { path: "owner", select: ["username"] },
})
.select("recentlyplayed")
return res.json(response.recentlyplayedgames)
})
router.post("/requestfriends", requireAuth, async (req, res) => {
let response = await User.findOne({userid: req.userdocument.userid}).lean().populate({path: "friendsdata",select: ["username","status","timesincelastrequest"]}).select("friends")
let response = await User.findOne({ userid: req.userdocument.userid })
.lean()
.populate({
path: "friendsdata",
select: ["username", "status", "timesincelastrequest"],
})
.select("friends")
let friendsdata = []
if (response.friendsdata) {
response.friendsdata.forEach(function (item, index) {
@ -44,13 +84,33 @@ if (response.friendsdata){
status = JSON.parse(item.status)
}
const actualTimeMilliseconds = new Date().getTime()
if (item.timesincelastrequest && actualTimeMilliseconds - item.timesincelastrequest >= 60000 * 3 /*3 minutes*/ && status && status.status.includes("Playing") === false || item.timesincelastrequest && actualTimeMilliseconds - item.timesincelastrequest >= 60000 * 3 /*3 minutes*/ && !status){
if (
(item.timesincelastrequest &&
actualTimeMilliseconds - item.timesincelastrequest >=
60000 * 3 /*3 minutes*/ &&
status &&
status.status.includes("Playing") === false) ||
(item.timesincelastrequest &&
actualTimeMilliseconds - item.timesincelastrequest >=
60000 * 3 /*3 minutes*/ &&
!status)
) {
// been 3 minutes since last request mark as offline make sure we don't mark them offline while they are playing a game
status.status = "Offline"
item.status = JSON.stringify(status)
status = JSON.parse(item.status)
}
if (item.timesincelastrequest && actualTimeMilliseconds - item.timesincelastrequest <= 60000 * 3 /*3 minutes*/ && status && status.status.includes("Playing") === false || item.timesincelastrequest && actualTimeMilliseconds - item.timesincelastrequest <= 60000 * 3 /*3 minutes*/ && !status){
if (
(item.timesincelastrequest &&
actualTimeMilliseconds - item.timesincelastrequest <=
60000 * 3 /*3 minutes*/ &&
status &&
status.status.includes("Playing") === false) ||
(item.timesincelastrequest &&
actualTimeMilliseconds - item.timesincelastrequest <=
60000 * 3 /*3 minutes*/ &&
!status)
) {
status.status = "Online"
item.status = JSON.stringify(status)
status = JSON.parse(item.status)
@ -61,16 +121,28 @@ if (response.friendsdata){
}
// playing is 1st online is second and offline is last :)
friendsdata.sort((a, b) => {
if (a.status.status.includes("Playing") === true && b.status.status !== 'Playing') {
return -1; // a should appear before b
} else if (a.status.status.includes("Playing") === false && b.status.status.includes("Playing") === true) {
return 1; // a should appear after b
} else if (a.status.status === 'Online' && b.status.status === 'Offline') {
return -1; // a should appear before b
} else if (a.status.status === 'Offline' && b.status.status === 'Online') {
return 1; // a should appear after b
if (
a.status.status.includes("Playing") === true &&
b.status.status !== "Playing"
) {
return -1 // a should appear before b
} else if (
a.status.status.includes("Playing") === false &&
b.status.status.includes("Playing") === true
) {
return 1 // a should appear after b
} else if (
a.status.status === "Online" &&
b.status.status === "Offline"
) {
return -1 // a should appear before b
} else if (
a.status.status === "Offline" &&
b.status.status === "Online"
) {
return 1 // a should appear after b
} else {
return 0; // the order of a and b doesn't matter
return 0 // the order of a and b doesn't matter
}
})

View File

@ -1,17 +1,17 @@
const express = require("express")
const router = express.Router()
const { requireAuth } = require('./../../middleware/authmiddleware')
const bodyParser = require('body-parser')
var numbtest = /^\d+\.?\d*$/;
const bank = require('./../../model/bank.js')
const User = require('./../../model/user.js')
const { requireAuth } = require("./../../middleware/authmiddleware")
const bodyParser = require("body-parser")
var numbtest = /^\d+\.?\d*$/
const bank = require("./../../model/bank.js")
const User = require("./../../model/user.js")
router.use(bodyParser.json())
const speakeasy = require('speakeasy')
const speakeasy = require("speakeasy")
async function Fill() {
if (!await bank.findOne()) {
if (!(await bank.findOne())) {
await bank.create({
balance: 5000
balance: 5000,
})
}
}
@ -36,10 +36,8 @@ router.post("/transaction/:id",async (req, res) => {
return res.json({ status: "error", error: "Amount must be a number!" })
}
const response = await bank.findOne()
if (amount > response.balance) {
return res.json({ status: "error", error: "Not enough money" })
}
@ -50,13 +48,18 @@ router.post("/transaction/:id",async (req, res) => {
return res.json({ status: "error", error: "User not found" })
}
if (amount < 0){ // negative
if (amount < 0) {
// negative
if (user.coins - Math.abs(amount) < 0){ // they will have negative coins
return res.json({status: "error", error: "User will have negative coins."})
if (user.coins - Math.abs(amount) < 0) {
// they will have negative coins
return res.json({
status: "error",
error: "User will have negative coins.",
})
} else {
user.coins += amount
user.markModified('coins')
user.markModified("coins")
await user.save()
}
}
@ -64,16 +67,15 @@ router.post("/transaction/:id",async (req, res) => {
if (amount > 0) {
user.coins += amount
user.markModified('coins')
user.markModified("coins")
await user.save()
}
response.balance += amount * -1
response.markModified('balance')
response.markModified("balance")
await response.save()
return res.json({ status: "success", balance: response.balance })
})

View File

@ -1,16 +1,16 @@
const express = require("express")
const router = express.Router()
const { requireAuth } = require('./../../middleware/authmiddleware')
const User = require('./../../model/user.js')
const bodyParser = require('body-parser')
const { requireAuth } = require("./../../middleware/authmiddleware")
const User = require("./../../model/user.js")
const bodyParser = require("body-parser")
const validTypes = [
'all',
'Head',
'Torso',
'Left Arm',
'Right Arm',
'Left Leg',
'Right Leg'
"all",
"Head",
"Torso",
"Left Arm",
"Right Arm",
"Left Leg",
"Right Leg",
]
router.use(bodyParser.json())
@ -30,19 +30,22 @@ router.post("/",requireAuth,async (req, res) => {
for (const obj of req.userdocument.colors) {
if (Type === "all") {
obj.value = color
req.userdocument.markModified('colors')
req.userdocument.markModified("colors")
await req.userdocument.save()
}
if (obj.name === Type) {
obj.value = color
req.userdocument.markModified('colors')
req.userdocument.markModified("colors")
await req.userdocument.save()
}
}
} catch (err) {
console.log(err)
}
return res.json({status: 'success', message: "Color change successful"})
return res.json({
status: "success",
message: "Color change successful",
})
}
// they tried to submit an invalid form
return res.json({ status: "error", error: "Invalid Type" })

View File

@ -1,37 +1,43 @@
const express = require("express")
const router = express.Router()
const { requireAuth } = require('./../../middleware/authmiddleware')
const User = require('./../../model/user.js')
const bodyParser = require('body-parser')
const bcrypt = require('bcrypt')
const { requireAuth } = require("./../../middleware/authmiddleware")
const User = require("./../../model/user.js")
const bodyParser = require("body-parser")
const bcrypt = require("bcrypt")
router.use(bodyParser.json())
router.post("/", requireAuth, async (req, res) => {
const { oldpassword, newpassword } = req.body
if (!oldpassword || typeof oldpassword !== 'string') {
return res.json({status: 'error', error: 'Old password needs to be sent and it needs to be a string'})
if (!oldpassword || typeof oldpassword !== "string") {
return res.json({
status: "error",
error: "Old password needs to be sent and it needs to be a string",
})
}
if (!newpassword || typeof newpassword !== 'string') {
return res.json({status: 'error', error: 'New password needs to be sent and it needs to be a string'})
if (!newpassword || typeof newpassword !== "string") {
return res.json({
status: "error",
error: "New password needs to be sent and it needs to be a string",
})
}
if (newpassword.length < 4) {
return res.json({status: 'error', error: 'Password needs to be at least 5 characters'})
return res.json({
status: "error",
error: "Password needs to be at least 5 characters",
})
}
if (await bcrypt.compare(oldpassword, req.userdocument.password)) {
// password matches
const newhashedpassword = (await bcrypt.hash(newpassword, 10))
const newhashedpassword = await bcrypt.hash(newpassword, 10)
try {
req.userdocument.password = newhashedpassword
req.userdocument.markModified('password')
req.userdocument.markModified("password")
await req.userdocument.save()
}catch{
} catch {}
return res.json({ status: "success", message: "Changed Password!" })
}
return res.json({status: 'success', message: 'Changed Password!'})
}
res.json({status: 'error', error: 'Invalid old password'})
res.json({ status: "error", error: "Invalid old password" })
})
module.exports = router

View File

@ -1,20 +1,23 @@
const express = require("express")
const router = express.Router()
const { requireAuth } = require('./../../middleware/authmiddleware')
const games = require('./../../model/games.js')
const catalog = require('./../../model/item.js')
const comments = require('./../../model/comment.js')
const bodyParser = require('body-parser')
const { requireAuth } = require("./../../middleware/authmiddleware")
const games = require("./../../model/games.js")
const catalog = require("./../../model/item.js")
const comments = require("./../../model/comment.js")
const bodyParser = require("body-parser")
router.use(bodyParser.json())
const rateLimit = require('express-rate-limit')
const rateLimit = require("express-rate-limit")
const limiter = rateLimit({
windowMs: 10 * 1000, // 10 seconds
max: 1, // Limit each IP to 1 requests per `window`
standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
legacyHeaders: false, // Disable the `X-RateLimit-*` headers
handler: (request, response, next, options) => {
return response.json({status: 'error', error: 'Too many requests try again later.'})
}
return response.json({
status: "error",
error: "Too many requests try again later.",
})
},
})
router.post("/post", requireAuth, limiter, async (req, res) => {
@ -25,24 +28,24 @@ router.post("/post", requireAuth,limiter,async (req, res) => {
return res.json("Send comment and associated asset id please")
}
if (comment.length > 200) {
return res.json({status: 'error', error: "Comment too long!"})
return res.json({ status: "error", error: "Comment too long!" })
}
if (AssociatedAssetType !== "game" && AssociatedAssetType !== "item") {
return res.json({status: 'error', error: "Invalid asset type!"})
return res.json({ status: "error", error: "Invalid asset type!" })
}
if (AssociatedAssetType === "game") {
const game = await games.findOne({ idofgame: AssociatedAssetId }).lean()
if (!game) {
return res.json({status: 'error', error: "Game not found!"})
return res.json({ status: "error", error: "Game not found!" })
}
}
if (AssociatedAssetType === "item") {
const item = await catalog.findOne({ ItemId: AssociatedAssetId }).lean()
if (!item) {
return res.json({status: 'error', error: "Game not found!"})
return res.json({ status: "error", error: "Game not found!" })
}
}
@ -52,14 +55,12 @@ router.post("/post", requireAuth,limiter,async (req, res) => {
posterid: req.userdocument.userid,
content: comment,
date: new Date().getTime(),
moderated: false
moderated: false,
})
return res.json({status: 'success', message: "Comment posted!"})
return res.json({ status: "success", message: "Comment posted!" })
})
router.post("/get", requireAuth, async (req, res) => {
let { AssociatedAssetType, AssociatedAssetId } = req.body
AssociatedAssetId = parseInt(AssociatedAssetId)
@ -70,11 +71,14 @@ router.post("/get", requireAuth,async (req, res) => {
}
if (!AssociatedAssetType || typeof AssociatedAssetId === undefined) {
return res.json({status: 'error', error: "Send comment and associated asset id please"})
return res.json({
status: "error",
error: "Send comment and associated asset id please",
})
}
if (AssociatedAssetType !== "game" && AssociatedAssetType !== "item") {
return res.json({status: 'error', error: "Invalid asset type!"})
return res.json({ status: "error", error: "Invalid asset type!" })
}
let commentsarray
@ -83,21 +87,38 @@ router.post("/get", requireAuth,async (req, res) => {
if (AssociatedAssetType === "game") {
const game = await games.findOne({ idofgame: AssociatedAssetId }).lean()
if (!game) {
return res.json({status: 'error', error: "Game not found!"})
return res.json({ status: "error", error: "Game not found!" })
}
}
if (AssociatedAssetType === "item") {
const item = await catalog.findOne({ ItemId: AssociatedAssetId }).lean()
if (!item) {
return res.json({status: 'error', error: "Game not found!"})
return res.json({ status: "error", error: "Game not found!" })
}
}
commentsarray = await comments.find({associatedassetid: AssociatedAssetId, associatedassettype: AssociatedAssetType}).lean().sort({date: 'descending'}).populate({path: "poster",select: ["username"]}).select(["posterid", "content", "date", "poster"]).skip(0+parseFloat(cursor)*resultsPerPage).limit(resultsPerPage)
commentscount = await comments.countDocuments({associatedassetid: AssociatedAssetId, associatedassettype: AssociatedAssetType})
commentsarray = await comments
.find({
associatedassetid: AssociatedAssetId,
associatedassettype: AssociatedAssetType,
})
.lean()
.sort({ date: "descending" })
.populate({ path: "poster", select: ["username"] })
.select(["posterid", "content", "date", "poster"])
.skip(0 + parseFloat(cursor) * resultsPerPage)
.limit(resultsPerPage)
commentscount = await comments.countDocuments({
associatedassetid: AssociatedAssetId,
associatedassettype: AssociatedAssetType,
})
return res.json({status: 'success', data: commentsarray, pages: Math.ceil(Math.max(commentscount/resultsPerPage, 1))})
return res.json({
status: "success",
data: commentsarray,
pages: Math.ceil(Math.max(commentscount / resultsPerPage, 1)),
})
})
module.exports = router

View File

@ -1,14 +1,14 @@
const express = require("express")
const router = express.Router()
const { requireAuth } = require('./../../middleware/authmiddleware')
const User = require('./../../model/user.js')
const bodyParser = require('body-parser')
const { requireAuth } = require("./../../middleware/authmiddleware")
const User = require("./../../model/user.js")
const bodyParser = require("body-parser")
router.use(bodyParser.json())
router.post("/share", requireAuth, async (req, res) => {
let { sharevalue } = req.body
if (!sharevalue || typeof sharevalue !== 'string'){
if (!sharevalue || typeof sharevalue !== "string") {
return res.json({ status: "error", error: "Share value not sent!" })
}
if (sharevalue.length > 100) {
@ -16,39 +16,53 @@ router.post("/share",requireAuth,async (req, res) => {
}
const date = new Date().getTime()
if (date - req.userdocument?.lastfeedsharetime < 3600000) {
return res.json({status: "error", error: "You can only share once an hour!"})
return res.json({
status: "error",
error: "You can only share once an hour!",
})
}
let posterid = req.userdocument.userid
User.updateOne({userid: req.userdocument.userid}, {
User.updateOne(
{ userid: req.userdocument.userid },
{
$push: {
feed: {posterid, content: sharevalue, date, moderated: false}
feed: { posterid, content: sharevalue, date, moderated: false },
},
$set: {
lastfeedsharetime: date
}
lastfeedsharetime: date,
},
function(err, doc) {
})
},
function (err, doc) {},
)
res.json({ status: "success", message: "Done!" }) // the next operation could take some time and we wouldn't want the client to cancel during that!!
if (req.userdocument.friends) {
//console.log(req.userdocument.friends)
for (let item of req.userdocument.friends) {
User.updateOne({userid: item.userid}, {
User.updateOne(
{ userid: item.userid },
{
$push: {
feed: {posterid, content: sharevalue, date, moderated: false}
}
feed: {
posterid,
content: sharevalue,
date,
moderated: false,
},
function(err, doc) {
})
},
},
function (err, doc) {},
)
}
}
})
router.post("/fetch", requireAuth, async (req, res) => {
let feed = await User.findOne({userid: req.userdocument.userid}).lean().populate({path: "feed.userdata",select: ["username"]}).select('feed')
let feed = await User.findOne({ userid: req.userdocument.userid })
.lean()
.populate({ path: "feed.userdata", select: ["username"] })
.select("feed")
return res.json({ status: "success", data: feed.feed })
})

View File

@ -1,9 +1,9 @@
const express = require("express")
const router = express.Router()
const { requireAuth } = require('./../../middleware/authmiddleware')
const games = require('./../../model/games.js')
const User = require('./../../model/user.js')
const bodyParser = require('body-parser')
const { requireAuth } = require("./../../middleware/authmiddleware")
const games = require("./../../model/games.js")
const User = require("./../../model/user.js")
const bodyParser = require("body-parser")
router.use(bodyParser.json())
router.post("/request-friendship", requireAuth, async (req, res) => {
@ -18,71 +18,97 @@ router.post("/request-friendship", requireAuth,async (req, res) => {
return res.json({ status: "error", error: "Can't find Recipent!" })
}
if (usertofriend.friends) {
const friends = usertofriend.friends.some(word => word.userid == req.userdocument.userid)
const friends = usertofriend.friends.some(
word => word.userid == req.userdocument.userid,
)
if (friends === true) {
return res.json({status:"error",error:"You are already friends!"})
return res.json({
status: "error",
error: "You are already friends!",
})
}
// already friends
}
if (req.userdocument.friendrequests) {
// check if the other user is already requesting to friend the player so then they both want to be firends so we can interperept this as an accept request
const bothwantobefriends = req.userdocument.friendrequests.some(word => word.userid == usertofriend.userid)
const bothwantobefriends = req.userdocument.friendrequests.some(
word => word.userid == usertofriend.userid,
)
if (bothwantobefriends === true) {
console.log(tofriend)
User.updateOne({userid: req.userdocument.userid}, {
User.updateOne(
{ userid: req.userdocument.userid },
{
$push: {
friends: {userid: usertofriend.userid, username: usertofriend.username}
friends: {
userid: usertofriend.userid,
username: usertofriend.username,
},
},
$pull: {
friendrequests: {userid: usertofriend.userid, username: usertofriend.username}
}
friendrequests: {
userid: usertofriend.userid,
username: usertofriend.username,
},
function(err, doc) {
},
},
function (err, doc) {},
)
})
User.updateOne({userid: tofriend}, {
User.updateOne(
{ userid: tofriend },
{
$push: {
friends: {userid: req.userdocument.userid, username: req.userdocument.username}
friends: {
userid: req.userdocument.userid,
username: req.userdocument.username,
},
},
$pull: {
friendrequests: {userid: req.userdocument.userid, username: req.userdocument.username}
}
friendrequests: {
userid: req.userdocument.userid,
username: req.userdocument.username,
},
function(err, doc) {
},
},
function (err, doc) {},
)
return res.json({
status: "success",
message: "You are now friends :D",
})
return res.json({status:"success",message:"You are now friends :D"})
}
}
if (usertofriend.friendrequests) {
const alreadyrequested = usertofriend.friendrequests.some(word => word.userid == req.userdocument.userid)
const alreadyrequested = usertofriend.friendrequests.some(
word => word.userid == req.userdocument.userid,
)
// already friend requested
if (alreadyrequested === true) {
return res.json({status:"error",error:"You already sent this request!"})
}
}
User.updateOne({userid: usertofriend.userid}, {
$push: {
friendrequests: {userid: req.userdocument.userid, username: req.userdocument.username}
}
},
function(err, doc) {
return res.json({
status: "error",
error: "You already sent this request!",
})
}
}
User.updateOne(
{ userid: usertofriend.userid },
{
$push: {
friendrequests: {
userid: req.userdocument.userid,
username: req.userdocument.username,
},
},
},
function (err, doc) {},
)
return res.json({ status: "success", message: "Friend request sent!" })
})
router.post("/decline-friend-request", requireAuth, async (req, res) => {
@ -96,53 +122,74 @@ router.post("/decline-friend-request",requireAuth,async (req, res) => {
return res.json({ status: "error", error: "Can't find Recipent!" })
}
const alreadyfriends = req.userdocument?.friends?.some(word => word.userid == tounfriend )
const alreadyfriends = req.userdocument?.friends?.some(
word => word.userid == tounfriend,
)
if (alreadyfriends === true) {
// already friends with the person so they want ro remove their friend
User.updateOne({userid: tounfriend}, {
User.updateOne(
{ userid: tounfriend },
{
$pull: {
friends: {userid: req.userdocument.userid, username: req.userdocument.username}
}
friends: {
userid: req.userdocument.userid,
username: req.userdocument.username,
},
},
},
function (err, doc) {
//console.log(err)
})
User.updateOne({userid: req.userdocument.userid}, {
},
)
User.updateOne(
{ userid: req.userdocument.userid },
{
$pull: {
friends: {userid:usertofriend.userid, username: usertofriend.username}
}
friends: {
userid: usertofriend.userid,
username: usertofriend.username,
},
},
},
function (err, doc) {
//console.log(err)
})
},
)
return res.json({ status: "error", error: "Unfriended friend!" })
}
//otherwise the user isn't friends but still declines the friend request
User.updateOne({userid: tounfriend}, {
User.updateOne(
{ userid: tounfriend },
{
$pull: {
friendrequests: {userid: req.userdocument.userid, username: req.userdocument.username}
}
friendrequests: {
userid: req.userdocument.userid,
username: req.userdocument.username,
},
},
},
function (err, doc) {
//console.log(err)
})
User.updateOne({userid: req.userdocument.userid}, {
},
)
User.updateOne(
{ userid: req.userdocument.userid },
{
$pull: {
friendrequests: {userid: usertofriend.userid, username: usertofriend.username}
}
friendrequests: {
userid: usertofriend.userid,
username: usertofriend.username,
},
},
},
function (err, doc) {
//console.log(err)
})
},
)
return res.json({ status: "success", message: "Declined friend request!" })
})
router.post("/has-sent-request", requireAuth, async (req, res) => {
@ -157,32 +204,38 @@ router.post("/has-sent-request",requireAuth,async (req, res) => {
return res.json({ status: "error", error: "Can't find Recipent!" })
}
const friends = usertofriend?.friends?.some(word => word.userid == req.userdocument.userid)
const friends = usertofriend?.friends?.some(
word => word.userid == req.userdocument.userid,
)
if (friends === true) {
return res.json({ status: "error", error: "You are already friends!" })
}
// already friends
const alreadyrequested = usertofriend?.friendrequests?.some(word => word.userid == req.userdocument.userid)
const alreadyrequested = usertofriend?.friendrequests?.some(
word => word.userid == req.userdocument.userid,
)
// already friend requested
if (alreadyrequested === true) {
return res.json({ status: "success", message: true })
}
const bothwantobefriends = req.userdocument?.friendrequests?.some(word => word.userid == usertofriend.userid)
const bothwantobefriends = req.userdocument?.friendrequests?.some(
word => word.userid == usertofriend.userid,
)
if (bothwantobefriends === true) {
return res.json({status:"success",message:"Other user wants to be friends."})
return res.json({
status: "success",
message: "Other user wants to be friends.",
})
}
return res.json({ status: "success", message: false })
})
router.post('/friend-requests',requireAuth, async (req, res) => {
router.post("/friend-requests", requireAuth, async (req, res) => {
res.json({ data: req.userdocument?.friendrequests })
});
})
module.exports = router

View File

@ -1,21 +1,21 @@
const express = require("express")
const router = express.Router()
const { requireAuth } = require('./../../middleware/authmiddleware')
const bodyParser = require('body-parser')
const keys = require('./../../model/keys.js')
const { requireAuth } = require("./../../middleware/authmiddleware")
const bodyParser = require("body-parser")
const keys = require("./../../model/keys.js")
router.use(bodyParser.json())
// hay this code hasn't been updated so it contains very old code because I haven't bothered to add key support since the last time they existed 2 months ago?
function stringGen(len) {
var text = "";
var text = ""
var charset = "abcdefghijklmnopqrstuvwxyz0123456789";
var charset = "abcdefghijklmnopqrstuvwxyz0123456789"
for (var i = 0; i < len; i++)
text += charset.charAt(Math.floor(Math.random() * charset.length));
text += charset.charAt(Math.floor(Math.random() * charset.length))
return text;
return text
}
router.post("/", requireAuth, async (req, res) => {
@ -24,26 +24,25 @@ router.post("/",requireAuth,async (req, res) => {
const response = await keys.create({
Creator: req.userdocument.username,
Key: key,
Used: false
Used: false,
})
return res.redirect(req.get('referer'));
return res.redirect(req.get("referer"))
}
if (req.userdocument.coins >= 100) {
// they have enough
req.userdocument.coins -= 100
req.userdocument.markModified('coins')
req.userdocument.markModified("coins")
await req.userdocument.save()
var key = stringGen(10)
const response = await keys.create({
Creator: req.userdocument.username,
Key: key,
Used: false
Used: false,
})
return res.redirect(req.get('referer'));
return res.redirect(req.get("referer"))
}
return res.redirect(req.get('referer'));
return res.redirect(req.get("referer"))
})
module.exports = router

View File

@ -1,15 +1,25 @@
const express = require("express")
const router = express.Router()
const { requireAuth } = require('./../../middleware/authmiddleware')
const bodyParser = require('body-parser')
const groups = require('./../../model/groups.js')
var multer = require('multer');
const fs = require('fs');
const path = require('path')
const { requireAuth } = require("./../../middleware/authmiddleware")
const bodyParser = require("body-parser")
const groups = require("./../../model/groups.js")
var multer = require("multer")
const fs = require("fs")
const path = require("path")
router.use(bodyParser.json())
router.post("/", requireAuth, async (req, res) => {
let mygroups = await groups.find({"members.userId": req.userdocument.userid}).lean().select(["Name","Description","Public","groupid","ownerid","memberscount"])
let mygroups = await groups
.find({ "members.userId": req.userdocument.userid })
.lean()
.select([
"Name",
"Description",
"Public",
"groupid",
"ownerid",
"memberscount",
])
return res.json(mygroups)
})
@ -19,7 +29,19 @@ router.post("/:id", requireAuth,async (req, res) => {
return res.json({ status: "error", error: "Not found" })
}
let groupresponse = await groups.findOne({groupid}).lean().select(["Name","Description","Public","groupid","ownerid","memberscount","currentshout"]).populate({path: "owner",select: ["username", "userid"]})
let groupresponse = await groups
.findOne({ groupid })
.lean()
.select([
"Name",
"Description",
"Public",
"groupid",
"ownerid",
"memberscount",
"currentshout",
])
.populate({ path: "owner", select: ["username", "userid"] })
if (!groupresponse) {
return res.json({ status: "error", error: "Not found" })
@ -46,7 +68,11 @@ router.post("/:id/members", requireAuth,async (req, res) => {
return res.json({ status: "error", error: "Not found" })
}
let groupresponse = await groups.findOne({groupid}).lean().select({"members": { "$slice" : [ skip, resultsPerPage ] }}).populate({path: "memberspoly",select: ["username", "userid"]})
let groupresponse = await groups
.findOne({ groupid })
.lean()
.select({ members: { $slice: [skip, resultsPerPage] } })
.populate({ path: "memberspoly", select: ["username", "userid"] })
if (!groupresponse) {
return res.json({ status: "error", error: "Not found" })
@ -56,23 +82,27 @@ router.post("/:id/members", requireAuth,async (req, res) => {
})
async function validateImage(groupid, res) {
return new Promise(async (resolve) => {
return new Promise(async resolve => {
try {
const myArrayBuffer = await fs.promises.readFile(path.resolve(`assets/groupicons/icon-${groupid}.png`), null)
pngValidator(myArrayBuffer);
const myArrayBuffer = await fs.promises.readFile(
path.resolve(`assets/groupicons/icon-${groupid}.png`),
null,
)
pngValidator(myArrayBuffer)
// success
} catch {
// file is invalid or corrupt
fs.unlink(path.resolve(`assets/groupicons/icon-${groupid}.png`), (err => {
fs.unlink(
path.resolve(`assets/groupicons/icon-${groupid}.png`),
err => {
if (err) console.log(err)
}));
},
)
return res.json({status: 'error', error: 'Image is invalid.'})
return res.json({ status: "error", error: "Image is invalid." })
}
resolve()
})
}
@ -80,58 +110,77 @@ var storage = multer.diskStorage({
destination: function (req, file, cb) {
// Uploads is the Upload_folder_name
cb(null, "./assets/groupicons")
},
filename: async function (req, file, cb) {
const groupid = await groups.countDocuments();
const groupid = await groups.countDocuments()
cb(null, "icon-" + groupid + ".png")
}
},
})
const uploadicon = multer({storage: storage,
const uploadicon = multer({
storage: storage,
fileFilter: function (req, file, callback) {
if(file.mimetype != 'image/png') {
return callback('Invalid file type')
if (file.mimetype != "image/png") {
return callback("Invalid file type")
}
callback(null, true)
},
limits: { fileSize: 1024 * 1024 } // 1mb
limits: { fileSize: 1024 * 1024 }, // 1mb
})
router.post("/create", requireAuth, async (req, res) => {
if (req.userdocument.coins < 100) {
return res.json({status: "error", error: "You don't have enough Rocks!"})
return res.json({
status: "error",
error: "You don't have enough Rocks!",
})
}
uploadicon.single("groupicon")(req, res, async function (err) {
if (err) {
if (err?.message === "File too large") {
return res.status(400).send({status: 'error', error: "File too large! 1MB Limit"})
return res
.status(400)
.send({
status: "error",
error: "File too large! 1MB Limit",
})
}
if (err === "Invalid file type") {
return res.status(400).send({status: 'error', error: "Invalid file type"})
return res
.status(400)
.send({ status: "error", error: "Invalid file type" })
}
return res.status(400).send({status: 'error', error: err.message})
return res.status(400).send({ status: "error", error: err.message })
}
var xss = require("xss")
const { groupname, description, publicgroup } = req.body
if (!groupname) {
return res.json({status: 'error', error: 'Group name needs to be sent.'})
return res.json({
status: "error",
error: "Group name needs to be sent.",
})
}
if (!description) {
return res.json({status: 'error', error: 'Description needs to be sent.'})
return res.json({
status: "error",
error: "Description needs to be sent.",
})
}
if (!publicgroup) {
return res.json({status: 'error', error: 'Public group needs to be sent.'})
return res.json({
status: "error",
error: "Public group needs to be sent.",
})
}
if (publicgroup != "true" && type != "false") {
return res.json({status: 'error', error: 'Public group needs to be a true or false value.'})
return res.json({
status: "error",
error: "Public group needs to be a true or false value.",
})
}
const groupid = await groups.countDocuments();
const groupid = await groups.countDocuments()
// check if the file they just uploaded is valid
await validateImage(groupid, res)
let IconApproved = req.userdocument.admin === false ? false : true
@ -145,38 +194,45 @@ router.post("/create", requireAuth,async (req, res) => {
ownerid: req.userdocument.userid,
memberscount: 1,
members: [{ userId: req.userdocument.userid, rank: 3 }],
Roles: [{RoleName: "Members", Permissions: {Shout: false, Kick: false, ChangeRoles: false, ModerateWall: false, ManageAllies: false}, Rank: 1}, {RoleName: "Admin", Permissions: {Shout: true, Kick: true, ChangeRoles: true, ModerateWall: true, ManageAllies: false}, Rank: 2}, {RoleName: "Owner", Permissions: {All: true}, Rank: 3}]
Roles: [
{
RoleName: "Members",
Permissions: {
Shout: false,
Kick: false,
ChangeRoles: false,
ModerateWall: false,
ManageAllies: false,
},
Rank: 1,
},
{
RoleName: "Admin",
Permissions: {
Shout: true,
Kick: true,
ChangeRoles: true,
ModerateWall: true,
ManageAllies: false,
},
Rank: 2,
},
{ RoleName: "Owner", Permissions: { All: true }, Rank: 3 },
],
})
return res.json({ status: "success", message: "Group created!" })
})
})
router.post("/editgroup", requireAuth,async (req, res) => {
router.post("/editgroup", requireAuth, async (req, res) => {})
router.post("/postshout", requireAuth, async (req, res) => {})
})
router.post("/joingroup", requireAuth, async (req, res) => {})
router.post("/postshout", requireAuth,async (req, res) => {
router.post("/leavegroup", requireAuth, async (req, res) => {})
})
router.post("/joingroup", requireAuth,async (req, res) => {
})
router.post("/leavegroup", requireAuth,async (req, res) => {
})
router.post("/exile", requireAuth,async (req, res) => {
})
router.post("/exile", requireAuth, async (req, res) => {})
module.exports = router

View File

@ -1,8 +1,8 @@
const express = require("express")
const router = express.Router()
const { requireAuth } = require('./../../middleware/authmiddleware')
const User = require('./../../model/user.js')
const bodyParser = require('body-parser')
const { requireAuth } = require("./../../middleware/authmiddleware")
const User = require("./../../model/user.js")
const bodyParser = require("body-parser")
router.use(bodyParser.json())
router.post("/", requireAuth, async (req, res) => {
@ -14,40 +14,32 @@ router.post("/", requireAuth,async (req, res) => {
return res.json("Send Itemid Please")
}
if (action === "wear") {
for (const obj of req.userdocument.inventory) {
if (parseInt(obj.ItemId) === itemid) {
// they own it
// lets check if they already have it equipped
if (obj.Equipped === true) {
return res.json({status: 'error', error: "You already have this Equipped!"})
return res.json({
status: "error",
error: "You already have this Equipped!",
})
}
// they own it and don't have it equipped already so lets add it
try {
obj.Equipped = true
req.userdocument.markModified('inventory')
req.userdocument.markModified("inventory")
await req.userdocument.save()
} catch (err) {
console.log(err)
}
return res.json({status: 'ok', error: "Equipped!"})
return res.json({ status: "ok", error: "Equipped!" })
}
}
// they don't own it
return res.json({status: 'error', error: "You don't own this!"})
return res.json({ status: "error", error: "You don't own this!" })
}
if (action === "remove") {
for (const obj of req.userdocument.inventory) {
if (parseInt(obj.ItemId) === itemid) {
@ -55,27 +47,24 @@ router.post("/", requireAuth,async (req, res) => {
// lets check if they don't already don't it equipped
if (obj.Equipped === false) {
return res.json({status: 'error', error: "You already don't this Equipped!"})
return res.json({
status: "error",
error: "You already don't this Equipped!",
})
}
// they own it and don't have it not equipped already lets remove it
try {
obj.Equipped = false
req.userdocument.markModified('inventory')
req.userdocument.markModified("inventory")
await req.userdocument.save()
} catch (err) {
console.log(err)
}
return res.json({status: 'ok', error: "Equipped!"})
return res.json({ status: "ok", error: "Equipped!" })
}
}
// they don't own it
return res.json({status: 'error', error: "You don't own this!"})
return res.json({ status: "error", error: "You don't own this!" })
}
})

View File

@ -1,45 +1,62 @@
const express = require("express")
const router = express.Router()
const { requireAuth } = require('./../../middleware/authmiddleware')
const items = require('./../../model/item.js')
const bodyParser = require('body-parser')
const fs = require('fs')
const path = require("path");
const { requireAuth } = require("./../../middleware/authmiddleware")
const items = require("./../../model/item.js")
const bodyParser = require("body-parser")
const fs = require("fs")
const path = require("path")
router.use(bodyParser.json())
router.post("/", requireAuth, async (req, res) => {
let { itemid } = req.body
if (typeof itemid == "undefined") {
return res.json({status: 'error', error: "itemid not sent!"})
return res.json({ status: "error", error: "itemid not sent!" })
}
itemid = parseInt(itemid)
if (req.userdocument.admin == false && req.userdocument?.ugcpermission == false) {
return res.redirect('/')
if (
req.userdocument.admin == false &&
req.userdocument?.ugcpermission == false
) {
return res.redirect("/")
}
const item = await items.findOne({ ItemId: itemid })
if (item.Creator != req.userdocument.userid && req.userdocument.admin === false){ // basically we want ugc uploaders to be able to delete there own items but not other peoples items
return res.json({status: 'error', error: "You don't own this item!"})
if (
item.Creator != req.userdocument.userid &&
req.userdocument.admin === false
) {
// basically we want ugc uploaders to be able to delete there own items but not other peoples items
return res.json({ status: "error", error: "You don't own this item!" })
}
try {
items.updateOne({ItemId: itemid}, {
items.updateOne(
{ ItemId: itemid },
{
$set: {
Hidden: true
}
Hidden: true,
},
},
function (err, doc) {
//console.log(err)
})
},
)
// delete the item from our servers
fs.unlink(path.resolve(path.resolve(__dirname, "../../assets/ugc/itemfile-"+itemid+".rbxm")), (err => {
fs.unlink(
path.resolve(
path.resolve(
__dirname,
"../../assets/ugc/itemfile-" + itemid + ".rbxm",
),
),
err => {
if (err) console.log(err)
}));
},
)
} catch (err) {
console.log(err)
}
return res.json({status: 'success'})
return res.json({ status: "success" })
})
router.post("/queue", requireAuth, async (req, res) => {
@ -51,7 +68,7 @@ router.post("/queue", requireAuth,async (req, res) => {
return res.json("Send Itemid Please")
}
if (req.userdocument.admin == false) {
return res.redirect('/')
return res.redirect("/")
}
const item = await items.findOne({ ItemId: itemid })
@ -67,9 +84,17 @@ router.post("/queue", requireAuth,async (req, res) => {
item.markModified("Hidden")
item.markModified("denied")
await item.save()
fs.unlink(path.resolve(path.resolve(__dirname, "../../assets/ugc/itemfile-"+itemid+".rbxm")), (err => {
fs.unlink(
path.resolve(
path.resolve(
__dirname,
"../../assets/ugc/itemfile-" + itemid + ".rbxm",
),
),
err => {
if (err) console.log(err)
}));
},
)
}
if (action === "approve") {
item.approved = true
@ -82,7 +107,6 @@ router.post("/queue", requireAuth,async (req, res) => {
image.markModified("approved")
await image.save()
}
}
// finish this LMAO pretty ez tho
return res.json({ status: "success", message: "Done!" })

View File

@ -1,15 +1,18 @@
const express = require("express")
const router = express.Router()
const { requireAuth } = require('./../../middleware/authmiddleware')
const bodyParser = require('body-parser')
var numbtest = /^\d+\.?\d*$/;
const items = require('./../../model/item.js')
const User = require('./../../model/user.js')
const { requireAuth } = require("./../../middleware/authmiddleware")
const bodyParser = require("body-parser")
var numbtest = /^\d+\.?\d*$/
const items = require("./../../model/item.js")
const User = require("./../../model/user.js")
router.use(bodyParser.json())
router.post("/", requireAuth, async (req, res) => {
if (!req.userdocument.discordid) {
return res.json({status: "error", error: "Discord link required for purchasing. Link your discord in the settings panel."})
return res.json({
status: "error",
error: "Discord link required for purchasing. Link your discord in the settings panel.",
})
}
const { itemid } = req.body
if (typeof itemid == "undefined") {
@ -19,65 +22,78 @@ router.post("/", requireAuth,async (req, res) => {
return res.json({ status: "error", error: "You need sum itemids bozo" })
}
const itemdoc = await items.findOne({ ItemId: itemid }) //.lean()
if (typeof req.userdocument.inventory !== "undefined") {
// check if user already owns item
for (var v of req.userdocument.inventory) {
if (v.ItemId === itemdoc.ItemId) {
// they already own it
return res.json({status: 'error', error: "You already own this!"})
return res.json({
status: "error",
error: "You already own this!",
})
}
}
}
if (itemdoc.Type === "Mesh" || itemdoc.Type === "Audio" || itemdoc.Type === "Mesh"){
return res.json({status: 'error', error: "You can't buy assets."})
if (
itemdoc.Type === "Mesh" ||
itemdoc.Type === "Audio" ||
itemdoc.Type === "Mesh"
) {
return res.json({ status: "error", error: "You can't buy assets." })
}
if (itemdoc.Hidden) {
return res.json({status: 'error', error: "You can't buy this."})
return res.json({ status: "error", error: "You can't buy this." })
}
if (req.userdocument.coins >= itemdoc.Price) {
// has enough money to purcahse item
try {
User.updateOne({userid: req.userdocument.userid}, {
User.updateOne(
{ userid: req.userdocument.userid },
{
$set: {
coins: req.userdocument.coins - itemdoc.Price
coins: req.userdocument.coins - itemdoc.Price,
},
$push: {
inventory: {Type: itemdoc.Type,ItemId: itemdoc.ItemId, ItemName: itemdoc.Name, Equipped: false}
}
inventory: {
Type: itemdoc.Type,
ItemId: itemdoc.ItemId,
ItemName: itemdoc.Name,
Equipped: false,
},
},
},
function (err, doc) {
//console.log(err)
})
},
)
// give owner cash
User.updateOne({userid: itemdoc.Creator}, {
User.updateOne(
{ userid: itemdoc.Creator },
{
$inc: {
coins: itemdoc.Price
}
coins: itemdoc.Price,
},
},
function (err, doc) {
//console.log(err)
})
},
)
itemdoc.Sales += 1
if (!itemdoc.Sales) {
itemdoc.Sales = 1
}
//console.log(itemdoc.Sales)
itemdoc.markModified('Sales')
itemdoc.markModified("Sales")
await itemdoc.save()
}catch{
}
return res.json({status: 'success', message: 'Purchase successful'})
} catch {}
return res.json({ status: "success", message: "Purchase successful" })
}
// too poor
return res.json({status: 'error', error: "You don't have enough rocks"})
return res.json({ status: "error", error: "You don't have enough rocks" })
})
module.exports = router

View File

@ -1,20 +1,21 @@
const express = require("express")
const router = express.Router()
const rcctalk = require('./../../thumbnailrcctalk')
const rcctalk2018 = require('./../../rcctalk2018')
const fs = require('fs')
const assetrenderscript = fs.readFileSync('assetthumbnailrenderer.lua','utf-8')
var path = require("path");
const User = require('./../../model/user.js')
const item = require('./../../model/item.js')
var rgx = /^[0-9]*\.?[0-9]*$/;
router.use(express.json({limit: '200mb'}));
const { requireAuth } = require('./../../middleware/authmiddleware.js')
const { grabAuth } = require('./../../middleware/grabauth.js')
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
require('dotenv').config()
const rcctalk = require("./../../thumbnailrcctalk")
const rcctalk2018 = require("./../../rcctalk2018")
const fs = require("fs")
const assetrenderscript = fs.readFileSync("assetthumbnailrenderer.lua", "utf-8")
var path = require("path")
const User = require("./../../model/user.js")
const item = require("./../../model/item.js")
var rgx = /^[0-9]*\.?[0-9]*$/
router.use(express.json({ limit: "200mb" }))
const { requireAuth } = require("./../../middleware/authmiddleware.js")
const { grabAuth } = require("./../../middleware/grabauth.js")
const fetch = (...args) =>
import("node-fetch").then(({ default: fetch }) => fetch(...args))
require("dotenv").config()
const RCC_HOST = process.env.RCC_HOST
const rateLimit = require('express-rate-limit')
const rateLimit = require("express-rate-limit")
const limiter = rateLimit({
windowMs: 2 * 1000, // 5 seconds
max: 1, // Limit each IP to 1 requests per `window`
@ -22,7 +23,7 @@ const limiter = rateLimit({
legacyHeaders: false, // Disable the `X-RateLimit-*` headers
handler: (request, response, next, options) => {
return response.sendFile(path.resolve("./assets/default.png"))
}
},
})
router.get("/", grabAuth, async (req, res) => {
@ -39,85 +40,98 @@ router.get("/",grabAuth,async (req, res) => {
const user = await User.findOne({ userid: sanitizedid }).lean()
if (!user) {
return res.json({status: 'error', error: 'User does not exist'})
return res.json({ status: "error", error: "User does not exist" })
}
// lets get our file path with sanitized id
let path2=path.resolve(__dirname, "../../assets/userthumbnails/"+sanitizedid+".png")
let path2 = path.resolve(
__dirname,
"../../assets/userthumbnails/" + sanitizedid + ".png",
)
if (headshot === true) {
path2=path.resolve(__dirname, "../../assets/userthumbnailsheadshots/"+sanitizedid+".png")
path2 = path.resolve(
__dirname,
"../../assets/userthumbnailsheadshots/" + sanitizedid + ".png",
)
}
fs.access(path2, fs.F_OK,async (err) => {
fs.access(path2, fs.F_OK, async err => {
if (err) {
let newrender = await rcctalk2018.OpenRender(sanitizedid, headshot)
if (newrender.error) {
return res.sendFile(path.resolve("./assets/default.png"))
}
newrender = newrender['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:OpenJobResponse']['ns1:OpenJobResult'][0]['ns1:value']._text
newrender =
newrender["SOAP-ENV:Envelope"]["SOAP-ENV:Body"][
"ns1:OpenJobResponse"
]["ns1:OpenJobResult"][0]["ns1:value"]._text
res.writeHead(200, {'Content-Type': 'image/png'})
res.writeHead(200, { "Content-Type": "image/png" })
fs.writeFile(path2,newrender,'base64',function(err){
fs.writeFile(path2, newrender, "base64", function (err) {
if (err) {
console.log("error")
}
})
return res.end(Buffer.from(newrender, 'base64'))
return res.end(Buffer.from(newrender, "base64"))
// if this timeouts and rcc doesn't return the image feor some reason then send the default fallback
//return res.sendFile(path.resolve("./assets/default.png"))
}
//file exists
if (req.query.method && req.userdocument && req.userdocument.userid == sanitizedid){ // don't allow unauthenticated users to regenerate avatars and don't allow authenticated users to regenerate other peoples avatars
if (
req.query.method &&
req.userdocument &&
req.userdocument.userid == sanitizedid
) {
// don't allow unauthenticated users to regenerate avatars and don't allow authenticated users to regenerate other peoples avatars
if (req.query.method === "regenerate") {
fs.unlink(path2, async function (err) {
if (err) {
console.log(err)
}
let newrender = await rcctalk2018.OpenRender(sanitizedid,headshot)
let newrender = await rcctalk2018.OpenRender(
sanitizedid,
headshot,
)
if (newrender.error) {
return res.sendFile(path.resolve("./assets/default.png"))
return res.sendFile(
path.resolve("./assets/default.png"),
)
}
newrender = newrender['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:OpenJobResponse']['ns1:OpenJobResult'][0]['ns1:value']._text
newrender =
newrender["SOAP-ENV:Envelope"]["SOAP-ENV:Body"][
"ns1:OpenJobResponse"
]["ns1:OpenJobResult"][0]["ns1:value"]._text
res.writeHead(200, {'Content-Type': 'image/png'})
res.writeHead(200, { "Content-Type": "image/png" })
fs.writeFile(path2,newrender,'base64',function(err){
fs.writeFile(path2, newrender, "base64", function (err) {
if (err) {
console.log("error")
}
})
return res.end(Buffer.from(newrender, 'base64'))
});
return res.end(Buffer.from(newrender, "base64"))
})
}
} else {
res.sendFile(path.resolve(path2))
return
}
})
})
router.post("/rcc", (req, res) => {
var ip = req.headers['cf-connecting-ip'] || req.socket.remoteAddress
var ip = req.headers["cf-connecting-ip"] || req.socket.remoteAddress
if (ip == RCC_HOST || ip == "::ffff:" + RCC_HOST) {
const { player, thumbnail } = req.body
let path2=path.resolve(__dirname, "../../assets/userthumbnails/"+player+".png")
fs.writeFile(path2,thumbnail,'base64',function(err){
let path2 = path.resolve(
__dirname,
"../../assets/userthumbnails/" + player + ".png",
)
fs.writeFile(path2, thumbnail, "base64", function (err) {
if (err) {
console.log("error")
// if writing fails we can still fallback
@ -130,9 +144,6 @@ router.post("/rcc", (req, res) => {
}
})
router.get(["/asset", "/asset.ashx"], grabAuth, async (req, res) => {
if (!req.query.id && !req.query.assetid) {
return res.status(400)
@ -143,7 +154,7 @@ router.get(["/asset","/asset.ashx"],grabAuth,async (req, res) => {
const user = await item.findOne({ ItemId: sanitizedid }).lean()
if (!user) {
return res.json({status: 'error', error: 'Item does not exist'})
return res.json({ status: "error", error: "Item does not exist" })
}
if (user.Type === "Audio") {
return res.sendFile(path.resolve("./assets/images/audio.png"))
@ -155,42 +166,77 @@ router.get(["/asset","/asset.ashx"],grabAuth,async (req, res) => {
if (user.approved === false && !req.query.nonapproved) {
return res.sendFile(path.resolve("./assets/approval.png"))
}
if (req.query.nonapproved && req?.userdocument?.admin === false){ // we only want admins to be able to see non approved assets anyways
if (req.query.nonapproved && req?.userdocument?.admin === false) {
// we only want admins to be able to see non approved assets anyways
return res.sendFile(path.resolve("./assets/approval.png"))
}
if (req.query.nonapproved && (user.Type === "Pants" || user.Type === "Shirts")){
if (
req.query.nonapproved &&
(user.Type === "Pants" || user.Type === "Shirts")
) {
sanitizedid -= 1
return res.sendFile(path.resolve(__dirname, "../../assets/ugc/itemfile-"+sanitizedid+".rbxm"))
return res.sendFile(
path.resolve(
__dirname,
"../../assets/ugc/itemfile-" + sanitizedid + ".rbxm",
),
)
}
if (req.query.nonapproved && user.Type === "Video") {
return res.sendFile(path.resolve(__dirname, "../../assets/ugc/itemfile-"+sanitizedid+".rbxm"))
return res.sendFile(
path.resolve(
__dirname,
"../../assets/ugc/itemfile-" + sanitizedid + ".rbxm",
),
)
}
if (user.Type === "Video") {
return res.sendFile(path.resolve("./assets/video.png"))
}
if (user.Type === "User Ad" || user.Type === "Gamepass") {
try {
await fs.promises.access(path.resolve(__dirname, "../../assets/ugc/itemfile-"+sanitizedid+".rbxm"), fs.constants.W_OK)
return res.sendFile(path.resolve(__dirname, "../../assets/ugc/itemfile-"+sanitizedid+".rbxm"))
await fs.promises.access(
path.resolve(
__dirname,
"../../assets/ugc/itemfile-" + sanitizedid + ".rbxm",
),
fs.constants.W_OK,
)
return res.sendFile(
path.resolve(
__dirname,
"../../assets/ugc/itemfile-" + sanitizedid + ".rbxm",
),
)
} catch {
return res.sendFile(path.resolve("./assets/images/defaultadsky.png"))
return res.sendFile(
path.resolve("./assets/images/defaultadsky.png"),
)
}
}
// lets get our file path with sanitized id
let path2=path.resolve(__dirname, "../../assets/ugc/asset-"+sanitizedid+".png")
let path2 = path.resolve(
__dirname,
"../../assets/ugc/asset-" + sanitizedid + ".png",
)
fs.access(path2, fs.F_OK,async (err) => {
fs.access(path2, fs.F_OK, async err => {
if (err) {
// get our renderscript with the new character app
var newrenderscript = assetrenderscript.replace('local asset = 0','local asset = "'+sanitizedid+'"')
var newrenderscript = assetrenderscript.replace(
"local asset = 0",
'local asset = "' + sanitizedid + '"',
)
//open a new job for our thumbnail render request
var response = await rcctalk.OpenJob("Thumbnailfor"+sanitizedid,newrenderscript,"120")
if (response['SOAP-ENV:Envelope']['SOAP-ENV:Body']['SOAP-ENV:Fault']){
var response = await rcctalk.OpenJob(
"Thumbnailfor" + sanitizedid,
newrenderscript,
"120",
)
if (
response["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["SOAP-ENV:Fault"]
) {
// if failed then print out error close job then send a fallback image
//console.dir(response,{ depth: null })
rcctalk.CloseJob("Thumbnailfor" + sanitizedid)
@ -206,7 +252,7 @@ router.get(["/asset","/asset.ashx"],grabAuth,async (req, res) => {
} else {
return res.sendFile(path2)
}
});
})
}, 3000)
}
}
@ -218,22 +264,19 @@ router.get(["/asset","/asset.ashx"],grabAuth,async (req, res) => {
res.sendFile(path.resolve(path2))
return
})
})
router.post("/rccasset", (req, res) => {
var ip = req.headers['cf-connecting-ip'] || req.socket.remoteAddress
var ip = req.headers["cf-connecting-ip"] || req.socket.remoteAddress
if (ip == RCC_HOST || ip == "::ffff:" + RCC_HOST) {
const { asset, thumbnail } = req.body
console.log(asset)
let path2=path.resolve(__dirname, "../../assets/ugc/asset-"+asset+".png")
fs.writeFile(path2,thumbnail,'base64',function(err){
let path2 = path.resolve(
__dirname,
"../../assets/ugc/asset-" + asset + ".png",
)
fs.writeFile(path2, thumbnail, "base64", function (err) {
if (err) {
console.log("error")
// if writing fails we can still fallback

View File

@ -1,14 +1,13 @@
const express = require("express")
const router = express.Router()
const { requireAuth } = require('./../../middleware/authmiddleware')
const bodyParser = require('body-parser')
const catalog = require('./../../model/item.js')
const { requireAuth } = require("./../../middleware/authmiddleware")
const bodyParser = require("body-parser")
const catalog = require("./../../model/item.js")
//const path = require('path');
router.use(bodyParser.json())
// only supports skyscraper ads for now
router.get("/", async (req, res) => {
const activeAdCount = await catalog.countDocuments({ ActiveAd: true })
//console.log(activeAdCount)
@ -18,13 +17,21 @@ router.get("/",async (req, res) => {
const Addoc = await catalog.findOne({ ActiveAd: true }).skip(random)
if (!Addoc) {
// no ads are running!
return res.json({imageUrl: "/assets/images/defaultadsky.png", redirectUrl: "#", AdID: 0})
return res.json({
imageUrl: "/assets/images/defaultadsky.png",
redirectUrl: "#",
AdID: 0,
})
}
if (Addoc.adstartedtime <= new Date(new Date().getTime() - (24 * 60 * 60 * 1000)).getTime() || Addoc.Hidden){
if (
Addoc.adstartedtime <=
new Date(new Date().getTime() - 24 * 60 * 60 * 1000).getTime() ||
Addoc.Hidden
) {
// more than 24 hours old invalidate ad OR ad was moderated
Addoc.ActiveAd = false
Addoc.markModified('ActiveAd')
Addoc.markModified("ActiveAd")
await Addoc.save()
}
let redirectUrl
@ -33,8 +40,11 @@ router.get("/",async (req, res) => {
redirectUrl = "/games/" + Addoc.adredirectid
}
return res.json({imageUrl: "/api/thumbnailrender/asset?id="+Addoc.ItemId, redirectUrl, AdID: Addoc.ItemId})
return res.json({
imageUrl: "/api/thumbnailrender/asset?id=" + Addoc.ItemId,
redirectUrl,
AdID: Addoc.ItemId,
})
})
module.exports = router

View File

@ -1,38 +1,43 @@
const express = require("express")
const router = express.Router()
const bodyParser = require('body-parser')
const rcc = require('./../../model/rcc.js')
const rcc2018 = require('./../../model/rcc2018.js')
const rcc2020 = require('./../../model/rcc2020.js')
const games = require('./../../model/games.js')
const rcctalk = require('./../../rcctalk')
const rcctalk2018 = require('./../../rcctalk2018')
const User = require('../../model/user.js')
const bodyParser = require("body-parser")
const rcc = require("./../../model/rcc.js")
const rcc2018 = require("./../../model/rcc2018.js")
const rcc2020 = require("./../../model/rcc2020.js")
const games = require("./../../model/games.js")
const rcctalk = require("./../../rcctalk")
const rcctalk2018 = require("./../../rcctalk2018")
const User = require("../../model/user.js")
router.use(bodyParser.json())
require('dotenv').config()
require("dotenv").config()
const RCC_HOST = process.env.RCC_HOST
router.post("/api/updategameinfo", async (req, res) => {
var ip = req.headers['cf-connecting-ip'] || req.socket.remoteAddress
var ip = req.headers["cf-connecting-ip"] || req.socket.remoteAddress
if (ip == RCC_HOST || ip == "::ffff:" + RCC_HOST) {
const { game, players } = req.body
//const instance = await rcc.findOne({PlaceId: game}).lean()
games.updateOne({idofgame: game}, {
games.updateOne(
{ idofgame: game },
{
$set: {
numberofplayers: parseInt(players).toString()
}
numberofplayers: parseInt(players).toString(),
},
},
function (err, doc) {
//console.log(err)
})
},
)
res.send("good")
}
})
router.all(["/api/updategameinfo/updatevisits","/game/placevisit.ashx"], async (req, res) => {
var ip = req.headers['cf-connecting-ip'] || req.socket.remoteAddress
router.all(
["/api/updategameinfo/updatevisits", "/game/placevisit.ashx"],
async (req, res) => {
var ip = req.headers["cf-connecting-ip"] || req.socket.remoteAddress
if (ip == RCC_HOST || ip == "::ffff:" + RCC_HOST) {
let { game } = req.body
if (req.query.AssociatedPlaceID) {
@ -40,92 +45,103 @@ router.all(["/api/updategameinfo/updatevisits","/game/placevisit.ashx"], async (
}
//const instance = await rcc.findOne({PlaceId: game}).lean()
games.updateOne({idofgame: game}, {
games.updateOne(
{ idofgame: game },
{
$inc: {
visits: 1
}
visits: 1,
},
},
function (err, doc) {
//console.log(err)
})
},
)
res.send("good")
}
})
},
)
router.all("/api/updategameinfo/gameloaded", async (req, res) => {
var ip = req.headers['cf-connecting-ip'] || req.socket.remoteAddress
var ip = req.headers["cf-connecting-ip"] || req.socket.remoteAddress
if (ip == RCC_HOST || ip == "::ffff:" + RCC_HOST) {
let { game } = req.body
const gamedoc = await games.findOne({ idofgame: game }).lean()
if (gamedoc.version === "2020") {
rcc2020.updateOne({PlaceId: game}, {
rcc2020.updateOne(
{ PlaceId: game },
{
$set: {
Status: 2
}
Status: 2,
},
},
function (err, doc) {
//console.log(err)
})
},
)
}
if (gamedoc.version === "2018") {
rcc2018.updateOne({PlaceId: game}, {
rcc2018.updateOne(
{ PlaceId: game },
{
$set: {
Status: 2
}
Status: 2,
},
},
function (err, doc) {
//console.log(err)
})
},
)
}
if (gamedoc.version === "2016") {
rcc.updateOne({PlaceId: game}, {
rcc.updateOne(
{ PlaceId: game },
{
$set: {
Status: 2
}
Status: 2,
},
},
function (err, doc) {
//console.log(err)
})
},
)
}
res.send("good")
}
})
router.post("/api/updategameinfo/closejob", async (req, res) => {
var ip = req.headers['cf-connecting-ip'] || req.socket.remoteAddress
var ip = req.headers["cf-connecting-ip"] || req.socket.remoteAddress
if (ip == RCC_HOST || ip == "::ffff:" + RCC_HOST) {
console.log("closed")
let { game } = req.body
if(typeof game === 'string'){
game = game.replace('game','')
if (typeof game === "string") {
game = game.replace("game", "")
}
//const instance = await rcc.findOne({PlaceId: game}).lean()
games.updateOne({idofgame: game}, {
games.updateOne(
{ idofgame: game },
{
$set: {
numberofplayers: "0"
}
numberofplayers: "0",
},
},
function (err, doc) {
//console.log(err)
})
games.updateOne({idofgame: game}, {
},
)
games.updateOne(
{ idofgame: game },
{
$set: {
players: []
}
players: [],
},
},
function (err, doc) {
//console.log(err)
})
},
)
const gamedoc = await games.findOne({ idofgame: game }).lean()
try {
if (gamedoc.version === "2018") {
@ -152,117 +168,147 @@ res.send("good")
})
router.get("/api/updategameinfo/closealljobs", async (req, res) => {
var ip = req.headers['cf-connecting-ip'] || req.socket.remoteAddress
var ip = req.headers["cf-connecting-ip"] || req.socket.remoteAddress
if (ip == RCC_HOST || ip == "::ffff:" + RCC_HOST) {
console.log("closed all")
//const instance = await rcc.findOne({PlaceId: game}).lean()
await rcc.deleteMany({})
games.updateMany({version: "2016"}, {
games.updateMany(
{ version: "2016" },
{
$set: {
numberofplayers: "0"
}
numberofplayers: "0",
},
},
function (err, doc) {
//console.log(err)
})
games.updateMany({version: "2016"}, {
},
)
games.updateMany(
{ version: "2016" },
{
$set: {
players: []
}
players: [],
},
},
function (err, doc) {
//console.log(err)
})
},
)
rcctalk.CloseAllJobs()
res.send("good")
}
})
router.all(["/api/updategameinfo/updatepresence"], async (req, res) => {
var ip = req.headers['cf-connecting-ip'] || req.socket.remoteAddress
var ip = req.headers["cf-connecting-ip"] || req.socket.remoteAddress
if (ip == RCC_HOST || ip == "::ffff:" + RCC_HOST) {
let { game, player, name, action } = req.body
game = await games.findOne({ idofgame: game })
if (action === "joining" || action === "connect") {
const updatedcount = parseFloat(game.numberofplayers) + 1
games.updateOne({idofgame: game.idofgame}, {
games.updateOne(
{ idofgame: game.idofgame },
{
$push: {
players: {userid: player, name: name}
players: { userid: player, name: name },
},
$set: {
numberofplayers: updatedcount.toString()
}
numberofplayers: updatedcount.toString(),
},
},
function (err, doc) {
//console.log(err)
})
User.updateOne({userid: player}, {
},
)
User.updateOne(
{ userid: player },
{
$set: {
status: JSON.stringify({status: "Playing "+game.nameofgame,id: game.idofgame})
status: JSON.stringify({
status: "Playing " + game.nameofgame,
id: game.idofgame,
}),
},
$addToSet: {
recentlyplayed: {id: game.idofgame}
recentlyplayed: { id: game.idofgame },
},
},
function (err, doc) {
//console.log(err)
})
User.updateOne({userid: player}, {
},
)
User.updateOne(
{ userid: player },
{
$set: {
status: JSON.stringify({status: "Playing "+game.nameofgame,id: game.idofgame})
status: JSON.stringify({
status: "Playing " + game.nameofgame,
id: game.idofgame,
}),
},
$push: {
recentlyplayed: {$each: [], $slice: -10}// limit for recently played is 10 so slice anything older than that
recentlyplayed: { $each: [], $slice: -10 }, // limit for recently played is 10 so slice anything older than that
},
},
function (err, doc) {
//console.log(err)
})
},
)
if (game.version === "2018" || game.version === "2020") {
rcctalk2018.RenewLease("game"+game.idofgame,"69530318916789546987353800") // if someone joins we want to renew the lease so it doesn't expire
rcctalk2018.RenewLease(
"game" + game.idofgame,
"69530318916789546987353800",
) // if someone joins we want to renew the lease so it doesn't expire
// mostly just for stopping people from spamming urls and keeping games loaded
}
if (game.version === "2020"){ // 2020 doesn't do visits for some reason
games.updateOne({idofgame: game.idofgame}, {
if (game.version === "2020") {
// 2020 doesn't do visits for some reason
games.updateOne(
{ idofgame: game.idofgame },
{
$inc: {
visits: 1
}
visits: 1,
},
},
function (err, doc) {
//console.log(err)
})
},
)
}
}
if (action === "leaving" || action === "disconnect") {
const updatedcount = parseFloat(game.numberofplayers) - 1
games.updateOne({idofgame: game.idofgame}, {
games.updateOne(
{ idofgame: game.idofgame },
{
$pull: {
players: {userid: player, name: name}
players: { userid: player, name: name },
},
$set: {
numberofplayers: updatedcount.toString()
}
numberofplayers: updatedcount.toString(),
},
},
function (err, doc) {
//console.log(err)
})
},
)
User.updateOne({userid: player}, {
User.updateOne(
{ userid: player },
{
$set: {
status: JSON.stringify({status: "Offline"})
}
status: JSON.stringify({ status: "Offline" }),
},
},
function (err, doc) {
//console.log(err)
})
},
)
}
res.send("good")
}
})

View File

@ -1,37 +1,40 @@
const express = require("express")
const router = express.Router()
const user = require('./../..//model/user.js')
const { requireAuth } = require('./../../middleware/authmiddleware')
const user = require("./../..//model/user.js")
const { requireAuth } = require("./../../middleware/authmiddleware")
router.post("/buymembership", requireAuth, async (req, res) => {
if (req.userdocument?.membership != "None") {
return res.json({status:"error",error:"You already have membership!"})
return res.json({
status: "error",
error: "You already have membership!",
})
}
if (req.userdocument.coins >= 200) {
req.userdocument.coins -= 200
req.userdocument.membership = "BuildersClub"
req.userdocument.markModified('coins')
req.userdocument.markModified('membership')
req.userdocument.markModified("coins")
req.userdocument.markModified("membership")
await req.userdocument.save()
return res.json({status:"success",message:"You have builders club now!"})
return res.json({
status: "success",
message: "You have builders club now!",
})
}
return res.json({ status: "error", error: "Not enough rocks!" })
})
router.post("/:id", async (req, res) => {
var id = req.params.id;
var id = req.params.id
if (isNaN(parseFloat(id)) === true) {
return res.json({ error: true })
}
var key = req.query.key;
var key = req.query.key
if (isNaN(parseFloat(key)) === true) {
return res.json({ error: true })
}
@ -47,11 +50,9 @@ router.post("/:id",async (req, res) => {
}
response.membership = req.query.newmembership
response.markModified('membership')
response.markModified("membership")
await response.save()
return res.json({ error: false })
})
module.exports = router

View File

@ -1,12 +1,12 @@
const express = require("express")
const router = express.Router()
const user = require('./../..//model/user.js')
const user = require("./../..//model/user.js")
const games = require("./../../model/games.js")
const RelativeTime = require("@yaireo/relative-time")
const relativeTime = new RelativeTime()
router.get("/:id", async (req, res) => {
var id = req.params.id;
var id = req.params.id
if (isNaN(parseFloat(id)) === true) {
return res.json({ error: true })
}
@ -21,25 +21,66 @@ router.get("/:id",async (req, res) => {
status = JSON.parse(response.status)
}
const actualTimeMilliseconds = new Date().getTime()
if (response.timesincelastrequest && actualTimeMilliseconds - response.timesincelastrequest >= 60000 * 3 /*3 minutes*/ && status && status.status.includes("Playing") === false || response.timesincelastrequest && actualTimeMilliseconds - response.timesincelastrequest >= 60000 * 3 /*3 minutes*/ && !status){
if (
(response.timesincelastrequest &&
actualTimeMilliseconds - response.timesincelastrequest >=
60000 * 3 /*3 minutes*/ &&
status &&
status.status.includes("Playing") === false) ||
(response.timesincelastrequest &&
actualTimeMilliseconds - response.timesincelastrequest >=
60000 * 3 /*3 minutes*/ &&
!status)
) {
// been 3 minutes since last request mark as offline make sure we don't mark them offline while they are playing a game
status.status = "Offline"
response.status = JSON.stringify(status)
status = JSON.parse(response.status)
}
if (response.timesincelastrequest && actualTimeMilliseconds - response.timesincelastrequest <= 60000 * 3 /*3 minutes*/ && status && status.status.includes("Playing") === false || response.timesincelastrequest && actualTimeMilliseconds - response.timesincelastrequest <= 60000 * 3 /*3 minutes*/ && !status){
if (
(response.timesincelastrequest &&
actualTimeMilliseconds - response.timesincelastrequest <=
60000 * 3 /*3 minutes*/ &&
status &&
status.status.includes("Playing") === false) ||
(response.timesincelastrequest &&
actualTimeMilliseconds - response.timesincelastrequest <=
60000 * 3 /*3 minutes*/ &&
!status)
) {
status.status = "Online"
response.status = JSON.stringify(status)
status = JSON.parse(response.status)
}
return res.json({error:false, userinfo: {joindate: response.joindate, joindateepoch:new Date(response._id.getTimestamp()).getTime(), lastonline: relativeTime.from(new Date(response.timesincelastrequest)), lastonlineepoch: response.timesincelastrequest, coins: response.coins, username: response.username,userid: response.userid,friends: response.friends, admin: response.admin, discordid: response.discordid, membership: response.membership, inventory: response.inventory, bio: response.bio, status,followers: response.followers?.length, css: response.css, aboutme: response.aboutme}})
return res.json({
error: false,
userinfo: {
joindate: response.joindate,
joindateepoch: new Date(response._id.getTimestamp()).getTime(),
lastonline: relativeTime.from(
new Date(response.timesincelastrequest),
),
lastonlineepoch: response.timesincelastrequest,
coins: response.coins,
username: response.username,
userid: response.userid,
friends: response.friends,
admin: response.admin,
discordid: response.discordid,
membership: response.membership,
inventory: response.inventory,
bio: response.bio,
status,
followers: response.followers?.length,
css: response.css,
aboutme: response.aboutme,
},
})
})
router.get("/:id/creations", async (req, res) => {
var id = req.params.id;
var id = req.params.id
if (isNaN(parseFloat(id)) === true) {
return res.json({ error: true })
}
@ -49,15 +90,23 @@ router.get("/:id/creations",async (req, res) => {
return res.status(404).json({ error: true, message: "Not found" })
}
const gameresponse = await games.find({useridofowner: id}).lean().select(['idofgame', 'version', 'nameofgame', 'numberofplayers', 'visits', 'useridofowner'])
const gameresponse = await games
.find({ useridofowner: id })
.lean()
.select([
"idofgame",
"version",
"nameofgame",
"numberofplayers",
"visits",
"useridofowner",
])
return res.json(gameresponse)
})
router.get("/:id/visits", async (req, res) => {
var id = req.params.id;
var id = req.params.id
if (isNaN(parseFloat(id)) === true) {
return res.json({ error: true })
}
@ -70,26 +119,24 @@ router.get("/:id/visits",async (req, res) => {
const visits = await games.aggregate([
{ $match: { useridofowner: parseFloat(id) } },
{
"$group": {
"_id": null,
"visits": {
'$sum': "$visits"
}
}
}
$group: {
_id: null,
visits: {
$sum: "$visits",
},
},
},
])
return res.json({ error: false, visits: visits[0]?.visits || 0 })
})
router.get("/usernametoid/:id", async (req, res) => {
var id = req.params.id
var id = req.params.id;
const response = await user.findOne({username: {'$regex': id,$options:'i'}}).lean()
const response = await user
.findOne({ username: { $regex: id, $options: "i" } })
.lean()
if (!response) {
console.log(response)
@ -100,8 +147,7 @@ router.get("/usernametoid/:id",async (req, res) => {
})
router.get("/discordidtouserid/:id", async (req, res) => {
var id = req.params.id;
var id = req.params.id
const response = await user.findOne({ discordid: id }).lean()

View File

@ -1,8 +1,8 @@
const express = require("express")
const router = express.Router()
const { requireAuth } = require('./../../middleware/authmiddleware')
const games = require('./../../model/games.js')
const bodyParser = require('body-parser')
const { requireAuth } = require("./../../middleware/authmiddleware")
const games = require("./../../model/games.js")
const bodyParser = require("body-parser")
router.use(bodyParser.json())
router.post("/", requireAuth, async (req, res) => {
@ -11,23 +11,25 @@ router.post("/", requireAuth,async (req, res) => {
return res.json("Send gameid Please")
}
if (req.userdocument.admin == false) {
return res.redirect('/')
return res.redirect("/")
}
try {
games.updateOne({idofgame: gameid}, {
games.updateOne(
{ idofgame: gameid },
{
$set: {
featured: true
}
featured: true,
},
},
function (err, doc) {
//console.log(err)
})
},
)
} catch (err) {
console.log(err)
}
return res.json({status: 'ok'})
return res.json({ status: "ok" })
})
module.exports = router

View File

@ -1,23 +1,24 @@
const { response } = require("express")
const express = require("express")
const router = express.Router()
const fs = require('fs')
var path = require('path');
const crypto = require('crypto');
require('dotenv').config()
const fs = require("fs")
var path = require("path")
const crypto = require("crypto")
require("dotenv").config()
const RCC_HOST = process.env.RCC_HOST
const User = require('../model/user.js')
const User = require("../model/user.js")
const catalog = require("../model/item")
const games = require('./../model/games.js')
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
const games = require("./../model/games.js")
const fetch = (...args) =>
import("node-fetch").then(({ default: fetch }) => fetch(...args))
//redirect hmmmm
var rgx = /^[0-9]*\.?[0-9]*$/;
var rgx = /^[0-9]*\.?[0-9]*$/
router.get("/", async (req, res) => {
if (req.query.name) {
const user = await User.findOne({ userid: req.query.name }).lean()
if (!user) {
return res.json({status: 'error', error: 'User not found!'})
return res.json({ status: "error", error: "User not found!" })
}
if (req.query.rcc) {
@ -28,20 +29,32 @@ if (req.query.name){
return res.json(empty)
}
res.type('application/xml');
var colorsxml = `<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
res.type("application/xml")
var colorsxml =
`<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
<External>null</External>
<External>nil</External>
<Item class="BodyColors">
<Properties>
<int name="HeadColor">`+user.colors.find(x => x.name === 'Head').value+`</int>
<int name="LeftArmColor">`+user.colors.find(x => x.name === 'Left Arm').value+`</int>
<int name="LeftLegColor">`+user.colors.find(x => x.name === 'Left Leg').value+`</int>
<int name="HeadColor">` +
user.colors.find(x => x.name === "Head").value +
`</int>
<int name="LeftArmColor">` +
user.colors.find(x => x.name === "Left Arm").value +
`</int>
<int name="LeftLegColor">` +
user.colors.find(x => x.name === "Left Leg").value +
`</int>
<string name="Name">Body Colors</string>
<int name="RightArmColor">`+user.colors.find(x => x.name === 'Right Arm').value+`</int>
<int name="RightLegColor">`+user.colors.find(x => x.name === 'Right Leg').value+`</int>
<int name="TorsoColor">`+user.colors.find(x => x.name === 'Torso').value+`</int>
<int name="RightArmColor">` +
user.colors.find(x => x.name === "Right Arm").value +
`</int>
<int name="RightLegColor">` +
user.colors.find(x => x.name === "Right Leg").value +
`</int>
<int name="TorsoColor">` +
user.colors.find(x => x.name === "Torso").value +
`</int>
<bool name="archivable">true</bool>
</Properties>
</Item>
@ -49,82 +62,129 @@ if (req.query.name){
return res.send(colorsxml)
}
if (req.query.method || /*req.headers?.["requester"] === "Server" &&*/ req.headers?.["assettype"] === "Place"){
var ip = req.headers['cf-connecting-ip'] || req.socket.remoteAddress
if (
req.query.method ||
/*req.headers?.["requester"] === "Server" &&*/ req.headers?.[
"assettype"
] === "Place"
) {
var ip = req.headers["cf-connecting-ip"] || req.socket.remoteAddress
console.log(ip)
var sanitizedid = req.query.id.match(rgx)
if (ip === RCC_HOST || ip === "::ffff:" + RCC_HOST) {
fs.access("./assets/ugc/gamefile-"+sanitizedid+".rbxl", fs.F_OK, (err) => {
fs.access(
"./assets/ugc/gamefile-" + sanitizedid + ".rbxl",
fs.F_OK,
err => {
if (err) {
res.status(404).send("not found")
return
}
//file exists
res.sendFile(path.resolve("./assets/ugc/gamefile-"+sanitizedid+".rbxl"))
res.sendFile(
path.resolve(
"./assets/ugc/gamefile-" + sanitizedid + ".rbxl",
),
)
return
})
},
)
}
} else {
if (!req.query.id) {
req.query.id = req.query.assetversionid
}
if (isNaN(parseFloat(req.query.id)) === true) {
res.writeHead(302, {'Location': 'https://assetdelivery.roblox.com/v1/asset?id=' + req.query.id});
return res.end();
res.writeHead(302, {
Location:
"https://assetdelivery.roblox.com/v1/asset?id=" +
req.query.id,
})
return res.end()
}
var sanitizedid = parseFloat(req.query.id)
const response = await catalog.findOne({ ItemId: sanitizedid }).lean()
var ip = req.headers['cf-connecting-ip'] || req.socket.remoteAddress
if (response?.approved === false && (ip != RCC_HOST || ip === "::ffff:"+RCC_HOST) && !req.query.nonapproved){
var ip = req.headers["cf-connecting-ip"] || req.socket.remoteAddress
if (
response?.approved === false &&
(ip != RCC_HOST || ip === "::ffff:" + RCC_HOST) &&
!req.query.nonapproved
) {
return res.status(401).end()
}
//this will only allow numbers in our system so that we don't allow nodejs to expose our whole server filesystem
fs.access("./assets/ugc/itemfile-"+sanitizedid+".rbxm", fs.F_OK,async (err) => {
fs.access(
"./assets/ugc/itemfile-" + sanitizedid + ".rbxm",
fs.F_OK,
async err => {
//console.log("./assets/ugc/itemfile-"+sanitizedid+".rbxm")
if (err) {
if (req.headers?.['user-agent']?.includes("Android") === true || req.headers?.['user-agent']?.includes("iPhone") === true){
const response = await fetch('https://assetdelivery.roblox.com/v1/assetId/' + req.query.id,{headers: {'User-Agent': 'Roblox/WinInet'}});
const data = await response.json();
if (
req.headers?.["user-agent"]?.includes("Android") ===
true ||
req.headers?.["user-agent"]?.includes("iPhone") === true
) {
const response = await fetch(
"https://assetdelivery.roblox.com/v1/assetId/" +
req.query.id,
{ headers: { "User-Agent": "Roblox/WinInet" } },
)
const data = await response.json()
if (data) {
if (data.location) {
res.writeHead(302, {'Location': data.location});
res.end();
res.writeHead(302, { Location: data.location })
res.end()
return
}
}
}
if (req.query.id === "507766666"){ // 2018 r15 animation use legacy
res.writeHead(302, {'Location': 'https://assetdelivery.roblox.com/v1/asset?id=' + req.query.id + '&version=3'});
if (req.query.id === "507766666") {
// 2018 r15 animation use legacy
res.writeHead(302, {
Location:
"https://assetdelivery.roblox.com/v1/asset?id=" +
req.query.id +
"&version=3",
})
return res.end()
}
if (req.query.id === "507766388") {
res.writeHead(302, {'Location': 'https://assetdelivery.roblox.com/v1/asset?id=' + req.query.id + '&version=2'});
res.writeHead(302, {
Location:
"https://assetdelivery.roblox.com/v1/asset?id=" +
req.query.id +
"&version=2",
})
return res.end()
}
if (req.query.id === "62633901") {
return res.sendFile(path.resolve('./assets/ugc/common/itemfile-'+sanitizedid+".rbxm"))
return res.sendFile(
path.resolve(
"./assets/ugc/common/itemfile-" +
sanitizedid +
".rbxm",
),
)
}
res.writeHead(302, {'Location': 'https://assetdelivery.roblox.com/v1/asset?id=' + req.query.id});
res.end();
res.writeHead(302, {
Location:
"https://assetdelivery.roblox.com/v1/asset?id=" +
req.query.id,
})
res.end()
return
}
res.sendFile(path.resolve('./assets/ugc/itemfile-'+sanitizedid+".rbxm"))
res.sendFile(
path.resolve(
"./assets/ugc/itemfile-" + sanitizedid + ".rbxm",
),
)
return
})
},
)
}
})
module.exports = router

View File

@ -1,7 +1,7 @@
const express = require("express")
const router = express.Router()
const { requireAuth } = require('./../middleware/authmiddleware')
const User = require('./../model/user.js')
const { requireAuth } = require("./../middleware/authmiddleware")
const User = require("./../model/user.js")
router.post("/updateavatartype", requireAuth, async (req, res) => {
let newavatartype
@ -11,10 +11,9 @@ router.post("/updateavatartype", requireAuth,async (req, res) => {
newavatartype = "R15"
}
req.userdocument.avatartype = newavatartype
req.userdocument.markModified('avatartype')
req.userdocument.markModified("avatartype")
await req.userdocument.save()
return res.json({ status: "success", message: "Done!" })
})
module.exports = router

View File

@ -1,8 +1,8 @@
const express = require("express")
const router = express.Router()
const { requireAuth } = require('./../middleware/authmiddleware')
const User = require('./../model/item.js')
const bodyParser = require('body-parser')
const { requireAuth } = require("./../middleware/authmiddleware")
const User = require("./../model/item.js")
const bodyParser = require("body-parser")
router.use(bodyParser.json())
router.post("/fetch", async (req, res) => {
@ -16,35 +16,78 @@ router.post("/fetch", async (req, res) => {
try {
if (filter === "Best Selling") {
if (sort != "All") {
response = await User.find({Type: sort,Hidden: {$exists:false}}).limit(resultsPerPage).skip(0+parseFloat(page)*resultsPerPage).sort({Sales: "descending"}).lean().select(['-_id'])
responsecount = await User.countDocuments({Type: sort, Hidden: {$exists:false}})
response = await User.find({
Type: sort,
Hidden: { $exists: false },
})
.limit(resultsPerPage)
.skip(0 + parseFloat(page) * resultsPerPage)
.sort({ Sales: "descending" })
.lean()
.select(["-_id"])
responsecount = await User.countDocuments({
Type: sort,
Hidden: { $exists: false },
})
}
if (sort === "All") {
response = await User.find({Hidden: {$exists:false}, Type: { $ne: "User Ad" } }).limit(resultsPerPage).skip(0+parseFloat(page)*resultsPerPage).sort({Sales: "descending"}).lean().select(['-_id'])
responsecount = await User.countDocuments({Hidden: {$exists:false}, Type: { $ne: "User Ad" }})
response = await User.find({
Hidden: { $exists: false },
Type: { $ne: "User Ad" },
})
.limit(resultsPerPage)
.skip(0 + parseFloat(page) * resultsPerPage)
.sort({ Sales: "descending" })
.lean()
.select(["-_id"])
responsecount = await User.countDocuments({
Hidden: { $exists: false },
Type: { $ne: "User Ad" },
})
}
} else {
if (sort != "All") {
response = await User.find({Type: sort, Hidden: {$exists:false}}).limit(resultsPerPage).skip(0+parseFloat(page)*resultsPerPage).lean().select(['-_id'])
responsecount = await User.countDocuments({Type: sort, Hidden: {$exists:false}})
response = await User.find({
Type: sort,
Hidden: { $exists: false },
})
.limit(resultsPerPage)
.skip(0 + parseFloat(page) * resultsPerPage)
.lean()
.select(["-_id"])
responsecount = await User.countDocuments({
Type: sort,
Hidden: { $exists: false },
})
}
if (sort === "All") {
response = await User.find({Hidden: {$exists:false}, Type: { $ne: "User Ad" }}).limit(resultsPerPage).skip(0+parseFloat(page)*resultsPerPage).lean().select(['-_id'])
responsecount = await User.countDocuments({Hidden: {$exists:false}, Type: { $ne: "User Ad" }})
response = await User.find({
Hidden: { $exists: false },
Type: { $ne: "User Ad" },
})
.limit(resultsPerPage)
.skip(0 + parseFloat(page) * resultsPerPage)
.lean()
.select(["-_id"])
responsecount = await User.countDocuments({
Hidden: { $exists: false },
Type: { $ne: "User Ad" },
})
}
}
//console.log(response.length)
res.json({data: response, pages: Math.ceil(Math.max(responsecount/resultsPerPage, 1))})
res.json({
data: response,
pages: Math.ceil(Math.max(responsecount / resultsPerPage, 1)),
})
} catch (error) {
res.json({ status: "error", error: "idk" })
}
})
router.get('/iteminfo/:id', async (req, res) => {
var id = req.params.id;
router.get("/iteminfo/:id", async (req, res) => {
var id = req.params.id
if (isNaN(parseFloat(id)) === true) {
return res.json({ status: "error", error: "Must be number" })
@ -55,8 +98,7 @@ router.get('/iteminfo/:id', async (req, res) => {
return res.json({ status: "error", error: "Not found" })
}
return res.json({ error: false, iteminfo: response })
});
})
router.post("/search", async (req, res) => {
const resultsPerPage = 30
@ -66,33 +108,78 @@ router.post("/search", async (req, res) => {
}
let { filter, sort, searchquery } = req.body
function escapeRegex(text) {
return text?.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
return text?.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&")
}
const regex = new RegExp(escapeRegex(searchquery), 'gi');
const regex = new RegExp(escapeRegex(searchquery), "gi")
//console.log(req.body)
try {
if (filter === "Best Selling") {
if (sort != "All") {
response = await User.find({Name: regex,Type: sort,Hidden: {$exists:false}}).limit(resultsPerPage).skip(0+parseFloat(page)*resultsPerPage).sort({Sales: "descending"}).lean().select(['-_id'])
responsecount = await User.countDocuments({Type: sort, Hidden: {$exists:false}})
response = await User.find({
Name: regex,
Type: sort,
Hidden: { $exists: false },
})
.limit(resultsPerPage)
.skip(0 + parseFloat(page) * resultsPerPage)
.sort({ Sales: "descending" })
.lean()
.select(["-_id"])
responsecount = await User.countDocuments({
Type: sort,
Hidden: { $exists: false },
})
}
if (sort === "All") {
response = await User.find({Name: regex,Hidden: {$exists:false}}).limit(resultsPerPage).skip(0+parseFloat(page)*resultsPerPage).sort({Sales: "descending"}).lean().select(['-_id'])
responsecount = await User.countDocuments({Hidden: {$exists:false}})
response = await User.find({
Name: regex,
Hidden: { $exists: false },
})
.limit(resultsPerPage)
.skip(0 + parseFloat(page) * resultsPerPage)
.sort({ Sales: "descending" })
.lean()
.select(["-_id"])
responsecount = await User.countDocuments({
Hidden: { $exists: false },
})
}
} else {
if (sort != "All") {
response = await User.find({Name: regex,Type: sort, Hidden: {$exists:false}}).limit(resultsPerPage).skip(0+parseFloat(page)*resultsPerPage).lean().select(['-_id'])
responsecount = await User.countDocuments({Type: sort, Hidden: {$exists:false}})
response = await User.find({
Name: regex,
Type: sort,
Hidden: { $exists: false },
})
.limit(resultsPerPage)
.skip(0 + parseFloat(page) * resultsPerPage)
.lean()
.select(["-_id"])
responsecount = await User.countDocuments({
Type: sort,
Hidden: { $exists: false },
})
}
if (sort === "All") {
response = await User.find({Name: regex,Hidden: {$exists:false}}).limit(resultsPerPage).skip(0+parseFloat(page)*resultsPerPage).lean().select(['-_id'])
responsecount = await User.countDocuments({Hidden: {$exists:false}})
response = await User.find({
Name: regex,
Hidden: { $exists: false },
})
.limit(resultsPerPage)
.skip(0 + parseFloat(page) * resultsPerPage)
.lean()
.select(["-_id"])
responsecount = await User.countDocuments({
Hidden: { $exists: false },
})
}
}
//console.log(response.length)
res.json({data: response, pages: Math.ceil(Math.max(responsecount/resultsPerPage, 1))})
res.json({
data: response,
pages: Math.ceil(Math.max(responsecount / resultsPerPage, 1)),
})
} catch (error) {
res.json({ status: "error", error: "idk" })
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +1,38 @@
const express = require("express")
const router = express.Router()
const signatures = require("./signatures.js")
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
const User = require('../model/user.js')
const { requireAuth } = require('../middleware/authmiddlewaregame')
const rcctalk = require('../rcctalk')
const games = require('../model/games.js')
const catalog = require('../model/item.js')
const rcc = require('../model/rcc.js')
var sanitize = require('mongo-sanitize');
const { getPort, checkPort, getRandomPort, waitForPort } = require('get-port-please')
const fs = require('fs')
const gamescript = fs.readFileSync('actualgameserver.lua','utf-8')
require('dotenv').config()
const fetch = (...args) =>
import("node-fetch").then(({ default: fetch }) => fetch(...args))
const User = require("../model/user.js")
const { requireAuth } = require("../middleware/authmiddlewaregame")
const rcctalk = require("../rcctalk")
const games = require("../model/games.js")
const catalog = require("../model/item.js")
const rcc = require("../model/rcc.js")
var sanitize = require("mongo-sanitize")
const {
getPort,
checkPort,
getRandomPort,
waitForPort,
} = require("get-port-please")
const fs = require("fs")
const gamescript = fs.readFileSync("actualgameserver.lua", "utf-8")
require("dotenv").config()
const RCC_HOST = process.env.RCC_HOST
const logshook = process.env.logshook
const crypto = require('crypto');
const key = fs.readFileSync('DefaultPrivateKey.pem')
const key2 = fs.readFileSync('DefaultPrivateKey.pem')
const key2020 = fs.readFileSync('PrivateKey2020.txt')
const { _2020placelauncher } = require('../routes/2020/game')
const { _2018placelauncher } = require('../routes/2018/game')
const crypto = require("crypto")
const key = fs.readFileSync("DefaultPrivateKey.pem")
const key2 = fs.readFileSync("DefaultPrivateKey.pem")
const key2020 = fs.readFileSync("PrivateKey2020.txt")
const { _2020placelauncher } = require("../routes/2020/game")
const { _2018placelauncher } = require("../routes/2018/game")
//join and placelauncher
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
return new Promise(resolve => {
setTimeout(resolve, ms)
})
}
router.get("/visit", async (req, res) => {
@ -65,65 +71,75 @@ pcall(function() game:GetService("InsertService"):SetFreeDecalUrl("http://mete0r
`
const sign = crypto.createSign('SHA1');
const sign = crypto.createSign("SHA1")
sign.update("\r\n" + string)
var signature = sign.sign(key, "base64")
res.send("--rbxsig%" + signature + "%\r\n" + string)
})
router.get(["/GetCurrentUser", "/GetCurrentUser.ashx"], async (req, res) => {
res.send("1") // 1 means logged in and null means logged out
}) // don't send 404 error but i don't think we will have studio publishing
router.post("/validate-machine", async (req, res) => {
res.json({"success":true,"message":""})
res.json({ success: true, message: "" })
})
router.get(["/join", "/join.ashx"], requireAuth, async (req, res) => {
if (!req.userdocument.discordid) {
return res.json({status:"error",error:"Link your discord account stinky"})
return res.json({
status: "error",
error: "Link your discord account stinky",
})
}
if (req.query.ver === "2018") {
if (!req.userdocument.gamejoin2018 || req.userdocument.gamejoin2018 === "{}"){
if (
!req.userdocument.gamejoin2018 ||
req.userdocument.gamejoin2018 === "{}"
) {
return res.json({ status: "error", error: "no placelauncher" })
}
var joinJson = JSON.parse(req.userdocument.gamejoin2018)
req.userdocument.gamejoin2018 = undefined
req.userdocument.markModified('gamejoin2018')
req.userdocument.markModified("gamejoin2018")
await req.userdocument.save()
//sign with our sign module
var signature = signatures.signer(joinJson)
//console.log(signature)
return res.send("--rbxsig%"+signature+"%\r\n"+JSON.stringify(joinJson))
return res.send(
"--rbxsig%" + signature + "%\r\n" + JSON.stringify(joinJson),
)
}
if (req.query.ver === "2020") {
if (!req.userdocument.gamejoin2020 || req.userdocument.gamejoin2020 === "{}"){
if (
!req.userdocument.gamejoin2020 ||
req.userdocument.gamejoin2020 === "{}"
) {
return res.json({ status: "error", error: "no placelauncher" })
}
var joinJson = JSON.parse(req.userdocument.gamejoin2020)
req.userdocument.gamejoin2020 = undefined
req.userdocument.markModified('gamejoin2020')
req.userdocument.markModified("gamejoin2020")
await req.userdocument.save()
//sign with our sign module
const sign = crypto.createSign('SHA1');
const sign = crypto.createSign("SHA1")
sign.update("\r\n" + JSON.stringify(joinJson))
var signature = sign.sign(key2020, "base64")
//console.log(signature)
return res.send("--rbxsig2%"+signature+"%\r\n"+JSON.stringify(joinJson))
return res.send(
"--rbxsig2%" + signature + "%\r\n" + JSON.stringify(joinJson),
)
}
if (!req.userdocument.gamejoin || req.userdocument.gamejoin === "{}") {
return res.json({ status: "error", error: "no placelauncher" })
}
var joinJson = JSON.parse(req.userdocument.gamejoin)
req.userdocument.gamejoin = undefined
req.userdocument.markModified('gamejoin')
req.userdocument.markModified("gamejoin")
await req.userdocument.save()
//sign with our sign module
var signature = signatures.signer(joinJson)
@ -132,32 +148,97 @@ router.get(["/join","/join.ashx"],requireAuth,async (req, res) => {
res.send("--rbxsig%" + signature + "%\r\n" + JSON.stringify(joinJson))
})
router.all(["/placelauncher","/placelauncher.ashx"],requireAuth,_2020placelauncher,_2018placelauncher,async (req, res, next) => {
router.all(
["/placelauncher", "/placelauncher.ashx"],
requireAuth,
_2020placelauncher,
_2018placelauncher,
async (req, res, next) => {
var enabled = req.config
if (enabled.GamesEnabled === false) {
return res.json({status:"error",error:"Games are disabled bad boy"})
return res.json({
status: "error",
error: "Games are disabled bad boy",
})
}
var joinJson = {
ClientPort: 0,
MachineAddress: "localhost",
ServerPort: 25564,
PingUrl: "",
PingInterval: 120,
UserName: "default",
SeleniumTestMode: false,
UserId: 0,
SuperSafeChat: false,
CharacterAppearance:
"http://shitncumblox.gq/game/charapp?name=default",
ClientTicket: "",
GameId: 1,
PlaceId: 1818,
MeasurementUrl: "",
WaitingForCharacterGuid: "cad99b30-7983-434b-b24c-eac12595e5fd",
BaseUrl: "http://www.mete0r.xyz/",
ChatStyle: "ClassicAndBubble",
VendorId: 0,
ScreenShotInfo: "",
VideoInfo:
'<?xml version="1.0"?><entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007"><media:group><media:title type="plain"><![CDATA[ROBLOX Place]]></media:title><media:description type="plain"><![CDATA[ For more games visit http://www.roblox.com]]></media:description><media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">Games</media:category><media:keywords>ROBLOX, video, free game, online virtual world</media:keywords></media:group></entry>',
CreatorId: 0,
CreatorTypeEnum: "User",
MembershipType: "None",
AccountAge: 365,
CookieStoreFirstTimePlayKey: "rbx_evt_ftp",
CookieStoreFiveMinutePlayKey: "rbx_evt_fmp",
CookieStoreEnabled: true,
IsRobloxPlace: false,
GenerateTeleportJoin: false,
IsUnknownOrUnder13: false,
SessionId:
"c25fd620-bbaa-4fb2-b022-3f053cdd1abd|00000000-0000-0000-0000-000000000000|0|204.236.226.210|8|2016-08-17T01:05:05.7115837Z|0|null|null|null|null",
DataCenterId: 0,
UniverseId: 0,
BrowserTrackerId: 0,
UsePortraitMode: false,
FollowUserId: 0,
CharacterAppearanceId: 1,
}
var joinJson = {"ClientPort":0,"MachineAddress":"localhost","ServerPort":25564,"PingUrl":"","PingInterval":120,"UserName":"default","SeleniumTestMode":false,"UserId":0,"SuperSafeChat":false,"CharacterAppearance":"http://shitncumblox.gq/game/charapp?name=default","ClientTicket":"","GameId":1,"PlaceId":1818,"MeasurementUrl":"","WaitingForCharacterGuid":"cad99b30-7983-434b-b24c-eac12595e5fd","BaseUrl":"http://www.mete0r.xyz/","ChatStyle":"ClassicAndBubble","VendorId":0,"ScreenShotInfo":"","VideoInfo":"<?xml version=\"1.0\"?><entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:media=\"http://search.yahoo.com/mrss/\" xmlns:yt=\"http://gdata.youtube.com/schemas/2007\"><media:group><media:title type=\"plain\"><![CDATA[ROBLOX Place]]></media:title><media:description type=\"plain\"><![CDATA[ For more games visit http://www.roblox.com]]></media:description><media:category scheme=\"http://gdata.youtube.com/schemas/2007/categories.cat\">Games</media:category><media:keywords>ROBLOX, video, free game, online virtual world</media:keywords></media:group></entry>","CreatorId":0,"CreatorTypeEnum":"User","MembershipType":"None","AccountAge":365,"CookieStoreFirstTimePlayKey":"rbx_evt_ftp","CookieStoreFiveMinutePlayKey":"rbx_evt_fmp","CookieStoreEnabled":true,"IsRobloxPlace":false,"GenerateTeleportJoin":false,"IsUnknownOrUnder13":false,"SessionId":"c25fd620-bbaa-4fb2-b022-3f053cdd1abd|00000000-0000-0000-0000-000000000000|0|204.236.226.210|8|2016-08-17T01:05:05.7115837Z|0|null|null|null|null","DataCenterId":0,"UniverseId":0,"BrowserTrackerId":0,"UsePortraitMode":false,"FollowUserId":0,"CharacterAppearanceId":1}
if (!req.query.name && !req.query.placeId) {
return res.json({ status: "error", error: "no placeid bad" })
}
if (req.userdocument.gamejoin) {
return res.json({"jobId":"Test","status":2,"joinScriptUrl":"http://mete0r.xyz/game/join.ashx?auth="+req.query.auth??req.cookies.jwt,"authenticationUrl":"http://mete0r.xyz/Login/Negotiate.ashx","authenticationTicket":"SomeTicketThatDosentCrash","message":""})
return res.json({
jobId: "Test",
status: 2,
joinScriptUrl:
"http://mete0r.xyz/game/join.ashx?auth=" + req.query.auth ??
req.cookies.jwt,
authenticationUrl: "http://mete0r.xyz/Login/Negotiate.ashx",
authenticationTicket: "SomeTicketThatDosentCrash",
message: "",
})
}
var sanitizedplaceid = sanitize(req.query.name ?? req.query.placeId)
const game = await games.findOne({ idofgame: sanitizedplaceid }).lean()
if (!game) {
return res.json({status:"error",error:"that game doesn't exist!"})
return res.json({
status: "error",
error: "that game doesn't exist!",
})
}
if (game.version != "2016") {
return res.json({status: "error",error:"game version is different than client requested"})
return res.json({
status: "error",
error: "game version is different than client requested",
})
}
const instance = await rcc.findOne({ PlaceId: sanitizedplaceid }).lean()
if (instance && instance.Status === 2) {
// if an rcc instance already exists we don't need to create a new one so we will just drag them into the existing game
joinJson.UserName = req.userdocument.username
joinJson.UserId = req.userdocument.userid
joinJson.CharacterAppearance = "http://mete0r.xyz/game/charapp?name=" + req.userdocument.userid
joinJson.CharacterAppearance =
"http://mete0r.xyz/game/charapp?name=" + req.userdocument.userid
joinJson.MachineAddress = RCC_HOST // need to put rcc host here lol
joinJson.ServerPort = instance.Port
joinJson.PlaceId = instance.PlaceId
@ -170,87 +251,125 @@ router.all(["/placelauncher","/placelauncher.ashx"],requireAuth,_2020placelaunch
const timestamp = Date.now()
joinJson.ClientTicket = timestamp + ";" // timestamp
//create signature 1
const sign1 = crypto.createSign('SHA1');
sign1.update(`${req.userdocument.userid}\n`/*userid*/+`${req.userdocument.username}\n`/*username*/+`http://mete0r.xyz/game/charapp?name=${req.userdocument.userid}\n`/*charapp*/+`game${sanitizedplaceid}\n`/*jobid*/+ timestamp/*timestamp*/)
const sign1 = crypto.createSign("SHA1")
sign1.update(
`${req.userdocument.userid}\n` /*userid*/ +
`${req.userdocument.username}\n` /*username*/ +
`http://mete0r.xyz/game/charapp?name=${req.userdocument.userid}\n` /*charapp*/ +
`game${sanitizedplaceid}\n` /*jobid*/ +
timestamp /*timestamp*/,
)
var signature1 = sign1.sign(key, "base64")
joinJson.ClientTicket += signature1 + ";"
//create signature 2
const sign2 = crypto.createSign('SHA1');
sign2.update(`${req.userdocument.userid}\n`/*userid*/+`game${sanitizedplaceid}\n`/*jobid*/+ timestamp/*timestamp*/)
const sign2 = crypto.createSign("SHA1")
sign2.update(
`${req.userdocument.userid}\n` /*userid*/ +
`game${sanitizedplaceid}\n` /*jobid*/ +
timestamp /*timestamp*/,
)
var signature2 = sign2.sign(key, "base64")
joinJson.ClientTicket += signature2
req.userdocument.gamejoin = JSON.stringify(joinJson)
req.userdocument.markModified('gamejoin')
req.userdocument.markModified("gamejoin")
await req.userdocument.save()
var joinScriptJson = {"jobId":"Test","status":2,"joinScriptUrl":"http://mete0r.xyz/game/join.ashx?auth="+joinJson.SessionId,"authenticationUrl":"http://mete0r.xyz/Login/Negotiate.ashx","authenticationTicket":"SomeTicketThatDosentCrash","message":""}
var joinScriptJson = {
jobId: "Test",
status: 2,
joinScriptUrl:
"http://mete0r.xyz/game/join.ashx?auth=" +
joinJson.SessionId,
authenticationUrl: "http://mete0r.xyz/Login/Negotiate.ashx",
authenticationTicket: "SomeTicketThatDosentCrash",
message: "",
}
return res.send(JSON.stringify(joinScriptJson))
}
if (instance && instance.Status === 1) {
var joinScriptJson = {"jobId":"Test","status":1,"joinScriptUrl":"http://mete0r.xyz/game/join.ashx?auth="+joinJson.SessionId,"authenticationUrl":"http://mete0r.xyz/Login/Negotiate.ashx","authenticationTicket":"SomeTicketThatDosentCrash","message":""}
var joinScriptJson = {
jobId: "Test",
status: 1,
joinScriptUrl:
"http://mete0r.xyz/game/join.ashx?auth=" +
joinJson.SessionId,
authenticationUrl: "http://mete0r.xyz/Login/Negotiate.ashx",
authenticationTicket: "SomeTicketThatDosentCrash",
message: "",
}
return res.send(JSON.stringify(joinScriptJson))
}
var port = await getPort({ random: true })
var newgamescript = "local placeId = "+sanitizedplaceid+"\n"+ gamescript
var newgamescript =
"local placeId = " + sanitizedplaceid + "\n" + gamescript
newgamescript = "local port = " + port + "\n" + newgamescript
// launch job
var response = await rcctalk.OpenJob("game"+sanitizedplaceid,newgamescript,"99999")
var response = await rcctalk.OpenJob(
"game" + sanitizedplaceid,
newgamescript,
"99999",
)
await rcc.create({
PlaceId: sanitizedplaceid,
Port: port,
Status: 1 // 1 means loading
Status: 1, // 1 means loading
})
//console.log(newrenderscript)
var joinScriptJson = {"jobId":"Test","status":1,"joinScriptUrl":"http://mete0r.xyz/game/join.ashx?auth="+joinJson.SessionId,"authenticationUrl":"http://mete0r.xyz/Login/Negotiate.ashx","authenticationTicket":"SomeTicketThatDosentCrash","message":""}
res.send(JSON.stringify(joinScriptJson))
var joinScriptJson = {
jobId: "Test",
status: 1,
joinScriptUrl:
"http://mete0r.xyz/game/join.ashx?auth=" + joinJson.SessionId,
authenticationUrl: "http://mete0r.xyz/Login/Negotiate.ashx",
authenticationTicket: "SomeTicketThatDosentCrash",
message: "",
}
res.send(JSON.stringify(joinScriptJson))
},
)
//charapp and colors stealing from roblox
router.get("/charapp", async (req, res) => {
if (Object.keys(req.query).length === 0) {
res.status(404).send('No variables :(');
res.status(404).send("No variables :(")
} else {
const user = await User.findOne({ userid: req.query.name }).lean()
const placeid = req.headers?.['roblox-place-id']??0
const placeid = req.headers?.["roblox-place-id"] ?? 0
const placedoc = await games.findOne({ idofgame: placeid })
if (!placedoc) {
return res.json({ status: "error", error: "Place not found." })
}
if (!user) {
return res.json({status: 'error', error: 'User not found!'})
return res.json({ status: "error", error: "User not found!" })
}
if (!user.inventory) {
if (req.query.rcc) {
return res.json([])
}
return res.send('http://mete0r.xyz/game/colors?name='+req.query.name+';')
return res.send(
"http://mete0r.xyz/game/colors?name=" + req.query.name + ";",
)
}
if (req.query.rcc) {
var empty = []
for (var key of user.inventory) {
if (key.Equipped === true) {
empty.push({"item": {itemid: key.ItemId, type: key.Type}})
empty.push({ item: { itemid: key.ItemId, type: key.Type } })
}
}
return res.json(empty)
}
var charapp = 'http://mete0r.xyz/asset?name='+req.query.name+';'
var charapp = "http://mete0r.xyz/asset?name=" + req.query.name + ";"
// add to charapp string by adding json to it
for (var key of user.inventory) {
if (key.Equipped === true) {
@ -258,7 +377,8 @@ router.get("/charapp", async (req, res) => {
charapp += "http://mete0r.xyz/asset?id=" + key.ItemId + ";"
} else {
if (key.Type != "Gears") {
charapp += "http://mete0r.xyz/asset?id=" + key.ItemId + ";"
charapp +=
"http://mete0r.xyz/asset?id=" + key.ItemId + ";"
}
}
}
@ -271,11 +391,11 @@ router.get("/charapp", async (req, res) => {
router.get("/colors", async (req, res) => {
if (Object.keys(req.query).length === 0) {
res.status(404).send('No variables :(');
res.status(404).send("No variables :(")
} else {
const user = await User.findOne({ userid: req.query.name }).lean()
if (!user) {
return res.json({status: 'error', error: 'User not found!'})
return res.json({ status: "error", error: "User not found!" })
}
if (req.query.rcc) {
@ -286,40 +406,51 @@ router.get("/colors", async (req, res) => {
return res.json(empty)
}
res.type('application/xml');
var colorsxml = `<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
res.type("application/xml")
var colorsxml =
`<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
<External>null</External>
<External>nil</External>
<Item class="BodyColors">
<Properties>
<int name="HeadColor">`+user.colors.find(x => x.name === 'Head').value+`</int>
<int name="LeftArmColor">`+user.colors.find(x => x.name === 'Left Arm').value+`</int>
<int name="LeftLegColor">`+user.colors.find(x => x.name === 'Left Leg').value+`</int>
<int name="HeadColor">` +
user.colors.find(x => x.name === "Head").value +
`</int>
<int name="LeftArmColor">` +
user.colors.find(x => x.name === "Left Arm").value +
`</int>
<int name="LeftLegColor">` +
user.colors.find(x => x.name === "Left Leg").value +
`</int>
<string name="Name">Body Colors</string>
<int name="RightArmColor">`+user.colors.find(x => x.name === 'Right Arm').value+`</int>
<int name="RightLegColor">`+user.colors.find(x => x.name === 'Right Leg').value+`</int>
<int name="TorsoColor">`+user.colors.find(x => x.name === 'Torso').value+`</int>
<int name="RightArmColor">` +
user.colors.find(x => x.name === "Right Arm").value +
`</int>
<int name="RightLegColor">` +
user.colors.find(x => x.name === "Right Leg").value +
`</int>
<int name="TorsoColor">` +
user.colors.find(x => x.name === "Torso").value +
`</int>
<bool name="archivable">true</bool>
</Properties>
</Item>
</roblox>`
res.send(colorsxml)
}
})
router.get("/", (req, res) => {
res.status(404).send('hmmm? kinda sus');
res.status(404).send("hmmm? kinda sus")
})
router.get("/players/:id", (req, res) => {
res.json({"ChatFilter":"whitelist"})
res.json({ ChatFilter: "whitelist" })
})
router.post("/load-place-info", (req, res) => {
res.json({"CreatorId": 0, "CreatorType": "User", "PlaceVersion": 1})
res.json({ CreatorId: 0, CreatorType: "User", PlaceVersion: 1 })
})
router.post("/badge/awardbadge", async (req, res) => {
@ -351,35 +482,61 @@ router.post("/badge/awardbadge",async (req, res) => {
}
}
User.updateOne({userid: req.query.UserID}, {
User.updateOne(
{ userid: req.query.UserID },
{
$push: {
badges: {badgeid: badgeid, badgename: badge.Name, creator: badge.Creator, placeid: placeid}
}
badges: {
badgeid: badgeid,
badgename: badge.Name,
creator: badge.Creator,
placeid: placeid,
},
},
},
function (err, doc) {
if (err) {
return res.send("0")
}
},
)
return res.send(
user.username +
" won " +
badgecreator.username +
"'s " +
badge.Name +
" award!",
)
})
return res.send(user.username+" won "+badgecreator.username+"'s "+badge.Name+" award!")
})
router.get(["/LuaWebService/HandleSocialRequest","/LuaWebService/HandleSocialRequest.ashx"],async (req, res) => {
res.type('application/xml');
router.get(
[
"/LuaWebService/HandleSocialRequest",
"/LuaWebService/HandleSocialRequest.ashx",
],
async (req, res) => {
res.type("application/xml")
if (req.query.method === "IsInGroup") {
if (req.query.groupid === '0' || req.query.groupid === '1200769'){ // 1200769 admin group
const user = await User.findOne({userid: req.query.playerid}).lean()
if (req.query.groupid === "0" || req.query.groupid === "1200769") {
// 1200769 admin group
const user = await User.findOne({
userid: req.query.playerid,
}).lean()
if (user) {
return res.send(`<Value Type="boolean">${user.admin}</Value>`)
return res.send(
`<Value Type="boolean">${user.admin}</Value>`,
)
}
}
return res.send('<Value Type="boolean">false</Value>')
}
if (req.query.method === "GetGroupRank") {
if (req.query.groupid === '0'|| req.query.groupid === '1200769'){
const user = await User.findOne({userid: req.query.playerid}).lean()
if (req.query.groupid === "0" || req.query.groupid === "1200769") {
const user = await User.findOne({
userid: req.query.playerid,
}).lean()
if (user) {
if (user.admin === true) {
return res.send(`<Value Type="integer">255</Value>`)
@ -394,12 +551,13 @@ router.get(["/LuaWebService/HandleSocialRequest","/LuaWebService/HandleSocialReq
if (req.query.method === "IsFriendsWith") {
return res.send('<Value Type="boolean">false</Value>')
}
res.type('html');
res.type("html")
return res.status(404).end()
})
},
)
router.get("/Tools/InsertAsset.ashx", async (req, res) => {
const lol = await fetch('http://sets.pizzaboxer.xyz/Game'+req.url);
const lol = await fetch("http://sets.pizzaboxer.xyz/Game" + req.url)
if (lol.status === 400) {
return res.send(``)
}
@ -407,7 +565,7 @@ router.get("/Tools/InsertAsset.ashx",async (req, res) => {
})
router.post("/MachineConfiguration.ashx", (req, res) => {
res.json({"success": true})
res.json({ success: true })
})
module.exports = router

View File

@ -1,67 +1,133 @@
const express = require("express")
const router = express.Router()
const { requireAuth } = require('./../middleware/authmiddleware')
const games = require('./../model/games.js')
const { requireAuth } = require("./../middleware/authmiddleware")
const games = require("./../model/games.js")
const catalog = require("./../model/item.js")
const { grabAuth } = require('./../middleware/grabauth.js')
const rcc = require('./../model/rcc.js')
const rcc2018 = require('./../model/rcc2018.js')
const rcc2020 = require('./../model/rcc2020.js')
const rcctalk = require('./../rcctalk')
const rcctalk2018 = require('./../rcctalk2018')
const bodyParser = require('body-parser')
const { grabAuth } = require("./../middleware/grabauth.js")
const rcc = require("./../model/rcc.js")
const rcc2018 = require("./../model/rcc2018.js")
const rcc2020 = require("./../model/rcc2020.js")
const rcctalk = require("./../rcctalk")
const rcctalk2018 = require("./../rcctalk2018")
const bodyParser = require("body-parser")
router.use(bodyParser.json())
router.post("/scroll", async (req, res) => {
const resultsPerPage = 10
let cursor = req.body.cursor >= 0 ? req.body.cursor : 0
let type = req.body.type ? req.body.type : "Popular"
let allowed = ['idofgame', 'version', 'nameofgame', 'numberofplayers', 'visits', 'useridofowner']
let allowed = [
"idofgame",
"version",
"nameofgame",
"numberofplayers",
"visits",
"useridofowner",
]
try {
if (type === "Popular") {
const response = await games.find().sort({numberofplayers: "descending", idofgame: 1}).skip(0+parseFloat(cursor)*resultsPerPage).limit(10).lean().select(allowed).populate("owner", "username")
const response = await games
.find()
.sort({ numberofplayers: "descending", idofgame: 1 })
.skip(0 + parseFloat(cursor) * resultsPerPage)
.limit(10)
.lean()
.select(allowed)
.populate("owner", "username")
return res.json(response)
}
if (type === "OurRecommendations") {
const featured = await games.find({featured: true}).skip(0+parseFloat(cursor)*resultsPerPage).limit(10).lean().select(allowed).populate("owner", "username")
const featured = await games
.find({ featured: true })
.skip(0 + parseFloat(cursor) * resultsPerPage)
.limit(10)
.lean()
.select(allowed)
.populate("owner", "username")
return res.json(featured)
}
if (type === "Visits") {
const mostvisitedresponse = await games.find().sort({visits: "descending", idofgame: 1}).skip(0+parseFloat(cursor)*resultsPerPage).limit(10).lean().select(allowed).populate("owner", "username")
const mostvisitedresponse = await games
.find()
.sort({ visits: "descending", idofgame: 1 })
.skip(0 + parseFloat(cursor) * resultsPerPage)
.limit(10)
.lean()
.select(allowed)
.populate("owner", "username")
return res.json(mostvisitedresponse)
}
if (type === "NewestArrivals") {
const newest = await games.find().sort({idofgame: "descending"}).skip(0+parseFloat(cursor)*resultsPerPage).limit(10).lean().select(allowed).populate("owner", "username")
const newest = await games
.find()
.sort({ idofgame: "descending" })
.skip(0 + parseFloat(cursor) * resultsPerPage)
.limit(10)
.lean()
.select(allowed)
.populate("owner", "username")
return res.json(newest)
}
return res.json({ status: "error", error: "wtf" })
} catch (error) {
console.log(error)
return res.json({ status: "error", error: "wtf" })
}
})
router.post("/firstpaint", async (req, res) => {
const resultsPerPage = 10
let cursor = 0
let allowed = ['idofgame', 'version', 'nameofgame', 'numberofplayers', 'visits', 'useridofowner']
let allowed = [
"idofgame",
"version",
"nameofgame",
"numberofplayers",
"visits",
"useridofowner",
]
try {
const response = await games.find().sort({numberofplayers: "descending", idofgame: 1}).skip(0+parseFloat(cursor)*resultsPerPage).limit(10).lean().select(allowed).populate("owner", "username")
const featured = await games.find({featured: true}).skip(0+parseFloat(cursor)*resultsPerPage).limit(10).lean().select(allowed).populate("owner", "username")
const mostvisitedresponse = await games.find().sort({visits: "descending", idofgame: 1}).skip(0+parseFloat(cursor)*resultsPerPage).limit(10).lean().select(allowed).populate("owner", "username")
const newest = await games.find().sort({idofgame: "descending"}).skip(0+parseFloat(cursor)*resultsPerPage).limit(10).lean().select(allowed).populate("owner", "username")
return res.json({Popular: {array: response},OurRecommendations: {array: featured}, Visits: {array: mostvisitedresponse}, NewestArrivals: {array: newest} })
const response = await games
.find()
.sort({ numberofplayers: "descending", idofgame: 1 })
.skip(0 + parseFloat(cursor) * resultsPerPage)
.limit(10)
.lean()
.select(allowed)
.populate("owner", "username")
const featured = await games
.find({ featured: true })
.skip(0 + parseFloat(cursor) * resultsPerPage)
.limit(10)
.lean()
.select(allowed)
.populate("owner", "username")
const mostvisitedresponse = await games
.find()
.sort({ visits: "descending", idofgame: 1 })
.skip(0 + parseFloat(cursor) * resultsPerPage)
.limit(10)
.lean()
.select(allowed)
.populate("owner", "username")
const newest = await games
.find()
.sort({ idofgame: "descending" })
.skip(0 + parseFloat(cursor) * resultsPerPage)
.limit(10)
.lean()
.select(allowed)
.populate("owner", "username")
return res.json({
Popular: { array: response },
OurRecommendations: { array: featured },
Visits: { array: mostvisitedresponse },
NewestArrivals: { array: newest },
})
} catch (error) {
console.log(error)
return res.json({ status: "error", error: "wtf" })
}
})
router.post("/shutdown", requireAuth, async (req, res) => {
@ -77,14 +143,22 @@ router.post("/shutdown",requireAuth, async (req, res) => {
if (!gamedoc) {
return res.json({ status: "error", error: "Not found" })
}
if (gamedoc.useridofowner != req.userdocument.userid && req.userdocument.admin === false){ // make sure we only let game owners and admins shut down the game
if (
gamedoc.useridofowner != req.userdocument.userid &&
req.userdocument.admin === false
) {
// make sure we only let game owners and admins shut down the game
return res.json({ status: "error", error: "Not Authorized" })
}
if (gamedoc.version === "2018" || gamedoc.version === "2020") {
let instance = await rcc2018.findOne({PlaceId: gamedoc.idofgame}).lean()
let instance = await rcc2018
.findOne({ PlaceId: gamedoc.idofgame })
.lean()
if (!instance) {
instance = await rcc2020.findOne({PlaceId: gamedoc.idofgame}).lean()
instance = await rcc2020
.findOne({ PlaceId: gamedoc.idofgame })
.lean()
if (!instance) {
return res.json({ status: "error", error: "Game not open." })
}
@ -106,8 +180,6 @@ router.post("/shutdown",requireAuth, async (req, res) => {
}
return res.json({ status: "success", message: "Done!" })
})
router.post("/evictplayer", requireAuth, async (req, res) => {
@ -123,20 +195,31 @@ router.post("/evictplayer",requireAuth, async (req, res) => {
if (!gamedoc) {
return res.json({ status: "error", error: "Not found" })
}
if (gamedoc.useridofowner != req.userdocument.userid && req.userdocument.admin === false){ // make sure we only let game owners and admins shut down the game
if (
gamedoc.useridofowner != req.userdocument.userid &&
req.userdocument.admin === false
) {
// make sure we only let game owners and admins shut down the game
return res.json({ status: "error", error: "Not Authorized" })
}
if (gamedoc.version === "2018" || gamedoc.version === "2020") {
let instance = await rcc2018.findOne({PlaceId: gamedoc.idofgame}).lean()
let instance = await rcc2018
.findOne({ PlaceId: gamedoc.idofgame })
.lean()
if (!instance) {
instance = await rcc2020.findOne({PlaceId: gamedoc.idofgame}).lean()
instance = await rcc2020
.findOne({ PlaceId: gamedoc.idofgame })
.lean()
if (!instance) {
return res.json({ status: "error", error: "Game not open." })
}
}
rcctalk2018.Execute("game"+gamedoc.idofgame,{"Mode":"EvictPlayer","Settings":{"PlayerId":userid}})
rcctalk2018.Execute("game" + gamedoc.idofgame, {
Mode: "EvictPlayer",
Settings: { PlayerId: userid },
})
}
if (gamedoc.version === "2016") {
const instance = await rcc.findOne({ PlaceId: gamedoc.idofgame }).lean()
@ -154,31 +237,42 @@ router.post("/evictplayer",requireAuth, async (req, res) => {
}
return res.json({ status: "success", message: "Done!" })
})
router.get('/gameinfo/:id', async (req, res) => {
var id = req.params.id;
router.get("/gameinfo/:id", async (req, res) => {
var id = req.params.id
if (isNaN(parseFloat(id)) === true) {
return res.json({ status: "error", error: "Not found" })
}
const response = await games.findOne({idofgame: id}).lean().select(['idofgame', 'version', 'nameofgame', 'numberofplayers', 'visits', 'useridofowner', 'players','descrption']).populate("owner", "username")
const response = await games
.findOne({ idofgame: id })
.lean()
.select([
"idofgame",
"version",
"nameofgame",
"numberofplayers",
"visits",
"useridofowner",
"players",
"descrption",
])
.populate("owner", "username")
//console.log(response)
if (!response) {
return res.json({ status: "error", error: "Not found" })
}
const date = new Date(response._id.getTimestamp())
response.creationdate = (date.getMonth()+1) + '/' + date.getDate() + '/' + date.getFullYear()
response.creationdate =
date.getMonth() + 1 + "/" + date.getDate() + "/" + date.getFullYear()
return res.json({ error: false, gameinfo: response })
})
router.get('/gameinfo/:id/store', async (req, res) => {
var id = req.params.id;
router.get("/gameinfo/:id/store", async (req, res) => {
var id = req.params.id
if (isNaN(parseFloat(id)) === true) {
return res.json({ status: "error", error: "Not found" })
}
@ -193,22 +287,34 @@ router.get('/gameinfo/:id/store', async (req, res) => {
return res.json({ status: "success", gameinfo: response })
})
router.post('/search', async (req, res) => {
router.post("/search", async (req, res) => {
const resultsPerPage = 100
let cursor = req.body.cursor >= 0 ? req.body.cursor : 0
function escapeRegex(text) {
return text?.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
return text?.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&")
}
const regex = new RegExp(escapeRegex(req.body.searchquery), 'gi');
const regex = new RegExp(escapeRegex(req.body.searchquery), "gi")
//const pages = await User.countDocuments({username: regex})/resultsPerPage
const response = await games.find({nameofgame: regex}).limit(resultsPerPage).skip(0+parseFloat(cursor)*resultsPerPage).lean().select(['idofgame', 'version', 'nameofgame', 'numberofplayers', 'visits', 'useridofowner', 'players','descrption'])
const response = await games
.find({ nameofgame: regex })
.limit(resultsPerPage)
.skip(0 + parseFloat(cursor) * resultsPerPage)
.lean()
.select([
"idofgame",
"version",
"nameofgame",
"numberofplayers",
"visits",
"useridofowner",
"players",
"descrption",
])
return res.json(response)
});
})
module.exports = router

View File

@ -1,37 +1,44 @@
const express = require("express")
const router = express.Router()
const bodyParser = require('body-parser')
var sanitize = require('mongo-sanitize');
const mongoose = require('mongoose');
const User = require('./../model/user.js')
const bcrypt = require('bcrypt')
const jwt = require('jsonwebtoken')
require('dotenv').config()
const bodyParser = require("body-parser")
var sanitize = require("mongo-sanitize")
const mongoose = require("mongoose")
const User = require("./../model/user.js")
const bcrypt = require("bcrypt")
const jwt = require("jsonwebtoken")
require("dotenv").config()
const JWT_SECRET = process.env.JWT_SECRET
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
const speakeasy = require('speakeasy')
const rateLimit = require('express-rate-limit')
const fetch = (...args) =>
import("node-fetch").then(({ default: fetch }) => fetch(...args))
const speakeasy = require("speakeasy")
const rateLimit = require("express-rate-limit")
const limiter = rateLimit({
windowMs: 5 * 1000, // 5 seconds
max: 1, // Limit each IP to 1 requests per `window`
standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
legacyHeaders: false, // Disable the `X-RateLimit-*` headers
handler: (request, response, next, options) => {
return response.json({status: 'error', error: 'Too many requests try again later.'})
}
return response.json({
status: "error",
error: "Too many requests try again later.",
})
},
})
router.use(bodyParser.json())
router.get("/", (req, res) => {
res.redirect('/')
res.redirect("/")
})
router.get(["/RequestAuth", "/RequestAuth.ashx"], (req, res) => {
if (!req.cookies['.ROBLOSECURITY']){
if (!req.cookies[".ROBLOSECURITY"]) {
res.status(403).end()
}
res.send('https://www.mete0r.xyz/Login/Negotiate.ashx?suggest='+req.cookies['.ROBLOSECURITY'])
res.send(
"https://www.mete0r.xyz/Login/Negotiate.ashx?suggest=" +
req.cookies[".ROBLOSECURITY"],
)
}) // studio
router.get(["/Negotiate", "/Negotiate.ashx"], (req, res) => {
@ -39,130 +46,178 @@ router.get(["/Negotiate","/Negotiate.ashx"], (req, res) => {
res.status(403).end()
}
//res.cookie('jwt', req.query.suggest) // maxage is 24 hours
res.cookie('.ROBLOSECURITY', req.query.suggest)
res.cookie('.RBXID', req.query.suggest)
res.cookie(".ROBLOSECURITY", req.query.suggest)
res.cookie(".RBXID", req.query.suggest)
res.send(req.query.suggest)
}) // studio
router.post("/", limiter, async (req, res) => {
//console.log(req.headers)
let { username, password, _2fa } = req.body
if (!username && req.headers?.["user-agent"]?.includes("RobloxStudio/WinInet") === true){ // Studio login
if (
!username &&
req.headers?.["user-agent"]?.includes("RobloxStudio/WinInet") === true
) {
// Studio login
username = req.body.cvalue ?? req.body.username
password = req.body.password ?? req.body.ticket
_2fa = req.body.code
}
if (!username || typeof username !== 'string') {
return res.json({status: 'error', error: 'Usernames needs to be sent and it needs to be a string'})
if (!username || typeof username !== "string") {
return res.json({
status: "error",
error: "Usernames needs to be sent and it needs to be a string",
})
}
if (!password || typeof password !== 'string') {
return res.json({status: 'error', error: 'Password needs to be sent and it needs to be a string'})
if (!password || typeof password !== "string") {
return res.json({
status: "error",
error: "Password needs to be sent and it needs to be a string",
})
}
if (password.length < 4) {
return res.json({status: 'error', error: 'Password needs to be at least 5 characters'})
return res.json({
status: "error",
error: "Password needs to be at least 5 characters",
})
}
sanitizedusername = sanitize(username)
const user = await User.findOne({ username: sanitizedusername }) /*.lean()*/
if (!user) {
if (req.headers?.["user-agent"] === "RobloxStudio/WinInet"){ // studio response
if (req.headers?.["user-agent"] === "RobloxStudio/WinInet") {
// studio response
return res.json({
"errors": [
errors: [
{
"code": 1,
"message": "Incorrect password"
}
]
code: 1,
message: "Incorrect password",
},
],
})
}
return res.json({status: 'error', error: 'Invalid username/password'})
return res.json({ status: "error", error: "Invalid username/password" })
}
if (user.twofasecrets) {
const json = JSON.parse(user.twofasecrets)
if (json.verified === true) {
if (!_2fa) {
if (req.headers?.["user-agent"] === "RobloxStudio/WinInet"){ // studio response
if (req.headers?.["user-agent"] === "RobloxStudio/WinInet") {
// studio response
return res.json({
"user": {
"id": user.userid,
"name": user.username,
user: {
id: user.userid,
name: user.username,
},
"twoStepVerificationData": {
"mediaType": "Email",
"ticket": password
twoStepVerificationData: {
mediaType: "Email",
ticket: password,
},
"isBanned": false
isBanned: false,
})
}
return res.json({status: 'error', error: '2FA Enabled on account but 2fa not sent'})
return res.json({
status: "error",
error: "2FA Enabled on account but 2fa not sent",
})
}
const valid = speakeasy.totp.verify({
secret: json.secret,
encoding: 'ascii',
token: _2fa
encoding: "ascii",
token: _2fa,
})
if (valid === false) {
if (req.headers?.["user-agent"] === "RobloxStudio/WinInet"){ // studio response
if (req.headers?.["user-agent"] === "RobloxStudio/WinInet") {
// studio response
return res.json({
"errors": [
errors: [
{
"code": 6,
"message": "Invalid two step verify code."
}
]
code: 6,
message: "Invalid two step verify code.",
},
],
})
}
return res.json({status: 'error', error: 'Invalid 2FA Code'})
return res.json({ status: "error", error: "Invalid 2FA Code" })
}
} else {
// basically if they haven't verified that they know the secret before we will just remove it for them
user.twofasecrets = undefined
user.markModified('twofasecrets')
user.markModified("twofasecrets")
user.save()
}
}
if(await bcrypt.compare(password, user.password) || password === user.password) {
if (
(await bcrypt.compare(password, user.password)) ||
password === user.password
) {
// the username and password match
// lets make a token for them using the data from our database
const ip = req.headers['cf-connecting-ip'] || req.socket.remoteAddress
const token = jwt.sign({ id: user._id, username: user.username, admin: user.admin, userid: user.userid, ip, furry: true },JWT_SECRET,{expiresIn: '24h'})
const ip = req.headers["cf-connecting-ip"] || req.socket.remoteAddress
const token = jwt.sign(
{
id: user._id,
username: user.username,
admin: user.admin,
userid: user.userid,
ip,
furry: true,
},
JWT_SECRET,
{ expiresIn: "24h" },
)
if (req.headers?.["user-agent"] != "RobloxStudio/WinInet") {
res.cookie('jwt', token, {SameSite: "Strict",httpOnly: true,maxAge: 24 * 60 * 60 * 1000 }) // maxage is 24 hours
res.cookie("jwt", token, {
SameSite: "Strict",
httpOnly: true,
maxAge: 24 * 60 * 60 * 1000,
}) // maxage is 24 hours
}
res.cookie('.ROBLOSECURITY', token, {SameSite: "Strict",httpOnly: true,maxAge: 24 * 60 * 60 * 1000 })
res.cookie('.RBXID', token, {SameSite: "Strict",httpOnly: true,maxAge: 24 * 60 * 60 * 1000 })
res.cookie(".ROBLOSECURITY", token, {
SameSite: "Strict",
httpOnly: true,
maxAge: 24 * 60 * 60 * 1000,
})
res.cookie(".RBXID", token, {
SameSite: "Strict",
httpOnly: true,
maxAge: 24 * 60 * 60 * 1000,
})
if (req.url === "/v2/twostepverification/verify") {
return res.json({})
}
if (req.headers?.["user-agent"] === "RobloxStudio/WinInet"){ // studio response
if (req.headers?.["user-agent"] === "RobloxStudio/WinInet") {
// studio response
return res.json({
"user": {
"id": user.userid,
"name": user.username,
user: {
id: user.userid,
name: user.username,
},
"isBanned": false
isBanned: false,
})
}
return res.json({status: 'ok', cookie: token})
return res.json({ status: "ok", cookie: token })
}
if (req.headers?.["user-agent"] === "RobloxStudio/WinInet"){ // studio response
if (req.headers?.["user-agent"] === "RobloxStudio/WinInet") {
// studio response
return res.json({
"errors": [
errors: [
{
"code": 1,
"message": "Incorrect password"
}
]
code: 1,
message: "Incorrect password",
},
],
})
}
res.status(403).json({status: 'error', error: 'Invalid username/password'})
res.status(403).json({
status: "error",
error: "Invalid username/password",
})
})
module.exports = router

View File

@ -2,8 +2,8 @@ const express = require("express")
const router = express.Router()
router.get("/", (req, res) => {
res.cookie('jwt', "", {SameSite: "Strict",maxAge: 1 })
res.redirect('/')
res.cookie("jwt", "", { SameSite: "Strict", maxAge: 1 })
res.redirect("/")
})
module.exports = router

View File

@ -1,19 +1,45 @@
const express = require("express")
const router = express.Router()
const games = require('./../model/games.js')
const User = require('./../model/user.js')
const games = require("./../model/games.js")
const User = require("./../model/user.js")
const item = require("./../model/item.js")
const { requireAuth } = require("../middleware/authmiddleware.js")
var rgx = /^[0-9]*\.?[0-9]*$/;
var rgx = /^[0-9]*\.?[0-9]*$/
router.get("/marketplace/productinfo", async (req, res) => {
const sanitizedid = req.query.assetId.match(rgx)
let json = {"TargetId":5009,"ProductType":"User Product","AssetId":93722443,"ProductId":13831621,"Name":"rrr","Description":"","AssetTypeId":19,"Creator":{"Id":1,"Name":"","CreatorType":"User","CreatorTargetId":1},"IconImageAssetId":0,"Created":"2012-09-28T01:09:47.077Z","Updated":"2017-01-03T00:25:45.8813192Z","PriceInRobux":null,"PriceInTickets":null,"Sales":0,"IsNew":false,"IsForSale":true,"IsPublicDomain":false,"IsLimited":false,"IsLimitedUnique":false,"Remaining":null,"MinimumMembershipLevel":0,"ContentRatingTypeId":0}
let json = {
TargetId: 5009,
ProductType: "User Product",
AssetId: 93722443,
ProductId: 13831621,
Name: "rrr",
Description: "",
AssetTypeId: 19,
Creator: { Id: 1, Name: "", CreatorType: "User", CreatorTargetId: 1 },
IconImageAssetId: 0,
Created: "2012-09-28T01:09:47.077Z",
Updated: "2017-01-03T00:25:45.8813192Z",
PriceInRobux: null,
PriceInTickets: null,
Sales: 0,
IsNew: false,
IsForSale: true,
IsPublicDomain: false,
IsLimited: false,
IsLimitedUnique: false,
Remaining: null,
MinimumMembershipLevel: 0,
ContentRatingTypeId: 0,
}
let response = await games.findOne({idofgame: parseFloat(sanitizedid)}).lean()
let response = await games
.findOne({ idofgame: parseFloat(sanitizedid) })
.lean()
if (!response) {
response = await item.findOne({ItemId: parseFloat(sanitizedid)}).lean()
response = await item
.findOne({ ItemId: parseFloat(sanitizedid) })
.lean()
json.PriceInRobux = parseFloat(response.Price)
json.AssetTypeId = 34
json.IconImageAssetId = parseFloat(req.query.assetId)
@ -22,7 +48,9 @@ router.get("/marketplace/productinfo", async (req, res) => {
}
}
const creator = await User.findOne({userid: parseFloat(response.useridofowner??response.Creator)}).lean()
const creator = await User.findOne({
userid: parseFloat(response.useridofowner ?? response.Creator),
}).lean()
json.AssetId = parseFloat(req.query.assetId)
json.ProductId = parseFloat(req.query.assetId)
json.TargetId = parseFloat(req.query.assetId)
@ -30,7 +58,9 @@ router.get("/marketplace/productinfo", async (req, res) => {
json.Description = response.descrption ?? ""
json.Creator.Id = parseFloat(response.useridofowner ?? response.Creator)
json.Creator.Name = creator.username
json.Creator.CreatorTargetId = parseFloat(response.useridofowner??response.Creator)
json.Creator.CreatorTargetId = parseFloat(
response.useridofowner ?? response.Creator,
)
res.json(json)
})
@ -40,68 +70,81 @@ router.post("/marketplace/purchase",requireAuth, async (req, res) => {
res.json({ success: false, status: "Error", receipt: "" })
}
const itemdoc = await item.findOne({ ItemId: productId }) //.lean()
if (typeof req.userdocument.inventory !== "undefined") {
// check if user already owns item
for (var v of req.userdocument.inventory) {
if (v.ItemId === itemdoc.ItemId) {
// they already own it
return res.json({status: 'error', error: "You already own this!"})
return res.json({
status: "error",
error: "You already own this!",
})
}
}
}
if (itemdoc.Type === "Mesh" || itemdoc.Type === "Audio" || itemdoc.Type === "Mesh"){
return res.json({status: 'error', error: "You can't buy assets."})
if (
itemdoc.Type === "Mesh" ||
itemdoc.Type === "Audio" ||
itemdoc.Type === "Mesh"
) {
return res.json({ status: "error", error: "You can't buy assets." })
}
if (itemdoc.Hidden) {
return res.json({ success: false, status: "Error", receipt: "" })
}
if (req.userdocument.coins >= itemdoc.Price) {
// has enough money to purcahse item
try {
User.updateOne({userid: req.userdocument.userid}, {
User.updateOne(
{ userid: req.userdocument.userid },
{
$set: {
coins: req.userdocument.coins - itemdoc.Price
coins: req.userdocument.coins - itemdoc.Price,
},
$push: {
inventory: {Type: itemdoc.Type,ItemId: itemdoc.ItemId, ItemName: itemdoc.Name, Equipped: false}
}
inventory: {
Type: itemdoc.Type,
ItemId: itemdoc.ItemId,
ItemName: itemdoc.Name,
Equipped: false,
},
},
},
function (err, doc) {
//console.log(err)
})
},
)
// give owner cash
User.updateOne({userid: itemdoc.Creator}, {
User.updateOne(
{ userid: itemdoc.Creator },
{
$inc: {
coins: itemdoc.Price
}
coins: itemdoc.Price,
},
},
function (err, doc) {
//console.log(err)
})
},
)
itemdoc.Sales += 1
if (!itemdoc.Sales) {
itemdoc.Sales = 1
}
//console.log(itemdoc.Sales)
itemdoc.markModified('Sales')
itemdoc.markModified("Sales")
await itemdoc.save()
}catch{
}
return res.json(({success: true,status: "Bought",receipt: ""}))
} catch {}
return res.json({ success: true, status: "Bought", receipt: "" })
}
// too poor
return res.json({ success: false, status: "Error", receipt: "" })
})
router.get('/ownership/hasasset',async (req, res) => {
router.get("/ownership/hasasset", async (req, res) => {
const userid = req.query?.userId
const assetId = req.query?.assetId
const doc = await User.findOne({ userid: userid })
@ -126,12 +169,12 @@ router.get('/ownership/hasasset',async (req, res) => {
return res.send("false")
})
router.get('/v1/users/:userId/items/gamepass/:assetId',async (req, res) => {
router.get("/v1/users/:userId/items/gamepass/:assetId", async (req, res) => {
const userid = req.params?.userId
const assetId = req.params?.assetId
const doc = await User.findOne({ userid: userid })
const itemdoc = await item.findOne({ ItemId: assetId })
let data = {"previousPageCursor":null,"nextPageCursor":null,"data":[]}
let data = { previousPageCursor: null, nextPageCursor: null, data: [] }
if (!doc) {
return res.json(data)
@ -145,7 +188,12 @@ router.get('/v1/users/:userId/items/gamepass/:assetId',async (req, res) => {
for (var v of doc.inventory) {
if (v.ItemId === itemdoc.ItemId) {
// they already own it
data.data.push({"type": "GamePass","id": req.params?.assetId,"name": itemdoc.Name,"instanceId": null})
data.data.push({
type: "GamePass",
id: req.params?.assetId,
name: itemdoc.Name,
instanceId: null,
})
return res.json(data)
}
}
@ -154,23 +202,26 @@ router.get('/v1/users/:userId/items/gamepass/:assetId',async (req, res) => {
return res.json(data)
})
router.post('/v1/purchases/products/:assetId',requireAuth,async (req, res) => {
router.post(
"/v1/purchases/products/:assetId",
requireAuth,
async (req, res) => {
const assetId = req.params?.assetId
const itemdoc = await item.findOne({ ItemId: assetId })
let error = {
"purchased": false,
"reason": "InsufficientFunds",
"productId": 15194787,
"statusCode": 500,
"title": "Not Enough Robux",
"errorMsg": "You do not have enough Robux to purchase this item.",
"showDivId": "InsufficientFundsView",
"shortfallPrice": 29,
"balanceAfterSale": -29,
"expectedPrice": 150,
"currency": 1,
"price": 150,
"assetId": 106690045
purchased: false,
reason: "InsufficientFunds",
productId: 15194787,
statusCode: 500,
title: "Not Enough Robux",
errorMsg: "You do not have enough Robux to purchase this item.",
showDivId: "InsufficientFundsView",
shortfallPrice: 29,
balanceAfterSale: -29,
expectedPrice: 150,
currency: 1,
price: 150,
assetId: 106690045,
}
if (!itemdoc) {
@ -185,76 +236,92 @@ router.post('/v1/purchases/products/:assetId',requireAuth,async (req, res) => {
error.balanceAfterSale = req.userdocument.coins - itemdoc.Price
error.shortfallPrice = Math.abs(req.userdocument.coins - itemdoc.Price)
if (typeof req.userdocument.inventory !== "undefined") {
// check if user already owns item
for (var v of req.userdocument.inventory) {
if (v.ItemId === itemdoc.ItemId) {
// they already own it
return res.json({status: 'error', error: "You already own this!"})
return res.json({
status: "error",
error: "You already own this!",
})
}
}
}
if (itemdoc.Type === "Mesh" || itemdoc.Type === "Audio" || itemdoc.Type === "Mesh"){
return res.json({status: 'error', error: "You can't buy assets."})
if (
itemdoc.Type === "Mesh" ||
itemdoc.Type === "Audio" ||
itemdoc.Type === "Mesh"
) {
return res.json({ status: "error", error: "You can't buy assets." })
}
if (itemdoc.Hidden) {
return res.json({status: 'error', error: "You can't buy this!"})
return res.json({ status: "error", error: "You can't buy this!" })
}
if (req.userdocument.coins >= itemdoc.Price) {
// has enough money to purcahse item
try {
User.updateOne({userid: req.userdocument.userid}, {
User.updateOne(
{ userid: req.userdocument.userid },
{
$set: {
coins: req.userdocument.coins - itemdoc.Price
coins: req.userdocument.coins - itemdoc.Price,
},
$push: {
inventory: {Type: itemdoc.Type,ItemId: itemdoc.ItemId, ItemName: itemdoc.Name, Equipped: false}
}
inventory: {
Type: itemdoc.Type,
ItemId: itemdoc.ItemId,
ItemName: itemdoc.Name,
Equipped: false,
},
},
},
function (err, doc) {
//console.log(err)
})
},
)
// give owner cash
User.updateOne({userid: itemdoc.Creator}, {
User.updateOne(
{ userid: itemdoc.Creator },
{
$inc: {
coins: itemdoc.Price
}
coins: itemdoc.Price,
},
},
function (err, doc) {
//console.log(err)
})
},
)
itemdoc.Sales += 1
if (!itemdoc.Sales) {
itemdoc.Sales = 1
}
//console.log(itemdoc.Sales)
itemdoc.markModified('Sales')
itemdoc.markModified("Sales")
await itemdoc.save()
}catch{
}
} catch {}
return res.json({
"purchased": true,
"reason": "Success",
"productId": assetId,
"currency": 1,
"price": itemdoc.Price,
"assetId": assetId,
"assetName": itemdoc.Name,
"assetType": "Gamepass",
"assetTypeDisplayName": "Gamepass",
"assetIsWearable": false,
"sellerName": "Robloxxx",
"transactionVerb": "bought",
"isMultiPrivateSale": false
purchased: true,
reason: "Success",
productId: assetId,
currency: 1,
price: itemdoc.Price,
assetId: assetId,
assetName: itemdoc.Name,
assetType: "Gamepass",
assetTypeDisplayName: "Gamepass",
assetIsWearable: false,
sellerName: "Robloxxx",
transactionVerb: "bought",
isMultiPrivateSale: false,
})
}
return res.json(error)
})
},
)
module.exports = router

View File

@ -1,43 +1,41 @@
const express = require("express")
const router = express.Router()
router.get('/check-app-version',async (req, res) => {
return res.json({Response: {"data":{"UpgradeAction":"NotRequired"}}})
router.get("/check-app-version", async (req, res) => {
return res.json({ Response: { data: { UpgradeAction: "NotRequired" } } })
})
router.post('/login',async (req, res) => {
router.post("/login", async (req, res) => {
return res.json({
"Status":"OK",
"UserInfo": {
"UserName":"meteorite",
"RobuxBalance":"69420",
"TicketsBalance":"69420",
"IsAnyBuildersClubMember":false,
"ThumbnailUrl":"http://www.mete0r.xyz/",
"UserID":1
}
Status: "OK",
UserInfo: {
UserName: "meteorite",
RobuxBalance: "69420",
TicketsBalance: "69420",
IsAnyBuildersClubMember: false,
ThumbnailUrl: "http://www.mete0r.xyz/",
UserID: 1,
},
})
})
router.get('/userinfo',async (req, res) => {
router.get("/userinfo", async (req, res) => {
return res.json({
"Status":"OK",
"UserInfo": {
"UserName":"meteorite",
"RobuxBalance":"69420",
"TicketsBalance":"69420",
"IsAnyBuildersClubMember":false,
"ThumbnailUrl":"http://www.mete0r.xyz/",
"UserID":1
}
Status: "OK",
UserInfo: {
UserName: "meteorite",
RobuxBalance: "69420",
TicketsBalance: "69420",
IsAnyBuildersClubMember: false,
ThumbnailUrl: "http://www.mete0r.xyz/",
UserID: 1,
},
})
})
router.all('/logout',async (req, res) => {
res.cookie('jwt', "", {SameSite: "Strict",maxAge: 1 })
res.cookie('.ROBLOSECURITY', "", {SameSite: "Strict",maxAge: 1 })
router.all("/logout", async (req, res) => {
res.cookie("jwt", "", { SameSite: "Strict", maxAge: 1 })
res.cookie(".ROBLOSECURITY", "", { SameSite: "Strict", maxAge: 1 })
return res.json({})
})

View File

@ -1,12 +1,14 @@
const express = require("express")
const router = express.Router()
const bodyParser = require('body-parser')
const games = require('./../model/games.js')
require('dotenv').config()
const bodyParser = require("body-parser")
const games = require("./../model/games.js")
require("dotenv").config()
const RCC_HOST = process.env.RCC_HOST
router.use(bodyParser.text({limit: '100mb'}))
router.use(bodyParser.text({ limit: "100mb" }))
router.use(async function (req, res, next) {
var ip = req.headers['cf-connecting-ip'] || req.socket.remoteAddress.replace(/^.*:/, '')
var ip =
req.headers["cf-connecting-ip"] ||
req.socket.remoteAddress.replace(/^.*:/, "")
console.log(ip)
if (ip === RCC_HOST || ip == "::ffff:" + RCC_HOST) {
@ -14,38 +16,70 @@ router.use(async function (req, res, next) {
}
return res.status(403)
})
router.post('/getV2', async (req, res)=>{
router.post("/getV2", async (req, res) => {
const placeid = req.query.placeId
const scope = req.query.scope
const game = await games.findOne({ idofgame: placeid }).lean()
if (!game.datastore) {
return res.json({"data": [{"Key": {"Scope": req.body.qkeys[0], "Target": "KEY", "Key": req.body.qkeys[1]}, "Value": "nil"}]})
return res.json({
data: [
{
Key: {
Scope: req.body.qkeys[0],
Target: "KEY",
Key: req.body.qkeys[1],
},
Value: "nil",
},
],
})
}
const datastore = JSON.parse(game.datastore)
// first make sure database exists then make sure scope exists finally make sure key exists inside scope
if (datastore[req.body.qkeys[2]] && datastore[req.body.qkeys[2]][req.body.qkeys[0]] && datastore[req.body.qkeys[2]][req.body.qkeys[0]][req.body.qkeys[1]]){
if (
datastore[req.body.qkeys[2]] &&
datastore[req.body.qkeys[2]][req.body.qkeys[0]] &&
datastore[req.body.qkeys[2]][req.body.qkeys[0]][req.body.qkeys[1]]
) {
// 2 = database name
// 1 = Key name
// 0 = scope
var wow = {"data": [{"Key": {"Scope": req.body.qkeys[0], "Target": "KEY", "Key": req.body.qkeys[1]}, "Value": datastore[req.body.qkeys[2]][req.body.qkeys[0]][req.body.qkeys[1]].value}]};
var wow = {
data: [
{
Key: {
Scope: req.body.qkeys[0],
Target: "KEY",
Key: req.body.qkeys[1],
},
Value: datastore[req.body.qkeys[2]][req.body.qkeys[0]][
req.body.qkeys[1]
].value,
},
],
}
//console.log(req.body)
console.dir(wow, { depth: null })
return res.json(wow)
}
return res.json({"data": [{"Key": {"Scope": req.body.qkeys[0], "Target": "KEY", "Key": req.body.qkeys[1]}, "Value": "nil"}]})
});
router.post('/set', async (req, res)=>{
return res.json({
data: [
{
Key: {
Scope: req.body.qkeys[0],
Target: "KEY",
Key: req.body.qkeys[1],
},
Value: "nil",
},
],
})
})
router.post("/set", async (req, res) => {
const placeid = req.query.placeId
const game = await games.findOne({ idofgame: placeid }).lean()
if (!game) {
@ -55,57 +89,105 @@ return res.json(wow)
let currentdatastore
if (!game.datastore) {
try {
await games.updateOne({idofgame: placeid}, {
await games.updateOne(
{ idofgame: placeid },
{
$set: {
datastore: JSON.stringify({[req.query.key]: {[req.query.scope]: {[req.query.target]: {value: req.body.value}},type: req.query.type}})
}
datastore: JSON.stringify({
[req.query.key]: {
[req.query.scope]: {
[req.query.target]: {
value: req.body.value,
},
},
type: req.query.type,
},
}),
},
},
function (err, doc) {
//console.log(err)
},
)
} catch {}
return res.json({
data: [
{
Key: {
Scope: req.query.key,
Target: "KEY",
Key: [req.query.target],
},
Value: req.body.value,
},
],
})
}catch{
}
return res.json({"data": [{"Key": {"Scope": req.query.key, "Target": "KEY", "Key": [req.query.target]}, "Value": req.body.value}]})
}
currentdatastore = JSON.parse(game.datastore)
if (currentdatastore[req.query.key]){ // if database name already exists
console.log('1')
if (currentdatastore[req.query.key][[req.query.scope]]){ // if database scope already exists
console.log('2')
if (currentdatastore[req.query.key][req.query.scope][req.query.target]){ // key already stored overwrite it
console.log('3')
currentdatastore[req.query.key][req.query.scope][req.query.target] = {value: req.body.value}
if (currentdatastore[req.query.key]) {
// if database name already exists
console.log("1")
if (currentdatastore[req.query.key][[req.query.scope]]) {
// if database scope already exists
console.log("2")
if (
currentdatastore[req.query.key][req.query.scope][
req.query.target
]
) {
// key already stored overwrite it
console.log("3")
currentdatastore[req.query.key][req.query.scope][
req.query.target
] = { value: req.body.value }
} else {
console.log('4')
currentdatastore[req.query.key][req.query.scope][req.query.target] = {value: req.body.value} // database scope exists but key doesn't so generate it
console.log("4")
currentdatastore[req.query.key][req.query.scope][
req.query.target
] = { value: req.body.value } // database scope exists but key doesn't so generate it
}
} else {
currentdatastore[req.query.key][req.query.scope] = {[req.query.target]: {value: req.body.value}} // scope doesn't exist
currentdatastore[req.query.key][req.query.scope] = {
[req.query.target]: { value: req.body.value },
} // scope doesn't exist
}
} else {
currentdatastore[req.query.key] = {[req.query.scope]: {[req.query.target]: {value: req.body.value}},type: req.query.type} // database doesn't exist make sure to pass database type as well
currentdatastore[req.query.key] = {
[req.query.scope]: {
[req.query.target]: { value: req.body.value },
},
type: req.query.type,
} // database doesn't exist make sure to pass database type as well
}
try {
await games.updateOne({idofgame: placeid}, {
await games.updateOne(
{ idofgame: placeid },
{
$set: {
datastore: JSON.stringify(currentdatastore)
}
datastore: JSON.stringify(currentdatastore),
},
},
function (err, doc) {
//console.log(err)
})
}catch{
}
},
)
} catch {}
//console.log(req.body)
res.json({"data": [{"Key": {"Scope": req.query.key, "Target": "KEY", "Key": [req.query.target]}, "Value": req.body.value}]})
res.json({
data: [
{
Key: {
Scope: req.query.key,
Target: "KEY",
Key: [req.query.target],
},
Value: req.body.value,
},
],
})
})
router.post("/increment", async (req, res) => {
const placeid = req.query.placeId
@ -115,37 +197,59 @@ router.post("/increment", async (req, res) => {
}
let currentdatastore
if (!game.datastore) {
res.json({"data": {}})
res.json({ data: {} })
}
currentdatastore = JSON.parse(game.datastore)
if (currentdatastore[req.query.key] && currentdatastore[req.query.key][req.query.scope] && currentdatastore[req.query.key][req.query.scope][req.query.target]){
let value = parseFloat(currentdatastore[req.query.key][req.query.scope][req.query.target].value)
if (
currentdatastore[req.query.key] &&
currentdatastore[req.query.key][req.query.scope] &&
currentdatastore[req.query.key][req.query.scope][req.query.target]
) {
let value = parseFloat(
currentdatastore[req.query.key][req.query.scope][req.query.target]
.value,
)
if (!isNaN(parseFloat(value)) === true) {
// is number
let newvalue = value += parseFloat(req.query.value)
currentdatastore[req.query.key][req.query.scope][req.query.target].value = newvalue.toString()
let newvalue = (value += parseFloat(req.query.value))
currentdatastore[req.query.key][req.query.scope][
req.query.target
].value = newvalue.toString()
try {
await games.updateOne({idofgame: placeid}, {
await games.updateOne(
{ idofgame: placeid },
{
$set: {
datastore: JSON.stringify(currentdatastore)
}
datastore: JSON.stringify(currentdatastore),
},
},
function (err, doc) {
//console.log(err)
})
}catch{
}
},
)
} catch {}
//console.log(req.body)
return res.json({"data": [{"Key": {"Scope": req.query.key, "Target": "KEY", "Key": [req.query.target]}, "Value": parseFloat(currentdatastore[req.query.key][req.query.scope][req.query.target].value)}]})
}
}
res.json({"data": {}})
return res.json({
data: [
{
Key: {
Scope: req.query.key,
Target: "KEY",
Key: [req.query.target],
},
Value: parseFloat(
currentdatastore[req.query.key][req.query.scope][
req.query.target
].value,
),
},
],
})
}
}
res.json({ data: {} })
})
router.post("/getSortedValues", async (req, res) => {
const placeid = req.query.placeId
@ -154,40 +258,51 @@ router.post("/getSortedValues", async (req, res) => {
return res.sendStatus(404)
}
if (!game.datastore) {
return res.json({"data":{"Entries":[],"ExclusiveStartKey":null}})
return res.json({ data: { Entries: [], ExclusiveStartKey: null } })
}
const datastore = JSON.parse(game.datastore)
// first make sure database exists then make sure scope exists
if (datastore[req.query.key] && datastore[req.query.key][req.query.scope]) {
function paginate(array, page_size, page_number) {
// human-readable page numbers usually start with 1, so we reduce 1 in the first argument
return array.slice((page_number - 1) * page_size, page_number * page_size);
return array.slice(
(page_number - 1) * page_size,
page_number * page_size,
)
}
let wow = {"data":{"Entries":[],"ExclusiveStartKey":null}}
let wow = { data: { Entries: [], ExclusiveStartKey: null } }
//console.log(datastore[req.query.key][req.query.scope])
const pageNumber = req.query.exclusiveStartKey ?? 1
for (const [key, value] of Object.entries(datastore[req.query.key][req.query.scope])) {
for (const [key, value] of Object.entries(
datastore[req.query.key][req.query.scope],
)) {
wow.data.Entries.push({ Target: key, Value: value.value })
}
if (req.query.ascending === "False") {
// descending order
wow.data.Entries.sort((a, b) => a.Value - b.Value).reverse();
wow.data.Entries.sort((a, b) => a.Value - b.Value).reverse()
} else {
//ascending
wow.data.Entries.sort((a, b) => a.Value - b.Value)
}
wow.data.Entries = paginate(wow.data.Entries,req.query.pageSize,pageNumber)
wow.data.Entries = paginate(
wow.data.Entries,
req.query.pageSize,
pageNumber,
)
if (Object.entries(datastore[req.query.key][req.query.scope]).length > pageNumber * req.query.pageSize ){ // if the next page exists fill the exclusivestartkey
if (
Object.entries(datastore[req.query.key][req.query.scope]).length >
pageNumber * req.query.pageSize
) {
// if the next page exists fill the exclusivestartkey
wow.data.ExclusiveStartKey = (parseFloat(pageNumber) + 1).toString()
}
@ -195,15 +310,10 @@ if (Object.entries(datastore[req.query.key][req.query.scope]).length > pageNumbe
//console.dir(wow,{ depth: null })
return res.json(wow)
}
return res.json({"data":{"Entries":[],"ExclusiveStartKey":null}})
return res.json({ data: { Entries: [], ExclusiveStartKey: null } })
})
module.exports = router

View File

@ -1,28 +1,32 @@
const { response } = require("express")
const express = require("express")
const router = express.Router()
const bodyParser = require('body-parser')
const mongoose = require('mongoose');
const User = require('./../model/user.js')
const keys = require('./../model/keys.js')
const bcrypt = require('bcrypt')
var sanitize = require('mongo-sanitize');
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
const bodyParser = require("body-parser")
const mongoose = require("mongoose")
const User = require("./../model/user.js")
const keys = require("./../model/keys.js")
const bcrypt = require("bcrypt")
var sanitize = require("mongo-sanitize")
const fetch = (...args) =>
import("node-fetch").then(({ default: fetch }) => fetch(...args))
var xss = require("xss")
function isAlphaNumeric(str) {
var code, i, len;
var code, i, len
for (i = 0, len = str.length; i < len; i++) {
code = str.charCodeAt(i);
if (!(code > 47 && code < 58) && // numeric (0-9)
code = str.charCodeAt(i)
if (
!(code > 47 && code < 58) && // numeric (0-9)
!(code > 64 && code < 91) && // upper alpha (A-Z)
!(code === 95) && // underscore
!(code > 96 && code < 123)) { // lower alpha (a-z)
return false;
!(code > 96 && code < 123)
) {
// lower alpha (a-z)
return false
}
}
return true;
return true
}
router.use(bodyParser.json())
@ -31,52 +35,75 @@ router.post("/",async (req, res) => {
//console.log(req.body)
let { username, password: plainTextPassword } = req.body
if (!req.body.captcha) {
return res.json({status: 'error', error: 'Need a valid captcha bozo'})
return res.json({ status: "error", error: "Need a valid captcha bozo" })
}
if (!username || typeof username !== 'string') {
return res.json({status: 'error', error: 'Usernames needs to be sent and it needs to be a string'})
if (!username || typeof username !== "string") {
return res.json({
status: "error",
error: "Usernames needs to be sent and it needs to be a string",
})
}
if (!plainTextPassword || typeof plainTextPassword !== 'string') {
return res.json({status: 'error', error: 'Password needs to be sent and it needs to be a string'})
if (!plainTextPassword || typeof plainTextPassword !== "string") {
return res.json({
status: "error",
error: "Password needs to be sent and it needs to be a string",
})
}
if (plainTextPassword.length < 4) {
return res.json({status: 'error', error: 'Password needs to be at least 5 characters'})
return res.json({
status: "error",
error: "Password needs to be at least 5 characters",
})
}
if (username.length > 20) {
return res.json({status: 'error', error: 'Username can not be more than 20 characters'})
return res.json({
status: "error",
error: "Username can not be more than 20 characters",
})
}
if (isAlphaNumeric(username) === false) {
return res.json({status: 'error', error: 'Usernames can not have special symbols except for underscores'})
return res.json({
status: "error",
error: "Usernames can not have special symbols except for underscores",
})
}
// verify our captcha
var captchaverifyreq = await fetch('https://hcaptcha.com/siteverify', {
method: 'POST',
var captchaverifyreq = await fetch("https://hcaptcha.com/siteverify", {
method: "POST",
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
"Content-Type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams({
'secret': '0xE05AB1CFB83252696175FA69E526a3048547Cf0d',
'response': req.body.captcha,
'sitekey': '30f6dee1-f765-42d0-ae34-29697c4aa623'
secret: "0xE05AB1CFB83252696175FA69E526a3048547Cf0d",
response: req.body.captcha,
sitekey: "30f6dee1-f765-42d0-ae34-29697c4aa623",
}),
})
});
var captcha = await captchaverifyreq.json()
if (captcha.success == false) {
return res.json({status: 'error', error: 'Invalid Captcha. Try again.'})
return res.json({
status: "error",
error: "Invalid Captcha. Try again.",
})
}
// check if keys are enabled
var registration = req.config
if (registration.RegistrationEnabled === false) {
return res.json({status: 'error', error: 'Registration has been temporarily disabled. Please join our discord.'})
return res.json({
status: "error",
error: "Registration has been temporarily disabled. Please join our discord.",
})
}
if (registration.KeysEnabled === true) {
if (!req.body.invitekey) {
return res.json({status: 'error', error: 'Invite key needs to be sent.'})
return res.json({
status: "error",
error: "Invite key needs to be sent.",
})
}
sanitizedkey = sanitize(req.body.invitekey)
@ -84,32 +111,36 @@ if (registration.KeysEnabled === true){
if (!key) {
// key is invalid
return res.json({status: 'error', error: 'Invalid Key.'})
return res.json({ status: "error", error: "Invalid Key." })
}
if (key.Used === true) {
// key has been used already
return res.json({status: 'error', error: 'Key has been used already.'})
}
keys.updateOne({Key: sanitizedkey}, {
$set: {
Used: true,
UsedBy: username
}
},
function(err, doc) {
//console.log(err)
return res.json({
status: "error",
error: "Key has been used already.",
})
}
keys.updateOne(
{ Key: sanitizedkey },
{
$set: {
Used: true,
UsedBy: username,
},
},
function (err, doc) {
//console.log(err)
},
)
}
// if all checks above have succceeded we can proceed with registering in our database
username = xss(username) // stop anyone doing anything silly :)
try {
const password = (await bcrypt.hash(plainTextPassword, 10))
const userid = await User.countDocuments();
const password = await bcrypt.hash(plainTextPassword, 10)
const userid = await User.countDocuments()
var datetime = new Date()
var datetimeepoch = new Date().getTime()
const response = await User.create({
@ -118,25 +149,41 @@ username = xss(username) // stop anyone doing anything silly :)
admin: false,
coins: 15,
userid,
moderation: JSON.stringify({status: "ok", Reason: "None", ExpiresIn: "None"}),
moderation: JSON.stringify({
status: "ok",
Reason: "None",
ExpiresIn: "None",
}),
joindate: datetime.toISOString().slice(0, 10),
colors: [{name: "Head",value: 1001 },{name: "Torso",value: 1001 },{name: "Left Arm",value: 1001 },{name: "Right Arm",value: 1001 },{name: "Left Leg",value: 1001 },{name: "Right Leg",value: 1001 }],
colors: [
{ name: "Head", value: 1001 },
{ name: "Torso", value: 1001 },
{ name: "Left Arm", value: 1001 },
{ name: "Right Arm", value: 1001 },
{ name: "Left Leg", value: 1001 },
{ name: "Right Leg", value: 1001 },
],
lastclaimofcurrency: datetimeepoch,
membership: "None",
timesincelastrequest: datetimeepoch
timesincelastrequest: datetimeepoch,
})
//console.log(response)
} catch (error) {
if (error.code === 11000) {
return res.json({status: 'error', error: 'Username already in use'})
return res.json({
status: "error",
error: "Username already in use",
})
} else if (error.errors.username.kind === "unique") {
return res.json({status: 'error', error: 'Username already in use'})
return res.json({
status: "error",
error: "Username already in use",
})
}
throw error
}
res.json({status: 'ok'})
res.json({ status: "ok" })
})
module.exports = router

View File

@ -1,17 +1,18 @@
const express = require("express")
const router = express.Router()
const { requireAuth } = require('./../middleware/authmiddleware')
const { requireAuth } = require("./../middleware/authmiddleware")
const clientid = "1008206768989544449"
const secret = "M2ixbjumSA6o1Qgt7KvCNcPb_giJHyp3"
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
const User = require('./../model/user.js')
const speakeasy = require('speakeasy')
const qrcode = require('qrcode')
const bodyParser = require('body-parser')
const xss = require('xss')
const fetch = (...args) =>
import("node-fetch").then(({ default: fetch }) => fetch(...args))
const User = require("./../model/user.js")
const speakeasy = require("speakeasy")
const qrcode = require("qrcode")
const bodyParser = require("body-parser")
const xss = require("xss")
router.use(bodyParser.json())
router.get('/authenticate',requireAuth,async function(req,rep){
router.get("/authenticate", requireAuth, async function (req, rep) {
const code = req.query.code
//console.log(code)
if (code) {
@ -20,14 +21,14 @@ router.get('/authenticate',requireAuth,async function(req,rep){
client_id: clientid,
client_secret: secret,
code,
grant_type: 'authorization_code',
grant_type: "authorization_code",
redirect_uri: `http://mete0r.xyz/settings/authenticate`,
scope: 'identify',
scope: "identify",
}),
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
"Content-Type": "application/x-www-form-urlencoded",
},
})
const son = await response.json()
@ -36,8 +37,8 @@ router.get('/authenticate',requireAuth,async function(req,rep){
const resp2 = await fetch("https://discord.com/api/users/@me", {
headers: {
"authorization": `${son["token_type"]} ${son["access_token"]}`
}
authorization: `${son["token_type"]} ${son["access_token"]}`,
},
})
const final = await resp2.json()
@ -49,19 +50,22 @@ router.get('/authenticate',requireAuth,async function(req,rep){
return rep.redirect("/settings?error=alreadyused")
}
const milliseconds = BigInt(dcid) >> 22n
if (new Date(Number(milliseconds) + 1420070400000)> Date.now() - (1000 * 60 * 60 * 24 * 7 * 4) === true){ // 1 month
if (
new Date(Number(milliseconds) + 1420070400000) >
Date.now() - 1000 * 60 * 60 * 24 * 7 * 4 ===
true
) {
// 1 month
return rep.redirect("/settings?error=toonew")
}
req.userdocument.discordid = dcid.toString()
req.userdocument.markModified('discordid')
req.userdocument.markModified("discordid")
await req.userdocument.save()
rep.redirect('/settings')
rep.redirect("/settings")
}
})
/*router.get("/unlink", requireAuth,async (req, res) => {
req.userdocument.discordid = undefined
req.userdocument.markModified('discordid')
@ -73,97 +77,103 @@ router.get("/2fa", requireAuth,async (req, res) => {
if (req.userdocument.twofasecrets) {
const json = JSON.parse(req.userdocument.twofasecrets)
if (json.verified === true) {
return res.json({status: "success", message: "2FA already set sorry."})
return res.json({
status: "success",
message: "2FA already set sorry.",
})
} else {
// basically if they haven't verified that they know the secret before we will just remove it for them
req.userdocument.twofasecrets = undefined
req.userdocument.markModified('twofasecrets')
req.userdocument.markModified("twofasecrets")
req.userdocument.save()
}
}
const secret = speakeasy.generateSecret({
name: "Meteorite"
name: "Meteorite",
})
qrcode.toDataURL(secret.otpauth_url, function (err, data) {
req.userdocument.twofasecrets = JSON.stringify({secret: secret.ascii, verified: false})
req.userdocument.markModified('twofasecrets')
req.userdocument.save()
return res.json({status: "success", message: "2FA set please verify to complete.", qrcode: data})
});
req.userdocument.twofasecrets = JSON.stringify({
secret: secret.ascii,
verified: false,
})
req.userdocument.markModified("twofasecrets")
req.userdocument.save()
return res.json({
status: "success",
message: "2FA set please verify to complete.",
qrcode: data,
})
})
})
router.post("/verify2fa", requireAuth, async (req, res) => {
const { code } = req.body
if (req.userdocument.twofasecrets) {
const json = JSON.parse(req.userdocument.twofasecrets)
if (json.verified === true) {
return res.json({status: "success", message: "2FA already set sorry."})
return res.json({
status: "success",
message: "2FA already set sorry.",
})
} else {
const valid = speakeasy.totp.verify({
secret: json.secret,
encoding: 'ascii',
token: code
encoding: "ascii",
token: code,
})
if (valid === false) {
return res.json({status: 'error', error: 'Invalid 2FA Code'})
return res.json({ status: "error", error: "Invalid 2FA Code" })
} else {
json.verified = true
req.userdocument.twofasecrets = JSON.stringify(json)
req.userdocument.markModified('twofasecrets')
req.userdocument.markModified("twofasecrets")
req.userdocument.save()
return res.json({ status: "success", message: "2FA verified." })
}
}
}
})
router.post("/setbio", requireAuth, async (req, res) => {
const { bio } = req.body
if (typeof bio !== 'string'){
return res.json({status: 'error', error: 'Bio not sent'})
if (typeof bio !== "string") {
return res.json({ status: "error", error: "Bio not sent" })
}
if (bio.length > 100) {
return res.json({status: 'error', error: 'Length over 100.'})
return res.json({ status: "error", error: "Length over 100." })
}
req.userdocument.bio = xss(bio)
req.userdocument.markModified('bio')
req.userdocument.markModified("bio")
req.userdocument.save()
return res.json({ status: "success", message: "Done." })
})
router.post("/changecss", requireAuth, async (req, res) => {
const { customcss } = req.body
if (typeof customcss !== 'string'){
return res.json({status: 'error', error: 'Bio not sent'})
if (typeof customcss !== "string") {
return res.json({ status: "error", error: "Bio not sent" })
}
if (customcss.length > 5000) {
return res.json({status: 'error', error: 'Length over 5000.'})
return res.json({ status: "error", error: "Length over 5000." })
}
req.userdocument.css = xss(customcss)
req.userdocument.markModified('css')
req.userdocument.markModified("css")
req.userdocument.save()
return res.json({ status: "success", message: "Done." })
})
router.post("/aboutme", requireAuth, async (req, res) => {
const { about } = req.body
if (typeof about !== 'string'){
return res.json({status: 'error', error: 'Bio not sent'})
if (typeof about !== "string") {
return res.json({ status: "error", error: "Bio not sent" })
}
if (about.length > 200) {
return res.json({status: 'error', error: 'Length over 200.'})
return res.json({ status: "error", error: "Length over 200." })
}
req.userdocument.aboutme = xss(about)
req.userdocument.markModified('aboutme')
req.userdocument.markModified("aboutme")
req.userdocument.save()
return res.json({ status: "success", message: "Done." })
})
module.exports = router

View File

@ -1,14 +1,14 @@
const crypto = require('crypto');
const fs = require('fs')
const key = fs.readFileSync('DefaultPrivateKey.pem')
const crypto = require("crypto")
const fs = require("fs")
const key = fs.readFileSync("DefaultPrivateKey.pem")
// signature API for roblos , used to bless scripts from site to client/rcc/studio and will grant
// FULL Lua permissions to scripts, and allow CoreGui access.
function signer(wow) {
const sign = crypto.createSign('SHA1');
const sign = crypto.createSign("SHA1")
sign.update("\r\n" + JSON.stringify(wow))
var signature_b64 = sign.sign(key, "base64")
//console.log(signature_b64)
return(signature_b64)
return signature_b64
}
module.exports = { signer }

View File

@ -1,36 +1,37 @@
const express = require("express")
const router = express.Router()
const User = require('./../model/user.js')
var bodyParser = require('body-parser');
router.use(bodyParser.json()); // support json encoded bodies
router.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
router.use(bodyParser.text()); // support encoded bodies
const User = require("./../model/user.js")
var bodyParser = require("body-parser")
router.use(bodyParser.json()) // support json encoded bodies
router.use(bodyParser.urlencoded({ extended: true })) // support encoded bodies
router.use(bodyParser.text()) // support encoded bodies
const JWT_SECRET = process.env.JWT_SECRET
const jwt = require('jsonwebtoken')
const jwt = require("jsonwebtoken")
const jwtverify = (req, res, next) => {
jwt.verify(req.headers['roblox-session-id'],JWT_SECRET, (err,decodedtoken) => {
jwt.verify(
req.headers["roblox-session-id"],
JWT_SECRET,
(err, decodedtoken) => {
if (err) {
return res.status(403).end()
} else {
var tokendata = decodedtoken
var name = tokendata.username
try {
User.findOne({username: new RegExp('^'+name+'$', "i")}, function(err, doc) {
User.findOne(
{ username: new RegExp("^" + name + "$", "i") },
function (err, doc) {
req.userdocument = doc
next()
})/*.lean()*/}
catch (error) {
console.error(error);
},
) /*.lean()*/
} catch (error) {
console.error(error)
}
}
})
};
},
)
}
// below is follow code
router.get("/user/following-exists", async (req, res) => {
@ -44,7 +45,9 @@ router.get("/user/following-exists",async (req, res) => {
return res.json({ isFollowing: "false" })
}
const follower = user.followers.some(word => word.userid == req.query.followerUserId )
const follower = user.followers.some(
word => word.userid == req.query.followerUserId,
)
if (follower === false) {
return res.json({ isFollowing: "false" })
@ -60,29 +63,32 @@ router.post("/user/follow",jwtverify,async (req, res) => {
}
let follower = false
if (req.userdocument.followers) {
follower = req.userdocument.followers.some(word => word.userid == req.query.followerUserId )
follower = req.userdocument.followers.some(
word => word.userid == req.query.followerUserId,
)
}
if (follower === true) {
// already following
res.json({ success: "true", isFollowing: "true" })
}
User.updateOne({userid: tofollow}, {
User.updateOne(
{ userid: tofollow },
{
$push: {
followers: {userid: req.userdocument.userid, username: req.userdocument.username}
}
followers: {
userid: req.userdocument.userid,
username: req.userdocument.username,
},
},
},
function (err, doc) {
//console.log(err)
})
},
)
res.json({ success: "true", isFollowing: "true" })
})
router.post("/user/unfollow", jwtverify, async (req, res) => {
@ -91,20 +97,22 @@ router.post("/user/unfollow",jwtverify,async (req, res) => {
return res.json({ isFollowing: "false" })
}
User.updateOne({userid: tofollow}, {
User.updateOne(
{ userid: tofollow },
{
$pull: {
followers: {userid: req.userdocument.userid, username: req.userdocument.username}
}
followers: {
userid: req.userdocument.userid,
username: req.userdocument.username,
},
},
},
function (err, doc) {
//console.log(err)
})
},
)
res.json({ success: "true", isFollowing: "false" })
})
//below is friend code
@ -126,11 +134,11 @@ router.post("/user/request-friendship",jwtverify,async (req, res) => {
return res.json({ success: "true", isFollowing: "true" })
}
if (usertofriend.friends) {
const friends = usertofriend.friends.some(word => word.userid == req.userdocument.userid)
const friends = usertofriend.friends.some(
word => word.userid == req.userdocument.userid,
)
if (friends === true) {
return res.json({ success: "true", isFollowing: "true" })
}
// already friends
@ -138,60 +146,77 @@ router.post("/user/request-friendship",jwtverify,async (req, res) => {
if (req.userdocument.friendrequests) {
// check if the other user is already requesting to friend the player so then they both want to be firends so we can interperept this as an accept request
const bothwantobefriends = req.userdocument.friendrequests.some(word => word.userid == usertofriend.userid)
const bothwantobefriends = req.userdocument.friendrequests.some(
word => word.userid == usertofriend.userid,
)
if (bothwantobefriends === true) {
console.log(tofriend)
User.updateOne({userid: req.userdocument.userid}, {
User.updateOne(
{ userid: req.userdocument.userid },
{
$push: {
friends: {userid: usertofriend.userid, username: usertofriend.username}
friends: {
userid: usertofriend.userid,
username: usertofriend.username,
},
},
$pull: {
friendrequests: {userid: usertofriend.userid, username: usertofriend.username}
}
friendrequests: {
userid: usertofriend.userid,
username: usertofriend.username,
},
function(err, doc) {
},
},
function (err, doc) {},
)
})
User.updateOne({userid: tofriend}, {
User.updateOne(
{ userid: tofriend },
{
$push: {
friends: {userid: req.userdocument.userid, username: req.userdocument.username}
friends: {
userid: req.userdocument.userid,
username: req.userdocument.username,
},
},
$pull: {
friendrequests: {userid: req.userdocument.userid, username: req.userdocument.username}
}
friendrequests: {
userid: req.userdocument.userid,
username: req.userdocument.username,
},
function(err, doc) {
})
},
},
function (err, doc) {},
)
return res.json({ success: "true", isFollowing: "true" })
}
}
if (usertofriend.friendrequests) {
const alreadyrequested = usertofriend.friendrequests.some(word => word.userid == req.userdocument.userid)
const alreadyrequested = usertofriend.friendrequests.some(
word => word.userid == req.userdocument.userid,
)
// already friend requested
if (alreadyrequested === true) {
return res.json({ success: "true", isFollowing: "true" })
}
}
User.updateOne({userid: usertofriend.userid}, {
User.updateOne(
{ userid: usertofriend.userid },
{
$push: {
friendrequests: {userid: req.userdocument.userid, username: req.userdocument.username}
}
friendrequests: {
userid: req.userdocument.userid,
username: req.userdocument.username,
},
function(err, doc) {
})
},
},
function (err, doc) {},
)
res.json({ success: "true", isFollowing: "true" })
})
router.post("/user/decline-friend-request", jwtverify, async (req, res) => {
@ -205,53 +230,74 @@ router.post("/user/decline-friend-request",jwtverify,async (req, res) => {
return res.json({ success: "true", isFollowing: "true" })
}
const alreadyfriends = req.userdocument.friends.some(word => word.userid == tounfriend )
const alreadyfriends = req.userdocument.friends.some(
word => word.userid == tounfriend,
)
if (alreadyfriends === true) {
// already friends with the person so they want ro remove their friend
User.updateOne({userid: tounfriend}, {
User.updateOne(
{ userid: tounfriend },
{
$pull: {
friends: {userid: req.userdocument.userid, username: req.userdocument.username}
}
friends: {
userid: req.userdocument.userid,
username: req.userdocument.username,
},
},
},
function (err, doc) {
//console.log(err)
})
User.updateOne({userid: req.userdocument.userid}, {
},
)
User.updateOne(
{ userid: req.userdocument.userid },
{
$pull: {
friends: {userid:usertofriend.userid, username: usertofriend.username}
}
friends: {
userid: usertofriend.userid,
username: usertofriend.username,
},
},
},
function (err, doc) {
//console.log(err)
})
},
)
return res.json({ success: "true", isFollowing: "true" })
}
//otherwise the user isn't friends but still declines the friend request
User.updateOne({userid: tounfriend}, {
User.updateOne(
{ userid: tounfriend },
{
$pull: {
friendrequests: {userid: req.userdocument.userid, username: req.userdocument.username}
}
friendrequests: {
userid: req.userdocument.userid,
username: req.userdocument.username,
},
},
},
function (err, doc) {
//console.log(err)
})
User.updateOne({userid: req.userdocument.userid}, {
},
)
User.updateOne(
{ userid: req.userdocument.userid },
{
$pull: {
friendrequests: {userid: usertofriend.userid, username: usertofriend.username}
}
friendrequests: {
userid: usertofriend.userid,
username: usertofriend.username,
},
},
},
function (err, doc) {
//console.log(err)
})
},
)
res.json({ success: "true", isFollowing: "true" })
})
module.exports = router

View File

@ -1,12 +1,12 @@
const express = require("express")
const router = express.Router()
const { requireAuth } = require('./../middleware/authmiddleware')
const User = require('./../model/user.js')
const games = require('./../model/games.js')
const bodyParser = require('body-parser')
const { requireAuth } = require("./../middleware/authmiddleware")
const User = require("./../model/user.js")
const games = require("./../model/games.js")
const bodyParser = require("body-parser")
router.use(bodyParser.json())
router.post('/api/users/search', async (req, res) => {
router.post("/api/users/search", async (req, res) => {
const resultsPerPage = 12
let page = req.body.page ?? 0
if (page != 0) {
@ -15,35 +15,50 @@ router.post('/api/users/search', async (req, res) => {
let { searchquery } = req.body
function escapeRegex(text) {
return text?.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
return text?.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&")
}
const regex = new RegExp(escapeRegex(searchquery), 'gi');
const regex = new RegExp(escapeRegex(searchquery), "gi")
//const pages = await User.countDocuments({username: regex})/resultsPerPage
const response = await User.find({username: regex}).limit(resultsPerPage).skip(0+parseFloat(page)*resultsPerPage).select(['userid','username']).lean()
const response = await User.find({ username: regex })
.limit(resultsPerPage)
.skip(0 + parseFloat(page) * resultsPerPage)
.select(["userid", "username"])
.lean()
let responsecount = await User.countDocuments({ username: regex })
res.json({data: response, pages: Math.ceil(Math.max(responsecount/resultsPerPage, 1))})
});
res.json({
data: response,
pages: Math.ceil(Math.max(responsecount / resultsPerPage, 1)),
})
})
router.get(['/users/:userid/canmanage/:gameid','//users/:userid/canmanage/:gameid'], async (req, res) => {
const user = await User.findOne({userid: req.params.userid})/*.lean()*/
router.get(
["/users/:userid/canmanage/:gameid", "//users/:userid/canmanage/:gameid"],
async (req, res) => {
const user = await User.findOne({
userid: req.params.userid,
}) /*.lean()*/
if (!user) {
return res.json({"Success":false,"CanManage":false})
return res.json({ Success: false, CanManage: false })
}
const game = await games.findOne({ idofgame: req.params.gameid }).lean()
if (!game) {
return res.json({"Success":false,"CanManage":false})
return res.json({ Success: false, CanManage: false })
}
if (game.useridofowner === user.userid || user.userid === 0 || user.userid === 18){
return res.json({"Success":true,"CanManage":true})
if (
game.useridofowner === user.userid ||
user.userid === 0 ||
user.userid === 18
) {
return res.json({ Success: true, CanManage: true })
}
return res.json({"Success":true,"CanManage":false})
});
return res.json({ Success: true, CanManage: false })
},
)
module.exports = router

File diff suppressed because one or more lines are too long

View File

@ -1,96 +1,112 @@
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
let controller = new AbortController();
require('dotenv').config()
const fetch = (...args) =>
import("node-fetch").then(({ default: fetch }) => fetch(...args))
let controller = new AbortController()
require("dotenv").config()
const RCC_HOST = process.env.RCC_HOST
const url = 'http://'+RCC_HOST+':64990'; // change this to rcc soap
var convert = require('xml-js');
const url = "http://" + RCC_HOST + ":64990" // change this to rcc soap
var convert = require("xml-js")
const sampleHeaders = {
'Content-Type': 'text/xml;charset=UTF-8',
};
"Content-Type": "text/xml;charset=UTF-8",
}
async function OpenJob(jobid, script, expiration) {
return new Promise(async (resolve, reject) => {
// this is all boilerplate because soap sucks
var xml = {
_declaration: { _attributes: { version: '1.0', encoding: 'UTF-8' } },
'SOAP-ENV:Envelope': {
_declaration: {
_attributes: { version: "1.0", encoding: "UTF-8" },
},
"SOAP-ENV:Envelope": {
_attributes: {
'xmlns:SOAP-ENV': 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:ns1': 'http://roblox.com/'
"xmlns:SOAP-ENV":
"http://schemas.xmlsoap.org/soap/envelope/",
"xmlns:ns1": "http://roblox.com/",
},
"SOAP-ENV:Body": {
"ns1:OpenJobEx": {
"ns1:job": {
"ns1:id": { _text: "StringTest11" },
"ns1:expirationInSeconds": { _text: "10" },
"ns1:category": { _text: "0" },
"ns1:cores": { _text: "1" },
},
"ns1:script": {
"ns1:name": { _text: "StringTest11-Script" },
"ns1:script": {
_text: 'print("Recieved job with ID " .. game.JobId)\r\n',
},
"ns1:arguments": {},
},
},
'SOAP-ENV:Body': {
'ns1:OpenJobEx': {
'ns1:job': {
'ns1:id': { _text: 'StringTest11' },
'ns1:expirationInSeconds': { _text: '10' },
'ns1:category': { _text: '0' },
'ns1:cores': { _text: '1' }
},
'ns1:script': {
'ns1:name': { _text: 'StringTest11-Script' },
'ns1:script': {
_text: 'print("Recieved job with ID " .. game.JobId)\r\n'
},
'ns1:arguments': {}
}
}
}
}
}
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:OpenJobEx']['ns1:job']['ns1:id']._text = jobid
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:OpenJobEx']['ns1:job']['ns1:expirationInSeconds']._text = expiration
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:OpenJobEx"]["ns1:job"][
"ns1:id"
]._text = jobid
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:OpenJobEx"]["ns1:job"][
"ns1:expirationInSeconds"
]._text = expiration
if (!expiration) {
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:OpenJobEx']['ns1:job']['ns1:expirationInSeconds']._text = "60"
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:OpenJobEx"][
"ns1:job"
]["ns1:expirationInSeconds"]._text = "60"
}
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:OpenJobEx']['ns1:script']['ns1:script']._text = script
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:OpenJobEx"][
"ns1:script"
]["ns1:script"]._text = script
const body = convert.js2xml(xml, { compact: true, spaces: 4 })
try {
const result = await fetch(url, { method: 'POST', body })
const result = await fetch(url, { method: "POST", body })
const data = await result.text()
const convertedData = convert.xml2js(data, { compact: true, spaces: 4 })
return resolve(
convertedData
)
const convertedData = convert.xml2js(data, {
compact: true,
spaces: 4,
})
return resolve(convertedData)
} catch (error) {
return reject(error)
}
})
}
async function GetAllJobs() {
return new Promise(async (resolve, reject) => {
const xmlData = (xml = {
_declaration: {
_attributes: { version: '1.0', encoding: 'UTF - 8' },
_attributes: { version: "1.0", encoding: "UTF - 8" },
},
'SOAP-ENV:Envelope': {
"SOAP-ENV:Envelope": {
_attributes: {
'xmlns:SOAP-ENV': 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:SOAP-ENC': 'http://schemas.xmlsoap.org/soap/encoding/',
'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
'xmlns:xsd': 'http://www.w3.org/2001/XMLSchema',
'xmlns:ns2': 'http://roblox.com/RCCServiceSoap',
'xmlns:ns1': 'http://roblox.com/',
'xmlns:ns3': 'http://roblox.com/RCCServiceSoap12',
"xmlns:SOAP-ENV":
"http://schemas.xmlsoap.org/soap/envelope/",
"xmlns:SOAP-ENC":
"http://schemas.xmlsoap.org/soap/encoding/",
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"xmlns:xsd": "http://www.w3.org/2001/XMLSchema",
"xmlns:ns2": "http://roblox.com/RCCServiceSoap",
"xmlns:ns1": "http://roblox.com/",
"xmlns:ns3": "http://roblox.com/RCCServiceSoap12",
},
'SOAP-ENV:Body': { 'ns1:GetAllJobsEx': {} },
"SOAP-ENV:Body": { "ns1:GetAllJobsEx": {} },
},
})
const body = convert.js2xml(xmlData, { compact: true, spaces: 4 })
try {
const result = await fetch(url, { method: 'POST', body })
const result = await fetch(url, { method: "POST", body })
const data = await result.text()
const convertedData = convert.xml2js(data, { compact: true, spaces: 4 })
const convertedData = convert.xml2js(data, {
compact: true,
spaces: 4,
})
return resolve(
convertedData['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:GetAllJobsExResponse']['ns1:GetAllJobsExResult']
convertedData["SOAP-ENV:Envelope"]["SOAP-ENV:Body"][
"ns1:GetAllJobsExResponse"
]["ns1:GetAllJobsExResult"],
)
} catch (error) {
return reject(error)
@ -101,119 +117,141 @@ async function GetAllJobs() {
async function Execute(jobid, script) {
return new Promise(async (resolve, reject) => {
var xml = {
_declaration: { _attributes: { version: '1.0', encoding: 'UTF - 8' } },
'SOAP-ENV:Envelope': {
_attributes: {
'xmlns:SOAP-ENV': 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:SOAP-ENC': 'http://schemas.xmlsoap.org/soap/encoding/',
'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
'xmlns:xsd': 'http://www.w3.org/2001/XMLSchema',
'xmlns:ns2': 'http://roblox.com/RCCServiceSoap',
'xmlns:ns1': 'http://roblox.com/',
'xmlns:ns3': 'http://roblox.com/RCCServiceSoap12'
_declaration: {
_attributes: { version: "1.0", encoding: "UTF - 8" },
},
"SOAP-ENV:Envelope": {
_attributes: {
"xmlns:SOAP-ENV":
"http://schemas.xmlsoap.org/soap/envelope/",
"xmlns:SOAP-ENC":
"http://schemas.xmlsoap.org/soap/encoding/",
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"xmlns:xsd": "http://www.w3.org/2001/XMLSchema",
"xmlns:ns2": "http://roblox.com/RCCServiceSoap",
"xmlns:ns1": "http://roblox.com/",
"xmlns:ns3": "http://roblox.com/RCCServiceSoap12",
},
"SOAP-ENV:Body": {
"ns1:ExecuteEx": {
"ns1:jobID": { _text: "Test" },
"ns1:script": {
"ns1:name": { _text: "Script" },
"ns1:script": { _text: 'print("no")' },
"ns1:arguments": { _text: "" },
},
},
},
},
'SOAP-ENV:Body': {
'ns1:ExecuteEx': {
'ns1:jobID': { _text: 'Test' },
'ns1:script': {
'ns1:name': { _text: 'Script' },
'ns1:script': { _text: 'print("no")' },
'ns1:arguments': { _text: '' }
}
}
}
}
}
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:ExecuteEx']['ns1:jobID']._text = jobid
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:ExecuteEx']['ns1:script']['ns1:script']._text = script
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:ExecuteEx"][
"ns1:jobID"
]._text = jobid
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:ExecuteEx"][
"ns1:script"
]["ns1:script"]._text = script
const body = convert.js2xml(xml, { compact: true, spaces: 4 })
try {
const result = await fetch(url, { method: 'POST', body })
const result = await fetch(url, { method: "POST", body })
const data = await result.text()
const convertedData = convert.xml2js(data, { compact: true, spaces: 4 })
return resolve(
convertedData
)
const convertedData = convert.xml2js(data, {
compact: true,
spaces: 4,
})
return resolve(convertedData)
} catch (error) {
return reject(error)
}
})
}
async function CloseJob(jobid) {
return new Promise(async (resolve, reject) => {
var xml = {
_declaration: { _attributes: { version: '1.0', encoding: 'UTF - 8' } },
'SOAP-ENV:Envelope': {
_attributes: {
'xmlns:SOAP-ENV': 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:SOAP-ENC': 'http://schemas.xmlsoap.org/soap/encoding/',
'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
'xmlns:xsd': 'http://www.w3.org/2001/XMLSchema',
'xmlns:ns2': 'http://roblox.com/RCCServiceSoap',
'xmlns:ns1': 'http://roblox.com/',
'xmlns:ns3': 'http://roblox.com/RCCServiceSoap12'
_declaration: {
_attributes: { version: "1.0", encoding: "UTF - 8" },
},
"SOAP-ENV:Envelope": {
_attributes: {
"xmlns:SOAP-ENV":
"http://schemas.xmlsoap.org/soap/envelope/",
"xmlns:SOAP-ENC":
"http://schemas.xmlsoap.org/soap/encoding/",
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"xmlns:xsd": "http://www.w3.org/2001/XMLSchema",
"xmlns:ns2": "http://roblox.com/RCCServiceSoap",
"xmlns:ns1": "http://roblox.com/",
"xmlns:ns3": "http://roblox.com/RCCServiceSoap12",
},
"SOAP-ENV:Body": {
"ns1:CloseJob": {
"ns1:jobID": { _text: "Test" },
},
},
},
'SOAP-ENV:Body': {
'ns1:CloseJob': {
'ns1:jobID': { _text: 'Test' }
}
}
}
}
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:CloseJob']['ns1:jobID']._text = jobid
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:CloseJob"][
"ns1:jobID"
]._text = jobid
const body = convert.js2xml(xml, { compact: true, spaces: 4 })
try {
const result = await fetch(url, { method: 'POST', body })
const result = await fetch(url, { method: "POST", body })
const data = await result.text()
const convertedData = convert.xml2js(data, { compact: true, spaces: 4 })
return resolve(
convertedData
)
const convertedData = convert.xml2js(data, {
compact: true,
spaces: 4,
})
return resolve(convertedData)
} catch (error) {
return reject(error)
}
})
}
async function RenewLease(jobid, expiration) {
return new Promise(async (resolve, reject) => {
var xml = {
_declaration: { _attributes: { version: '1.0', encoding: 'UTF-8' } },
'SOAP-ENV:Envelope': {
_declaration: {
_attributes: { version: "1.0", encoding: "UTF-8" },
},
"SOAP-ENV:Envelope": {
_attributes: {
'xmlns:SOAP-ENV': 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:ns1': 'http://roblox.com/',
'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance'
"xmlns:SOAP-ENV":
"http://schemas.xmlsoap.org/soap/envelope/",
"xmlns:ns1": "http://roblox.com/",
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
},
"SOAP-ENV:Body": {
"ns1:RenewLease": {
"ns1:jobID": {
_attributes: { "xsi:type": "ns1:Job" },
"ns1:id": { _text: "StringTest11" },
"ns1:expirationInSeconds": { _text: "10" },
"ns1:category": { _text: "0" },
"ns1:cores": { _text: "1" },
},
"ns1:expirationInSeconds": { _text: "100" },
},
},
'SOAP-ENV:Body': {
'ns1:RenewLease': {
'ns1:jobID': {
_attributes: { 'xsi:type': 'ns1:Job' },
'ns1:id': { _text: 'StringTest11' },
'ns1:expirationInSeconds': { _text: '10' },
'ns1:category': { _text: '0' },
'ns1:cores': { _text: '1' }
},
'ns1:expirationInSeconds': { _text: '100' }
}
}
}
}
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:RenewLease']['ns1:jobID']['ns1:id']._text = jobid
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:RenewLease']['ns1:expirationInSeconds']._text = expiration
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:RenewLease"][
"ns1:jobID"
]["ns1:id"]._text = jobid
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:RenewLease"][
"ns1:expirationInSeconds"
]._text = expiration
const body = convert.js2xml(xml, { compact: true, spaces: 4 })
try {
const result = await fetch(url, { method: 'POST', body })
const result = await fetch(url, { method: "POST", body })
const data = await result.text()
const convertedData = convert.xml2js(data, { compact: true, spaces: 4 })
return resolve(
convertedData
)
const convertedData = convert.xml2js(data, {
compact: true,
spaces: 4,
})
return resolve(convertedData)
} catch (error) {
return reject(error)
}
@ -223,25 +261,33 @@ async function RenewLease(jobid,expiration) {
async function GetExpiration(jobid) {
return new Promise(async (resolve, reject) => {
var xml = {
_declaration: { _attributes: { version: '1.0', encoding: 'UTF-8' } },
'SOAP-ENV:Envelope': {
_attributes: {
'xmlns:SOAP-ENV': 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:ns1': 'http://roblox.com/'
_declaration: {
_attributes: { version: "1.0", encoding: "UTF-8" },
},
"SOAP-ENV:Envelope": {
_attributes: {
"xmlns:SOAP-ENV":
"http://schemas.xmlsoap.org/soap/envelope/",
"xmlns:ns1": "http://roblox.com/",
},
"SOAP-ENV:Body": {
"ns1:GetExpiration": { "ns1:jobID": { _text: "Test" } },
},
},
'SOAP-ENV:Body': { 'ns1:GetExpiration': { 'ns1:jobID': { _text: 'Test' } } }
}
}
xml['SOAP-ENV:Envelope']['SOAP-ENV:Body']['ns1:GetExpiration']['ns1:jobID']._text = jobid
xml["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:GetExpiration"][
"ns1:jobID"
]._text = jobid
const body = convert.js2xml(xml, { compact: true, spaces: 4 })
try {
const result = await fetch(url, { method: 'POST', body })
const result = await fetch(url, { method: "POST", body })
const data = await result.text()
const convertedData = convert.xml2js(data, { compact: true, spaces: 4 })
return resolve(
convertedData
)
const convertedData = convert.xml2js(data, {
compact: true,
spaces: 4,
})
return resolve(convertedData)
} catch (error) {
return reject(error)
}
@ -252,26 +298,30 @@ async function GetExpiration(jobid){
async function CloseExpiredJobs() {
return new Promise(async (resolve, reject) => {
var xml = xml = {
_declaration: { _attributes: { version: '1.0', encoding: 'UTF-8' } },
'SOAP-ENV:Envelope': {
_attributes: {
'xmlns:SOAP-ENV': 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:ns1': 'http://roblox.com/'
var xml = (xml = {
_declaration: {
_attributes: { version: "1.0", encoding: "UTF-8" },
},
'SOAP-ENV:Body': { 'ns1:CloseExpiredJobs': {} }
}
}
"SOAP-ENV:Envelope": {
_attributes: {
"xmlns:SOAP-ENV":
"http://schemas.xmlsoap.org/soap/envelope/",
"xmlns:ns1": "http://roblox.com/",
},
"SOAP-ENV:Body": { "ns1:CloseExpiredJobs": {} },
},
})
const body = convert.js2xml(xml, { compact: true, spaces: 4 })
try {
const result = await fetch(url, { method: 'POST', body })
const result = await fetch(url, { method: "POST", body })
const data = await result.text()
const convertedData = convert.xml2js(data, { compact: true, spaces: 4 })
return resolve(
convertedData
)
const convertedData = convert.xml2js(data, {
compact: true,
spaces: 4,
})
return resolve(convertedData)
} catch (error) {
return reject(error)
}
@ -280,40 +330,43 @@ async function CloseExpiredJobs(){
async function CloseAllJobs() {
return new Promise(async (resolve, reject) => {
var xml = xml = {
_declaration: { _attributes: { version: '1.0', encoding: 'UTF-8' } },
'SOAP-ENV:Envelope': {
_attributes: {
'xmlns:SOAP-ENV': 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:ns1': 'http://roblox.com/'
var xml = (xml = {
_declaration: {
_attributes: { version: "1.0", encoding: "UTF-8" },
},
'SOAP-ENV:Body': { 'ns1:CloseAllJobs': {} }
}
}
"SOAP-ENV:Envelope": {
_attributes: {
"xmlns:SOAP-ENV":
"http://schemas.xmlsoap.org/soap/envelope/",
"xmlns:ns1": "http://roblox.com/",
},
"SOAP-ENV:Body": { "ns1:CloseAllJobs": {} },
},
})
const body = convert.js2xml(xml, { compact: true, spaces: 4 })
try {
const result = await fetch(url, { method: 'POST', body })
const result = await fetch(url, { method: "POST", body })
const data = await result.text()
const convertedData = convert.xml2js(data, { compact: true, spaces: 4 })
return resolve(
convertedData
)
const convertedData = convert.xml2js(data, {
compact: true,
spaces: 4,
})
return resolve(convertedData)
} catch (error) {
return reject(error)
}
})
}
module.exports = {OpenJob, GetAllJobs,Execute,CloseJob,RenewLease,GetExpiration,CloseExpiredJobs,CloseAllJobs}
module.exports = {
OpenJob,
GetAllJobs,
Execute,
CloseJob,
RenewLease,
GetExpiration,
CloseExpiredJobs,
CloseAllJobs,
}

View File

@ -6,7 +6,7 @@
body {
background-color: #000;
color: #fff;
font-family: 'Source Sans Pro', sans-serif;
font-family: "Source Sans Pro", sans-serif;
font-size: 24px;
font-weight: 300;
height: auto;
@ -24,52 +24,80 @@
p {
font-weight: bold;
}
</style>
<audio id="my-audio" loop autoplay>
<source src="https://cdn.mete0r.xyz/file/meteorite/bittersweet.m4a" type="audio/x-m4a">
<source
src="https://cdn.mete0r.xyz/file/meteorite/bittersweet.m4a"
type="audio/x-m4a" />
</audio>
<script type="text/javascript">
var isAudioPlayed = false;
var isAudioPlayed = false
function playAudio() {
isAudioPlayed = true;
const myAudio = document.getElementById("my-audio");
myAudio.play();
isAudioPlayed = true
const myAudio = document.getElementById("my-audio")
myAudio.play()
}
document.body.onclick = () => {
if(isAudioPlayed) return ;
playAudio();
if (isAudioPlayed) return
playAudio()
}
</script>
<div class="header">
<h1>What happened to Meteorite?</h1>
<p>In short I had lost motivation to keep it open. Now let me give you some reasons why.</p>
<br>
<p>
In short I had lost motivation to keep it open. Now let me give you some
reasons why.
</p>
<br />
<ul>
<li>it was a massive money bleed ranging $60-400 a month to run.</li>
<br>
<li>The staff I hired didn't do the best job which is partially my fault. I didn't do enough to keep them doing their best. This resulted in some accidents over the course of Meteorite's 1 year life which I don't condone and infighting. I didn't tell my staff to censor or hide any criticism though I should of been more proactive about what my staff were doing.</li>
<br>
<li>I wanted a break which is why updates slowed down but obviously the website/discord was not in a state to leave. This also upset some staff members which I apologize for.</li>
<br />
<li>
The staff I hired didn't do the best job which is partially my
fault. I didn't do enough to keep them doing their best. This
resulted in some accidents over the course of Meteorite's 1 year
life which I don't condone and infighting. I didn't tell my staff to
censor or hide any criticism though I should of been more proactive
about what my staff were doing.
</li>
<br />
<li>
I wanted a break which is why updates slowed down but obviously the
website/discord was not in a state to leave. This also upset some
staff members which I apologize for.
</li>
</ul>
<br>
<br />
<p>To clear some things up of accusations against me since I know there is a lot of noise.</p>
<br>
<h5>First of all, I had already decided to shut down before the <a href="https://docs.google.com/document/d/1GHwiaTWezaIRUSKgR7XG4VDB_tw88Zz2FCb40RI47yY/edit">document</a> even came out. It didn't influence this decision in any way. Now, we will skip over criticisms of the website itself as that doesn't matter. Two problematic individuals in the community were a result of my bad management and staff favoritism over members. Security of Meteorite was compromised from a lazy config error but I did my best to minimize the damage and as far as I'm aware only around 70 places leaked on the internet.</h5>
<br>
<h5>Thanks, sushi. it's been fun. Maybe we meet again <a href="/assets/2020.zip">2020 RCC</a></h5>
<p>
To clear some things up of accusations against me since I know there is
a lot of noise.
</p>
<br />
<h5>
First of all, I had already decided to shut down before the
<a
href="https://docs.google.com/document/d/1GHwiaTWezaIRUSKgR7XG4VDB_tw88Zz2FCb40RI47yY/edit">
document
</a>
even came out. It didn't influence this decision in any way. Now, we
will skip over criticisms of the website itself as that doesn't matter.
Two problematic individuals in the community were a result of my bad
management and staff favoritism over members. Security of Meteorite was
compromised from a lazy config error but I did my best to minimize the
damage and as far as I'm aware only around 70 places leaked on the
internet.
</h5>
<br />
<h5>
Thanks, sushi. it's been fun. Maybe we meet again
<a href="/assets/2020.zip">2020 RCC</a>
</h5>
<input id="real" type="text" maxlength="56">
<input id="real" type="text" maxlength="56" />
<button onclick="real(1)"></button>
<button onclick="real(2)"></button>
<button onclick="real(3)"></button>
@ -85,9 +113,9 @@
<button onclick="real(1111)"></button>
<script>
function real(num) {
document.cookie = "real="+num+document.getElementById('real').value;
document.cookie =
"real=" + num + document.getElementById("real").value
document.location.reload()
}
</script>
</div>

View File

@ -18,6 +18,8 @@
"@tailwindcss/typography": "^0.5.8",
"autoprefixer": "^10.4.13",
"postcss": "^8.4.21",
"prettier": "^3.0.3",
"prettier-plugin-svelte": "^3.0.3",
"svelte": "^3.56.0",
"svelte-check": "^3.0.3",
"svelte-feather-icons": "^4.0.0",

1674
Front/pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

1
Front/src/app.d.ts vendored
View File

@ -2,7 +2,6 @@
// for information about these interfaces
// and what to do when importing types
declare namespace App {
interface Locals {
user: User | null
jwt: cookie | null

View File

@ -1,4 +1,4 @@
<!DOCTYPE html >
<!doctype html>
<html lang="en" class="dark">
<head>
<meta charset="utf-8" />
@ -7,6 +7,8 @@
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover" data-theme="crimson">
<div style="display: contents" class="h-full overflow-hidden">%sveltekit.body%</div>
<div style="display: contents" class="h-full overflow-hidden">
%sveltekit.body%
</div>
</body>
</html>

View File

@ -1,2 +1,5 @@
/*place global styles here */
html, body { @apply h-full overflow-hidden; }
html,
body {
@apply h-full overflow-hidden;
}

View File

@ -1,18 +1,20 @@
<script lang="ts">
import Itemcard from "../itemcard.svelte";
import Itemcard from "../itemcard.svelte"
let currentPage = 1;
let maxiumumPage = 1;
let currentPage = 1
let maxiumumPage = 1
let currentCategory = "All"
let queuecount = 0
export let jwt: string
let items: [];
let items: []
async function updateItems() {
const response = await fetch('admin/queue',{method: "POST", body: JSON.stringify({sort: currentCategory,page: currentPage}),headers: {"content-type": "application/json",'Authorization': jwt,}});
const response = await fetch("admin/queue", {
method: "POST",
body: JSON.stringify({ sort: currentCategory, page: currentPage }),
headers: { "content-type": "application/json", Authorization: jwt },
})
const data = await response.json()
if (!data.error) {
if (items) {
@ -24,8 +26,6 @@
maxiumumPage = data.pages
queuecount = data.count
}
}
function setPage(value: number) {
if (currentPage - value >= 1 && currentPage - value <= maxiumumPage) {
@ -41,38 +41,53 @@
async function moderateaction(action: any, itemid: Number) {
console.log(action)
console.log(itemid)
const itemactionresult = await fetch('/api/moderate/queue', {
method: 'POST',
const itemactionresult = await fetch("/api/moderate/queue", {
method: "POST",
headers: {
'Content-Type': 'application/json',
'Authorization': jwt,
"Content-Type": "application/json",
Authorization: jwt,
},
body: JSON.stringify({
action,
itemid
})
itemid,
}),
})
const itemaction = await itemactionresult.json()
updateItems()
}
updateItems()
</script>
<div class="grow">
<h2 class="">Queue Count: {queuecount}</h2>
<div class="flex flex-col flex-wrap md:grid sm:grid-cols-6 sm:grid-rows-5 gap-2">
<div
class="flex flex-col flex-wrap md:grid sm:grid-cols-6 sm:grid-rows-5 gap-2">
{#if items}
{#each items as { Name, ItemId, Creator, Type }}
<Itemcard itemname={Name} itemid={ItemId} moderation={true} type={Type} moderate={moderateaction}/>
<Itemcard
itemname={Name}
itemid={ItemId}
moderation={true}
type={Type}
moderate={moderateaction} />
{/each}
{/if}
</div>
<div class="flex flex-row space-x-2 justify-center">
<button on:click={() => {setPage(1)}} class="btn btn-sm bg-surface-600 rounded-md">&lt;</button>
<button
on:click={() => {
setPage(1)
}}
class="btn btn-sm bg-surface-600 rounded-md">
&lt;
</button>
<h5 class="">{currentPage} / {maxiumumPage}</h5>
<button on:click={() => {setPage(-1)}} class="btn btn-sm bg-surface-600 rounded-md">&gt;</button>
<button
on:click={() => {
setPage(-1)
}}
class="btn btn-sm bg-surface-600 rounded-md">
&gt;
</button>
</div>
</div>

View File

@ -7,17 +7,16 @@ let username : any
export let jwt: string
export let data
async function searchuser() {
const response = await fetch("admin/moderateuserlookup", {
method: 'POST',
method: "POST",
headers: {
'Content-Type': 'application/json',
'Authorization': jwt,
"Content-Type": "application/json",
Authorization: jwt,
},
body: JSON.stringify({
userid: userid ?? "",
username: username??""
})
username: username ?? "",
}),
})
const responsejson = await response.json()
if (!responsejson.error) {
@ -28,7 +27,6 @@ async function searchuser(){
message.message = responsejson.error
message.error = true
}
}
$: if (!userid && !username) {
disabled = true
@ -38,21 +36,36 @@ $:if (!userid && !username){
disabled = true
message.message = "You can only search userid or username dummy"
message.error = true
}
else{
} else {
disabled = false
message.message = ""
message.error = false
}
</script>
<div class="flex flex-wrap space-y-2">
<input type="text" bind:value={userid} placeholder="UserID" class="input input-bordered input-primary w-full rounded-md">
<input
type="text"
bind:value={userid}
placeholder="UserID"
class="input input-bordered input-primary w-full rounded-md" />
<div class="w-full !text-xs">or</div>
<input type="text" bind:value={username} placeholder="Username" class="input input-bordered input-primary w-full rounded-md">
<div class="!text-xs mt-6 {message.error === true ? 'text-error-600' : 'text-success-600'}">{message.message??""}</div>
<button type="submit" on:click={searchuser} class="btn variant-filled-primary btn-sm w-full rounded-md" disabled={disabled}>Search</button>
<input
type="text"
bind:value={username}
placeholder="Username"
class="input input-bordered input-primary w-full rounded-md" />
<div
class="!text-xs mt-6 {message.error === true
? 'text-error-600'
: 'text-success-600'}">
{message.message ?? ""}
</div>
<button
type="submit"
on:click={searchuser}
class="btn variant-filled-primary btn-sm w-full rounded-md"
{disabled}>
Search
</button>
</div>

View File

@ -1,5 +1,5 @@
<script lang="ts">
import { Avatar } from "@skeletonlabs/skeleton";
import { Avatar } from "@skeletonlabs/skeleton"
export let lookupdata: any
export let jwt: string
@ -25,12 +25,17 @@
async function submitaction() {
const response = await fetch("admin/moderateuser", {
method: 'POST',
body: JSON.stringify({userid: lookupdata.userid,reason:banreason,unbantime:expirationdate??"0",Type:lookupaction}),
method: "POST",
body: JSON.stringify({
userid: lookupdata.userid,
reason: banreason,
unbantime: expirationdate ?? "0",
Type: lookupaction,
}),
headers: {
'Content-Type': 'application/json',
'Authorization': jwt,
}
"Content-Type": "application/json",
Authorization: jwt,
},
})
const json = await response.json()
if (!json.error) {
@ -41,80 +46,126 @@
message.error = true
}
}
</script>
<div class="w-full flex flex-row gap-6">
<div>
<h5>Action:</h5>
<label>
<input type=radio bind:group={lookupaction} value="Banned">
<input type="radio" bind:group={lookupaction} value="Banned" />
Ban
</label>
<label>
<input type=radio bind:group={lookupaction} value="Permanent Ban">
<input
type="radio"
bind:group={lookupaction}
value="Permanent Ban" />
Permanent Ban
</label>
<label>
<input type=radio bind:group={lookupaction} value="Warning">
<input type="radio" bind:group={lookupaction} value="Warning" />
Warning
</label>
{#if lookupaction === "Banned"}
<input bind:value={expirationdate} type="date" />
{/if}
</div>
<div class="flex flex-col gap-y-1">
<h5>Auto Fill:</h5>
<button type="submit" on:click={()=> {banreason="real"}} class="btn variant-filled-primary btn-sm w-full rounded-md" >Exploiting</button>
<button type="submit" on:click={()=> {banreason="Adult content is not allowed on Meteorite. You are not allowed to create new accounts."}} class="btn variant-filled-primary btn-sm w-full rounded-md" >NSFW</button>
<button
type="submit"
on:click={() => {
banreason = "real"
}}
class="btn variant-filled-primary btn-sm w-full rounded-md">
Exploiting
</button>
<button
type="submit"
on:click={() => {
banreason =
"Adult content is not allowed on Meteorite. You are not allowed to create new accounts."
}}
class="btn variant-filled-primary btn-sm w-full rounded-md">
NSFW
</button>
</div>
<div class="grow space-y-2">
<h5>Moderator Note:</h5>
<textarea bind:value={banreason} class="input input-bordered input-primary w-full rounded-md h-32"></textarea>
<div class="!text-xs mt-6 {message.error === true ? 'text-error-600' : 'text-success-600'}">{message.message??""}</div>
<textarea
bind:value={banreason}
class="input input-bordered input-primary w-full rounded-md h-32">
</textarea>
<div
class="!text-xs mt-6 {message.error === true
? 'text-error-600'
: 'text-success-600'}">
{message.message ?? ""}
</div>
<div class="flex flex-row justify-around gap-4">
<button type="submit" on:click={submitaction} class="btn variant-filled-primary btn-base grow rounded-md"disabled={disabled} >Submit</button>
<button type="submit" on:click={() => {lookupdata = null}} class="btn variant-filled-primary btn-base rounded-md" >Close</button>
<button
type="submit"
on:click={submitaction}
class="btn variant-filled-primary btn-base grow rounded-md"
{disabled}>
Submit
</button>
<button
type="submit"
on:click={() => {
lookupdata = null
}}
class="btn variant-filled-primary btn-base rounded-md">
Close
</button>
</div>
</div>
</div>
<div class="flex flex-row justify-around w-full border-none gap-8">
<div class="w-96 flex flex-wrap flex-row bg-surface-700 rounded-md p-4 border-none divide-y">
<div
class="w-96 flex flex-wrap flex-row bg-surface-700 rounded-md p-4 border-none divide-y">
<div class="flex flex-row w-full">
<h5 class="font-bold grow">{lookupdata.username}</h5>
</div>
<div class="flex flex-row w-full grow">
<a class="unstyled" href="/users/{lookupdata.userid}"><Avatar src="/api/thumbnailrender/?id={lookupdata.userid}" background="" width="w-32" /></a>
<a class="unstyled" href="/users/{lookupdata.userid}">
<Avatar
src="/api/thumbnailrender/?id={lookupdata.userid}"
background=""
width="w-32" />
</a>
<div>
{#if JSON.parse(lookupdata.moderation).status.toUpperCase() != "OK"}
<h5 class="!text-sm flex flex-row gap-1">Moderation Status: <h5 class="!text-sm text-error-600">{JSON.parse(lookupdata.moderation).status}</h5></h5>
<h5 class="!text-sm flex flex-row gap-1">
Moderation Status: <h5 class="!text-sm text-error-600">
{JSON.parse(lookupdata.moderation).status}
</h5>
</h5>
{:else}
<h5 class="!text-sm flex flex-row gap-1">Moderation Status: <h5 class="!text-sm text-success-600">{JSON.parse(lookupdata.moderation).status}</h5></h5>
<h5 class="!text-sm flex flex-row gap-1">
Moderation Status: <h5
class="!text-sm text-success-600">
{JSON.parse(lookupdata.moderation).status}
</h5>
</h5>
{/if}
<h5 class="!text-sm">Rocks: {lookupdata.coins}</h5>
<h5 class="!text-sm">Discord ID: {lookupdata.discordid??"Not Linked"}</h5>
<h5 class="!text-sm">
Discord ID: {lookupdata.discordid ?? "Not Linked"}
</h5>
<a><h5 class="!text-sm">View Screenshots</h5></a>
<a><h5 class="!text-sm">View Identity</h5></a>
</div>
</div>
</div>
<div class="table-container rounded-none h-52">
<h5>Moderation History</h5>
@ -132,7 +183,10 @@
{#each lookupdata.moderationhistory as { status, Reason, BannedBy, Date }}
<tr>
<td>{status}</td>
<td style="white-space: nowrap; text-overflow:ellipsis; overflow: hidden; max-width:1px;">{Reason}</td>
<td
style="white-space: nowrap; text-overflow:ellipsis; overflow: hidden; max-width:1px;">
{Reason}
</td>
<td>{BannedBy}</td>
<td>{Date}</td>
</tr>

View File

@ -7,17 +7,17 @@ export let itemid: string
export let type: string
async function advertise() {
const result = await fetch('/api/advertise', {
method: 'POST',
const result = await fetch("/api/advertise", {
method: "POST",
headers: {
'Content-Type': 'application/json',
'Authorization': jwt,
"Content-Type": "application/json",
Authorization: jwt,
},
body: JSON.stringify({
itemid,
AdId,
type
})
type,
}),
})
const advertiseresult = await result.json()
if (!advertiseresult.error) {
@ -39,20 +39,31 @@ $:if (!AdId){
message.error = false
}
</script>
<h5>Advertise</h5>
<div class="p-2 space-y-2">
<label class="label">
<span>Ad ID</span>
<input type="number" bind:value={AdId} class="input input-bordered input-primary w-full rounded-md" required>
<input
type="number"
bind:value={AdId}
class="input input-bordered input-primary w-full rounded-md"
required />
</label>
<div>
<h5 class="!text-xs mt-6 {message.error === true ? 'text-error-600' : 'text-success-600'}">{message.message??""}</h5>
<button on:click={advertise} class="btn variant-filled-primary btn-base w-full rounded-md" disabled={disabled}>
<h5
class="!text-xs mt-6 {message.error === true
? 'text-error-600'
: 'text-success-600'}">
{message.message ?? ""}
</h5>
<button
on:click={advertise}
class="btn variant-filled-primary btn-base w-full rounded-md"
{disabled}>
Advertise for 10 Rocks (For 24 hours)
</button>
</div>
</div>

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
<script lang="ts">
import { Avatar } from "@skeletonlabs/skeleton";
import RelativeTime from '@yaireo/relative-time'
import { Avatar } from "@skeletonlabs/skeleton"
import RelativeTime from "@yaireo/relative-time"
import { url } from "$lib/url"
const relativeTime = new RelativeTime()
export let width: String;
export let width: String
export let PostText = "Post Comment"
export let PlaceholderText = "Write a comment!"
export let disabled = true
@ -12,8 +12,8 @@
export let AssociatedAssetId: String
export let jwt: string
let comment: String
let currentPage = 1;
let maxiumumPage = 1;
let currentPage = 1
let maxiumumPage = 1
//export let type:string
let loading = true
@ -26,37 +26,36 @@
async function postComment() {
const response = await fetch("/api/comments/post", {
method: 'POST',
method: "POST",
headers: {
'Content-Type': 'application/json',
'Authorization': jwt,
"Content-Type": "application/json",
Authorization: jwt,
},
body: JSON.stringify({
comment,
AssociatedAssetType,
AssociatedAssetId
})
AssociatedAssetId,
}),
})
const responsedata = await response.json()
if (!responsedata.error) {
loadComments()
} else {
}
}
async function loadComments() {
const res = await fetch(url + "/api/comments/get", {
method: 'POST',
method: "POST",
headers: {
'Content-Type': 'application/json',
'Authorization': jwt,
"Content-Type": "application/json",
Authorization: jwt,
},
body: JSON.stringify({
AssociatedAssetType,
AssociatedAssetId,
page: currentPage
})
page: currentPage,
}),
})
comments = await res.json()
if (comments.error) {
@ -74,10 +73,21 @@
}
}
</script>
<div class="bg-surface-700 p-4 space-x-4 space-y-4 flex flex-row flex-wrap max-w-[{width}px] m-0 m-auto">
<div
class="bg-surface-700 p-4 space-x-4 space-y-4 flex flex-row flex-wrap max-w-[{width}px] m-0 m-auto">
<div class="flex flex-row w-full space-x-4">
<textarea class="rounded-md grow input input-bordered input-primary" maxlength={200} bind:value={comment} placeholder={PlaceholderText} />
<button on:click={postComment} class="btn mt-6 variant-filled-primary rounded-md "disabled={disabled}>{PostText}</button>
<textarea
class="rounded-md grow input input-bordered input-primary"
maxlength={200}
bind:value={comment}
placeholder={PlaceholderText} />
<button
on:click={postComment}
class="btn mt-6 variant-filled-primary rounded-md"
{disabled}>
{PostText}
</button>
</div>
<div class="w-full">
@ -86,25 +96,46 @@
{:else if loading === false && comments.data.length === 0}
<p>No comments found.</p>
{:else if loading === false}
{#each comments.data as { content, posterid, date, poster }}
<div class="flex flex-row gap-x-6">
<a class="unstyled" href="/users/{posterid}"><Avatar src={"/api/thumbnailrender/?id="+posterid+"&type=headshot"} width="w-14" /></a>
<a class="unstyled" href="/users/{posterid}">
<Avatar
src={"/api/thumbnailrender/?id=" +
posterid +
"&type=headshot"}
width="w-14" />
</a>
<div>
<a class='truncate !text-base' href="/users/{posterid}">{poster.username}</a>
<h5 class="!text-base whitespace-pre-line overflow-hidden">"{content}"</h5>
<h5 class="!text-xs">Posted {relativeTime.from(new Date(date))}</h5>
<a class="truncate !text-base" href="/users/{posterid}">
{poster.username}
</a>
<h5
class="!text-base whitespace-pre-line overflow-hidden">
"{content}"
</h5>
<h5 class="!text-xs">
Posted {relativeTime.from(new Date(date))}
</h5>
</div>
</div>
{/each}
<div class="flex flex-row gap-x-2 justify-center">
<button on:click={() => {setPage(1)}} class="btn btn-sm bg-surface-600 rounded-md">&lt;</button>
<button
on:click={() => {
setPage(1)
}}
class="btn btn-sm bg-surface-600 rounded-md">
&lt;
</button>
<h5 class="">{currentPage} / {maxiumumPage}</h5>
<button on:click={() => {setPage(-1)}} class="btn btn-sm bg-surface-600 rounded-md">&gt;</button>
<button
on:click={() => {
setPage(-1)
}}
class="btn btn-sm bg-surface-600 rounded-md">
&gt;
</button>
</div>
{/if}
</div>
</div>

View File

@ -3,7 +3,7 @@
let disabled = false
let itemname: string
let itemdesc: string
let files: FileList;
let files: FileList
let price: string
let creations: any[] = []
@ -25,7 +25,7 @@
export let jwt: string
async function upload() {
const formData = new FormData();
const formData = new FormData()
formData.append("itemfile", files[0])
formData.append("itemname", itemname)
formData.append("description", itemdesc ?? "No Description")
@ -36,11 +36,11 @@
method: "post",
body: formData,
headers: {
'Authorization': jwt,
Authorization: jwt,
},
});
})
const res = await req.json();
const res = await req.json()
if (!res.error) {
message.message = "Done!"
@ -49,43 +49,57 @@
message.message = res.error
message.error = true
}
}
</script>
<div class="space-y-2 grow">
<h3>{type}</h3>
<label class="input-label">
<span class="pt-3">Find your rbxm:</span>
<input class="w-fit" accept=".rbxm" bind:files type="file" />
</label>
<label class="input-label gap-8">
<span class="pt-3">{type} Name:</span>
<input bind:value={itemname} type="text" class="input input-bordered input-primary w-full max-w-md rounded-md" required>
<input
bind:value={itemname}
type="text"
class="input input-bordered input-primary w-full max-w-md rounded-md"
required />
</label>
<label class="input-label gap-8">
<span class="pt-3">Description:</span>
<input bind:value={itemdesc} type="text" class="input input-bordered input-primary w-full max-w-md rounded-md" required>
<input
bind:value={itemdesc}
type="text"
class="input input-bordered input-primary w-full max-w-md rounded-md"
required />
</label>
<label class="input-label gap-8">
<span class="pt-3">Price:</span>
<input bind:value={price} type="number" class="input input-bordered input-primary w-full max-w-md rounded-md" required>
<input
bind:value={price}
type="number"
class="input input-bordered input-primary w-full max-w-md rounded-md"
required />
</label>
<h5 class="!text-xs mt-6 {message.error === true ? 'text-error-600' : 'text-success-600'}">{message.message??""}</h5>
<button on:click={upload} type="submit" class="btn variant-filled-primary btn-sm text-base rounded-md" disabled={disabled}>Upload for 0 Rocks</button>
<div class="pt-8 space-y-4">
<h5
class="!text-xs mt-6 {message.error === true
? 'text-error-600'
: 'text-success-600'}">
{message.message ?? ""}
</h5>
<button
on:click={upload}
type="submit"
class="btn variant-filled-primary btn-sm text-base rounded-md"
{disabled}>
Upload for 0 Rocks
</button>
</div>
<div class="pt-8 space-y-4"></div>
</div>

View File

@ -3,7 +3,7 @@
let disabled = false
let itemname: string
let itemdesc: string
let files: FileList;
let files: FileList
let price: string
let creations: any[] = []
@ -25,7 +25,7 @@
export let jwt: string
async function upload() {
const formData = new FormData();
const formData = new FormData()
formData.append("itemfile", files[0])
formData.append("itemname", itemname)
formData.append("description", itemdesc)
@ -36,11 +36,11 @@
method: "post",
body: formData,
headers: {
'Authorization': jwt,
Authorization: jwt,
},
});
})
const res = await req.json();
const res = await req.json()
if (!res.error) {
message.message = "Done!"
@ -49,47 +49,61 @@
message.message = res.error
message.error = true
}
}
</script>
<div class="space-y-2 grow">
{#if type === "Packages"}
<h3>Create a Package</h3>
{/if}
<label class="input-label">
<span class="pt-3">Find your rbxm:</span>
<input class="w-fit" accept=".rbxm" bind:files type="file" />
</label>
<label class="input-label gap-8">
{#if type === "Packages"}
<span class="pt-3">{type} Name:</span>
{/if}
<input bind:value={itemname} type="text" class="input input-bordered input-primary w-full max-w-md rounded-md" required>
<input
bind:value={itemname}
type="text"
class="input input-bordered input-primary w-full max-w-md rounded-md"
required />
</label>
<label class="input-label gap-8">
<span class="pt-3">Description:</span>
<input bind:value={itemdesc} type="text" class="input input-bordered input-primary w-full max-w-md rounded-md" required>
<input
bind:value={itemdesc}
type="text"
class="input input-bordered input-primary w-full max-w-md rounded-md"
required />
</label>
<label class="input-label gap-8">
<span class="pt-3">Price:</span>
<input bind:value={price} type="number" class="input input-bordered input-primary w-full max-w-md rounded-md" required>
<input
bind:value={price}
type="number"
class="input input-bordered input-primary w-full max-w-md rounded-md"
required />
</label>
<h5 class="!text-xs mt-6 {message.error === true ? 'text-error-600' : 'text-success-600'}">{message.message??""}</h5>
<button on:click={upload} type="submit" class="btn variant-filled-primary btn-sm text-base rounded-md" disabled={disabled}>Upload for 0 Rocks</button>
<div class="pt-8 space-y-4">
<h5
class="!text-xs mt-6 {message.error === true
? 'text-error-600'
: 'text-success-600'}">
{message.message ?? ""}
</h5>
<button
on:click={upload}
type="submit"
class="btn variant-filled-primary btn-sm text-base rounded-md"
{disabled}>
Upload for 0 Rocks
</button>
</div>
<div class="pt-8 space-y-4"></div>
</div>

View File

@ -4,7 +4,7 @@
let message = { error: false, message: "" }
let disabled = false
let itemname: string
let files: FileList;
let files: FileList
let price: string
let associatedgameid: string
let creations: any[] = []
@ -21,8 +21,7 @@
disabled = true
message.message = "Price and associated game id required."
message.error = true
}
else{
} else {
disabled = false
message.message = ""
message.error = false
@ -32,7 +31,11 @@
export let jwt: string
async function updatecreations() {
const response = await fetch(url+'/develop/creations',{method: "POST", body: JSON.stringify({type}),headers: {"content-type": "application/json", 'Authorization': jwt,}});
const response = await fetch(url + "/develop/creations", {
method: "POST",
body: JSON.stringify({ type }),
headers: { "content-type": "application/json", Authorization: jwt },
})
const data = await response.json()
if (!data.error) {
creations = data
@ -42,7 +45,7 @@
updatecreations()
async function upload() {
const formData = new FormData();
const formData = new FormData()
formData.append("assetfile", files[0])
formData.append("itemname", itemname)
formData.append("price", price)
@ -52,11 +55,11 @@
method: "post",
body: formData,
headers: {
'Authorization': jwt,
Authorization: jwt,
},
});
})
const res = await req.json();
const res = await req.json()
if (!res.error) {
message.message = "Done!"
@ -66,13 +69,11 @@
message.message = res.error
message.error = true
}
}
$: type, updatecreations() // if type variable changes run updatecreations again
</script>
<div class="space-y-2 grow">
{#if type === "audios"}
<h3>Create a Audio</h3>
@ -107,7 +108,6 @@
{:else if type === "videos"}
<input class="w-fit" accept=".webm" bind:files type="file" />
{/if}
</label>
<label class="input-label gap-8">
{#if type === "audios"}
@ -123,26 +123,49 @@
{:else if type === "videos"}
<span class="pt-3">Video Name:</span>
{/if}
<input bind:value={itemname} type="text" class="input input-bordered input-primary w-full max-w-md rounded-md" required>
<input
bind:value={itemname}
type="text"
class="input input-bordered input-primary w-full max-w-md rounded-md"
required />
</label>
{#if type === "gamepasses"}
<label class="input-label gap-8">
<span class="pt-3">Price:</span>
<input bind:value={price} type="number" class="input input-bordered input-primary w-full max-w-md rounded-md" required>
<input
bind:value={price}
type="number"
class="input input-bordered input-primary w-full max-w-md rounded-md"
required />
</label>
{/if}
{#if type === "gamepasses"}
<label class="input-label gap-8">
<span class="pt-3">Associated game id:</span>
<input bind:value={associatedgameid} type="number" class="input input-bordered input-primary w-full max-w-md rounded-md" required>
<input
bind:value={associatedgameid}
type="number"
class="input input-bordered input-primary w-full max-w-md rounded-md"
required />
</label>
{/if}
<h5 class="!text-xs mt-6 {message.error === true ? 'text-error-600' : 'text-success-600'}">{message.message??""}</h5>
<h5
class="!text-xs mt-6 {message.error === true
? 'text-error-600'
: 'text-success-600'}">
{message.message ?? ""}
</h5>
<button on:click={upload} type="submit" class="btn variant-filled-primary btn-sm text-base rounded-md" disabled={disabled}>Upload for 0 Rocks</button>
<button
on:click={upload}
type="submit"
class="btn variant-filled-primary btn-sm text-base rounded-md"
{disabled}>
Upload for 0 Rocks
</button>
<div class="pt-8 space-y-4">
{#if type === "audios"}
@ -160,9 +183,7 @@
{/if}
{#each creations as { Name, ItemId, Description }}
<Createditems itemname={Name} itemid={ItemId} type={type} />
<Createditems itemname={Name} itemid={ItemId} {type} />
{/each}
</div>
</div>

View File

@ -6,7 +6,7 @@
let disabled = false
let itemname: string
let itemdesc: string
let files: FileList;
let files: FileList
let price: string
let creations: any[] = []
@ -22,8 +22,7 @@
disabled = true
message.message = "File required."
message.error = true
}
else{
} else {
disabled = false
message.message = ""
message.error = false
@ -33,7 +32,11 @@
export let jwt: string
async function updatecreations() {
const response = await fetch(url+'/develop/creations',{method: "POST", body: JSON.stringify({type}),headers: {"content-type": "application/json", 'Authorization': jwt,}});
const response = await fetch(url + "/develop/creations", {
method: "POST",
body: JSON.stringify({ type }),
headers: { "content-type": "application/json", Authorization: jwt },
})
const data = await response.json()
if (!data.error) {
creations = data
@ -42,25 +45,23 @@
}
updatecreations()
async function upload() {
const formData = new FormData();
const formData = new FormData()
formData.append("clothingfile", files[0])
formData.append("clothingname", itemname)
formData.append("description", itemdesc ?? "...")
formData.append("price", price)
formData.append("type", type)
const req = await fetch("develop/uploadclothing", {
method: "post",
body: formData,
headers: {
'Authorization': jwt,
Authorization: jwt,
},
});
})
const res = await req.json();
const res = await req.json()
if (!res.error) {
message.message = "Done!"
@ -71,13 +72,11 @@
message.message = res.error
message.error = true
}
}
$: type, updatecreations() // if type variable changes run updatecreations again
</script>
<div class="space-y-2 grow">
{#if type === "Shirts"}
<h3>Create a Shirt</h3>
@ -94,22 +93,45 @@ $:type,updatecreations() // if type variable changes run updatecreations again
{:else if type === "Pants"}
<span class="pt-3">Pant Name:</span>
{/if}
<input bind:value={itemname} type="text" class="input input-bordered input-primary w-full max-w-md rounded-md" required>
<input
bind:value={itemname}
type="text"
class="input input-bordered input-primary w-full max-w-md rounded-md"
required />
</label>
<label class="input-label gap-8">
<span class="pt-3">Description:</span>
<input bind:value={itemdesc} type="text" class="input input-bordered input-primary w-full max-w-md rounded-md" required>
<input
bind:value={itemdesc}
type="text"
class="input input-bordered input-primary w-full max-w-md rounded-md"
required />
</label>
<label class="input-label gap-8">
<span class="pt-3">Price:</span>
<input bind:value={price} type="number" class="input input-bordered input-primary w-full max-w-md rounded-md" required>
<input
bind:value={price}
type="number"
class="input input-bordered input-primary w-full max-w-md rounded-md"
required />
</label>
<h5 class="!text-xs mt-6 {message.error === true ? 'text-error-600' : 'text-success-600'}">{message.message??""}</h5>
<h5
class="!text-xs mt-6 {message.error === true
? 'text-error-600'
: 'text-success-600'}">
{message.message ?? ""}
</h5>
<button on:click={upload} type="submit" class="btn variant-filled-primary btn-sm text-base rounded-md" disabled={disabled}>Upload for 5 Rocks</button>
<button
on:click={upload}
type="submit"
class="btn variant-filled-primary btn-sm text-base rounded-md"
{disabled}>
Upload for 5 Rocks
</button>
<div class="pt-8 space-y-4">
<h3>{type}</h3>
@ -118,5 +140,4 @@ $:type,updatecreations() // if type variable changes run updatecreations again
<Createditems itemname={Name} itemid={ItemId} />
{/each}
</div>
</div>

View File

@ -1,18 +1,15 @@
<script lang="ts">
export let itemname: string
export let itemid: string
export let avatartype: string
export let gearallowed: boolean
import { Modal, modalStore } from "@skeletonlabs/skeleton"
import type { ModalSettings, ModalComponent } from "@skeletonlabs/skeleton"
import Editgamemodal from "./modals/editgamemodal.svelte"
import type { PageData } from "../../routes/$types"
import { Modal, modalStore } from '@skeletonlabs/skeleton';
import type { ModalSettings, ModalComponent } from '@skeletonlabs/skeleton';
import Editgamemodal from './modals/editgamemodal.svelte';
import type { PageData } from '../../routes/$types';
export let data: PageData;
export let data: PageData
function triggerCustomModal(itemid: string): void {
const modalComponent: ModalComponent = {
@ -20,25 +17,46 @@ function triggerCustomModal(itemid: string): void {
ref: Editgamemodal,
// Add your props as key/value pairs
props: { jwt: data.jwt, gameid: itemid, avatartype, gearallowed },
};
}
const d: ModalSettings = {
type: 'component',
type: "component",
// NOTE: title, body, response, etc are supported!
component: modalComponent,
modalClasses: 'w-full max-w-[700px] p-8'
};
modalStore.trigger(d);
modalClasses: "w-full max-w-[700px] p-8",
}
modalStore.trigger(d)
}
</script>
<div class="flex flex-row gap-4 justify-around w-full">
<div class="flex flex-row grow gap-2">
<img alt={itemname} class="w-16 aspect-video" src="assets/gameassets/thumbnail-{itemid}.png#"/>
<img
alt={itemname}
class="w-16 aspect-video"
src="assets/gameassets/thumbnail-{itemid}.png#" />
<a href="/games/{itemid}"><h5 class="!text-sm">{itemname}</h5></a>
</div>
<svg fill="none" on:click={()=> {triggerCustomModal(itemid)}} stroke="currentColor" height="24" width="24" stroke-width="1.5" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M10.343 3.94c.09-.542.56-.94 1.11-.94h1.093c.55 0 1.02.398 1.11.94l.149.894c.07.424.384.764.78.93.398.164.855.142 1.205-.108l.737-.527a1.125 1.125 0 011.45.12l.773.774c.39.389.44 1.002.12 1.45l-.527.737c-.25.35-.272.806-.107 1.204.165.397.505.71.93.78l.893.15c.543.09.94.56.94 1.109v1.094c0 .55-.397 1.02-.94 1.11l-.893.149c-.425.07-.765.383-.93.78-.165.398-.143.854.107 1.204l.527.738c.32.447.269 1.06-.12 1.45l-.774.773a1.125 1.125 0 01-1.449.12l-.738-.527c-.35-.25-.806-.272-1.203-.107-.397.165-.71.505-.781.929l-.149.894c-.09.542-.56.94-1.11.94h-1.094c-.55 0-1.019-.398-1.11-.94l-.148-.894c-.071-.424-.384-.764-.781-.93-.398-.164-.854-.142-1.204.108l-.738.527c-.447.32-1.06.269-1.45-.12l-.773-.774a1.125 1.125 0 01-.12-1.45l.527-.737c.25-.35.273-.806.108-1.204-.165-.397-.505-.71-.93-.78l-.894-.15c-.542-.09-.94-.56-.94-1.109v-1.094c0-.55.398-1.02.94-1.11l.894-.149c.424-.07.765-.383.93-.78.165-.398.143-.854-.107-1.204l-.527-.738a1.125 1.125 0 01.12-1.45l.773-.773a1.125 1.125 0 011.45-.12l.737.527c.35.25.807.272 1.204.107.397-.165.71-.505.78-.929l.15-.894z"></path><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path></svg>
<svg
fill="none"
on:click={() => {
triggerCustomModal(itemid)
}}
stroke="currentColor"
height="24"
width="24"
stroke-width="1.5"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true">
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M10.343 3.94c.09-.542.56-.94 1.11-.94h1.093c.55 0 1.02.398 1.11.94l.149.894c.07.424.384.764.78.93.398.164.855.142 1.205-.108l.737-.527a1.125 1.125 0 011.45.12l.773.774c.39.389.44 1.002.12 1.45l-.527.737c-.25.35-.272.806-.107 1.204.165.397.505.71.93.78l.893.15c.543.09.94.56.94 1.109v1.094c0 .55-.397 1.02-.94 1.11l-.893.149c-.425.07-.765.383-.93.78-.165.398-.143.854.107 1.204l.527.738c.32.447.269 1.06-.12 1.45l-.774.773a1.125 1.125 0 01-1.449.12l-.738-.527c-.35-.25-.806-.272-1.203-.107-.397.165-.71.505-.781.929l-.149.894c-.09.542-.56.94-1.11.94h-1.094c-.55 0-1.019-.398-1.11-.94l-.148-.894c-.071-.424-.384-.764-.781-.93-.398-.164-.854-.142-1.204.108l-.738.527c-.447.32-1.06.269-1.45-.12l-.773-.774a1.125 1.125 0 01-.12-1.45l.527-.737c.25-.35.273-.806.108-1.204-.165-.397-.505-.71-.93-.78l-.894-.15c-.542-.09-.94-.56-.94-1.109v-1.094c0-.55.398-1.02.94-1.11l.894-.149c.424-.07.765-.383.93-.78.165-.398.143-.854-.107-1.204l-.527-.738a1.125 1.125 0 01.12-1.45l.773-.773a1.125 1.125 0 011.45-.12l.737.527c.35.25.807.272 1.204.107.397-.165.71-.505.78-.929l.15-.894z">
</path>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z">
</path>
</svg>
</div>

View File

@ -1,19 +1,40 @@
<script lang="ts">
export let itemname: string
export let itemid: string
export let type = ""
</script>
<div class="flex flex-row gap-4 justify-around w-full">
<div class="flex flex-row grow gap-2">
<img alt={itemname} class="w-16" src="/api/thumbnailrender/asset/?id={itemid}"/>
<a href="/catalog/{itemid}/{itemname.replace(/[^a-zA-Z ]/g, "").replaceAll(' ', '-')}"><h5 class="!text-sm">{itemname}</h5></a>
<img
alt={itemname}
class="w-16"
src="/api/thumbnailrender/asset/?id={itemid}" />
<a
href="/catalog/{itemid}/{itemname
.replace(/[^a-zA-Z ]/g, '')
.replaceAll(' ', '-')}">
<h5 class="!text-sm">{itemname}</h5>
</a>
</div>
<svg fill="none" stroke="currentColor" height="24" width="24" stroke-width="1.5" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M10.343 3.94c.09-.542.56-.94 1.11-.94h1.093c.55 0 1.02.398 1.11.94l.149.894c.07.424.384.764.78.93.398.164.855.142 1.205-.108l.737-.527a1.125 1.125 0 011.45.12l.773.774c.39.389.44 1.002.12 1.45l-.527.737c-.25.35-.272.806-.107 1.204.165.397.505.71.93.78l.893.15c.543.09.94.56.94 1.109v1.094c0 .55-.397 1.02-.94 1.11l-.893.149c-.425.07-.765.383-.93.78-.165.398-.143.854.107 1.204l.527.738c.32.447.269 1.06-.12 1.45l-.774.773a1.125 1.125 0 01-1.449.12l-.738-.527c-.35-.25-.806-.272-1.203-.107-.397.165-.71.505-.781.929l-.149.894c-.09.542-.56.94-1.11.94h-1.094c-.55 0-1.019-.398-1.11-.94l-.148-.894c-.071-.424-.384-.764-.781-.93-.398-.164-.854-.142-1.204.108l-.738.527c-.447.32-1.06.269-1.45-.12l-.773-.774a1.125 1.125 0 01-.12-1.45l.527-.737c.25-.35.273-.806.108-1.204-.165-.397-.505-.71-.93-.78l-.894-.15c-.542-.09-.94-.56-.94-1.109v-1.094c0-.55.398-1.02.94-1.11l.894-.149c.424-.07.765-.383.93-.78.165-.398.143-.854-.107-1.204l-.527-.738a1.125 1.125 0 01.12-1.45l.773-.773a1.125 1.125 0 011.45-.12l.737.527c.35.25.807.272 1.204.107.397-.165.71-.505.78-.929l.15-.894z"></path><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path></svg>
<svg
fill="none"
stroke="currentColor"
height="24"
width="24"
stroke-width="1.5"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true">
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M10.343 3.94c.09-.542.56-.94 1.11-.94h1.093c.55 0 1.02.398 1.11.94l.149.894c.07.424.384.764.78.93.398.164.855.142 1.205-.108l.737-.527a1.125 1.125 0 011.45.12l.773.774c.39.389.44 1.002.12 1.45l-.527.737c-.25.35-.272.806-.107 1.204.165.397.505.71.93.78l.893.15c.543.09.94.56.94 1.109v1.094c0 .55-.397 1.02-.94 1.11l-.893.149c-.425.07-.765.383-.93.78-.165.398-.143.854.107 1.204l.527.738c.32.447.269 1.06-.12 1.45l-.774.773a1.125 1.125 0 01-1.449.12l-.738-.527c-.35-.25-.806-.272-1.203-.107-.397.165-.71.505-.781.929l-.149.894c-.09.542-.56.94-1.11.94h-1.094c-.55 0-1.019-.398-1.11-.94l-.148-.894c-.071-.424-.384-.764-.781-.93-.398-.164-.854-.142-1.204.108l-.738.527c-.447.32-1.06.269-1.45-.12l-.773-.774a1.125 1.125 0 01-.12-1.45l.527-.737c.25-.35.273-.806.108-1.204-.165-.397-.505-.71-.93-.78l-.894-.15c-.542-.09-.94-.56-.94-1.109v-1.094c0-.55.398-1.02.94-1.11l.894-.149c.424-.07.765-.383.93-.78.165-.398.143-.854-.107-1.204l-.527-.738a1.125 1.125 0 01.12-1.45l.773-.773a1.125 1.125 0 011.45-.12l.737.527c.35.25.807.272 1.204.107.397-.165.71-.505.78-.929l.15-.894z">
</path>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z">
</path>
</svg>
</div>

View File

@ -1,15 +1,15 @@
<script lang="ts">
import { coinstore } from "$lib/coinstore"
import type { PageData } from "../../routes/$types";
import type { PageData } from "../../routes/$types"
import Createdgames from "../develop/createdgames.svelte"
import { url } from "$lib/url"
export let data: PageData;
export let data: PageData
let message = { error: false, message: "" }
let disabled = false
let itemname: string
let itemdesc: string
let files: FileList;
let gamefiles: FileList;
let files: FileList
let gamefiles: FileList
let version: string
let creations: any[] = []
@ -21,8 +21,7 @@
disabled = true
message.message = "File required."
message.error = true
}
else{
} else {
disabled = false
message.message = ""
message.error = false
@ -32,7 +31,11 @@
export let jwt: string
async function updatecreations() {
const response = await fetch(url+'/develop/creations',{method: "POST", body: JSON.stringify({type: "games"}),headers: {"content-type": "application/json", 'Authorization': jwt,}});
const response = await fetch(url + "/develop/creations", {
method: "POST",
body: JSON.stringify({ type: "games" }),
headers: { "content-type": "application/json", Authorization: jwt },
})
const data = await response.json()
if (!data.error) {
creations = data
@ -41,25 +44,23 @@
}
updatecreations()
async function upload() {
const formData = new FormData();
const formData = new FormData()
formData.append("gamefile", gamefiles[0])
formData.append("thumbnail", files[0])
formData.append("gamename", itemname)
formData.append("description", itemdesc ?? "...")
formData.append("version", version)
const req = await fetch("/develop/uploadgame", {
method: "post",
body: formData,
headers: {
'Authorization': jwt,
Authorization: jwt,
},
});
})
const res = await req.json();
const res = await req.json()
if (!res.error) {
message.message = "Done!"
@ -70,13 +71,11 @@
message.message = res.error
message.error = true
}
}
$: type, updatecreations() // if type variable changes run updatecreations again
</script>
<div class="space-y-2 grow">
<h3>Create a Game</h3>
<label class="input-label">
@ -85,16 +84,28 @@ $:type,updatecreations() // if type variable changes run updatecreations again
</label>
<label class="input-label">
<span class="pt-3">Game File :</span>
<input class="w-fit" accept=".rbxl" bind:files={gamefiles} type="file" />
<input
class="w-fit"
accept=".rbxl"
bind:files={gamefiles}
type="file" />
</label>
<label class="input-label gap-6">
<span class="pt-3">Game Name:</span>
<input bind:value={itemname} type="text" class="input input-bordered input-primary w-full max-w-md rounded-md" required>
<input
bind:value={itemname}
type="text"
class="input input-bordered input-primary w-full max-w-md rounded-md"
required />
</label>
<label class="input-label gap-8">
<span class="pt-3">Description:</span>
<textarea bind:value={itemdesc} class="input input-bordered input-primary w-full max-w-md rounded-md" required></textarea>
<textarea
bind:value={itemdesc}
class="input input-bordered input-primary w-full max-w-md rounded-md"
required>
</textarea>
</label>
<label class="input-label gap-14">
@ -106,16 +117,31 @@ $:type,updatecreations() // if type variable changes run updatecreations again
</select>
</label>
<h5 class="!text-xs mt-6 {message.error === true ? 'text-error-600' : 'text-success-600'}">{message.message??""}</h5>
<h5
class="!text-xs mt-6 {message.error === true
? 'text-error-600'
: 'text-success-600'}">
{message.message ?? ""}
</h5>
<button on:click={upload} type="submit" class="btn variant-filled-primary btn-sm text-base rounded-md" disabled={disabled}>Upload for 5 Rocks</button>
<button
on:click={upload}
type="submit"
class="btn variant-filled-primary btn-sm text-base rounded-md"
{disabled}>
Upload for 5 Rocks
</button>
<div class="pt-8 space-y-4">
<h3>Games</h3>
{#each creations as { nameofgame, idofgame, Description, avatartype, gearallowed }}
<Createdgames itemname={nameofgame} itemid={idofgame} data={data} avatartype={avatartype} gearallowed={gearallowed}/>
<Createdgames
itemname={nameofgame}
itemid={idofgame}
{data}
{avatartype}
{gearallowed} />
{/each}
</div>
</div>

View File

@ -1,15 +1,15 @@
<script lang="ts">
let title:string;
let title: string
let description: string
let files: FileList;
let files: FileList
let disabled = false
let disabledupload = false
let message = { error: false, message: "" }
let messageupload = { error: false, message: "" }
let allowmeshes = false
import { RadioGroup, RadioItem } from '@skeletonlabs/skeleton';
export let jwt: string;
import { RadioGroup, RadioItem } from "@skeletonlabs/skeleton"
export let jwt: string
export let gameid: string
export let avatartype = "PC"
export let gearallowed = false
@ -34,20 +34,18 @@
messageupload.error = false
}
async function updategame() {
const updategameresp = await fetch("/develop/editgame", {
method: 'POST',
method: "POST",
headers: {
'Content-Type': 'application/json',
'Authorization': jwt,
"Content-Type": "application/json",
Authorization: jwt,
},
body: JSON.stringify({
nameofgame: title,
description: description,
gameid: gameid.toString()
})
gameid: gameid.toString(),
}),
})
const updategamejson = await updategameresp.json()
console.log(updategamejson)
@ -58,24 +56,22 @@
message.message = updategamejson.error
message.error = true
}
}
async function uploadnew() {
const formData = new FormData();
const formData = new FormData()
formData.append("gameid", gameid.toString())
formData.append("gamefile", files[0])
const req = await fetch("/develop/editgameupload", {
method: "post",
body: formData,
headers: {
'Authorization': jwt,
Authorization: jwt,
},
});
})
const res = await req.json();
const res = await req.json()
console.log(res)
if (!res.error) {
messageupload.message = res.message
@ -90,15 +86,15 @@
if (avatartype != newavatartype) {
avatartype = newavatartype
const updateAvatarType = await fetch("/develop/editavatartype", {
method: 'POST',
method: "POST",
headers: {
'Content-Type': 'application/json',
'Authorization': jwt,
"Content-Type": "application/json",
Authorization: jwt,
},
body: JSON.stringify({
avatartype,
gameid: gameid.toString()
})
gameid: gameid.toString(),
}),
})
const updateAvatarTypejson = await updateAvatarType.json()
console.log(updateAvatarTypejson)
@ -109,57 +105,104 @@
if (allowmeshes != newgearstatus) {
allowmeshes = newgearstatus
const updateGearStatus = await fetch("/develop/editgearstatus", {
method: 'POST',
method: "POST",
headers: {
'Content-Type': 'application/json',
'Authorization': jwt,
"Content-Type": "application/json",
Authorization: jwt,
},
body: JSON.stringify({
newgearstatus,
gameid: gameid.toString()
})
gameid: gameid.toString(),
}),
})
const updateGearStatusjson = await updateGearStatus.json()
console.log(updateGearStatusjson)
}
}
</script>
<div class="space-y-2 flex flex-row flex-wrap justify-center">
<div class="w-full flex flex-row gap-4">
<div class="space-y-4 w-full">
<h5 class="m-auto tex t-center w-full">Edit Game</h5>
<label class="label">
<span>Title</span>
<input type="text" bind:value={title} class="input input-bordered input-primary w-full rounded-md" required>
<input
type="text"
bind:value={title}
class="input input-bordered input-primary w-full rounded-md"
required />
</label>
<label class="label">
<span>Description</span>
<textarea bind:value={description} class="input input-bordered input-primary w-full rounded-md" required></textarea>
<textarea
bind:value={description}
class="input input-bordered input-primary w-full rounded-md"
required>
</textarea>
</label>
<!-- svelte-ignore a11y-label-has-associated-control -->
<label class="label">
<span>Avatar Type</span>
<RadioGroup rounded="rounded-md" display="flex flex-row flex-wrap">
<RadioItem bind:group={avatartype} on:click={() => {updateAvatarType("R15")}} value="R15">R15</RadioItem>
<RadioItem bind:group={avatartype} on:click={() => {updateAvatarType("R6")}} value="R6">R6</RadioItem>
<RadioItem bind:group={avatartype} on:click={() => {updateAvatarType("PC")}} value="PC">Player Choice</RadioItem>
<RadioGroup
rounded="rounded-md"
display="flex flex-row flex-wrap">
<RadioItem
bind:group={avatartype}
on:click={() => {
updateAvatarType("R15")
}}
value="R15">
R15
</RadioItem>
<RadioItem
bind:group={avatartype}
on:click={() => {
updateAvatarType("R6")
}}
value="R6">
R6
</RadioItem>
<RadioItem
bind:group={avatartype}
on:click={() => {
updateAvatarType("PC")
}}
value="PC">
Player Choice
</RadioItem>
</RadioGroup>
</label>
<!-- svelte-ignore a11y-label-has-associated-control -->
<label class="label">
<span>Allow Gear</span>
<RadioGroup rounded="rounded-md" display="flex flex-row flex-wrap">
<RadioItem bind:group={gearallowed} on:click={() => {updateGearStatus(true)}} value={true}>Yes</RadioItem>
<RadioItem bind:group={gearallowed} on:click={() => {updateGearStatus(false)}} value={false}>No</RadioItem>
<RadioGroup
rounded="rounded-md"
display="flex flex-row flex-wrap">
<RadioItem
bind:group={gearallowed}
on:click={() => {
updateGearStatus(true)
}}
value={true}>
Yes
</RadioItem>
<RadioItem
bind:group={gearallowed}
on:click={() => {
updateGearStatus(false)
}}
value={false}>
No
</RadioItem>
</RadioGroup>
</label>
<h5 class="!text-xs mt-6 {message.error === true ? 'text-error-600' : 'text-success-600'}">{message.message??""}</h5>
<h5
class="!text-xs mt-6 {message.error === true
? 'text-error-600'
: 'text-success-600'}">
{message.message ?? ""}
</h5>
</div>
<div class="space-y-4 w-full h-full">
@ -169,24 +212,28 @@
<span>RBXL File</span>
<input class="w-full" accept=".rbxl" bind:files type="file" />
</label>
<h5 class="!text-xs {messageupload.error === true ? 'text-error-600' : 'text-success-600'}">{messageupload.message??""}</h5>
<h5
class="!text-xs {messageupload.error === true
? 'text-error-600'
: 'text-success-600'}">
{messageupload.message ?? ""}
</h5>
</div>
</div>
<div class="flex flex-row w-full gap-4">
<button on:click={updategame} class="btn variant-filled-primary btn-base w-full" disabled={disabled}>
<button
on:click={updategame}
class="btn variant-filled-primary btn-base w-full"
{disabled}>
Update
</button>
<button on:click={uploadnew} class="btn variant-filled-primary btn-base w-full" disabled={disabledupload}>
<button
on:click={uploadnew}
class="btn variant-filled-primary btn-base w-full"
disabled={disabledupload}>
Upload
</button>
</div>
</div>

View File

@ -1,12 +1,12 @@
<script lang="ts">
import { Avatar } from "@skeletonlabs/skeleton";
import { onMount } from "svelte";
export let gamename= "";
export let playercount = "";
export let idofgame: String;
export let version = "";
export let visits= "";
export let useridofowner = "";
import { Avatar } from "@skeletonlabs/skeleton"
import { onMount } from "svelte"
export let gamename = ""
export let playercount = ""
export let idofgame: String
export let version = ""
export let visits = ""
export let useridofowner = ""
export let useragent: string
export let username = ""
let imageloading = true
@ -14,46 +14,94 @@
if (node.complete) {
imageloading = false
} else {
node.addEventListener('load', callback)
node.addEventListener("load", callback)
return {
destroy() {
node.removeEventListener('load', callback)
node.removeEventListener("load", callback)
},
}
}
}
</script>
{#if useragent.includes("Android") === true || useragent.includes("iPhone") === true}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="unstyled group" on:click={()=> {document.location.href="/games/"+idofgame+"/"+gamename.replace(/[^a-zA-Z ]/g, "").replaceAll(' ', '-')}}>
<div class="card rounded-md card-glass-surface snap-center card-hover w-20 sm:w-40 relative">
<div
class="unstyled group"
on:click={() => {
document.location.href =
"/games/" +
idofgame +
"/" +
gamename.replace(/[^a-zA-Z ]/g, "").replaceAll(" ", "-")
}}>
<div
class="card rounded-md card-glass-surface snap-center card-hover w-20 sm:w-40 relative">
{#if imageloading}
<div class="w-20 h-20 sm:w-40 sm:h-40 rounded-none placeholder animate-pulse"></div>
<div
class="w-20 h-20 sm:w-40 sm:h-40 rounded-none placeholder animate-pulse">
</div>
{/if}
<img alt="" class="avatar-image w-20 h-20 sm:w-40 sm:h-40 object-cover {imageloading === true ? 'hidden' : ''} " use:onload={()=> imageloading=false} src="/assets/gameassets/thumbnail-{idofgame}.png#" />
<img
alt=""
class="avatar-image w-20 h-20 sm:w-40 sm:h-40 object-cover {imageloading ===
true
? 'hidden'
: ''} "
use:onload={() => (imageloading = false)}
src="/assets/gameassets/thumbnail-{idofgame}.png#" />
<p class="truncate w-auto">{gamename}</p>
<div class="!text-sm">{playercount} Playing</div>
<div class="btn h-2 w-6 sm:w-14 variant-filled-surface rounded-none absolute top-0 right-0 ">{version}</div>
<div class="hidden group-hover:block hover:block absolute top-32 sm:top-52">
<div class="!text-xs">By <a href="/users/{useridofowner}">{username}</a></div>
<div
class="btn h-2 w-6 sm:w-14 variant-filled-surface rounded-none absolute top-0 right-0">
{version}
</div>
<div
class="hidden group-hover:block hover:block absolute top-32 sm:top-52">
<div class="!text-xs">
By <a href="/users/{useridofowner}">{username}</a>
</div>
<div class="!text-xs">{visits ?? "0"} Visits</div>
</div>
</div>
</div>
{:else}
<a class="unstyled group" href="/games/{idofgame}/{gamename.replace(/[^a-zA-Z ]/g, "").replaceAll(' ', '-')}">
<div class="card rounded-md card-glass-surface snap-center card-hover w-20 sm:w-40 relative">
<a
class="unstyled group"
href="/games/{idofgame}/{gamename
.replace(/[^a-zA-Z ]/g, '')
.replaceAll(' ', '-')}">
<div
class="card rounded-md card-glass-surface snap-center card-hover w-20 sm:w-40 relative">
{#if imageloading}
<div class="w-20 h-20 sm:w-40 sm:h-40 rounded-none placeholder animate-pulse"></div>
<div
class="w-20 h-20 sm:w-40 sm:h-40 rounded-none placeholder animate-pulse">
</div>
{/if}
<img alt="" class="avatar-image w-20 h-20 sm:w-40 sm:h-40 object-cover {imageloading === true ? 'hidden' : ''} " use:onload={()=> imageloading=false} src="/assets/gameassets/thumbnail-{idofgame}.png#" />
<img
alt=""
class="avatar-image w-20 h-20 sm:w-40 sm:h-40 object-cover {imageloading ===
true
? 'hidden'
: ''} "
use:onload={() => (imageloading = false)}
src="/assets/gameassets/thumbnail-{idofgame}.png#" />
<p class="truncate w-auto">{gamename}</p>
<div class="!text-sm">{playercount} Playing</div>
<div class="btn h-2 w-6 sm:w-14 variant-filled-surface rounded-none absolute top-0 right-0 ">{version}</div>
{#if username}<div class="hidden group-hover:block hover:block absolute top-32 sm:top-52">
<div class="!text-xs flex flex-row">By <div class="text-primary-700 dark:text-primary-500 hover:brightness-110 underline truncate w-20 sm:w-40">{username}</div></div> <!-- not using anchor links here because it breaks styling in certain instances -->
<div
class="btn h-2 w-6 sm:w-14 variant-filled-surface rounded-none absolute top-0 right-0">
{version}
</div>
{#if username}<div
class="hidden group-hover:block hover:block absolute top-32 sm:top-52">
<div class="!text-xs flex flex-row">
By <div
class="text-primary-700 dark:text-primary-500 hover:brightness-110 underline truncate w-20 sm:w-40">
{username}
</div>
</div>
<!-- not using anchor links here because it breaks styling in certain instances -->
<div class="!text-xs">{visits ?? "0"} Visits</div>
</div>{/if}
</div>

View File

@ -1,9 +1,21 @@
<script lang="ts">
import { ProgressBar } from '@skeletonlabs/skeleton';
import { ProgressBar } from "@skeletonlabs/skeleton"
</script>
<div class="flex flex-wrap flex-row justify-center gap-y-6">
<div class="w-full"><img alt="meteorite" class="h-32 m-auto" src="/assets/images/logosmall.png"></div>
<h5 class="text-base">Do you have Meteorite Installed? If not install now!</h5>
<ProgressBar meter="variant-filled-primary" />
<a href="https://cdn.discordapp.com/attachments/1015311856744792104/1087210604273606766/Meteorite_0.5.0_x64_en-US.msi" class="btn variant-filled-primary btn-base rounded-md">Download</a>
<div class="w-full">
<img
alt="meteorite"
class="h-32 m-auto"
src="/assets/images/logosmall.png" />
</div>
<h5 class="text-base">
Do you have Meteorite Installed? If not install now!
</h5>
<ProgressBar meter="variant-filled-primary" />
<a
href="https://cdn.discordapp.com/attachments/1015311856744792104/1087210604273606766/Meteorite_0.5.0_x64_en-US.msi"
class="btn variant-filled-primary btn-base rounded-md">
Download
</a>
</div>

View File

@ -1,6 +1,29 @@
<div class="flex flex-wrap flex-row justify-center gap-y-6">
<svg xmlns="http://www.w3.org/2000/svg" width="44" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-full"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path><line x1="12" y1="9" x2="12" y2="13"></line><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>
<h5>Hi! In order to play games here at Meteorite you must link your discord account.</h5>
<svg
xmlns="http://www.w3.org/2000/svg"
width="44"
height="64"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="w-full">
<path
d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z">
</path>
<line x1="12" y1="9" x2="12" y2="13"></line>
<line x1="12" y1="17" x2="12.01" y2="17"></line>
</svg>
<h5>
Hi! In order to play games here at Meteorite you must link your discord
account.
</h5>
<h5 class="!text-sm m-auto w-full">Thank you...</h5>
<a href="https://discord.com/api/oauth2/authorize?client_id=1008206768989544449&redirect_uri=http%3A%2F%2Fmete0r.xyz%2Fsettings%2Fauthenticate&response_type=code&scope=identify" class="btn variant-filled-primary btn-base rounded-md">Link</a>
<a
href="https://discord.com/api/oauth2/authorize?client_id=1008206768989544449&redirect_uri=http%3A%2F%2Fmete0r.xyz%2Fsettings%2Fauthenticate&response_type=code&scope=identify"
class="btn variant-filled-primary btn-base rounded-md">
Link
</a>
</div>

View File

@ -1,9 +1,9 @@
<script lang="ts">
import { Avatar } from "@skeletonlabs/skeleton";
import { Avatar } from "@skeletonlabs/skeleton"
export let selectedgroup: string
export let grouplist: array
</script>
<div class="hidden sm:block">
<div class="flex flex-col">
<h2 class="font-bold">Groups</h2>
@ -11,17 +11,25 @@
{#if grouplist}
{#each grouplist as { Name, groupid }}
<a class="unstyled group" href="/groups/{groupid}">
<div class="flex flex-row bg-surface-700 p-4 gap-2 shadow-[inset_4px_0_0_0_white]" >
<Avatar width="w-8" rounded="rounded-none" src="/assets/groupicons/icon-0.png" />
<h5 class="!text-xs truncate w-48 m-auto group-hover:text-white">{Name}</h5>
<div
class="flex flex-row bg-surface-700 p-4 gap-2 shadow-[inset_4px_0_0_0_white]">
<Avatar
width="w-8"
rounded="rounded-none"
src="/assets/groupicons/icon-0.png" />
<h5
class="!text-xs truncate w-48 m-auto group-hover:text-white">
{Name}
</h5>
</div>
</a>
{/each}
{/if}
<a href="/groups/create" class="btn variant-ringed-surface rounded-md w-full btn-sm">Create Group</a>
<a
href="/groups/create"
class="btn variant-ringed-surface rounded-md w-full btn-sm">
Create Group
</a>
</div>
</div>

View File

@ -1,9 +1,9 @@
<script lang="ts">
import { Avatar } from "@skeletonlabs/skeleton";
import Rocks from '../components/rocks.svelte';
export let itemname: String;
import { Avatar } from "@skeletonlabs/skeleton"
import Rocks from "../components/rocks.svelte"
export let itemname: String
export let price: any = undefined
export let itemid: String;
export let itemid: String
export let sales: any = undefined
export let type = ""
@ -24,46 +24,77 @@
if (node.complete) {
imageloading = false
} else {
node.addEventListener('load', callback)
node.addEventListener("load", callback)
return {
destroy() {
node.removeEventListener('load', callback)
node.removeEventListener("load", callback)
},
}
}
}
</script>
<div class="card rounded-md card-glass-surface snap-center card-hover {width} relative hidden sm:block">
<a class="unstyled hidden sm:block" href="/catalog/{itemid}/{itemname.replace(/[^a-zA-Z ]/g, "").replaceAll(' ', '-')}">
<div
class="card rounded-md card-glass-surface snap-center card-hover {width} relative hidden sm:block">
<a
class="unstyled hidden sm:block"
href="/catalog/{itemid}/{itemname
.replace(/[^a-zA-Z ]/g, '')
.replaceAll(' ', '-')}">
{#if type != "Audio" && type != "Video"}
{#if imageloading}
<div class="w-36 h-36 rounded-none placeholder animate-pulse"></div>
<div class="w-36 h-36 rounded-none placeholder animate-pulse">
</div>
{/if}
<img alt="" class="avatar-image bg-surface-400-500-token w-full h-full flex aspect-square object-cover {imageloading === true ? 'hidden' : ''} " use:onload={()=> imageloading=false} src="/api/thumbnailrender/asset/?id={itemid}{moderation === false ? "": "&nonapproved=true"}" />
<img
alt=""
class="avatar-image bg-surface-400-500-token w-full h-full flex aspect-square object-cover {imageloading ===
true
? 'hidden'
: ''} "
use:onload={() => (imageloading = false)}
src="/api/thumbnailrender/asset/?id={itemid}{moderation ===
false
? ''
: '&nonapproved=true'}" />
{/if}
</a>
{#if type === "Audio"}
<audio class="block" controls>
<source src="/asset?id={itemid}&nonapproved=true" type="audio/mp3">
<source
src="/asset?id={itemid}&nonapproved=true"
type="audio/mp3" />
</audio>
{/if}
{#if type === "Video"}
<!-- svelte-ignore a11y-media-has-caption -->
<video controls>
<source src="/asset?id={itemid}&nonapproved=true" type="video/webm">
<source
src="/asset?id={itemid}&nonapproved=true"
type="video/webm" />
</video>
{/if}
{#if interact === "true"}
{#if equipped === true}
<button on:click={() => {action('remove',parseFloat({itemid}.itemid))}} class="btn variant-filled-primary rounded-md btn-sm absolute right-0 top-0">Remove</button>
<button
on:click={() => {
action("remove", parseFloat({ itemid }.itemid))
}}
class="btn variant-filled-primary rounded-md btn-sm absolute right-0 top-0">
Remove
</button>
{:else}
<button on:click={() => {action('wear',parseFloat({itemid}.itemid))}} class="btn variant-filled-primary rounded-md btn-sm absolute right-0 top-0">Wear</button>
<button
on:click={() => {
action("wear", parseFloat({ itemid }.itemid))
}}
class="btn variant-filled-primary rounded-md btn-sm absolute right-0 top-0">
Wear
</button>
{/if}
{/if}
<p class="truncate w-28">{itemname}</p>
@ -75,15 +106,26 @@
<p class="!text-xs">{type}</p>
<div class="flex flex-col gap-y-1">
<div class="flex flex-row gap-x-2">
<button on:click={() => {moderate('deny',parseFloat({itemid}.itemid))}} class="btn variant-filled-primary rounded-md btn-sm grow">Deny</button>
<button on:click={() => {moderate('approve',parseFloat({itemid}.itemid))}} class="btn variant-filled-primary rounded-md btn-sm grow">Approve</button>
<button
on:click={() => {
moderate("deny", parseFloat({ itemid }.itemid))
}}
class="btn variant-filled-primary rounded-md btn-sm grow">
Deny
</button>
<button
on:click={() => {
moderate("approve", parseFloat({ itemid }.itemid))
}}
class="btn variant-filled-primary rounded-md btn-sm grow">
Approve
</button>
</div>
<!--<button on:click={() => {}} class="btn variant-filled-primary rounded-md btn-sm w-full">Download</button>-->
</div>
{/if}
{#if price}
<div class="flex flex-row">
<Rocks width="w-5" />
<div class="!text-sm">{price}</div>

View File

@ -1,11 +1,10 @@
<script lang="ts">
import { toastStore, type ToastSettings } from "@skeletonlabs/skeleton";
import { toastStore, type ToastSettings } from "@skeletonlabs/skeleton"
let message = { error: false, message: "" }
let disabled = false
let _2fa: number;
let _2fa: number
export let username: string
export let password: string
@ -21,62 +20,82 @@
}
const t: ToastSettings = {
message: 'resp',
message: "resp",
// Optional: Presets for primary | secondary | tertiary | warning
preset: 'error',
preset: "error",
// Optional: The auto-hide settings
autohide: true,
timeout: 2000
};
timeout: 2000,
}
async function retrylogin() {
if (username && password) {
const loginresp = await fetch('/login', {
method: 'POST',
const loginresp = await fetch("/login", {
method: "POST",
headers: {
'Content-Type': 'application/json'
"Content-Type": "application/json",
},
credentials: 'include',
credentials: "include",
body: JSON.stringify({
username,
password,
_2fa
})
_2fa,
}),
})
const login = await loginresp.json()
if (!login.error) {
t.preset = 'success'
t.message = 'Logged in!'
t.preset = "success"
t.message = "Logged in!"
toastStore.trigger(t)
document.location = '/home'
document.location = "/home"
} else {
t.message = login.error
toastStore.trigger(t)
}
}
}
</script>
<div class="space-y-2 flex flex-row flex-wrap justify-center">
<h5 class="m-auto text-center w-full">Confirm 2FA</h5>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="w-32">
<path
d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4">
</path>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-32"><path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"></path></svg>
<h5 class="m-auto text-center w-full">Enter the code generated by your authenticator app.</h5>
<h5 class="m-auto text-center w-full">
Enter the code generated by your authenticator app.
</h5>
<div class="space-y-4 w-full">
<input type="number" bind:value={_2fa} placeholder="Input 2FA" class="input input-bordered input-primary w-full rounded-md" required>
<h5 class="!text-xs mt-6 {message.error === true ? 'text-error-600' : 'text-success-600'}">{message.message??""}</h5>
<input
type="number"
bind:value={_2fa}
placeholder="Input 2FA"
class="input input-bordered input-primary w-full rounded-md"
required />
<h5
class="!text-xs mt-6 {message.error === true
? 'text-error-600'
: 'text-success-600'}">
{message.message ?? ""}
</h5>
</div>
<button on:click={retrylogin} class="btn variant-filled-primary btn-base rounded-md" disabled={disabled}>
<button
on:click={retrylogin}
class="btn variant-filled-primary btn-base rounded-md"
{disabled}>
Confirm
</button>
</div>

View File

@ -1,44 +1,50 @@
<script>
import { tweened } from 'svelte/motion';
import { cubicOut } from 'svelte/easing';
import { navigating } from '$app/stores';
import { fade } from 'svelte/transition';
import { tweened } from "svelte/motion"
import { cubicOut } from "svelte/easing"
import { navigating } from "$app/stores"
import { fade } from "svelte/transition"
// progress bar value
const p = tweened(0, {
duration: 200,
easing: cubicOut
});
easing: cubicOut,
})
let isVisible = false;
let isVisible = false
function increase() {
if ($p >= 0 && $p < 0.2) { p.update(_ => _ + 0.04); }
else if ($p >= 0.2 && $p < 0.5) { p.update(_ => _ + 0.02); }
else if ($p >= 0.5 && $p < 0.8) { p.update(_ => _ + 0.002); }
else if ($p >= 0.8 && $p < 0.99) { p.update(_ => _ + 0.0005); }
else { p.set(0) }
if ($p >= 0 && $p < 0.2) {
p.update(_ => _ + 0.04)
} else if ($p >= 0.2 && $p < 0.5) {
p.update(_ => _ + 0.02)
} else if ($p >= 0.5 && $p < 0.8) {
p.update(_ => _ + 0.002)
} else if ($p >= 0.8 && $p < 0.99) {
p.update(_ => _ + 0.0005)
} else {
p.set(0)
}
if ($navigating) {
const rand = Math.round(Math.random() * (300 - 50)) + 50;
const rand = Math.round(Math.random() * (300 - 50)) + 50
setTimeout(function () {
increase();
}, rand);
increase()
}, rand)
}
}
$: {
if ($navigating) {
increase();
isVisible = true;
increase()
isVisible = true
}
if (!$navigating) {
p.update(_ => _ + 0.3);
p.update(_ => _ + 0.3)
setTimeout(function () {
p.set(1);
p.set(1)
setTimeout(function () {
isVisible = false;
p.set(0);
isVisible = false
p.set(0)
}, 100)
}, 100)
}
@ -62,11 +68,22 @@
border-radius: 0;
}
/* bar: */
progress::-webkit-progress-bar {background-color: var(--bar-color); width: 100%;}
progress {background-color: var(--bar-color);}
progress::-webkit-progress-bar {
background-color: var(--bar-color);
width: 100%;
}
progress {
background-color: var(--bar-color);
}
/* value: */
progress::-webkit-progress-value {background-color: var(--val-color) !important;}
progress::-moz-progress-bar {background-color: var(--val-color) !important;}
progress {color: var(--val-color);}
progress::-webkit-progress-value {
background-color: var(--val-color) !important;
}
progress::-moz-progress-bar {
background-color: var(--val-color) !important;
}
progress {
color: var(--val-color);
}
</style>

View File

@ -1,4 +1,23 @@
<script lang="ts">
export let width = "w-6"
</script>
<svg class={width} fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 18.657A8 8 0 016.343 7.343S7 9 9 10c0-2 .5-5 2.986-7C14 5 16.09 5.777 17.656 7.343A7.975 7.975 0 0120 13a7.975 7.975 0 01-2.343 5.657z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.879 16.121A3 3 0 1012.015 11L11 14H9c0 .768.293 1.536.879 2.121z"></path></svg>
<svg
class={width}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M17.657 18.657A8 8 0 016.343 7.343S7 9 9 10c0-2 .5-5 2.986-7C14 5 16.09 5.777 17.656 7.343A7.975 7.975 0 0120 13a7.975 7.975 0 01-2.343 5.657z">
</path>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9.879 16.121A3 3 0 1012.015 11L11 14H9c0 .768.293 1.536.879 2.121z">
</path>
</svg>

View File

@ -1,24 +1,25 @@
<script lang="ts">
export let scrollDirection: String;
export let scrollElement: HTMLDivElement;
export let scrollDirection: String
export let scrollElement: HTMLDivElement
const scroll = async (node: HTMLDivElement, direction: String) => {
if (direction === "right") {
if (window.matchMedia("(min-width: 640px)").matches === true) {
return node.scrollLeft += 800
return (node.scrollLeft += 800)
}
node.scrollLeft += 200
} else {
if (window.matchMedia("(min-width: 640px)").matches === true) {
return node.scrollLeft -= 800
return (node.scrollLeft -= 800)
}
node.scrollLeft -= 200
}
};
}
</script>
<button class="btn btn-ringed btn-base w-3 rounded-md float-{scrollDirection} h-32 sm:h-52" on:click={() => scroll(scrollElement, scrollDirection)} style="transition: none !important;transform: none !important;">
<button
class="btn btn-ringed btn-base w-3 rounded-md float-{scrollDirection} h-32 sm:h-52"
on:click={() => scroll(scrollElement, scrollDirection)}
style="transition: none !important;transform: none !important;">
{#if scrollDirection === "right"}
&gt;
{:else}

View File

@ -3,8 +3,8 @@
let message = { error: false, message: "" }
let disabled = false
export let jwt: string;
export let qrcode: string;
export let jwt: string
export let qrcode: string
$: if (!_2facode) {
disabled = true
@ -18,43 +18,49 @@
async function verify2fa() {
const response = await fetch("/settings/verify2fa", {
method: 'POST',
method: "POST",
body: JSON.stringify({ code: _2facode }),
headers: {
'Content-Type': 'application/json',
'Authorization': jwt,
}
"Content-Type": "application/json",
Authorization: jwt,
},
})
const json = await response.json()
if (!json.error) {
message.message = "2FA Enabled"
message.error = false
document.location = '/settings'
document.location = "/settings"
} else {
message.message = json.error
message.error = true
}
}
</script>
<div class="space-y-2 flex flex-row flex-wrap justify-center">
<h5 class="m-auto text-center w-full">Confirm 2FA</h5>
<img alt={qrcode} class="w-64" src={qrcode} />
<div class="space-y-4 w-full">
<input type="text" bind:value={_2facode} placeholder="Input 2FA" class="input input-bordered input-primary w-full rounded-md" required>
<h5 class="!text-xs mt-6 {message.error === true ? 'text-error-600' : 'text-success-600'}">{message.message??""}</h5>
<input
type="text"
bind:value={_2facode}
placeholder="Input 2FA"
class="input input-bordered input-primary w-full rounded-md"
required />
<h5
class="!text-xs mt-6 {message.error === true
? 'text-error-600'
: 'text-success-600'}">
{message.message ?? ""}
</h5>
</div>
<button on:click={verify2fa} class="btn variant-filled-primary btn-base rounded-md" disabled={disabled}>
<button
on:click={verify2fa}
class="btn variant-filled-primary btn-base rounded-md"
{disabled}>
Confirm
</button>
</div>

View File

@ -1,12 +1,12 @@
<script lang="ts">
let currentp:string;
let newp:string;
let confp:string;
let currentp: string
let newp: string
let confp: string
let disabled = false
let message = { error: false, message: "" }
export let jwt: string;
export let jwt: string
$:if (newp != confp || !newp && !confp){
$: if (newp != confp || (!newp && !confp)) {
disabled = true
message.message = "New password and Confirm Password are not the same."
message.error = true
@ -17,16 +17,16 @@ $:if (newp != confp || !newp && !confp){
}
async function changepassword() {
const changepasswordresp = await fetch('/api/changepassword', {
method: 'POST',
const changepasswordresp = await fetch("/api/changepassword", {
method: "POST",
headers: {
'Content-Type': 'application/json',
'Authorization': jwt,
"Content-Type": "application/json",
Authorization: jwt,
},
body: JSON.stringify({
oldpassword: currentp,
newpassword:confp
})
newpassword: confp,
}),
})
const changepassword = await changepasswordresp.json()
if (!changepassword.error) {
@ -37,24 +37,42 @@ async function changepassword(){
message.error = true
}
}
</script>
<div class="space-y-2 flex flex-row flex-wrap justify-center">
<h5 class="m-auto text-center">Change Password</h5>
<div class="space-y-4">
<input type="password" bind:value={currentp} placeholder="Current Password" class="input input-bordered input-primary w-full rounded-md" required>
<input type="password" bind:value={newp} placeholder="New Password" class="input input-bordered input-primary w-full rounded-md" required>
<input type="password" bind:value={confp} placeholder="Confirm Password" class="input input-bordered input-primary w-full rounded-md" required>
<h5 class="!text-xs mt-6 {message.error === true ? 'text-error-600' : 'text-success-600'}">{message.message??""}</h5>
<input
type="password"
bind:value={currentp}
placeholder="Current Password"
class="input input-bordered input-primary w-full rounded-md"
required />
<input
type="password"
bind:value={newp}
placeholder="New Password"
class="input input-bordered input-primary w-full rounded-md"
required />
<input
type="password"
bind:value={confp}
placeholder="Confirm Password"
class="input input-bordered input-primary w-full rounded-md"
required />
<h5
class="!text-xs mt-6 {message.error === true
? 'text-error-600'
: 'text-success-600'}">
{message.message ?? ""}
</h5>
</div>
<button on:click={changepassword} class="btn variant-filled-primary btn-base" disabled={disabled}>
<button
on:click={changepassword}
class="btn variant-filled-primary btn-base"
{disabled}>
Update
</button>
</div>

View File

@ -1,9 +1,6 @@
<script lang="ts">
import { url } from "$lib/url"
export let customclass: string
export let customMediaClass = "hidden lg:block"
let imageUrl = ""
@ -11,18 +8,28 @@ let redirectUrl = "/games/0"
let loading = true
async function grabAd() {
const res = await fetch(url + `/api/requestad`)
const data = await res.json()
imageUrl = data.imageUrl
redirectUrl = data.redirectUrl
}
grabAd()
</script>
{#if loading}
<div class="hidden lg:block w-[160px] h-[600px] rounded-none placeholder animate-pulse {customclass}"></div>
<div
class="hidden lg:block w-[160px] h-[600px] rounded-none placeholder animate-pulse {customclass}">
</div>
{/if}
<a on:click={grabAd} href={redirectUrl}><img class="w-[160px] h-[600px] rounded-none {customclass} {loading === true ? 'hidden' : customMediaClass}" on:load={() => {loading = false}} alt="Ad" src={imageUrl}/></a>
<a on:click={grabAd} href={redirectUrl}>
<img
class="w-[160px] h-[600px] rounded-none {customclass} {loading === true
? 'hidden'
: customMediaClass}"
on:load={() => {
loading = false
}}
alt="Ad"
src={imageUrl} />
</a>

View File

@ -1,8 +1,7 @@
<script lang="ts">
import { onMount } from "svelte";
import { onMount } from "svelte"
export let size: string;
export let size: string
export let status = "Offline"
export let userid = "0"
export let gameid = "0"
@ -12,11 +11,19 @@ $:if (status === "Offline"){
offline = true
}
</script>
{#if status === "Offline"}
<div class="{customclass} absolute bottom-2 right-5 w-{size} h-{size} bg-surface-300 rounded-full"></div>
{#if status === "Offline"}
<div
class="{customclass} absolute bottom-2 right-5 w-{size} h-{size} bg-surface-300 rounded-full">
</div>
{:else if status === "Online"}
<div class="{customclass} absolute bottom-2 right-5 w-{size} h-{size} bg-blue-500 rounded-full"></div>
{:else if status.includes('Playing') === true}
<a class="unstyled" href="http://mete0r.xyz/games/{gameid}"><div class="{customclass} absolute bottom-2 right-5 w-{size} h-{size} bg-green-500 rounded-full"></div></a>
<div
class="{customclass} absolute bottom-2 right-5 w-{size} h-{size} bg-blue-500 rounded-full">
</div>
{:else if status.includes("Playing") === true}
<a class="unstyled" href="http://mete0r.xyz/games/{gameid}">
<div
class="{customclass} absolute bottom-2 right-5 w-{size} h-{size} bg-green-500 rounded-full">
</div>
</a>
{/if}

View File

@ -1,52 +1,47 @@
<script lang="ts">
import { Avatar } from "@skeletonlabs/skeleton";
import { Avatar } from "@skeletonlabs/skeleton"
export let userid: string
export let username: string
export let friendRequest = false
export let jwt = ""
export let refresh = async function(){
}
export let refresh = async function () {}
async function ignore() {
const result = await fetch('/api/friends/decline-friend-request', {
method: 'POST',
const result = await fetch("/api/friends/decline-friend-request", {
method: "POST",
headers: {
'Content-Type': 'application/json',
'Authorization': jwt,
"Content-Type": "application/json",
Authorization: jwt,
},
body: JSON.stringify({
recipientUserId: userid.toString()
})
recipientUserId: userid.toString(),
}),
})
const requestresult = await result.json()
console.log(requestresult)
refresh()
}
async function accept() {
const result = await fetch('/api/friends/request-friendship', {
method: 'POST',
const result = await fetch("/api/friends/request-friendship", {
method: "POST",
headers: {
'Content-Type': 'application/json',
'Authorization': jwt,
"Content-Type": "application/json",
Authorization: jwt,
},
body: JSON.stringify({
recipientUserId: userid.toString()
})
recipientUserId: userid.toString(),
}),
})
const requestresult = await result.json()
console.log(requestresult)
refresh()
}
</script>
<div class="card rounded-md card-glass-surface snap-center card-hover group w-full lg:w-96 relative p-2">
<div
class="card rounded-md card-glass-surface snap-center card-hover group w-full lg:w-96 relative p-2">
<a class="unstyled" href="/users/{userid}">
<div class="flex flex-row gap-4">
<Avatar width="w-32" src="/api/thumbnailrender/?id={userid}#" />
@ -54,16 +49,20 @@
</div>
</a>
{#if friendRequest === true}
<div class="flex flex-row gap-4 justify-around p-4">
<button
on:click={ignore}
type="submit"
class="btn variant-filled-primary btn-base rounded-md w-full">
Ignore
</button>
<button on:click={ignore} type="submit" class="btn variant-filled-primary btn-base rounded-md w-full">Ignore</button>
<button on:click={accept} type="submit" class="btn variant-filled-primary btn-base rounded-md w-full">Accept</button>
<button
on:click={accept}
type="submit"
class="btn variant-filled-primary btn-base rounded-md w-full">
Accept
</button>
</div>
{/if}
</div>

View File

@ -1,31 +1,40 @@
import { authenticateUser } from "$lib/auth"
import { redirect, type Handle } from "@sveltejs/kit"
const protectedroutes = [
'/home',
'/catalog',
'/develop',
'/users',
'/avatar',
'/settings',
'/admin'
"/home",
"/catalog",
"/develop",
"/users",
"/avatar",
"/settings",
"/admin",
]
export const handle: Handle = async ({ event, resolve }) => {
// Stage 1
event.locals.user = await authenticateUser(event)
event.locals.jwt = event.cookies.get('jwt')??""
event.locals.useragent = event.request.headers.get('user-agent')
event.locals.jwt = event.cookies.get("jwt") ?? ""
event.locals.useragent = event.request.headers.get("user-agent")
//console.log(event.locals.user)
if (protectedroutes.includes(event.url.pathname) === true || protectedroutes.some(substr => event.url.pathname.toLowerCase().startsWith(substr.toLowerCase())) === true) {
if (
protectedroutes.includes(event.url.pathname) === true ||
protectedroutes.some(substr =>
event.url.pathname.toLowerCase().startsWith(substr.toLowerCase()),
) === true
) {
if (!event.locals.user) {
throw redirect(303, "/")
}
if (event.locals.user?.moderationstatus && event.locals.user.moderationstatus?.status.toUpperCase() != "OK" && event.url.pathname != "moderated"){
throw redirect(303, '/moderated')
if (
event.locals.user?.moderationstatus &&
event.locals.user.moderationstatus?.status.toUpperCase() != "OK" &&
event.url.pathname != "moderated"
) {
throw redirect(303, "/moderated")
}
}
if (event.url.pathname.toLowerCase().startsWith('/admin') === true){
if (event.url.pathname.toLowerCase().startsWith("/admin") === true) {
// admin route
if (!event.locals.user) {
throw redirect(303, "/")
@ -39,10 +48,16 @@ export const handle: Handle = async ({ event, resolve }) => {
// Stage 3
//console.log(event.url.protocol)
if (event.url.protocol === 'https:'){
response.headers.append("Content-Security-Policy","img-src 'self' data: wsrv.nl images.weserv.nl;upgrade-insecure-requests;")
if (event.url.protocol === "https:") {
response.headers.append(
"Content-Security-Policy",
"img-src 'self' data: wsrv.nl images.weserv.nl;upgrade-insecure-requests;",
)
} else {
response.headers.append("Content-Security-Policy","img-src 'self' data: wsrv.nl images.weserv.nl;")
response.headers.append(
"Content-Security-Policy",
"img-src 'self' data: wsrv.nl images.weserv.nl;",
)
}
return response

View File

@ -13,7 +13,10 @@ export const authenticateUser = async (event: RequestEvent) => {
// if the user token is not valid, return null
// this is where you would check the user token against your database
// to see if it is valid and return the user object
const res = await fetch("http://mete0r.xyz/api/auth",{credentials: 'include', headers: {cookie: "jwt="+userToken,route: route.id as string}})
const res = await fetch("http://mete0r.xyz/api/auth", {
credentials: "include",
headers: { cookie: "jwt=" + userToken, route: route.id as string },
})
const data = await res.json()
if (!data.error) {
return data

Some files were not shown because too many files have changed in this diff Show More