Updated 6 files and added 9 files (automated)

mane
Mia Raindrops 2 months ago
parent d08872c5ca
commit 17694a2661
Signed by: Mia Raindrops
GPG Key ID: EFBDC68435A574B7

@ -0,0 +1,12 @@
{
"configurations": [
{
"type": "command",
"name": "Client",
"program": "$PROJECT_DIR$/launcher/client/node_modules/electron/dist/Electron.app/Contents/MacOS/Electron",
"args": ["main.js", "$PROJECT_DIR$/client"],
"workingDir": "$PROJECT_DIR$/launcher/client",
},
]
}

@ -91,6 +91,36 @@ commands = {
user: argument
});
},
"ops": (argument, _) => {
send({
server: true,
type: "ops"
});
},
"op": (argument, _) => {
if (argument.trim() === "") {
localSystemMessage("Please specify the IP address of a client you want to make an operator");
return;
}
send({
server: true,
type: "op",
user: argument
});
},
"deop": (argument, _) => {
if (argument.trim() === "") {
localSystemMessage("Please specify the IP address of a client you want to not make an operator");
return;
}
send({
server: true,
type: "deop",
user: argument
});
},
"msg": (argument, _) => {
let parts = argument.split(" ");
@ -146,11 +176,14 @@ commands = {
},
"help": (_1, _2) => {
localSystemMessage("Available commands: " + Object.keys(commands).filter(i => i !== "_").sort((a, b) => a.localeCompare(b)).join(", "));
},
"reload": (_1, _2) => {
location.reload();
}
}
function runCommand(message) {
let words = message.substring(1).split(" ").filter(i => i.trim() !== "");
let words = message.replaceAll(" ", " ").trim().substring(1).split(" ").filter(i => i.trim() !== "");
let command = stripHTML(words[0]);
words.shift();
let argument = words.join(" ");

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 96 960 960" width="48" fill="#e0e3e2"><path d="m81 976 800-800v800H81Z"/></svg>

After

Width:  |  Height:  |  Size: 142 B

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 96 960 960" width="48" fill="#e0e3e2"><path d="m81 976 800-800v800H81Zm525-60h215V320L606 535v381Z"/></svg>

After

Width:  |  Height:  |  Size: 170 B

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 96 960 960" width="48" fill="#e0e3e2"><path d="m81 976 800-800v800H81Zm445-60h295V320L526 615v301Z"/></svg>

After

Width:  |  Height:  |  Size: 170 B

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 96 960 960" width="48" fill="#e0e3e2"><path d="m81 976 800-800v800H81Zm325-60h415V320L406 735v181Z"/></svg>

After

Width:  |  Height:  |  Size: 170 B

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 96 960 960" width="48" fill="#e0e3e2"><path d="m79 976 800-800v800H79Zm144-60h596V320L223 916Z"/></svg>

After

Width:  |  Height:  |  Size: 166 B

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 96 960 960" width="48" fill="#e0e3e2"><path d="m676 942-42-42 84-84-84-84 42-42 84 84 84-84 42 42-83 84 83 84-42 42-84-83-84 83ZM80 976l800-800v466q-14-9-28.5-16.5T820 613V320L224 916h350q9 17 21.5 32t26.5 28H80Zm144-60 596-596-183 183-140.5 140.5-128 128L224 916Z"/></svg>

After

Width:  |  Height:  |  Size: 336 B

@ -1,11 +1,11 @@
<!DOCTYPE html>
<html>
<html> <!-- 006a6c -->
<head>
<script>
window.version = "2.0-dev.m2.2023-04-16";
window.version = "2.0-dev.m2.2023-04-17";
</script>
<meta charset="UTF-8">
<title>LocalChat</title>
<title>Localchat</title>
<script src="../shared/crypt.js"></script>
<script src="commands.js"></script>
<script type="text/javascript" src="lib/purify.min.js"></script>
@ -24,6 +24,13 @@
outline: none;
}
.message-badge {
vertical-align: middle;
height: 16px;
width: 16px;
margin-left: 3px;
}
#chat-log {
position: fixed;
top: 34px;
@ -32,6 +39,7 @@
bottom: 48px;
padding: 20px 20px 28px;
overflow-y: auto;
z-index: -1;
}
#input {
@ -70,7 +78,7 @@
height: 34px;
-webkit-app-region: drag;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-columns: 1fr max-content;
color: #e0e3e2;
font-size: 14px;
}
@ -83,11 +91,29 @@
padding-right: 138px;
}
#title-bar-user {
padding: 0 5px;
}
#title-bar-status {
padding: 0 5px;
}
#title-bar-signal {
width: 24px;
}
#title-bar.platform-mac #title-bar-status {
padding-right: 10px !important;
}
#title-bar.platform-windows #title-bar-user {
padding-left: 10px !important;
}
#title-bar > div {
display: flex;
align-items: center;
text-align: center;
justify-content: center;
}
.message {
@ -552,11 +578,12 @@
</div>
<div id="title-bar">
<div>
<div id="title-bar-user">
<b>Localchat</b>
</div>
<div><span id="users">-</span>&nbsp;online</div>
<div id="ping">Offline</div>
<div id="title-bar-status">
<img src="icons/signal-none.svg" id="title-bar-signal">
</div>
</div>
<script>
if (require('os').platform() === "darwin") {
@ -567,7 +594,7 @@
</script>
<div id="chat-log"></div>
<div id="input">
<a class="input-icon" onclick="if (window.connected) uploadFile();"><img src="icons/upload.svg"></a>
<a title="Upload a file" class="input-icon" onclick="if (window.connected) uploadFile();"><img src="icons/upload.svg"></a>
<div contenteditable="true" style="font-family: inherit; font-size: 14px;" id="input-text">&nbsp;</div>
<div style="font-family: inherit; font-size: 14px; opacity: .5;" id="input-text-placeholder">Send a message</div>
</div>
@ -624,6 +651,7 @@
window.files = {};
window.ping = -1;
window.displayedMessages = [];
window.isAdmin = false;
setInterval(() => {
if (JSON.stringify(messages) !== lastMessages) {
@ -645,9 +673,7 @@
let willScroll = false;
let el = document.getElementById("chat-log");
if (el.scrollTop === el.scrollHeight) {
willScroll = true;
} else if (Math.abs(el.scrollTop - el.scrollHeight) < 10) {
if (el.scrollTop !== el.scrollHeight) {
willScroll = true;
} else if (!document.hasFocus()) {
willScroll = true;
@ -659,7 +685,7 @@
${message['type'] === "text" ? `
<div class="message user-message" id="message-${message['_id']}">
<span class="message-date" title="${new Date(message['date']).toString()}">${new Date(message['date']).toTimeString().split(":").splice(0, 2).join(":")}</span>
<span class="message-author" style="-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-image: linear-gradient(90deg, #${stripHTML(message['colors'][0])} 0%, #${stripHTML(message['colors'][1])} 100%)" title="${stripHTML(message['_source'])}">${stripHTML(message['author'])}</span>
<span class="message-author" style="-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-image: linear-gradient(90deg, #${stripHTML(message['colors'][0])} 0%, #${stripHTML(message['colors'][1])} 100%)" title="${stripHTML(message['_source'])}">${stripHTML(message['author'])}${message['admin'] ? `<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 96 960 960" width="48" class="message-badge" fill="#${stripHTML(message['colors'][1])}"><path d="M480 975q-140-35-230-162.5T160 533V295l320-120 320 120v238q0 152-90 279.5T480 975Zm0-62q115-38 187.5-143.5T740 533V337l-260-98-260 98v196q0 131 72.5 236.5T480 913Zm0-337Z"/></svg>` : ``}</span>
<span class="message-text">${DOMPurify.sanitize(marked.parse(message['text'].replaceAll("\r\n", "\n").replaceAll("\n", "<br>"))).replaceAll("<p>", "").replaceAll("</p>", "").replaceAll("&lt;br&gt;", "<br>")}</span>
</div>
` : (message['type'] === "system" ? `
@ -810,13 +836,12 @@
}
if (!window.banned && !window.connected && window.reconnect && !showedServerErrorMessage) {
localSystemMessage("Unable to connect with the Localchat server at " + window.serverURL + ", make sure the server is turned on");
localSystemMessage("Unable to connect to the Localchat server at " + window.serverURL + ", make sure the server is turned on");
}
window.connected = false;
console.log(e);
document.getElementById("ping").innerText = "Offline";
document.getElementById("users").innerText = "-";
document.getElementById("title-bar-signal").src = "icons/signal-none.svg";
clearInterval(wsPingInterval);
if (!showedServerErrorMessage) {
@ -912,9 +937,20 @@
console.log(decrypted);
displayMessages();
} else if (data.type === "pong") {
document.getElementById("users").innerText = data.users;
document.getElementById("ping").innerText = (new Date().getTime() - data.original.date).toString() + " ms";
window.isAdmin = data.admin;
window.ping = new Date().getTime() - data.original.date;
if (window.ping < 100) {
document.getElementById("title-bar-signal").src = "icons/signal-0.svg";
} else if (window.ping < 200) {
document.getElementById("title-bar-signal").src = "icons/signal-100.svg";
} else if (window.ping < 300) {
document.getElementById("title-bar-signal").src = "icons/signal-200.svg";
} else if (window.ping < 400) {
document.getElementById("title-bar-signal").src = "icons/signal-300.svg";
} else {
document.getElementById("title-bar-signal").src = "icons/signal-400.svg";
}
}
}
}
@ -1074,6 +1110,7 @@
send(obj);
obj['_source'] = "localhost";
obj['_id'] = uuid();
obj['admin'] = window.isAdmin;
messages.push(obj);

@ -20,8 +20,8 @@ const createWindow = () => {
vibrancy: "menu",
frame: false,
titleBarOverlay: {
color: "#151515",
symbolColor: "#ffffff",
color: "#191c1c",
symbolColor: "#e0e3e2",
height: 34
},
trafficLightPosition: {

@ -12,6 +12,7 @@ const createWindow = () => {
icon: require('os').platform() ? "./icon.icns" : "./icon.ico",
resizable: false,
maximizable: false,
show: false,
minimizable: false,
disableAutoHideCursor: true,
backgroundColor: "#111111",
@ -35,11 +36,15 @@ const createWindow = () => {
require(path + "/main.js");
});
if (process.argv[1]) {
loaderWindow.send("local", process.argv[1]);
} else {
loaderWindow.send("download");
}
loaderWindow.once("ready-to-show", () => {
loaderWindow.show();
if (process.argv[1]) {
loaderWindow.send("local", process.argv[1]);
} else {
loaderWindow.send("download");
}
});
}
app.whenReady().then(() => {

@ -1,5 +1,5 @@
{
"version": "1.0.0",
"version": "1.2.0",
"dependencies": {
"@electron/remote": "^2.0.9",
"axios": "^1.3.5",

@ -6,7 +6,7 @@ const fs = require('fs');
const crypto = require('crypto');
const zlib = require("zlib");
const version = "1.6-dev";
const version = "1.8-dev";
const port = 27342;
function log(message, address) {
@ -67,6 +67,11 @@ readline.question("Enter the IP address users would use to connect to the server
let clients = [];
log("Loaded ban list");
log("Loading operators list...");
if (!fs.existsSync("./ops.json")) fs.writeFileSync("./ops.json", "[]");
let operators = JSON.parse(fs.readFileSync("./ops.json").toString());
log("Loaded operators list");
function parseAddress(address) {
if (address.startsWith("::ffff:")) {
return address.substring(7);
@ -314,15 +319,27 @@ readline.question("Enter the IP address users would use to connect to the server
}));
log("Requested ban list", ws.address);
} else if (message.type === "ops") {
ws.send(JSON.stringify({
type: "encrypted",
source: ws.address,
message: encrypt(JSON.stringify({
type: "system",
date: new Date().getTime(),
text: operators.length > 0 ? "Server operators: " + operators.join(", ") : "There are no additional operators"
}), ws.publicKey)
}));
log("Requested operators list", ws.address);
} else if (message.type === "ban") {
if (ws.address !== "::1" && !ws.address.startsWith("127.")) {
if (ws.address !== "::1" && !ws.address.startsWith("127.") && !operators.includes(ws.address)) {
ws.send(JSON.stringify({
type: "encrypted",
source: ws.address,
message: encrypt(JSON.stringify({
type: "system",
date: new Date().getTime(),
text: "Only the server owner can use the /ban command"
text: "Only server operators can use the /ban command"
}), ws.publicKey)
}));
@ -373,7 +390,7 @@ readline.question("Enter the IP address users would use to connect to the server
type: "system",
date: new Date().getTime(),
text: ws.address + " blocked " + message.user
}), ws.publicKey)
}), socket.publicKey)
}));
} catch (e) {}
}
@ -383,14 +400,14 @@ readline.question("Enter the IP address users would use to connect to the server
log("Banned user " + message.user, ws.address);
}
} else if (message.type === "unban") {
if (ws.address !== "::1" && !ws.address.startsWith("127.")) {
if (ws.address !== "::1" && !ws.address.startsWith("127.") && !operators.includes(ws.address)) {
ws.send(JSON.stringify({
type: "encrypted",
source: ws.address,
message: encrypt(JSON.stringify({
type: "system",
date: new Date().getTime(),
text: "Only the server owner can use the /unban command"
text: "Only server operators can use the /unban command"
}), ws.publicKey)
}));
@ -430,7 +447,7 @@ readline.question("Enter the IP address users would use to connect to the server
type: "system",
date: new Date().getTime(),
text: ws.address + " unblocked " + message.user
}), ws.publicKey)
}), socket.publicKey)
}));
} catch (e) {}
}
@ -439,6 +456,152 @@ readline.question("Enter the IP address users would use to connect to the server
log("Unbanned user " + message.user, ws.address);
fs.writeFileSync("./bans.json", JSON.stringify(bans));
}
} else if (message.type === "op") {
if (ws.address !== "::1" && !ws.address.startsWith("127.")) {
ws.send(JSON.stringify({
type: "encrypted",
source: ws.address,
message: encrypt(JSON.stringify({
type: "system",
date: new Date().getTime(),
text: "Only the server owner can use the /op command"
}), ws.publicKey)
}));
log("Permission denied while running op", ws.address);
} else if (operators.includes(message.user)) {
ws.send(JSON.stringify({
type: "encrypted",
source: ws.address,
message: encrypt(JSON.stringify({
type: "system",
date: new Date().getTime(),
text: message.user + " is already operator on this server"
}), ws.publicKey)
}));
log("Failed to op " + message.user + ": user is already operator", ws.address);
} else {
operators.push(message.user);
for (let socket of clients) {
if (socket.address === message.user) {
try {
socket.send(JSON.stringify({
type: "encrypted",
source: ws.address,
message: encrypt(JSON.stringify({
type: "system",
date: new Date().getTime(),
text: "You are now a server operator"
}), socket.publicKey)
}));
} catch (e) {}
}
}
ws.send(JSON.stringify({
type: "encrypted",
source: ws.address,
message: encrypt(JSON.stringify({
type: "system",
date: new Date().getTime(),
text: "Successfully made " + message.user + " a server operator"
}), ws.publicKey)
}));
for (let socket of clients) {
if (socket.address !== ws.address) {
try {
socket.send(JSON.stringify({
type: "encrypted",
source: ws.address,
message: encrypt(JSON.stringify({
type: "system",
date: new Date().getTime(),
text: ws.address + " made " + message.user + " a server operator"
}), socket.publicKey)
}));
} catch (e) {}
}
}
fs.writeFileSync("./operators.json", JSON.stringify(operators));
log("Op-ed user " + message.user, ws.address);
}
} else if (message.type === "deop") {
if (ws.address !== "::1" && !ws.address.startsWith("127.")) {
ws.send(JSON.stringify({
type: "encrypted",
source: ws.address,
message: encrypt(JSON.stringify({
type: "system",
date: new Date().getTime(),
text: "Only the server owner can use the /deop command"
}), ws.publicKey)
}));
log("Permission denied while running deop", ws.address);
} else if (!operators.includes(message.user)) {
ws.send(JSON.stringify({
type: "encrypted",
source: ws.address,
message: encrypt(JSON.stringify({
type: "system",
date: new Date().getTime(),
text: message.user + " is not an operator on this server"
}), ws.publicKey)
}));
log("Failed to deop " + message.user + ": user is not operator", ws.address);
} else {
operators = operators.filter(i => i !== message.user);
ws.send(JSON.stringify({
type: "encrypted",
source: ws.address,
message: encrypt(JSON.stringify({
type: "system",
date: new Date().getTime(),
text: "Successfully made " + message.user + " not a server operator"
}), ws.publicKey)
}));
for (let socket of clients) {
if (socket.address === message.user) {
try {
socket.send(JSON.stringify({
type: "encrypted",
source: ws.address,
message: encrypt(JSON.stringify({
type: "system",
date: new Date().getTime(),
text: "You are not a server operator anymore"
}), socket.publicKey)
}));
} catch (e) {}
}
}
for (let socket of clients) {
if (socket.address !== ws.address) {
try {
socket.send(JSON.stringify({
type: "encrypted",
source: ws.address,
message: encrypt(JSON.stringify({
type: "system",
date: new Date().getTime(),
text: ws.address + " made " + message.user + " not a server operator"
}), socket.publicKey)
}));
} catch (e) {}
}
}
log("Deop-ed user " + message.user, ws.address);
fs.writeFileSync("./operators.json", JSON.stringify(operators));
}
}
} else {
log("Encrypted message, MD5: " + require('crypto').createHash("md5").update(data.message).digest("hex"), ws.address);
@ -448,6 +611,11 @@ readline.question("Enter the IP address users would use to connect to the server
if (socket.id === ws.id) continue;
data.source = ws.address;
let _decrypted = JSON.parse(decrypted);
_decrypted.admin = !(ws.address !== "::1" && !ws.address.startsWith("127.") && !operators.includes(ws.address));
decrypted = JSON.stringify(_decrypted);
data.message = encrypt(decrypted, socket.publicKey);
socket.send(JSON.stringify(data));
@ -457,6 +625,7 @@ readline.question("Enter the IP address users would use to connect to the server
} else if (data.type === "ping") {
ws.send(JSON.stringify({
type: "pong",
admin: !(ws.address !== "::1" && !ws.address.startsWith("127.") && !operators.includes(ws.address)),
users: clients.length,
original: data
}));

Loading…
Cancel
Save