diff options
author | RaindropsSys <contact@minteck.org> | 2023-09-09 19:22:06 +0200 |
---|---|---|
committer | RaindropsSys <contact@minteck.org> | 2023-09-09 19:22:06 +0200 |
commit | f581fff0254dba02181465153bb6a16aaff63311 (patch) | |
tree | 6c636ad458c6bfb5300c492549c627a201861f25 | |
parent | 7f779ed7c1f1f50fe3dd11690b871b0d2d8a0113 (diff) | |
download | chatroom-f581fff0254dba02181465153bb6a16aaff63311.tar.gz chatroom-f581fff0254dba02181465153bb6a16aaff63311.tar.bz2 chatroom-f581fff0254dba02181465153bb6a16aaff63311.zip |
Updated 6 files, added shared/verity.js and deleted 2 files (automated)
-rw-r--r-- | client/commands.js | 15 | ||||
-rwxr-xr-x | client/index.html | 123 | ||||
-rwxr-xr-x | client/main.js | 8 | ||||
-rwxr-xr-x | server/server.js | 87 | ||||
-rw-r--r-- | shared/lang/de.json | 158 | ||||
-rw-r--r-- | shared/lang/en.json | 9 | ||||
-rw-r--r-- | shared/lang/es.json | 158 | ||||
-rw-r--r-- | shared/lang/fr.json | 9 | ||||
-rw-r--r-- | shared/verity.js | 7 |
9 files changed, 183 insertions, 391 deletions
diff --git a/client/commands.js b/client/commands.js index 84b37d2..3740fab 100644 --- a/client/commands.js +++ b/client/commands.js @@ -1,6 +1,14 @@ commands = { - "verify": (_1, _2) => { - localSystemMessage(l("commands/verify") + "<br><pre style='margin: 0 !important;'>" + require('crypto').createHash("sha256").update(window.serverVerifyKey).digest("base64").match(/.{1,35}/g).join("\n") + "</pre>", true); + "verify": (argument, _2) => { + if (argument.trim() === "") { + localSystemMessage(l("commands/verify/server") + "<br><pre style='margin: 0 !important;'>" + require('crypto').createHash("sha256").update(window.serverVerifyKey).digest("base64").match(/.{1,35}/g).join("\n") + "</pre><br>" + l("commands/verify/user") + "<br><pre style='margin: 0 !important;'>" + require('crypto').createHash("sha256").update(window.verifyKey.publicKey).digest("base64").match(/.{1,35}/g).join("\n"), true); + } else { + send({ + server: true, + type: "verify", + user: argument + }); + } }, "nick": (argument, _) => { if (argument.trim() === "") argument = require('os').userInfo().username; @@ -19,6 +27,9 @@ commands = { location.reload(); }, + "whoami": (argument, _) => { + localSystemMessage(l("commands/whoami").replace("%1", localStorage.getItem("userLogin"))); + }, "switch": async (argument, _) => { await updateServer(); location.reload(); diff --git a/client/index.html b/client/index.html index d64159f..e17cdcd 100755 --- a/client/index.html +++ b/client/index.html @@ -3,27 +3,31 @@ <head>
<script>
//window.version = "2.4";
- window.version = "2.5-beta.2023-05-08";
+ window.version = "3.0-beta.2023-09-07";
window.betaVersion = true;
window.changeLog = `
Thanks for using Localchat. You are currently running Localchat version %1, below are all the changes in that version compared to the previous version.
-Localchat Client 2.5 Beta:
- - Localization coverage is now complete
- - Added Spanish and German translations
- - Added a "New" badge next to the language selector
- - Fixed translations not loading in some cases
- - Fixed being able to drag title bar icons on Linux
- - Fixed odd titlebar behavior on KDE Plasma
- - Both server and client data are in the same place:
- - ~/.localchat on Linux
- - ~/Library/Application Support/Localchat on macOS
- - %appdata%/.localchat on Windows
- * Requires Launcher 1.4.0 or newer
- - Added /lang to change the language after OOBE
- - Added /switch to import another .ltcsc file
+Localchat Client 3.0 Beta:
+ - Removed Spanish and German translations
+ - Instead of an IP address, users are now identified by a unique username
Here is what changed in the previous versions:
+ * Localchat Client 2.5:
+ - Localization coverage is now complete
+ - Added Spanish and German translations
+ - Added a "New" badge next to the language selector
+ - Fixed translations not loading in some cases
+ - Fixed being able to drag title bar icons on Linux
+ - Fixed odd titlebar behavior on KDE Plasma
+ - Both server and client data are in the same place:
+ - ~/.localchat on Linux
+ - ~/Library/Application Support/Localchat on macOS
+ - %appdata%/.localchat on Windows
+ * Requires Launcher 1.4.0 or newer
+ - Added /lang to change the language after OOBE
+ - Added /switch to import another .ltcsc file
+
* Localchat Client 2.4:
- Added experimental localization support (only on beta)
- Added Linux support, without content protection
@@ -78,6 +82,7 @@ Here is what changed in the previous versions: <meta charset="UTF-8">
<title>Localchat</title>
<script src="../shared/crypt.js"></script>
+ <script src="../shared/verity.js"></script>
<script src="commands.js"></script>
<script type="text/javascript" src="lib/purify.min.js"></script>
<script src="lib/marked.min.js"></script>
@@ -105,6 +110,10 @@ Here is what changed in the previous versions: color: #e0e3e2;
}
+ pre {
+ margin: inherit !important;
+ }
+
.message-file .message-text {
background-color: #3f4949;
color: #bec8c8;
@@ -583,6 +592,10 @@ Here is what changed in the previous versions: }
</style>
<script>
+ if (!localStorage.getItem("userLogin")) {
+ localStorage.setItem("userLogin", generateUsername());
+ }
+
function oobePage(page) {
document.getElementById("oobe-" + page).classList.add("oobe-page-shown");
}
@@ -624,8 +637,8 @@ Here is what changed in the previous versions: window.addEventListener('load', () => {
document.getElementById("emoji-picker").addEventListener('emoji-click', (event) => {
- if (document.getElementById("input-text").contentEditable && !document.getElementById("input-text").disabled) {
- document.getElementById("input-text").insertAdjacentText("beforeend", event.detail.unicode);
+ if (!document.getElementById("input-text").disabled) {
+ document.getElementById("input-text").value += event.detail.unicode;
unpickEmoji();
document.getElementById("input-text").focus();
}
@@ -909,12 +922,17 @@ Here is what changed in the previous versions: <a data-i18n-title="input/upload" class="input-icon" onclick="if (window.connected) uploadFile();"><img src="icons/upload.svg"></a>
<a data-i18n-title="input/emoji" class="input-icon" onclick="pickEmoji();"><img src="icons/emojis.svg"></a>
</div>
- <div contenteditable="true" style="font-family: inherit; font-size: 14px;" id="input-text"></div>
+ <input type="text" placeholder="Message" style="font-family: inherit; font-size: 14px;" id="input-text"></input>
</div>
<div id="typing"><b id="typing-single">X</b><span id="typing-two-outer"> <span data-i18n-text="input/typing/and"></span> <b id="typing-two">X</b></span><span id="typing-many" data-i18n-text="input/typing/many"></span> <span id="typing-singular" data-i18n-text="input/typing/singular"></span> <span id="typing-plural" data-i18n-text="input/typing/plural"></span> <span data-i18n-text="input/typing/end"></span></div>
</div>
<script>
+ if (!localStorage.getItem("verifyKey")) {
+ localStorage.setItem("verifyKey", JSON.stringify(generateKeys()));
+ }
+
+ window.verifyKey = JSON.parse(localStorage.getItem("verifyKey"));
const { ipcRenderer } = require('electron');
const os = require("os");
@@ -992,7 +1010,7 @@ Here is what changed in the previous versions: window.directOverview = false;
window.typing = {};
window.lastTyping = 0;
- window.token = generateToken();
+ window.token = null;
window.files = {};
window.ping = -1;
window.displayedMessages = [];
@@ -1006,7 +1024,7 @@ Here is what changed in the previous versions: }, 100);
function stripHTML(text) {
- return text.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
+ return text.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\n", "<br>");
}
function displayMessages() {
@@ -1036,7 +1054,7 @@ Here is what changed in the previous versions: ` : (message['type'] === "system" ? `
<div class="message system-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-text">${stripHTML(message['text'])}</span>
+ <span class="message-text">${stripHTML(message['text']).replaceAll("[[", "<pre>").replaceAll("]]", "</pre>")}</span>
</div>
` : (message['type'] === "system-raw" ? `
<div class="message system-message" id="message-${message['_id']}">
@@ -1104,9 +1122,9 @@ Here is what changed in the previous versions: ws.onopen = () => {
ws.send(JSON.stringify({
- type: "keyExchange",
- key: keys.publicKey,
- token: encrypt(token, serverInfo.key)
+ type: "authenticate",
+ userName: localStorage.getItem("userLogin"),
+ publicKey: verifyKey.publicKey
}));
}
@@ -1127,20 +1145,9 @@ Here is what changed in the previous versions: rej(new Error("Received invalid data"));
}
- if (data.type === "keyExchange") {
- if (data.token === token) {
- success = true;
- ws.close();
- res(true);
- } else {
- success = true;
- ws.close();
- rej(new Error("Invalid server key"));
- }
- } else if (data.type === "banned") {
+ if (data.type === "authenticated") {
success = true;
ws.close();
- rej(new Error("Banned from server"));
}
}
} catch (e) {
@@ -1186,9 +1193,9 @@ Here is what changed in the previous versions: console.log(e);
ws.send(JSON.stringify({
- type: "keyExchange",
- key: keys.publicKey,
- token: encrypt(token, serverVerifyKey)
+ type: "authenticate",
+ userName: localStorage.getItem("userLogin"),
+ publicKey: verifyKey.publicKey
}));
wsPingInterval = setInterval(() => {
@@ -1248,6 +1255,16 @@ Here is what changed in the previous versions: return;
}
+ if (data.type === "authenticated") {
+ window.token = decrypt(data.token, verifyKey.privateKey);
+
+ ws.send(JSON.stringify({
+ type: "keyExchange",
+ key: keys.publicKey,
+ token: encrypt(token, serverVerifyKey)
+ }));
+ }
+
if (data.type === "keyExchange") {
if (data.token === window.token) {
window.serverKey = data.key;
@@ -1276,8 +1293,10 @@ Here is what changed in the previous versions: deciphered += decipher.final("utf8");
decrypted.file.content = deciphered;
- if (crypto.createHash("md5").update(Buffer.from(deciphered, "base64")).digest("hex") !== decrypted.file.md5) {
- localSystemMessage(l("upload/corrupt"));
+ let compare = crypto.createHash("md5").update(Buffer.from(deciphered, "base64")).digest("hex");
+
+ if (compare !== decrypted.file.md5) {
+ console.warn("Potentially corrupted file. Expected " + decrypted.file.md5 + " but got " + compare + ".");
}
}
@@ -1421,7 +1440,7 @@ Here is what changed in the previous versions: cryptObj[token] = encrypted;
ws.send(JSON.stringify(cryptObj));
- fileObj['_source'] = "localhost";
+ fileObj['_source'] = localStorage.getItem("userLogin");
fileObj['_id'] = uuid();
fileObj['file']['content'] = content;
fileObj['admin'] = window.isAdmin;
@@ -1448,23 +1467,23 @@ Here is what changed in the previous versions: }
document.getElementById("input-text").onkeyup = () => {
- if (document.getElementById("input-text").innerText.length > 501) document.getElementById("input-text").innerText = document.getElementById("input-text").innerText.substring(0, 501);
+ if (document.getElementById("input-text").value.length > 501) document.getElementById("input-text").value = document.getElementById("input-text").value.substring(0, 501);
}
document.getElementById("input-text").onkeydown = (e) => {
- if (document.getElementById("input-text").innerText.length > 501) document.getElementById("input-text").innerText = document.getElementById("input-text").innerText.substring(0, 501);
+ if (document.getElementById("input-text").value.length > 501) document.getElementById("input-text").value = document.getElementById("input-text").value.substring(0, 501);
if (e.code === "Enter" && !e.shiftKey) {
e.preventDefault();
- if (document.getElementById("input-text").innerText.trim() === "" || !window.connected || window.banned) return;
+ if (document.getElementById("input-text").value.trim() === "" || !window.connected || window.banned) return;
- if (document.getElementById("input-text").innerText.trim().startsWith("/") && document.getElementById("input-text").innerText.trim().length > 1) {
- let text = document.getElementById("input-text").innerText.trim();
- document.getElementById("input-text").innerText = "";
+ if (document.getElementById("input-text").value.trim().startsWith("/") && document.getElementById("input-text").value.trim().length > 1) {
+ let text = document.getElementById("input-text").value.trim();
+ document.getElementById("input-text").value = "";
runCommand(text);
} else {
- let text = document.getElementById("input-text").innerText.trim();
- if (document.getElementById("input-text").innerText.startsWith("\\/")) text = document.getElementById("input-text").innerText.substring(1);
+ let text = document.getElementById("input-text").value.trim();
+ if (document.getElementById("input-text").value.startsWith("\\/")) text = document.getElementById("input-text").value.substring(1);
let obj = {
type: "text",
@@ -1475,7 +1494,7 @@ Here is what changed in the previous versions: }
send(obj);
- obj['_source'] = "localhost";
+ obj['_source'] = localStorage.getItem("userLogin");
obj['_id'] = uuid();
obj['admin'] = window.isAdmin;
@@ -1488,7 +1507,7 @@ Here is what changed in the previous versions: }
displayMessages();
- document.getElementById("input-text").innerText = "";
+ document.getElementById("input-text").value = "";
}
} else {
if (window.connected && !window.banned && new Date().getTime() - window.lastTyping > 1000) {
diff --git a/client/main.js b/client/main.js index c2590c6..257d3a2 100755 --- a/client/main.js +++ b/client/main.js @@ -144,10 +144,12 @@ app.whenReady().then(() => { globalShortcut.register('Alt+CommandOrControl+C', () => {
if (mainWindow) {
try {
- if (mainWindow.isMinimized()) {
- mainWindow.restore();
+ if (!mainWindow.isVisible()) {
+ mainWindow.show();
+ if (process.platform === "darwin") app.dock.show();
} else {
- mainWindow.minimize();
+ mainWindow.hide();
+ if (process.platform === "darwin") app.dock.hide();
}
} catch (e) {}
}
diff --git a/server/server.js b/server/server.js index 1ead0c6..e2a399a 100755 --- a/server/server.js +++ b/server/server.js @@ -1,6 +1,7 @@ const { WebSocketServer } = require('ws');
const crypt = require('../shared/crypt');
-const {decrypt, encrypt} = require("../shared/crypt");
+const verity = require('../shared/verity');
+const {decrypt, encrypt, generateToken} = require("../shared/crypt");
const uuid = require('uuid-v4');
const fs = require('fs');
const crypto = require('crypto');
@@ -17,7 +18,7 @@ if (!fs.existsSync(localchatDataRoot + "/server/logs")) fs.mkdirSync(localchatDa if (!fs.existsSync(localchatDataRoot + "/server/data")) fs.mkdirSync(localchatDataRoot + "/server/data");
process.chdir(localchatDataRoot + "/server");
-const version = "1.11";
+const version = "2.0b";
const port = 27342;
function mergeRecursive(obj1, obj2) {
@@ -80,7 +81,7 @@ function log(message, address) { console.log("Localchat Server v" + version + "; (c) Equestria.dev Developers");
console.log("powered by love and friendship");
-console.log(" - Want to contribute? https://git.equestria.dev/equestria.dev/localchat");
+console.log(" - Want to contribute? https://source.equestria.dev/equestria.dev/localchat");
console.log(" - Found a bug? https://bugs.equestria.dev/issues/LCHT\n");
const readline = require('readline').createInterface({
@@ -128,6 +129,11 @@ readline.question("Enter the IP address users would use to connect to the server let clients = [];
log("Loaded ban list");
+ log("Loading user identities list...");
+ if (!fs.existsSync("./config/identities.json")) fs.writeFileSync("./config/identities.json", "{}");
+ let identities = JSON.parse(fs.readFileSync("./config/identities.json").toString());
+ log("Loaded user identities list");
+
log("Loading operators list...");
if (!fs.existsSync("./config/ops.json")) fs.writeFileSync("./config/ops.json", "[]");
let operators = JSON.parse(fs.readFileSync("./config/ops.json").toString());
@@ -144,21 +150,15 @@ readline.question("Enter the IP address users would use to connect to the server wss.on('connection', function connection(ws, req) {
log("Connection from " + req.socket.remoteAddress);
ws.publicKey = null;
+ ws.verityKey = null;
+ ws.token = null;
ws.lang = "en";
ws.id = uuid();
- ws.address = parseAddress(req.socket.remoteAddress);
+ ws.ipAddress = parseAddress(req.socket.remoteAddress);
+ ws.userName = ws.address = null;
ws.lastPacket = 0;
ws.rateLimitAttempts = [];
- if (bans.includes(ws.address)) {
- log("Kicking user because they are banned", ws.address);
-
- ws.send(JSON.stringify({
- type: "banned"
- }));
- ws.close();
- }
-
clients.push(ws);
ws.on('error', (error) => {
@@ -168,9 +168,43 @@ readline.question("Enter the IP address users would use to connect to the server ws.on('message', function message(_data) {
try {
+ if (ws.userName && bans.includes(ws.userName)) {
+ log("Kicking user because they are banned", ws.userName);
+
+ ws.send(JSON.stringify({
+ type: "banned"
+ }));
+ ws.close();
+ }
+
let data = JSON.parse(_data);
let diff = new Date().getTime() - ws.lastPacket;
+ if (data.type === "authenticate") {
+ log("User authenticated as " + data.userName, ws.ipAddress);
+ ws.userName = ws.address = data.userName;
+
+ ws.token = generateToken();
+ let publicKey = data.publicKey;
+
+ if (identities[data.userName]) {
+ ws.verityKey = publicKey = identities[data.userName];
+ } else {
+ ws.verityKey = identities[data.userName] = publicKey;
+ fs.writeFileSync("./config/identities.json", JSON.stringify(identities));
+ }
+
+ ws.send(JSON.stringify({
+ type: "authenticated",
+ token: encrypt(ws.token, publicKey)
+ }));
+
+ return
+ } else if (!ws.userName) {
+ log("User did not attempt authentication and instead sent a " + data.type + " request", ws.ipAddress);
+ ws.close();
+ }
+
if (diff <= 75 && ws.publicKey && data.type !== "keyExchange" && data.type !== "ping") {
ws.send(JSON.stringify({
type: "encrypted",
@@ -232,6 +266,10 @@ readline.question("Enter the IP address users would use to connect to the server let token = decrypt(data.token, verify.privateKey);
+ if (token !== ws.token) {
+ ws.close();
+ }
+
ws.send(JSON.stringify({
type: "keyExchange",
key: keys.publicKey,
@@ -388,11 +426,32 @@ readline.question("Enter the IP address users would use to connect to the server message: encrypt(JSON.stringify({
type: "system",
date: new Date().getTime(),
- text: l('server/ops', ws.lang) + " " + [...operators, "127.0.0.1"].join(", ")
+ text: l('server/ops', ws.lang) + " " + operators.join(", ")
}), ws.publicKey)
}));
log("Requested operators list", ws.address);
+ } else if (message.type === "verify") {
+ let key = "-";
+
+ for (let client of clients) {
+ if (client.userName === message.user) {
+ key = require('crypto').createHash("sha256").update(client.verityKey).digest("base64").match(/.{1,35}/g).join("\n");
+ break;
+ }
+ }
+
+ ws.send(JSON.stringify({
+ type: "encrypted",
+ source: ws.address,
+ message: encrypt(JSON.stringify({
+ type: "system",
+ date: new Date().getTime(),
+ text: l('commands/verify/other', ws.lang).replace("%1", message.user) + "\n[[" + key + "]]"
+ }), ws.publicKey)
+ }));
+
+ log("Requested verity key of " + message.user, ws.address);
} else if (message.type === "ban") {
if (ws.address !== "::1" && !ws.address.startsWith("127.") && !operators.includes(ws.address)) {
ws.send(JSON.stringify({
diff --git a/shared/lang/de.json b/shared/lang/de.json deleted file mode 100644 index eb84bdc..0000000 --- a/shared/lang/de.json +++ /dev/null @@ -1,158 +0,0 @@ -{ - "_locale": "de_DE", - "oobe": { - "title": "Willkommen in Ihrer örtlichen Messaging -App", - "developer": "Entwickleroptionen aktivieren", - "beta": "Gehen Sie zum Beta -Kanal", - "stable": "Gehen Sie zum stabilen Kanal", - "navigation": { - "start": "Start", - "restart": "Neustarten", - "next": "Folgen" - }, - "connect": { - "title": "Lassen Sie uns eine Verbindung herstellen", - "description": "Ihr Administrator hätte Ihnen eine Localchat (.lctsc) -Konfigurationsdatei zur Verfügung gestellt haben. Stellen Sie sicher, dass Sie diese Datei haben, bevor Sie auf Weiter klicken.", - "check": "Dateiüberprüfung ..." - }, - "error": { - "title": "Irgendwas stimmt nicht", - "description": "Wir können Ihre Konfiguration nicht überprüfen. Stellen Sie sicher, dass Sie die richtige Datei zur Verfügung gestellt haben und der Server eingeschaltet ist und ordnungsgemäß funktioniert." - }, - "disclaimers": { - "title": "Benutzerwarnungen" - }, - "diagnostics": { - "title": "Diagnosedaten autorisieren?", - "description": "Equestria.dev kann diagnostische Daten sammeln, während Sie Localchat verwenden, um die Probleme zu lösen, die Sie begegnen, und Ihre Erfahrung zu verbessern.", - "no": "Ignorieren", - "yes": "Ich nehme an" - }, - "changelog": { - "title": "Kürzliche Änderungen" - }, - "done": { - "title": "Es ist alles gut !", - "description": "Bitte verwenden Sie Localchat. Sie haben jetzt den Konfigurationsprozess abgeschlossen und können Localchat verwenden. Klicken Sie auf Fertig stellen, um zu starten", - "complete": "Beenden" - } - }, - "beta": "Beta", - "input": { - "upload": "Sende eine Datei", - "emoji": "Fügen Sie Emojis hinzu", - "typing": { - "and": "Und", - "many": "einige Leute", - "singular": "Ost", - "plural": "Sind", - "end": "Schreiben…" - } - }, - "error": "Es trat ein Fehler auf: %1: %2; Bitte melden Sie es unter https://bugs.equestria.dev/issues/LCHT", - "background_error": "Es ist unmöglich, das Hintergrundbild zu laden: %1; Ausführen /background, um es zu ändern oder zu entfernen", - "byte": "B", - "invalid_config": "Die von Ihnen ausgewählte Serverkonfiguration ist nicht gültig. Bitte wählen Sie eine andere aus.", - "status": { - "leave": "Sie haben die Diskussion verlassen", - "leave2": "%1 verließ die Diskussion", - "error": "Es ist nicht möglich", - "import": "Wenn Sie eine Verbindung zu einem anderen Server herstellen möchten, erhalten Sie %1hier, um eine andere .lctsc%2 -Datei zu importieren", - "join": "Sie haben sich der Diskussion angeschlossen", - "join2": "%1 (%2) schloss sich der Diskussion an", - "unverify": "Es ist unmöglich, die Identität des Servers zu überprüfen", - "banned": "Sie wurden von diesem Server blockiert" - }, - "upload": { - "folder": "Ordner oder andere spezielle Dateien können nicht gesendet werden", - "corrupt": "WARNUNG: Diese Datei ist möglicherweise korrupt. Überprüfen Sie sie unbedingt, bevor Sie sie öffnen", - "size": "Diese Datei kann nicht gesendet werden, da sie die maximal autorisierte Größe überschreitet (%1)", - "error": "Bei der Senden Ihrer Datei trat ein Fehler auf. Versuchen Sie es später erneut" - }, - "dm_notice": "Dies ist eine private Nachricht vom Serverbesitzer. Verwenden Sie /r, um privat zu antworten.", - "send": { - "offline": "Es ist unmöglich, diese Nachricht zu senden, da Sie nicht mit dem Server verbunden sind", - "banned": "Es ist unmöglich, diese Nachricht zu senden, da Sie vom Server blockiert sind" - }, - "commands": { - "_server": "Bitte stellen Sie eine Verbindung zu einem Server her, bevor Sie Befehle verwenden", - "_server2": "Sie sind derzeit nicht mit einem Server verbunden", - "_": "Entschuldigung, /%1 ist kein gültiger Befehl, verwenden /help, um eine Liste zu haben", - "help": "Verfügbare Befehle:", - "channel": { - "beta": "Localchat verwendet nun den Beta -Kanal und starten Sie die Anwendung neu, um die Änderung abzuschließen.", - "stable": "Localchat verwendet nun den stabilen Kanal und starten Sie die Anwendung neu, um die Änderung abzuschließen." - }, - "version": { - "localchat": "Localchat Version:", - "launcher": "Launcher-Version:", - "node": "Node.js Version:", - "chrome": "Chrome Version:", - "electron": "Electron Version:", - "server": "Serverversion:" - }, - "url": "Der Server, den Sie angeschlossen sind, lautet:", - "ping": "Ihre Antwortzeit ist: %1 ms", - "r": "Bitte geben Sie die Senden der Nachricht an", - "msg": "Bitte geben Sie die IP -Adresse des Kunden an, an wen die Nachricht", - "deop": "Bitte geben Sie die IP -Adresse eines Kunden an, den Sie Operator machen möchten", - "op": "Bitte geben Sie die IP -Adresse eines Kunden an, den Sie Operator machen möchten", - "unban": "Bitte geben Sie die IP -Adresse eines Kunden an, den Sie freischalten möchten", - "ban": "Bitte geben Sie die IP -Adresse eines Kunden an, den Sie blockieren möchten", - "verify": "Verwenden Sie diese Ausleihe, um die Identität des Servers zu überprüfen:", - "nick": { - "self": "Ihr Name ist jetzt \"%1\"", - "other": "%1 hat seinen Namen für \"%2\" geändert." - }, - "background": { - "error": "Es ist unmöglich, den Hintergrund zu ändern: %1", - "removed": "Erfolgreich das Hintergrundbild entfernt", - "changed": "Veränderte das Hintergrundbild für %1 erfolgreich" - }, - "color": { - "reset": { - "self": "Ihre Profilfarben sind jetzt standardmäßig diejenigen", - "other": "%1 hat seine Profilfarben für diejenigen standardmäßig geändert" - }, - "invalid": { - "first": "Die erste Farbe ist kein gültiger hexadezimaler Farbcode", - "second": "Die zweite Farbe ist kein gültiger hexadezimaler Farbcode" - }, - "changed": { - "self": "Ihre Profilfarben sind jetzt #%1 und #%2", - "other": "%1 hat seine Profilfarben geändert" - } - } - }, - "server": { - "ratelimit": "Sie sind in der Zeit begrenzt, versuchen Sie es in wenigen Augenblicken erneut", - "autoban": "%1 wurde automatisch blockiert, um Zeitgrenzen zu oft zu überschreiten", - "list": { - "users": "Verbundene Benutzer:", - "alone": "Sie sind der einzige Benutzer auf diesem Server" - }, - "permission": "Auf dem Serverbesitzer kann die Bestellung %1 verwenden", - "mod": "Nur Serveroperatoren können den Befehl %1 verwenden", - "invalid": "%1 ist keine gültige Kunden -IP -Adresse", - "no_owner": "Der Eigentümer des Servers ist derzeit nicht online", - "ops": "Serverbetreiber:", - "block": { - "already": "%1 ist auf diesem Server bereits blockiert", - "banned": "%1 erfolgreich blockiert", - "unbanned": "Schloss %1 erfolgreich entsperrt", - "broadcast": "%1 blockiert %2", - "broadcast2": "%1 a freigeschaltet %2", - "nothing": "%1 ist auf diesem Server nicht blockiert" - }, - "op": { - "already": "%1 ist bereits ein Serverbetreiber", - "oped": "%1 als Erfolgsbetreiber erfolgreich hinzugefügt", - "unoped": "Rückzug %1 der Serverbetreiber erfolgreich", - "broadcast": "%1 hat %2 als Serverbetreiber hinzugefügt", - "broadcast2": "%1 zog %2 von Serverbetreibern zurück", - "nothing": "%1 ist kein Serverbetreiber", - "you": "Sie sind jetzt Serverbetreiber", - "you2": "Sie sind kein Betreiber des Servers mehr" - } - } -}
\ No newline at end of file diff --git a/shared/lang/en.json b/shared/lang/en.json index 141f0cc..3e30058 100644 --- a/shared/lang/en.json +++ b/shared/lang/en.json @@ -99,7 +99,11 @@ "op": "Please specify the IP address of a client you want to make an operator", "unban": "Please specify the IP address of a client you want to unblock", "ban": "Please specify the IP address of a client you want to block", - "verify": "Use this fingerprint to verify the server's identity:", + "verify": { + "server": "Use this fingerprint to verify the server's identity:", + "user": "Others can use this fingerprint to verify your identity:", + "other": "Use this fingerprint to verify %1's identity:" + }, "nick": { "self": "Your name is now \"%1\"", "other": "%1 changed their name to \"%2\"" @@ -122,7 +126,8 @@ "self": "Your profile colors are now #%1 and #%2", "other": "%1 changed their profile colors" } - } + }, + "whoami": "Your login name is: %1. This name is used to prove your identity to the server and to other users." }, "server": { "ratelimit": "You are being rate limited, try again in a few moments", diff --git a/shared/lang/es.json b/shared/lang/es.json deleted file mode 100644 index 624e306..0000000 --- a/shared/lang/es.json +++ /dev/null @@ -1,158 +0,0 @@ -{ - "_locale": "es_ES", - "oobe": { - "title": "Bienvenido a su aplicación de mensajería local", - "developer": "Activar opciones de desarrollador", - "beta": "Ir al canal beta", - "stable": "Ir al canal estable", - "navigation": { - "start": "Comenzar", - "restart": "Para reiniciar", - "next": "Próximo" - }, - "connect": { - "title": "Conectemos", - "description": "Su administrador debería haberle proporcionado un archivo de configuración Localchat (.lctsc). Asegúrese de tener este archivo antes de hacer clic en Siguiente.", - "check": "Verificación de archivos..." - }, - "error": { - "title": "Algo no va bien", - "description": "No podemos verificar su configuración. Asegúrese de haber proporcionado el archivo correcto y el servidor está encendido y funciona correctamente." - }, - "disclaimers": { - "title": "Advertencias de usuario" - }, - "diagnostics": { - "title": "Autorizar datos de diagnóstico?", - "description": "Equestria.dev puede recopilar datos de diagnóstico mientras usa Localchat para resolver los problemas que encuentra y mejorar su experiencia.", - "no": "Ignorar", - "yes": "Acepto" - }, - "changelog": { - "title": "Cambios recientes" - }, - "done": { - "title": "Todo es bueno !", - "description": "Por favor, use Localchat. Ahora ha completado el proceso de configuración y puede usar Localchat. Haga clic en Finalizar para comenzar", - "complete": "Para terminar" - } - }, - "beta": "Beta", - "input": { - "upload": "Enviar un archivo", - "emoji": "Agregar emojis", - "typing": { - "and": "y", - "many": "Varias personas", - "singular": "Este", - "plural": "están", - "end": "escribiendo…" - } - }, - "error": "Se produjo un error: %1: %2; Informe en https://bugs.equestria.dev/issues/LCHT", - "background_error": "Imposible cargar la imagen de fondo: %1; Ejecutar /background para cambiarlo o eliminarlo", - "byte": "B", - "invalid_config": "La configuración del servidor que ha seleccionado no es válida, seleccione otra.", - "status": { - "leave": "Dejaste la discusión", - "leave2": "%1 dejó la discusión", - "error": "Imposible conectarse al servidor Localchat en %1, asegúrese de que el servidor esté en servicio", - "import": "Si desea conectarse a otro servidor, %1llegar aquí para importar otro archivo .lctsc%2", - "join": "Te has unido a la discusión", - "join2": "%1 (%2) se unió a la discusión", - "unverify": "Imposible verificar la identidad del servidor", - "banned": "Fuiste bloqueado desde este servidor" - }, - "upload": { - "folder": "No se puede enviar carpetas u otros archivos especiales", - "corrupt": "Advertencia: este archivo es posiblemente corrupto, asegúrese de verificarlo antes de abrirlo", - "size": "No se puede enviar este archivo porque excede el tamaño máximo autorizado (%1)", - "error": "Se produjo un error al enviar su archivo, intente nuevamente más tarde" - }, - "dm_notice": "Este es un mensaje privado del propietario del servidor. Usar /r para responder en privado.", - "send": { - "offline": "Imposible enviar este mensaje porque no está conectado al servidor", - "banned": "Imposible enviar este mensaje porque está bloqueado desde el servidor" - }, - "commands": { - "_server": "Conéctese a un servidor antes de usar comandos", - "_server2": "Actualmente no está conectado a un servidor", - "_": "Lo siento, /%1 no es un comando válido, use /help a tener una lista", - "help": "Comandos disponibles:", - "channel": { - "beta": "Localchat ahora usará el canal beta, reiniciará la aplicación para completar el cambio.", - "stable": "Localchat ahora usará el canal estable, reiniciará la aplicación para completar el cambio." - }, - "version": { - "localchat": "Versión de Localchat:", - "launcher": "Versión del lanzador:", - "node": "Versión de Node.js:", - "chrome": "Versión de Chrome:", - "electron": "Versión de Electron:", - "server": "Versión del servidor:" - }, - "url": "El servidor que está conectado es:", - "ping": "Su tiempo de respuesta es: %1 ms", - "r": "Especifique el mensaje para enviar", - "msg": "Especifique la dirección IP del cliente a quien el mensaje", - "deop": "Especifique la dirección IP de un cliente que desea hacer operador", - "op": "Especifique la dirección IP de un cliente que desea hacer operador", - "unban": "Especifique la dirección IP de un cliente que desea desbloquear", - "ban": "Especifique la dirección IP de un cliente que desea bloquear", - "verify": "Use este préstamo para verificar la identidad del servidor:", - "nick": { - "self": "Tu nombre ahora es \"%1\"", - "other": "%1 ha cambiado su nombre para \"%2\"" - }, - "background": { - "error": "Imposible cambiar el fondo: %1", - "removed": "Eliminó con éxito la imagen de fondo", - "changed": "Cambió la imagen de fondo para %1 correctamente" - }, - "color": { - "reset": { - "self": "Los colores de su perfil son ahora aquellos de forma predeterminada", - "other": "%1 ha cambiado sus colores de perfil para aquellos por defecto" - }, - "invalid": { - "first": "El primer color no es un código de color hexadecimal válido", - "second": "El segundo color no es un código de color hexadecimal válido" - }, - "changed": { - "self": "Los colores de su perfil ahora son #%1 y #%2", - "other": "%1 ha cambiado sus colores de perfil" - } - } - }, - "server": { - "ratelimit": "Estás limitado en el tiempo, intente de nuevo en unos momentos", - "autoban": "%1 se bloqueó automáticamente para los límites de tiempo superiores demasiadas veces", - "list": { - "users": "Usuarios conectados:", - "alone": "Eres el único usuario en este servidor" - }, - "permission": "En el propietario del servidor puede usar el pedido %1", - "mod": "Solo los operadores del servidor pueden usar el comando %1", - "invalid": "%1 no es una dirección IP de cliente válida", - "no_owner": "El propietario del servidor no está actualmente en línea", - "ops": "Operadores de servidor:", - "block": { - "already": "%1 ya está bloqueado en este servidor", - "banned": "Bloqueado %1 con éxito", - "unbanned": "Desbloqueado %1 con éxito", - "broadcast": "%1 bloqueado %2", - "broadcast2": "%1 A desbloqueado %2", - "nothing": "%1 no está bloqueado en este servidor" - }, - "op": { - "already": "%1 ya es un operador de servidor", - "oped": "Se agregó %1 como operador de éxito con éxito", - "unoped": "Retirado %1 de los operadores del servidor con éxito", - "broadcast": "%1 agregado %2 como operador de servidor", - "broadcast2": "%1 Retirar %2 de los operadores del servidor", - "nothing": "%1 no es un operador de servidor", - "you": "Ahora eres un operador del servidor", - "you2": "Ya no eres un operador del servidor" - } - } -}
\ No newline at end of file diff --git a/shared/lang/fr.json b/shared/lang/fr.json index 0bb0e88..663685a 100644 --- a/shared/lang/fr.json +++ b/shared/lang/fr.json @@ -99,7 +99,11 @@ "op": "Veuillez spécifier l'adresse IP d'un client que vous voulez rendre opérateur", "unban": "Veuillez spécifier l'adresse IP d'un client que vous voulez débloquer", "ban": "Veuillez spécifier l'adresse IP d'un client que vous voulez bloquer", - "verify": "Utilisez cette emprunte pour vérifier l'identité du serveur :", + "verify": { + "server": "Utilisez cette emprunte pour vérifier l'identité du serveur :", + "user": "Les autres peuvent utiliser cette emprunte pour vérifier votre identité :", + "other": "Utilisez cette emprunte pour vérifier l'identité de %1 :" + }, "nick": { "self": "Votre nom est désormais \"%1\"", "other": "%1 a changé son nom pour \"%2\"" @@ -122,7 +126,8 @@ "self": "Vos couleurs de profil sont désormais #%1 et #%2", "other": "%1 a changé ses couleurs de profil" } - } + }, + "whoami": "Votre nom de connexion est : %1. Ce nom est utilisé pour prouver votre identité au serveur et aux autres utilisateurs." }, "server": { "ratelimit": "Vous êtes limité dans le temps, essayez de nouveau dans quelques instants", diff --git a/shared/verity.js b/shared/verity.js new file mode 100644 index 0000000..3bfc5a5 --- /dev/null +++ b/shared/verity.js @@ -0,0 +1,7 @@ +function generateUsername() { + const crypto = require('crypto'); + + return (parseInt(crypto.randomBytes(8).toString("hex"), 16).toString(36).replace(/\d/g, "") + parseInt(crypto.randomBytes(8).toString("hex"), 16).toString(36).replace(/\d/g, "")).substring(0, 7) + "_" + (parseInt(crypto.randomBytes(8).toString("hex"), 16).toString(36).replace(/\d/g, "") + parseInt(crypto.randomBytes(8).toString("hex"), 16).toString(36).replace(/\d/g, "")).substring(0, 7) + "_" + parseInt(crypto.randomBytes(5).toString("hex"), 16).toString().substring(0, 3); +} + +if (module) module.exports = {generateUsername}
\ No newline at end of file |