Added commenting!
This commit is contained in:
parent
bebf1eb1fd
commit
469ffaf4b7
10 changed files with 177 additions and 22 deletions
|
@ -38,6 +38,7 @@ module.exports = async (app, req, res) => {
|
|||
|
||||
let comment = {}
|
||||
comment.content = app.clean(Buffer.from(x[2], 'base64').toString());
|
||||
comment.ID = x[6]
|
||||
comment.likes = x[4]
|
||||
comment.date = (x[9] || "?") + " ago"
|
||||
if (req.query.type == "commentHistory") comment.levelID = x[1]
|
||||
|
|
58
api/postComment.js
Normal file
58
api/postComment.js
Normal file
|
@ -0,0 +1,58 @@
|
|||
const request = require('request')
|
||||
const XOR = require('../misc/XOR.js');
|
||||
const xor = new XOR();
|
||||
const crypto = require('crypto')
|
||||
function sha1(data) { return crypto.createHash("sha1").update(data, "binary").digest("hex"); }
|
||||
|
||||
let rateLimit = {};
|
||||
let cooldown = 10000
|
||||
|
||||
function getTime(time) {
|
||||
let seconds = Math.ceil(time / 1000);
|
||||
seconds = seconds % 60;
|
||||
return seconds}
|
||||
|
||||
module.exports = async (app, req, res) => {
|
||||
|
||||
if (!req.body.comment) return res.status(400).send("No comment provided!")
|
||||
if (!req.body.username) return res.status(400).send("No username provided!")
|
||||
if (!req.body.levelID) return res.status(400).send("No level ID provided!")
|
||||
if (!req.body.accountID) return res.status(400).send("No account ID provided!")
|
||||
if (!req.body.password) return res.status(400).send("No password provided!")
|
||||
|
||||
if (rateLimit[req.body.username]) return res.status(400).send(`Please wait ${getTime(rateLimit[req.body.username] + cooldown - Date.now())} seconds before posting another comment!`)
|
||||
|
||||
let params = {
|
||||
gameVersion: '21',
|
||||
binaryVersion: '35',
|
||||
secret: app.secret,
|
||||
percent: 0
|
||||
}
|
||||
|
||||
params.comment = new Buffer(req.body.comment).toString('base64').replace(/\//g, '_').replace(/\+/g, "-")
|
||||
params.gjp = xor.encrypt(req.body.password, 37526)
|
||||
params.levelID = req.body.levelID
|
||||
params.accountID = req.body.accountID
|
||||
params.userName = req.body.username
|
||||
|
||||
let percent = parseInt(req.body.percent)
|
||||
if (percent && percent > 0 && percent <= 100) params.percent = percent
|
||||
|
||||
let chk = params.userName + params.comment + params.levelID + params.percent + "0xPT6iUrtws0J"
|
||||
chk = sha1(chk)
|
||||
chk = xor.encrypt(chk, 29481)
|
||||
|
||||
params.chk = chk
|
||||
|
||||
console.log(params)
|
||||
|
||||
request.post('http://boomlings.com/database/uploadGJComment21.php', {
|
||||
form: params
|
||||
}, function (err, resp, body) {
|
||||
if (err) return res.status(400).send("The Geometry Dash servers returned an error! Perhaps they're down for maintenance")
|
||||
if (!body || body == "-1") return res.status(400).send("The Geometry Dash servers rejected your comment! Make sure your username and password are entered correctly.")
|
||||
res.status(200).send(`Comment posted to level ${params.levelID} with ID ${body}`)
|
||||
rateLimit[req.body.username] = Date.now();
|
||||
setTimeout(() => {delete rateLimit[req.body.username]; }, cooldown);
|
||||
})
|
||||
}
|
BIN
assets/btn-submit.png
Normal file
BIN
assets/btn-submit.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 100 KiB |
|
@ -125,7 +125,7 @@ img, .noSelect {
|
|||
}
|
||||
|
||||
p {
|
||||
font-family: aller, helvetica;
|
||||
font-family: aller, helvetica, arial;
|
||||
color: white;
|
||||
font-size: 2.9vh;
|
||||
word-break: break-word;
|
||||
|
@ -155,7 +155,7 @@ h2 {
|
|||
text-shadow: -0.275vh -0.275vh 0vh #000, 0.275vh -0.275vh 0vh #000, -0.275vh 0.275vh 0vh #000, 0.275vh 0.275vh 0vh #000, 0.5vh 0.5vh 0vh rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
h3, input[type=text], input[type=number] {
|
||||
h3, input[type=text], input[type=password], input[type=number] {
|
||||
font-weight: normal;
|
||||
margin: 0 0;
|
||||
font-size: 3.5vh;
|
||||
|
@ -177,7 +177,7 @@ hr {
|
|||
background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 500, from(rgba(255, 255, 255, 0.5)), to(rgba(0, 0, 0, 0)));
|
||||
}
|
||||
|
||||
input[type=text], input[type=number] {
|
||||
input[type=text], input[type=password], input[type=number] {
|
||||
padding-left: 1.2%;
|
||||
border-radius: 1vh;
|
||||
height: 80%;
|
||||
|
@ -190,6 +190,37 @@ input[type=checkbox] {
|
|||
display: none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: none;
|
||||
font-family: aller, helvetica, arial;
|
||||
padding: 2% 1%;
|
||||
border-radius: 1vh;
|
||||
height: 18.5vh;
|
||||
margin-top: 1%;
|
||||
width: 90%;
|
||||
font-size: 3vh;
|
||||
color: white;
|
||||
text-align: center;
|
||||
word-break: break-word;
|
||||
white-space: initial !important;
|
||||
}
|
||||
|
||||
textarea::-webkit-scrollbar {
|
||||
height: 8%;
|
||||
width: 2.2%;
|
||||
background: #6d3c24;
|
||||
}
|
||||
|
||||
textarea::-webkit-scrollbar-thumb {
|
||||
background: rgb(83, 47, 28);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
input:-webkit-autofill, input:-webkit-autofill:hover, input:-webkit-autofill:focus, input:-webkit-autofill:active {
|
||||
-webkit-box-shadow: 0 0 0px 1000px #764F1A inset !important;
|
||||
-webkit-text-fill-color: white !important;
|
||||
}
|
||||
|
||||
.gdcheckbox {
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
|
@ -209,7 +240,12 @@ input[type=checkbox]:checked + label.gdcheckbox {
|
|||
font-size: 4vh;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
textarea::placeholder {
|
||||
color: lightgray;
|
||||
font-size: 3vh;
|
||||
}
|
||||
|
||||
input:focus, textarea:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
|
@ -225,7 +261,7 @@ input:focus {
|
|||
margin: 1% 1%
|
||||
}
|
||||
|
||||
.transparentBox, input[type=text], input[type=number] {
|
||||
.transparentBox, input[type=text], input[type=password], input[type=number], textarea {
|
||||
border: 0 solid transparent;
|
||||
border-radius: 2vh;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
|
@ -437,7 +473,7 @@ input::-webkit-inner-spin-button {
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0; left: 0; right: 0; bottom: 0;
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
background-color: rgba(0,0,0,0.6);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
|
@ -646,7 +682,7 @@ input::-webkit-inner-spin-button {
|
|||
display: inline-block;
|
||||
width: 27%;
|
||||
height: 21%;
|
||||
margin: 2% 0%;
|
||||
margin: 0% 0% 7.5% 0%;
|
||||
}
|
||||
|
||||
.specialThanks h2 {
|
||||
|
|
|
@ -403,6 +403,7 @@
|
|||
<div class="subdiv" id="response-comment">
|
||||
<p>The API will return an array of each comment with the following information.<br>Values that don't work for profile posts are in <span style="color:red">red</span></p>
|
||||
<p>content: The comment text</p>
|
||||
<p>ID: The ID of the comment (used for liking and deleting)</p>
|
||||
<p>likes: The number of likes the comment has</p>
|
||||
<p>date: Time since the comment was posted (sent as "x days/weeks/months" ago, since it's all the API sends)</p>
|
||||
<p class="red">levelID: The ID of the level [COMMENT HISTORY ONLY]</p>
|
||||
|
|
|
@ -12,6 +12,24 @@
|
|||
<body class="levelBG" onbeforeunload="saveUrl()">
|
||||
|
||||
<div id="everything">
|
||||
|
||||
<div class="popup" id="postComment">
|
||||
<div class="brownbox bounce center supercenter" style="height: 80%; width: 110vh">
|
||||
<h1 class="smaller center" style="font-size: 5.5vh">Add Comment (Beta)</h1>
|
||||
<textarea placeholder="Insert comment" id="content" maxlength="150" style="margin: 2% 0%"></textarea><br>
|
||||
<form id="form" action="nothing lol">
|
||||
<h3 class="center">GD Username</h3>
|
||||
<input type="text" name="gdbrowser" id="username" maxlength="50" style="height: 8vh; width: 90%; text-align: center; margin-top: 0.5%"></textarea>
|
||||
<h3 class="center" style="margin-top: 2%">GD Password</h3>
|
||||
<input type="password" id="password" maxlength="50" style="height: 8vh; width: 90%; text-align: center; margin-top: 0.5%"></textarea>
|
||||
</form>
|
||||
<div style="min-height: 16%; max-height: 16%">
|
||||
<p id="message" style="padding: 0% 10%; margin-top: 1.5%"></p>
|
||||
</div>
|
||||
<img src="../assets/btn-cancel.png" height=10%; class="postButton gdButton center" style="margin-right: 1%" onclick="$('#postComment').hide(); $('textarea').val('')">
|
||||
<img src="../assets/btn-submit.png" type="submit" height=10%; class="postButton gdButton center" style="margin-left: 1%" id="submitComment">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="position:absolute; bottom: 0%; left: 0%; width: 100%">
|
||||
<img class="cornerPiece" src="../assets/corner.png" width=7%;>
|
||||
|
@ -58,13 +76,13 @@
|
|||
<h2 class="smallGold inline" id="levelVersion"></h2>
|
||||
<a id="levelLink"><h2 class="smallGold inline gdButton" id="levelID" style="margin-left: 6vh"></h2></a>
|
||||
</div>
|
||||
|
||||
<div style="position:absolute;bottom: 0%;right: 0%;width: 14%;text-align: right;transform: translate(30%, 40%);">
|
||||
<img class="gdButton" src="../assets/comment.png" width="60%" onclick="$('#postComment').show()">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style="position:absolute; top: 2%; left: 1.5%; width: 10%; height: 25%; pointer-events: none">
|
||||
<img class="gdButton yesClick" id="backButton" src="../assets/back.png" height="30%" onclick="backButton()">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
@ -74,6 +92,8 @@
|
|||
<script>
|
||||
|
||||
let {mode, compact} = JSON.parse(localStorage.getItem('commentPreset') || '{"mode": "top", "compact": true}')
|
||||
let messageText = 'Your <span style="color: yellow">Geometry Dash password</span> will <span style="color: lime">not be stored</span> anywhere on the site, both <span style="color:rgb(113, 234, 255)">locally and server-side.</span> You can view the code used for posting a comment <a class="menuLink" target="_blank" href="https://github.com/GDColon/GDBrowser/blob/master/api/postComment.js">here</a>.'
|
||||
$('#message').html(messageText)
|
||||
|
||||
let lvlID = window.location.pathname.split('/')[2]
|
||||
let history = false;
|
||||
|
@ -107,7 +127,6 @@ fetch(target).then(res => res.json()).then(lvl => {
|
|||
}
|
||||
|
||||
else {
|
||||
console.log(lvl)
|
||||
if (lvl.accountID == undefined) $('#levelAuthor').remove()
|
||||
else if (lvl.accountID == 0) {
|
||||
$('#levelAuthor').addClass("green").addClass("unregistered")
|
||||
|
@ -259,6 +278,40 @@ $('#refresh').click(function() {
|
|||
appendComments()
|
||||
})
|
||||
|
||||
$('#submitComment').click(function() {
|
||||
let comment = $('#content').val()
|
||||
let username = $('#username').val()
|
||||
let password = $('#password').val()
|
||||
let levelID = window.location.pathname.split('/')[2]
|
||||
let accountID = 0
|
||||
|
||||
if (!content || !username || !password || loadingComments) return $('#postComment').hide()
|
||||
|
||||
$('#message').text("Posting comment...")
|
||||
$('.postbutton').hide()
|
||||
allowEsc = false
|
||||
|
||||
fetch(`../api/profile/${username}`).then(res => res.json()).then(res => {
|
||||
if (!res || res == "-1") {$('.postbutton').show(); return $('#message').text("The username you provided doesn't exist!")}
|
||||
else accountID = res.accountID
|
||||
|
||||
$.post("../postComment", {comment, username, password, levelID, accountID, })
|
||||
.done(x => {
|
||||
$('#content').val("")
|
||||
$('#postComment').hide()
|
||||
$('.postbutton').show()
|
||||
$('#message').html(messageText)
|
||||
$('#timeSort').attr('src', "../assets/sort-time-on.png")
|
||||
$('#topSort').attr('src', "../assets/sort-likes.png")
|
||||
allowEsc = true
|
||||
mode = "time"
|
||||
page = 0
|
||||
appendComments()
|
||||
})
|
||||
.fail(e => {$('.postbutton').show();$('#message').text(e.responseText.includes("DOCTYPE") ? "Something went wrong..." : e.responseText)})
|
||||
})
|
||||
})
|
||||
|
||||
$(window).on('beforeunload ',function() {
|
||||
//0 - recent, 1 - top, 2 - recent/compact, 3 - top/compact
|
||||
localStorage.setItem('commentPreset', JSON.stringify({
|
||||
|
|
|
@ -94,14 +94,13 @@ infoText(accurateText)
|
|||
|
||||
function leaderboard() {
|
||||
|
||||
if (loading == true) return;
|
||||
|
||||
$('#searchBox').html(`<div style="height: 4.5%"></div>`)
|
||||
loading = true;
|
||||
$('#loading').show()
|
||||
|
||||
fetch(`../api/leaderboard?count=250&${type}`).then(res => res.json()).then(res => {
|
||||
|
||||
$('.ranking').remove()
|
||||
|
||||
res.forEach((x, y) => {
|
||||
|
||||
$('#searchBox').append(`<div class="searchresult leaderboardSlot">
|
||||
|
@ -117,7 +116,7 @@ function leaderboard() {
|
|||
${x.cp != 0 ? `${x.cp} <img class="valign" src="../assets/cp.png" style="cursor: help" title="Creator Points">` : ""}
|
||||
</h3>
|
||||
|
||||
<div class="center"
|
||||
<div class="center ranking"
|
||||
style="position:absolute; top: ${6.5 + (y * 26.572)}%; left: 3.5%; transform:scale(0.82); height: 10%; width: 12.5%;">
|
||||
<img class="spaced lazyLoad" data-src="./icon/${x.username}" height="150%"
|
||||
style="margin-bottom: 0%; transform:scale(1.1)">
|
||||
|
@ -127,7 +126,6 @@ function leaderboard() {
|
|||
})
|
||||
|
||||
$('#searchBox').append('<div style="height: 4.5%"></div>')
|
||||
loading = false;
|
||||
$('#loading').hide();
|
||||
$('.lazyLoad').Lazy({
|
||||
appendScroll: '#searchBox'
|
||||
|
@ -140,7 +138,7 @@ function leaderboard() {
|
|||
leaderboard()
|
||||
|
||||
$('#topTabOff').click(function() {
|
||||
if (type == "top" || loading) return;
|
||||
if (type == "top") return;
|
||||
type = "top"
|
||||
leaderboard()
|
||||
$('.leaderboardTab').hide();
|
||||
|
@ -151,7 +149,7 @@ function leaderboard() {
|
|||
})
|
||||
|
||||
$('#accurateTabOff').click(function() {
|
||||
if (type == "accurate" || loading) return;
|
||||
if (type == "accurate") return;
|
||||
type = "accurate"
|
||||
leaderboard()
|
||||
$('.leaderboardTab').hide();
|
||||
|
@ -162,7 +160,7 @@ function leaderboard() {
|
|||
})
|
||||
|
||||
$('#creatorTabOff').click(function() {
|
||||
if (type == "creator" || loading) return;
|
||||
if (type == "creator") return;
|
||||
type = "creator"
|
||||
leaderboard()
|
||||
$('.leaderboardTab').hide();
|
||||
|
|
4
index.js
4
index.js
|
@ -52,6 +52,10 @@ app.use('/difficulty', express.static(__dirname + '/assets/gdfaces', {maxAge: "7
|
|||
app.use('/iconkitbuttons', express.static(__dirname + '/assets/iconkitbuttons', {maxAge: "7d"}));
|
||||
app.use('/gdicon', express.static(__dirname + '/icons/iconkit', {maxAge: "7d"}));
|
||||
|
||||
app.post("/postComment", function(req, res) {
|
||||
app.modules.postComment(app, req, res)
|
||||
})
|
||||
|
||||
app.get("/api", function(req, res) {
|
||||
res.sendFile(__dirname + "/html/api.html")
|
||||
})
|
||||
|
|
|
@ -68,8 +68,10 @@
|
|||
],
|
||||
|
||||
"specialThanks": [
|
||||
["Qufyy", "qufy"],
|
||||
["Qufy", "Qufy"],
|
||||
["AlFas", "AlFas"],
|
||||
["ViPriN", "ViPriN"]
|
||||
["ViPriN", "ViPriN"],
|
||||
["NeKitDS", "NeKitDS"],
|
||||
["cos8o", "cos8o"]
|
||||
]
|
||||
}
|
|
@ -34,8 +34,10 @@ function backButton() {
|
|||
else window.location.href = "../../../../../"
|
||||
}
|
||||
|
||||
let allowEsc = true;
|
||||
$(document).keydown(function(k) {
|
||||
if (k.keyCode == 27) { //esc
|
||||
if (!allowEsc) return
|
||||
k.preventDefault()
|
||||
if ($('.popup').is(":visible")) $('.popup').hide();
|
||||
else $('#backButton').trigger('click')
|
||||
|
|
Loading…
Reference in a new issue