ADDED MESSAGES!!!

You can now read, write, and delete messages through GDBrowser!

Blocking and viewing sent messages have not been done yet.

Also, a message now appears if you're comment banned
This commit is contained in:
GDColon 2019-12-29 18:59:29 -05:00
parent cf6bc46304
commit 451c933301
27 changed files with 716 additions and 19 deletions

2
.gitignore vendored
View file

@ -64,3 +64,5 @@ typings/
# next.js build output
.next
misc/secretStuff.json
misc/secretStuff.json

View file

@ -0,0 +1,29 @@
const request = require('request')
const XOR = require('../../classes/XOR.js');
const xor = new XOR();
module.exports = async (app, req, res) => {
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!")
let params = {
accountID: req.body.accountID,
targetAccountID: req.body.accountID,
gjp: xor.encrypt(req.body.password, 37526),
secret: app.secret,
gameVersion: app.gameVersion,
binaryVersion: app.binaryVersion,
}
request.post(app.endpoint + 'getGJUserInfo20.php', {
form: params
}, async function (err, resp, body) {
if (err || body == '-1' || body == '-2' || !body) return res.status(400).send("Error fetching profile! Make sure your username and password are entered correctly.")
let count = app.parseResponse(body)[38]
if (!count) return res.status(400).send("Error fetching unread messages!")
else res.status(200).send(count)
})
}

View file

@ -6,6 +6,7 @@ module.exports = async (app, req, res, api) => {
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 (!req.body.id) return res.status(400).send("No message ID(s) provided!")
let params = {
accountID: req.body.accountID,

View file

@ -23,13 +23,17 @@ module.exports = async (app, req, res, api) => {
let x = app.parseResponse(body)
let msg = {}
msg.id = x[1];
msg.playerID = x[2]
msg.accountID = x[3]
msg.playerID = x[3]
msg.accountID = x[2]
msg.author = x[6]
msg.subject = Buffer.from(x[4], "base64").toString()
msg.content = xor.decrypt(x[5], 14251)
msg.date = x[7] + app.config.timestampSuffix
if (msg.subject.endsWith("☆")) {
msg.subject = msg.subject.slice(0, -1)
msg.browserColor = true
}
return res.status(200).send(msg)
})

View file

@ -4,6 +4,7 @@ const xor = new XOR();
module.exports = async (app, req, res, api) => {
if (req.body.count) return app.run.countMessages(app, req, res)
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!")
@ -14,7 +15,7 @@ module.exports = async (app, req, res, api) => {
secret: app.secret,
gameVersion: app.gameVersion,
binaryVersion: app.binaryVersion,
getSent: req.query.hasOwnProperty("sent") ? 1 : 0
getSent: req.query.sent ? 1 : 0
}
request.post(app.endpoint + 'getGJMessages20.php', {
@ -29,12 +30,16 @@ module.exports = async (app, req, res, api) => {
let msg = {}
msg.id = x[1];
msg.playerID = x[2]
msg.accountID = x[3]
msg.playerID = x[3]
msg.accountID = x[2]
msg.author = x[6]
msg.subject = Buffer.from(x[4], "base64").toString()
msg.date = x[7] + app.config.timestampSuffix
msg.unread = x[8] != "1"
if (msg.subject.endsWith("☆")) {
msg.subject = msg.subject.slice(0, -1)
msg.browserColor = true
}
messageArray.push(msg)
})

View file

@ -9,7 +9,7 @@ module.exports = async (app, req, res, api) => {
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!")
let subject = new Buffer(req.body.subject.slice(0, 50) || "No subject").toString('base64').replace(/\//g, '_').replace(/\+/g, "-")
let subject = new Buffer(req.body.subject ? (req.body.subject.slice(0, 50) + (req.body.color ? "☆" : "")) : "No subject").toString('base64').replace(/\//g, '_').replace(/\+/g, "-")
let body = xor.encrypt(req.body.message.slice(0, 300), 14251)
let params = {

View file

@ -50,6 +50,10 @@ module.exports = async (app, req, res) => {
}, 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! Try again later, or make sure your username and password are entered correctly.")
if (body.startsWith("temp")) {
let banStuff = body.split("_")
return res.status(400).send(`You have been banned from commenting for ${(parseInt(banStuff[1]) / 86400).toFixed(0)} days. Reason: ${banStuff[2]}`)
}
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-cancel-green.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 69 KiB

BIN
assets/check.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View file

@ -41,6 +41,10 @@ img, .noSelect {
max-width: 100%;
}
.fit {
width: fit-content;
}
.supercenter {
position: absolute;
top: 50%;
@ -302,6 +306,13 @@ input::-webkit-inner-spin-button {
border-image: url('./../assets/brownbox.png') 10% round;
}
.blueBox {
border: 2.5vh solid transparent;
border-radius: 3vh;
background-color: #334499;
border-image: url('./../assets/bluebox.png') 10% round;
}
.fancybox {
width: 69vh;
padding: 1vh 3vh;
@ -412,16 +423,20 @@ input::-webkit-inner-spin-button {
height: 11%
}
.msgAuthor:hover {
transform: scale(1.03);
}
.gdButton {
cursor: pointer;
z-index: 1;
user-select: none;
pointer-events: all;
transition-duration: 0.07s;
transition-timing-function: ease-in-out;
}
.gdButton:active {
transition-duration: 0.07s;
transition-timing-function: ease-in-out;
transform: scale(1.08);
}
@ -686,6 +701,110 @@ input::-webkit-inner-spin-button {
height: 5.5%;
}
#msgList {
margin: 2% auto;
width: 115vh;
height: 75%;
background-color: #BE6F3F;
overflow-y: scroll;
scrollbar-width: none;
-ms-overflow-style: none;
}
#msgList::-webkit-scrollbar {
width: 0;
height: 0;
}
#theMfMessage {
margin: 2% auto 1.2% auto;
width: 90%;
height: 65%;
display: table;
padding: 1% 3%;
}
#theMfMessage p {
white-space: normal;
vertical-align: middle;
display: table-cell;
font-size: 3.5vh;
}
#messageOptions img {
margin: 0% 5%;
}
.gdMessage {
text-align: left;
padding-left: 10%;
padding-top: 0.75%;
height: 12.5vh;
width: auto;
overflow: hidden;
cursor: pointer;
border: 0.6vh solid transparent;
transition-duration: 0.07s;
}
.gdMessage h3 {
font-size: 4vh;
min-height: 35%;
}
.gdMessage:hover {
border: 0.6vh solid rgba(0, 0, 0, 0.5);
}
/* .gdMessage:active {
box-shadow: inset 0px 0px 400px 400px rgba(0, 0, 0, .1);
} */
.messageInput {
font-size: 3.5vh;
text-align: left;
padding: 1.5%;
overflow: hidden;
background-color: rgba(0, 0, 0, 0.35);
}
.labelButton {
pointer-events: none;
position: relative;
bottom: 90%;
right: 9.25%;
}
.labelButton label {
padding: 3% 3.5%;
}
.xButton {
pointer-events: none;
position: relative;
bottom: 152%;
text-align: right;
margin-right: 2.5%;
}
#selectCount {
position: absolute;
bottom: 7.5%;
left: 4.8%;
background-color: red;
width: 4.5vh;
height: 4.5vh;
border-radius: 10vh;
border: 0.25vh solid white;
}
.msgDate {
text-align: left;
font-size: 1.9vh;
color: rgba(0, 0, 0, 0.5);
margin-top: 0.4%;
}
.specialThanks {
display: inline-block;
width: 27%;

BIN
assets/exclamation.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
assets/messagerope.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
assets/reply.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
assets/select-all.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
assets/select-none.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
assets/trash-square.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
assets/trash.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
assets/xbutton.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

View file

@ -1,5 +1,5 @@
const XOR = require(__dirname + "../../classes/XOR");
const config = require(__dirname + "../../misc/gdpsConfig");
const XOR = require(__dirname + "/../classes/XOR");
const config = require(__dirname + "/../misc/gdpsConfig");
let orbs = [0, 0, 50, 75, 125, 175, 225, 275, 350, 425, 500]
let length = ['Tiny', 'Short', 'Medium', 'Long', 'XL']

View file

@ -645,6 +645,7 @@
<br><p><b>/messages:</b></p>
<p>page: The page of the search</p>
<p>sent: Set to 1 or true to fetch your sent messages</p>
<p>count: Set to 1 or true to fetch your number of unread messages</p>
<br><p><b>/deleteMessage:</b></p>
<p>id: The ID of the message to delete, or an array of multiple IDs</p>
@ -653,6 +654,7 @@
<p>targetID: The account ID of the message recipient</p>
<p>subject: The subject of the message, max 50 characters</p>
<p>message: The content of the message, max 300 characters</p>
<p>color: If the message should have a special pink color on GDBrowser (optional)</p>
</div>
<br>

View file

@ -422,11 +422,16 @@ $(window).on('beforeunload ', function() {
localStorage.setItem('commentPreset', JSON.stringify({mode, compact}))
})
$('#content').keydown(function(k){
if (k.keyCode == 13) return false
$('#postComment').on("change keyup keydown paste click", "textarea", function () {
$('#content').val($('#content').val().replace(/[^\S ]+/g, ""))
})
$(document).keydown(function(k) {
if ($('#content').is(':visible')) {
if (k.which == 13) k.preventDefault() //enter
}
if (loadingComments || $('.popup').is(":visible")) return;
if (k.which == 37 && $('#pageDown').is(":visible")) { //left

View file

@ -31,6 +31,10 @@
<div style="position:absolute; top: -1.5%; right: 10%; text-align: right; width: 10%;">
<a href="../iconkit"><img class="iconRope" src="../assets/iconrope.png" width="40%"></a>
</div>
<div style="position:absolute; top: -1.7%; left: 5%; text-align: right; width: 10%;">
<a href="../messages"><img class="iconRope" src="../assets/messagerope.png" width="40%"></a>
</div>
<div class="supercenter center" id="menuButtons" style="bottom: 5%;">
<table>

508
html/messages.html Normal file
View file

@ -0,0 +1,508 @@
<head>
<title>Messages</title>
<meta charset="utf-8">
<link href="../css/browser.css" type="text/css" rel="stylesheet">
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135255146-3"></script>
<script>window.dataLayer = window.dataLayer || []; function gtag() { dataLayer.push(arguments); } gtag('js', new Date()); gtag('config', 'UA-135255146-3');</script>
<link rel="icon" href="../assets/messages.png">
<meta id="meta-title" property="og:title" content="Messages">
<meta id="meta-desc" property="og:description" content="Read, write, and delete your Geometry Dash messages!">
<meta id="meta-image" name="og:image" itemprop="image" content="https://gdbrowser.com/assets/messages.png">
</head>
<body class="levelBG" onbeforeunload="saveUrl()">
<div id="everything">
<div id="access">
<div class="brownbox center supercenter" style="height: 65%; width: 110vh">
<h1 class="smaller center" style="font-size: 5.5vh; margin-top: 1.5%">Sign In</h1>
<form>
<h3 class="center" style="margin-top: 4%">GD Username</h3>
<input type="text" name="gdbrowser" id="username" maxlength="50"
style="height: 8vh; width: 90%; text-align: center; margin-top: 0.5%">
<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%">
</form>
<div style="margin-bottom: 3%">
<p id="message" style="padding: 0% 10%; margin-top: 1.5%"></p>
</div>
<img src="../assets/btn-cancel.png" height=11%; class="gdButton postbutton center"
style="margin-right: 1%" onclick="backButton()">
<img src="../assets/btn-submit.png" type="submit" height=11%; class="gdButton postbutton center"
style="margin-left: 1%" id="logIn">
</div>
</div>
<div id="loading" style="display: none;">
<div class="brownbox center supercenter" style="height: 65%; width: 110vh">
<div style="position:absolute; top: 25%; width: 100%">
<p id="msgCount" style="font-size: 3.5vh; margin-bottom: 5%"></p>
<img class="spin noSelect" id="loadingicon" src="../assets/loading.png" width="10%">
</div>
</div>
</div>
<div id="messages" style="display: none;">
<div class="brownbox center supercenter" style="height: 85%; width: 138vh">
<h1 class="smaller center" style="font-size: 5.5vh; margin-top: 1.5%">Messages</h1>
<div class="lightBox center dragscroll" id="msgList" style="margin-bottom: 0.7%">
</div>
<div style="text-align: left">
<img class="gdButton inline" id="purge" src="../assets/trash-square.png" width="7%">
<div id="selectCount" style="display: none; pointer-events: none;">
<h3 class="center" style="font-size: 3vh; margin-top: 12%"></h3>
</div>
<img class="gdButton inline" id="selectAll" src="../assets/select-all.png" width="15%"
style="margin: 0% 0% 0.5% 2%">
<img class="gdButton inline" id="selectNone" src="../assets/select-none.png" width="15%"
style="display: none; margin: 0% 0% 0.5% 2%">
</div>
<img src="../assets/refresh.png" style="height: 13%;position: absolute;right: 0%;bottom: 0%;" onclick="page = 0; getMessages()" class="gdButton center sideSpaceB">
<div style="position: absolute; left: 0.5%; top: 45%; height: 11%;">
<img class="gdButton" style="display: none" id="pageDown" src="../assets/arrow-left.png"
height="90%">
</div>
<div style="position: absolute; right: 0.5%; top: 45%; height: 11%;">
<img class="gdButton" style="display: none" id="pageUp" src="../assets/arrow-right.png"
height="90%">
</div>
</div>
</div>
<div class="popup" id="confirmDelete" style="z-index: 3;">
<div class="fancybox bounce center supercenter" style="width: 47%; height: 25%">
<div id="preDelete">
<h2 class="smaller center" style="font-size: 5.5vh">Delete</h2>
<p class="bigger center" style="line-height: 6vh; margin-top: 1.5vh;">
Are you sure you want to <span style="color: #F05C5C">delete</span> this message?
</p>
<img src="../assets/btn-cancel.png" height=29%; class="gdButton center"
onclick="$('#confirmDelete').hide()">
<img src="../assets/btn-delete.png" height=29%; id="deleteCurrentMessage"
class="gdButton center sideSpaceB">
</div>
<div id="deleting" style="display: none">
<h2 class="smaller center" style="font-size: 5.5vh">Delete</h2>
<p class="bigger center" style="line-height: 6vh; margin-top: 1.5vh;">Deleting message...</p>
<img src="../assets/loading.png" class="spin noSelect" style="height: 35%; margin-top: -2%">
</div>
</div>
</div>
<div class="popup" id="bulkDelete">
<div class="fancybox bounce center supercenter" style="width: 47%; height: 25%">
<div id="preBulkDelete">
<h2 class="smaller center" style="font-size: 5.5vh">Bulk Delete</h2>
<p class="bigger center" style="line-height: 6vh; margin-top: 1.5vh;">
Are you sure you want to <span style="color: #F05C5C">delete</span> <span class="selectedAmount"
style="color: yelow"></span>?
</p>
<img src="../assets/btn-cancel-green.png" height=29%; class="gdButton center"
onclick="$('#bulkDelete').hide()">
<img src="../assets/btn-delete.png" height=29%; id="bulkDeleteMessages"
class="gdButton center sideSpaceB">
</div>
<div id="bulkDeleting" style="display: none">
<h2 class="smaller center" style="font-size: 5.5vh">Delete</h2>
<p class="bigger center" style="line-height: 6vh; margin-top: 1.5vh;">Deleting <span
class="selectedAmount"></span>...</p>
<img src="../assets/loading.png" class="spin noSelect" style="height: 35%; margin-top: -2%">
</div>
</div>
</div>
<div id="selectedMessage" class="popup">
<div class="bounce center supercenter" style="height: 70%; width: 115vh">
<div class="bluebox center supercenter" style="width: 100%; height: 100%">
<img class="gdButton" src="../assets/close.png" width="9%"
style="position: absolute; top: -7.5%; left: -6.5vh" onclick="$('#selectedMessage').hide()">
<h1 id="messageSubject" class="smaller center"
style="font-size: 5.5vh; min-height: 9%; margin-top: 1%"></h1>
<h3 id="messageAuthor" class="gold center gauntletText gdButton"></h3>
<div class="transparentBox center dragscroll" id="theMfMessage">
<img id="messageLoad" src="../assets/loading.png" class="spin noSelect"
style="width: 10%; margin-top: 15%">
<p id="messageBody"></p>
</div>
<div id="messageOptions">
<img class="gdButton" style="width: 8%" title="Reply" src="../assets/reply.png" id="replyButton">
<img class="gdButton" style="width: 8%" title="Delete" src="../assets/trash.png"
onclick="$('#confirmDelete').show()">
</div>
</div>
</div>
</div>
<div id="sendMessage" class="popup">
<div class="bounce center supercenter" style="height: 70%; width: 115vh">
<div class="bluebox center supercenter" style="width: 100%; height: 100%">
<h1 id="sendreply" class="smaller center" style="font-size: 5.5vh; min-height: 9%; margin-top: 1%">Send Reply</h1>
<h3 id="replyAuthor" class="gold center gauntletText gdButton" style="min-height: 6.2%"></h3>
<div id="textareas">
<textarea id="postSubject" maxlength="50" style="height: 7vh; white-space: nowrap !important;"
class="messageInput" placeholder="Subject"></textarea>
<textarea id="postContent" maxlength="300" style="height: 35vh" class="messageInput"
placeholder="Message"></textarea>
</div>
<p id="messageStatus" style="margin: 1% 0% 1.5% 0%; min-height: 5%;"></p>
<img src="../assets/btn-cancel.png" height=10%; class="gdButton center"
onclick="$('textarea').val(''); $('#sendMessage').hide()">
<img src="../assets/btn-submit.png" height=10%; id="postMessage" class="gdButton center sideSpaceB">
<img src="../assets/refresh.png" style="height: 10%; position: absolute; right: 0%"
onclick="$('#postContent').val('');" class="gdButton center sideSpaceB">
</div>
</div>
</div>
<div class="popup" id="postingMessage" style="z-index: 3">
<div class="bluebox bounce center supercenter" style="height: 27%; width: 55vh">
<div id="reply-loading">
<img src="../assets/loading.png" class="spin noSelect" style="height: 40%; margin-top: 7.5%">
<p class="bigger">Sending...</p>
</div>
<div id="reply-sent" style="display: none;">
<img class="gdButton" src="../assets/close.png" style="width: 15%; position: absolute; top: -17.5%; left: -5.5vh" onclick="$('.popup').hide()">
<img src="../assets/check.png" style="height: 40%; margin-top: 7.5%">
<p class="bigger">Message sent!</p>
</div>
<div id="reply-error" style="display: none;">
<img class="gdButton" src="../assets/close.png" style="width: 15%; position: absolute; top: -17.5%; left: -5.5vh" onclick="$('.popup').hide()">
<img src="../assets/exclamation.png" style="height: 40%; margin-top: 7.5%">
<p class="bigger" style="margin-bottom: 0%;">Something went wrong!</p>
<p style="font-size: 2.4vh; margin-top: 1%">Does the recipient have messages enabled?</p>
</div>
</div>
</div>
<div style="position:absolute; bottom: 0%; left: 0%; width: 100%; pointer-events: none;">
<img class="cornerPiece" src="../assets/corner.png" width=7%;>
</div>
<div style="position:absolute; bottom: 0%; right: 0%; width: 100%; text-align: right; pointer-events: none;">
<img class="cornerPiece" src="../assets/corner.png" width=7%; style="transform: scaleX(-1)">
</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>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script async type="text/javascript" src="../assets/sizecheck.js"></script>
<script type="text/javascript" src="../assets/dragscroll.js"></script>
<script>
let accountID;
let password;
let page = 0;
let messageID = 0;
let authorID = 0;
let messages = [];
let messageStatus = {};
let cache = {};
let loading = false;
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> For security, it will be <span style="color:yellow">forgotten</span> when you exit this page.'
$('#message').html(messageText)
function appendMessages(dontCheckPages) {
if (!dontCheckPages) {
if (page > 0) $('#pageDown').show()
else $('#pageDown').hide()
if (messages.length >= 48) $('#pageUp').show()
else $('#pageUp').hide()
}
$('#selectCount').hide()
$('#selectAll').show()
$('#selectNone').hide()
$('#msgList').html('')
messages.forEach((x, y) => {
$('#msgList').append(`
<div messageID=${x.id} authorID="${x.accountID}" ${x.browserColor ? 'browserColor="true" ' : ""}class="commentBG gdMessage">
<h3 style="color: ${x.browserColor ? 'rgb(120, 200, 255)' : 'white'}; font-size: ${x.subject.length > 35 ? "3" : x.subject.length > 30 ? "3.5" : x.subject.length > 25 ? "3.75" : "4"}vh">${x.subject}${x.unread ? " <span style='color:#00E600'>!</span>" : ""}</h3>
<h3 class="gold gdButton msgAuthor hitbox fit"><a href="../profile/${x.author}" target="_blank">From: ${x.author}</a></h3>
<p class="msgDate">${x.date}</p>
<div class="labelButton hitbox">
<input id="message-${y}" type="checkbox" class="chk" messageID=${x.id}>
<label for="message-${y}" class="gdcheckbox gdButton"></label>
</div>${/*
<div class="xButton hitbox">
<img class="gdButton" style="width: 8%" src="../assets/xbutton.png">
</div>*/""}
</div>`)
})
loading = false
}
$('#logIn').click(function () {
let username = $('#username').val()
password = $('#password').val()
accountID = 0
if (!username || !password) return;
$('#message').text("Logging in...")
$('.postbutton').hide()
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("../messages", { password, accountID, count: true })
.done(count => {
$('#msgCount').html(`Loading <span style="color: yellow">${count}</span> unread messages...`)
$('#access').hide()
$('#loading').show()
$.post("../messages", { password, accountID })
.done(msgs => {
messages = msgs
$('#loading').hide()
appendMessages()
$('#messages').show()
let targetUser = window.location.search.match(/\?sendTo=(.+)/)
if (targetUser) {
targetUser = decodeURIComponent(targetUser[1])
fetch(`../api/profile/${targetUser}`).then(res => res.json()).then(res => {
if (res == "-1" || !res) return;
$('#replyAuthor').html(`<a href="../profile/${res.username}" target="_blank">To: ${res.username}</a>`)
messageStatus[res.accountID] = [res.messages, res.username]
authorID = res.accountID
if (res.messages == "all") $('#messageStatus').html(`<span style="color:yellow">${res.username}</span> has messages <span style="color:lime">enabled</span>`)
else if (res.messages == "friends") $('#messageStatus').html(`<span style="color:yellow">${res.username}</span> has messages set to <span style="color:orange">friends only</span>`)
else {
$('#messageStatus').html(`<span style="color:yellow">${res.username}</span> has messages <span style="color:#F05C5C">disabled</span>`)
$('#postMessage').addClass('grayscale')
}
$('#sendMessage').show()
$('#sendreply').text("Send Message")
})
}
})
.fail(e => { $('#loadingicon').hide(); $('#msgCount').text(e.responseText.includes("DOCTYPE") ? "Something went wrong..." : e.responseText) })
})
.fail(e => { $('.postbutton').show(); $('#message').text(e.responseText.includes("DOCTYPE") ? "Something went wrong..." : e.responseText) })
})
})
function getMessages() {
loading = true
$('#selectCount').hide()
$('#selectAll').show()
$('#selectNone').hide()
$('#msgList').html('<img src="../assets/loading.png" class="spin noSelect" style="margin-top: 20%; height: 20%;">')
$.post("../messages", { password, accountID, page })
.done(msgs => {
messages = msgs
appendMessages()
})
}
$(document).on('click', '.hitbox', function (x) {
x.stopImmediatePropagation();
})
$(document).on('mouseover', '.hitbox', function (x) {
$('.gdMessage').css('border', '0.6vh solid transparent')
})
$(document).on('mouseleave', '.hitbox', function (x) {
$('.gdMessage').removeAttr('style');
})
$(document).on('change', '.chk', function () {
let checked = $(document).find('.chk:checked').length
if (checked == 0) $('#selectCount').hide()
else $('#selectCount').show().children().text(checked)
})
$(document).on('click', '.gdMessage', function () {
messageID = $(this).attr('messageID')
authorID = $(this).attr('authorID')
let subject = $(this).find('h3:first')
subject.html(subject.html().replace('<span style="color:#00E600">!</span>', "")) //lazy way to mark as read
$('#messageSubject').attr('style', `color: ${$(this).attr('browserColor') ? 'rgb(120, 200, 255)' : "white"}`).text(subject.text())
$('#messageAuthor').html($(this).find('.gdButton').html())
$('#messageBody').text('').hide()
$('#messageLoad').show()
$('#selectedMessage').show()
$('textarea').val('');
$('#replyAuthor').html($(this).find('.gdButton').html().replace("From:", "To:"))
$('#postSubject').val("Re: " + subject.text())
if (cache[messageID]) {
$('#messageBody').attr('style', `color: ${cache[messageID][1] ? 'rgb(255, 140, 255)' : "white"}`).text(cache[messageID][0]).show()
$('#messageLoad').hide()
}
else $.post("../messages/" + messageID, { password, accountID })
.done(msg => {
cache[messageID] = [msg.content, msg.browserColor]
function loadMsg() {
$('#messageBody').attr('style', `color: ${msg.browserColor ? 'rgb(255, 140, 255)' : "white"}`).text(msg.content).show()
$('#messageLoad').hide()
}
if (!messageStatus[msg.accountID]) fetch(`../api/profile/${msg.author}`).then(res => res.json()).then(res => {
messageStatus[msg.accountID] = [res.messages, msg.author]
loadMsg()
})
else {
loadMsg()
}
})
})
$('#deleteCurrentMessage').click(function () {
allowEsc = false
$('#preDelete').hide()
$('#deleting').show()
$.post("../deleteMessage/", { password, accountID, id: messageID })
.done(msg => {
messages = messages.filter(x => x.id != messageID)
appendMessages(true)
allowEsc = true
$('#selectedMessage').hide()
$('#confirmDelete').hide()
$('#preDelete').show()
$('#deleting').hide()
})
})
$('#purge').click(function () {
let checked = $(document).find('.chk:checked').length
if (checked == 0) return
let selectStr = checked + " message" + (checked != 1 ? "s" : "")
$('.selectedAmount').text(selectStr)
$('#bulkDelete').show()
})
$('#bulkDeleteMessages').click(function () {
allowEsc = false
let msgIDs = []
$('.chk:checked').each(function () { msgIDs.push($(this).attr('messageID')) })
$('#preBulkDelete').hide()
$('#bulkDeleting').show()
$.post("../deleteMessage/", { password, accountID, id: msgIDs })
.done(msg => {
if (msgIDs.length > 10) getMessages()
else {
messages = messages.filter(x => !msgIDs.includes(x.id))
appendMessages(true)
}
allowEsc = true
$('#bulkDelete').hide()
$('#preBulkDelete').show()
$('#bulkDeleting').hide()
})
})
$('#replyButton').click(function() {
if (!messageStatus[authorID]) return;
let status = messageStatus[authorID][0]
let name = messageStatus[authorID][1]
$('#postMessage').removeClass('grayscale')
if (status == "all") $('#messageStatus').html(`<span style="color:yellow">${name}</span> has messages <span style="color:lime">enabled</span>`)
else if (status == "friends") $('#messageStatus').html(`<span style="color:yellow">${name}</span> has messages set to <span style="color:orange">friends only</span>`)
else {
$('#messageStatus').html(`<span style="color:yellow">${name}</span> has messages <span style="color:#F05C5C">disabled</span>`)
$('#postMessage').addClass('grayscale')
}
$('#sendreply').text("Send Reply")
$('#sendMessage').show()
})
$('#postMessage').click(function () {
let subject = $('#postSubject').val()
let message = $('#postContent').val()
if (!subject || !message || !messageStatus[authorID] || messageStatus[authorID][0] == "off") return;
allowEsc = false
$('#reply-loading').show()
$('#reply-sent').hide()
$('#reply-error').hide()
$('#postingMessage').show()
$.post("../sendMessage/", { password, accountID, subject, message, targetID: authorID, color: true })
.done(msg => {
$('#reply-loading').hide()
$('#reply-sent').show()
allowEsc = true
})
.fail(e => {
$('#reply-loading').hide()
$('#reply-error').show()
allowEsc = true
})
})
$('#pageUp').click(function () { page += 1; getMessages() })
$('#pageDown').click(function () { page -= 1; getMessages() })
$('#selectAll').click(function () {
$('#selectAll').hide()
$('#selectNone').show()
$('.chk').prop('checked', true).trigger('change')
})
$('#selectNone').click(function () {
$('#selectAll').show()
$('#selectNone').hide()
$('.chk').prop('checked', false).trigger('change')
})
$('#textareas').on("change keyup keydown paste click", "textarea", function () {
$('textarea').each(function () {
$(this).val($(this).val().replace(/[^\S ]+/g, ""))
})
});
$(document).keydown(function (k) {
if (loading) return;
if ($('#access').is(':visible')) {
if (k.which == 13) $('#logIn').trigger('click') //enter
else return;
}
if ($('textarea').is(':visible')) {
if (k.which == 13) k.preventDefault() //enter
}
if (k.which == 37 && $('#pageDown').is(":visible") && !$('.popup').is(":visible")) { //left
$('#pageDown').trigger('click')
}
if (k.which == 39 && $('#pageUp').is(":visible") && !$('.popup').is(":visible")) { //right
$('#pageUp').trigger('click')
}
});
</script>

View file

@ -106,7 +106,7 @@
</div>
<div class="center" style="margin: 1.5% auto 2.5% auto;">
<img src="../assets/messages.png" height="10%" id="msgButton" class="sideSpace gdButton" onclick="$('#settingsDiv').show()">
<a id="msgA" target="_blank"><img src="../assets/messages.png" height="10%" id="msgButton" class="sideSpace gdButton" onclick="$('#settingsDiv').show()"></a>
<img src="../assets/friends.png" height="10%" id="friendButton" class="sideSpace gdButton" onclick="$('#settingsDiv').show()">
<a href="../search/[[USERNAME]]?user"><img height="10%" src="../assets/levels.png" class="sideSpace gdButton"></a>
</div>
@ -175,6 +175,11 @@ else {
$('#commentA').attr('href', '../comments/[[USERNAME]]')
}
if (messages == "all") {
$('#msgButton').attr('onclick', '')
$('#msgA').attr('href', '../messages?sendTo=[[USERNAME]]')
}
if (messages == "friends") $('#msgButton').attr('src', '../assets/messages-yellow.png')
else if (messages == "off") $('#msgButton').attr('src', '../assets/messages-grey.png')
@ -183,7 +188,7 @@ if (![[FRIENDREQUESTS]]) $('#friendButton').attr('src', '../assets/friends-grey.
$('#userInfo').html($('#userInfo').html()
.replace("[[REQS]]", reqMode)
.replace("[[DMS]]", dmMode)
.replace("[[COMMENTS]]", commentMode))
.replace("[[COMMENTS]]", commentMode) + (messages == "friends" ? "<br style='line-height: 69%'><span style='color: lime' class='youCanClickThis2'><a target='_blank' href='../messages?sendTo=[[USERNAME]]'>Send message</a></span><br>(if friended)" : ""))
function appendComments() {
@ -329,8 +334,16 @@ $('#submitVote').click(function() {
})
})
$(document).keydown(function(k){
if (k.keyCode == 13) return false
$('#leavePost').on("change keyup keydown paste click", "textarea", function () {
$('#content').val($('#content').val().replace(/[^\S ]+/g, ""))
})
$(document).keydown(function(k) {
if ($('#content').is(':visible')) {
if (k.which == 13) k.preventDefault() //enter
}
})

View file

@ -78,8 +78,8 @@ app.post("/like", function(req, res) { app.run.like(app, req, res) })
app.post("/postComment", function(req, res) { app.run.postComment(app, req, res) })
app.post("/postProfileComment", function(req, res) { app.run.postProfileComment(app, req, res) })
app.post("/messages", async function(req, res) { app.run.getMessages(app, req, res, api) })
app.post("/messages/:id", async function(req, res) { app.run.fetchMessage(app, req, res, api) })
app.post("/messages", async function(req, res) { app.run.getMessages(app, req, res) })
app.post("/messages/:id", async function(req, res) { app.run.fetchMessage(app, req, res) })
app.post("/deleteMessage", function(req, res) { app.run.deleteMessage(app, req, res) })
app.post("/sendMessage", function(req, res) { app.run.sendMessage(app, req, res) })
@ -95,6 +95,7 @@ app.get("/iconkit", function(req, res) { res.sendFile(__dirname + "/html/iconkit
app.get("/leaderboard", function(req, res) { res.sendFile(__dirname + "/html/leaderboard.html") })
app.get("/leaderboard/:text", function(req, res) { res.sendFile(__dirname + "/html/levelboard.html") })
app.get("/mappacks", function(req, res) { res.sendFile(__dirname + "/html/mappacks.html") })
app.get("/messages", function(req, res) { res.sendFile(__dirname + "/html/messages.html") })
app.get("/search", function(req, res) { res.sendFile(__dirname + "/html/filters.html") })
app.get("/search/:text", function(req, res) { res.sendFile(__dirname + "/html/search.html") })