chat and localisation

more translations
allow links in chat
parallell webpack builds
This commit is contained in:
HF 2021-01-31 14:03:53 +01:00
parent 1db8adbb39
commit 26c6de0b02
14 changed files with 2316 additions and 818 deletions

View File

@ -775,7 +775,7 @@ msgstr "Gesamtzeit"
#: src/components/CanvasItem.jsx:54
msgid "Ranked"
msgstr ""
msgstr "Gewertet"
#: src/components/CanvasItem.jsx:56
msgid "Requirements"

1087
i18n/dz.po Normal file

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,62 @@ msgstr ""
"Plural-Forms: nplurals = 2; plural = (n != 1);\n"
"X-Generator: Poedit 2.3\n"
#: src/core/ChatProvider.js:243
msgid "You can not send chat messages with proxy"
msgstr "Du kannst keine Nachrichten senden wenn du ein Proxy benutzt"
#: src/core/ChatProvider.js:248
msgid "Couldn't send your message, pls log out and back in again."
msgstr "Konnte die Nachricht nicht senden, bitte logge duch aus und wieder an."
#: src/core/ChatProvider.js:262
#, javascript-format
msgid "You are sending messages too fast, you have to wait ${ waitTime }s :("
msgstr "Du sendest zu viele Nachrichten, du musst ${ waitTime }s warten :("
#: src/core/ChatProvider.js:266
msgid "You don't have access to this channel"
msgstr "Du hast keinen Zugriff zu diesen Kanal"
#: src/core/ChatProvider.js:282
msgid "Your mail has to be verified in order to chat"
msgstr "E-Mail muss verifiziert sein um Nachrichten zu senden"
#: src/core/ChatProvider.js:287
msgid "You are permanently muted, join our guilded to apppeal the mute"
msgstr ""
"Du bsit permanent stummgeschaltet, gehe zu unser guilded um dagegen "
"einzusprechen"
#: src/core/ChatProvider.js:292
#, javascript-format
msgid "You are muted for another ${ timeMin } minutes"
msgstr "Du bist für ${ timeMin } Minuten stummgeschaltet"
#: src/core/ChatProvider.js:294
msgid "You are muted for another ${ muted } seconds"
msgstr "Du bist for ${ muted } Sekunden stummgeschaltet"
#: src/core/ChatProvider.js:302
msgid "Ow no! Spam protection decided to mute you"
msgstr "Oh nein! Spam-Schutz hat dich stummgeschaltet"
#: src/core/ChatProvider.js:313
msgid "You can't send a message this long :("
msgstr "Do kannst keine so langen Nachrichten senden"
#: src/core/ChatProvider.js:317
msgid "Please use int channel"
msgstr "Bitte benutze int Kanal"
#: src/core/ChatProvider.js:321
msgid "Your country is temporary muted from chat"
msgstr "Dein Land ist temporär stummgeschaltet"
#: src/core/ChatProvider.js:329
msgid "Stop flooding."
msgstr "Stoppe zu spamen."
#: src/ssr-components/Main.jsx:53
msgid "PixelPlanet.fun"
msgstr "PixelPlanet.Fun"
@ -141,7 +197,7 @@ msgid ""
"next 30min here: "
msgstr ""
"Du hast ein neues Passwort beantragt. Du kannst es nun während der nächsten "
"30min hier ändern:"
"30min hier ändern"
#: src/core/mail.js:128 src/ssr-components/PasswordReset.jsx:19
#: src/ssr-components/PasswordReset.jsx:28
@ -237,7 +293,7 @@ msgstr "Passwort muss mindestens 6 Zeichen lang sein."
#: src/utils/validation.js:60
msgid "Password must be shorter than 60 characters."
msgstr "Passwort muss kürzer als 60 Zeichen sein"
msgstr "Passwort muss kürzer als 60 Zeichen sein."
#: src/utils/validation.js:74
msgid "Could not connect to server, please try again later :("
@ -302,7 +358,7 @@ msgstr "Du wirst automatisch weitergeleitet nach 15s"
#: src/ssr-components/RedirectionPage.jsx:21
#, javascript-format
msgid "Or ${ clickHere } to go back to pixelplanet"
msgstr "oder ${ clickHere } um zu pixelplanet zurückzukehren"
msgstr "Oder ${ clickHere } um zu pixelplanet zurückzukehren"
#: src/ssr-components/RedirectionPage.jsx:25
msgid "PixelPlanet.fun Accounts"

View File

@ -3,6 +3,60 @@ msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Plural-Forms: nplurals=2; plural=(n!=1);\n"
#: src/core/ChatProvider.js:243
msgid "You can not send chat messages with proxy"
msgstr ""
#: src/core/ChatProvider.js:248
msgid "Couldn't send your message, pls log out and back in again."
msgstr ""
#: src/core/ChatProvider.js:262
#, javascript-format
msgid "You are sending messages too fast, you have to wait ${ waitTime }s :("
msgstr ""
#: src/core/ChatProvider.js:266
msgid "You don't have access to this channel"
msgstr ""
#: src/core/ChatProvider.js:282
msgid "Your mail has to be verified in order to chat"
msgstr ""
#: src/core/ChatProvider.js:287
msgid "You are permanently muted, join our guilded to apppeal the mute"
msgstr ""
#: src/core/ChatProvider.js:292
#, javascript-format
msgid "You are muted for another ${ timeMin } minutes"
msgstr ""
#: src/core/ChatProvider.js:294
msgid "You are muted for another ${ muted } seconds"
msgstr ""
#: src/core/ChatProvider.js:302
msgid "Ow no! Spam protection decided to mute you"
msgstr ""
#: src/core/ChatProvider.js:313
msgid "You can't send a message this long :("
msgstr ""
#: src/core/ChatProvider.js:317
msgid "Please use int channel"
msgstr ""
#: src/core/ChatProvider.js:321
msgid "Your country is temporary muted from chat"
msgstr ""
#: src/core/ChatProvider.js:329
msgid "Stop flooding."
msgstr ""
#: src/ssr-components/Main.jsx:53
msgid "PixelPlanet.fun"
msgstr ""

File diff suppressed because it is too large Load Diff

677
i18n/template.txt Normal file
View File

@ -0,0 +1,677 @@
"Copied!"
"Error :("
"Didn't get an answer from pixelplanet. Maybe try to refresh?"
"OK"
"Invalid Canvas"
"This canvas doesn't exist"
"Invalid Coordinates"
"x out of bounds"
"y out of bounds"
"z out of bounds"
"Wrong Color"
"Invalid color selected"
"Just for registered Users"
"You have to be logged in to place on this canvas"
"Place more :)"
"You can not access this canvas yet. You need to place more pixels"
"Pixel protected!"
"No Proxies Allowed :("
"You are using a Proxy."
"Weird"
"Couldn't set Pixel"
"Error ${ retCode }"
"Close"
"Close Menu"
"Open Menu"
"Close Chat"
"Open Chat"
"Copy to Clipboard"
"User online"
"Pixels placed"
"Canvas Selection"
"Make Screenshot"
"User Area"
"Settings"
"Help"
"Channel settings"
"maximize"
"Start chatting here"
"Chat here"
"You must be logged in to chat"
"Close Palette"
"Open Palette"
"Globe View"
"Ping"
"DM"
"Block"
"Privacy Policy"
"Terms of Service"
"your IP"
"Place color pixels on a large canvas with other players online!"
""
"Our main canvas is a huge worldmap, you can place wherever you like, but "
"you will have to wait a specific Cooldown between pixels. You can check out "
"the cooldown and requiremnts on the Canvas Selection menu (globe button on "
"top). Some canvases have a different cooldown for replacing a user-set "
"pixels than placing on a unset pixel. i.e. 4s/7s means 4s on fresh pixels "
"and 7s on already set pixels."
""
"Higher zoomlevels take some time to update, the 3D globe gets updated at "
"least once per day."
"Have fun!"
"recommended"
"Source on "
"Map Data"
""
"The bare map data that we use, together with converted OpenStreetMap tiles "
"for orientation, can be downloaded from mega.nz here: "
"Detected as Proxy?"
""
"If you got detected as proxy, but you are none, please go to our ${ "
"guildedLink } or send us an e-mail with ${ getIPLink } to ${ mailLink }. Do "
"not post your IP anywhere else. We are sorry for the inconvenience."
"Controls"
"Click a color in palette to select it"
"Press ${ bindG } to toggle grid"
"Press ${ bindX } to toggle showing of pixel activity"
"Press ${ bindH } to toggle historical view"
"Press ${ bindR } to copy coordinates"
"Press ${ bindQ } or ${ bindE } to zoom"
"Press ${ bindW }, ${ bindA }, ${ bindS }, ${ bindD } to move"
"Press ${ bindAUp }, ${ bindALeft }, ${ bindADown }, ${ bindARight } to move"
"Drag ${ mouseSymbol } mouse or ${ touchSymbol } pan to move"
"Scroll ${ mouseSymbol } mouse wheel or ${ touchSymbol } pinch to zoom"
"Hold left ${ bindShift } for placing while moving mouse"
""
"Hold right ${ bindShift } for placing while moving mouse according to "
"historical view"
"${ mouseSymbol } Left click or ${ touchSymbol } tap to place a pixel"
""
"Click ${ mouseSymbol } middle mouse button or ${ touchSymbol } long-tap to "
"select current hovering color"
"Press ${ bindE } and ${ bindC } to fly up and down"
"${ mouseSymbol } Hold left mouse button and drag mouse to rotate"
""
"${ mouseSymbol } Scroll mouse wheel or hold ${ mouseSymbol } middle mouse "
"button and drag to zoom"
"${ mouseSymbol } Right click and drag mouse to pan"
""
"${ mouseSymbol } Right click or ${ touchSymbol } double-tap to remove a "
"pixel"
"Partners:"
""
"This site is protected by reCAPTCHA and the Google ${ reCaptchaPP } and ${ "
"reCaptchaTOS } apply."
""
"This site is protected by hCAPTCHA and its ${ hCaptchaPP } and ${ "
"hCaptchaTOS } apply."
"Welcome to PixelPlanet.fun"
"Mute"
"Show Grid"
"Turn on grid to highlight pixel borders."
"Show Pixel Activity"
"Show circles where pixels are placed."
"Disable Game Sounds"
"All sound effects will be disabled."
"Enable chat notifications"
"Play a sound when new chat messages arrive"
"Auto Zoom In"
""
"Zoom in instead of placing a pixel when you tap the canvas and your zoom is "
"small."
"Compact Palette"
"Display Palette in a compact form that takes less screen space."
"Potato Mode"
"For when you are playing on a potato."
"Light Grid"
"Show Grid in white instead of black."
"Historical View"
"Check out past versions of the canvas."
"Themes"
"How pixelplanet should look like."
"Register new account here"
"Consider joining us on Guilded:"
"Register New Account"
"Login to access more features and stats."
"Login with Name or Mail:"
"I forgot my Password."
"or login with:"
"or register here:"
"Register"
"Profile"
"Ranking"
"Converter"
"Admintools"
"Modtools"
"Loading..."
""
"While we tend to not delete canvases, some canvases are started for fun or "
"as a request by users who currently like a meme. Those canvases can get "
"boring after a while and after weeks of no major change and if they really "
"aren't worth being kept active, we decide to remove them."
""
"Here we collect those canvases to archive them in a proper way (which is "
"currently just one)."
"Political Compass Canvas"
""
"This canvas got requested during a time of political conflicts on the main "
"Earth canvas. It was a 1024x1024 representation of the political compass "
"with a 5s coolodwn and 60s stacking. It got launched on May 11th and "
"remained active for months till it got shut down on November 30th."
""
"We decided to archive it as a timelapse with lossless encoded webm. Taking "
"a screenshot from the timelapse results in a perfect 1:1 representation of "
"how the canvas was at that time."
"Canvas Archive"
""
"Select the canvas you want to use. Every canvas is unique and has different "
"palettes, cooldown and requirements. Archive of closed canvases can be "
"accessed here:"
"Archive"
"Enter your mail adress and we will send you a new password:"
"Restore my Password"
"Chat"
"Error"
"Name or Email"
"Password"
"LogIn"
"Todays Placed Pixels"
"Daily Rank"
"Placed Pixels"
"Total Rank"
"Your name is: ${ name }"
"Log out"
"Change Username"
"Change Mail"
"Change Password"
"Delete Account"
"Social Settings"
"Total"
"Daily"
"Ranking updates every 5 min. Daily rankings get reset at midnight UTC."
"Cooldown"
"Stacking till"
"Ranked"
"Requirements"
"User Account"
"and ${ canvas.req } Pixels set"
"Dimensions"
"Sent you a mail with instructions to reset your password."
"Email"
"Submit"
"Cancel"
"Name"
"Confirm Password"
"Build image on canvas."
"Build image and set it to protected."
"Build image, but reset cooldown to unset-pixel cd."
"Image Upload"
"Upload images to canvas"
"File"
"Coordinates in X_Y format:"
"Pixel Protection"
""
"Set protection of areas (if you need finer grained control, "
"use protect with image upload and alpha layers)"
"Rollback to Date"
"Rollback an area of the canvas to a set date (00:00 UTC)"
"IP Actions"
"Do stuff with IPs (one IP per line)"
"Manage Moderators"
"Remove Moderator"
"There are no mods"
"Assign new Mod"
"Enter UserName of new Mod"
"User Name"
"Choose Canvas"
"Palette Download"
"Palette for ${ gimpLink }"
"Credit for the Palette of the Moon goes to ${ starhouseLink }."
"Image Converter"
"Convert an image to canvas colors"
"Choose Strategy"
"Choose Color Mode"
"Add Grid (uncheck if you need a 1:1 template)"
"Offset"
"Scale Image"
"Width"
"Height"
"Keep Ratio"
"Anti Aliasing"
"Reset"
"Download Template"
"Email can't be empty."
"Email should be at least 5 characters long."
"Email can't be longer than 40 characters."
"Email should at least contain a dot"
"Email should contain a @"
"Name can't be empty."
"Name must be at least 4 characters long"
"Name must be shorter than 26 characters"
"Name contains invalid character like @, /, \\ or #"
"No password given."
"Password must be at least 6 characters long."
"Password must be shorter than 60 characters."
"Could not connect to server, please try again later :("
"I think we experienced some error :("
"Block all Private Messages"
"Unblock Users"
"You have no users blocked"
""
"Changed Mail successfully. We sent you a verification mail, "
"please verify your new mail adress."
"New Mail"
"Save"
"Passwords do not match."
"Changed Password successfully."
"Old Password"
"New Password"
"Confirm New Password"
"Yes, Delete My Account!"
"A new verification mail is getting sent to you."
"You successfully linked your mc account."
"You denied."
""
"Please verify your mail address \n"
"or your account could get deleted after a few days."
"Click here to request a new verification mail."
"You requested to link your mc account ${ minecraftname }."
"Accept"
"Deny"
"New Username"
"Place color pixels on an map styled canvas with other players online"
"Double click on globe to go back."
"Loading..."
"PixelPlanet.Fun 3DGlobe"
"A 3D globe of our whole map"
"You sent an empty password or invalid data :("
"This password-reset link isn't valid anymore :("
"Your passwords do not match :("
"User doesn't exist in our database :("
"Passowrd successfully changed."
"Invalid url :( Please check your mail again."
"This passwort reset link is wrong or already expired, please request a new "
"one (Note: you can use those links just once)"
""
"We already sent you a verification mail, you can request another one in ${ "
"minLeft } minutes."
"Welcome ${ name } to PixelPlanet, plese verify your mail"
"Hello ${ name }"
""
"welcome to our little community of pixelplacers, to use your account, you "
"have to verify your mail. You can do that here: "
"Click to Verify"
"Or by copying following url:"
"Have fun and don't hesitate to contact us if you encouter any problems :)"
"Thanks"
""
"We already sent you a mail with instructions. Please wait before requesting "
"another mail."
"Couldn't find this mail in our database"
"You forgot your password for PixelPlanet? Get a new one here"
"Hello"
""
"You requested to get a new password. You can change your password within "
"the next 30min here: "
"Reset Password"
""
"If you did not request this mail, please just ignore it (the ip that "
"requested this mail was ${ ip })."
"Click here"
"to go back to pixelplanet"
"Hello ${ name }, you can set your new password here:"
"New Password"
"Confirm New Password"
"Submit"
"PixelPlanet.fun Password Reset"
"Reset your password here"
"Email can't be empty."
"Email should be at least 5 characters long."
"Email can't be longer than 40 characters."
"Email should at least contain a dot"
"Email should contain a @"
"Name can't be empty."
"Name must be at least 4 characters long"
"Name must be shorter than 26 characters"
"Name contains invalid character like @, /, \\ or #"
"No password given."
"Password must be at least 6 characters long."
"Password must be shorter than 60 characters."
"Could not connect to server, please try again later :("
"I think we experienced some error :("
"You are not authenticated."
"Incorrect password!"
"You are not even logged in."
"Mail verification"
"You are now verified :)"
""
"Your mail verification code is invalid or already expired :(, please "
"request a new one."
"E-Mail already in use."
"Username already in use."
"Failed to create new user :("
"Failed to establish session after register :("
"You will be automatically redirected after 15s"
"Or ${ clickHere } to go back to pixelplanet"
"PixelPlanet.fun Accounts"
"Earth"
"Moon"
"3D Canvas"
"Coronavirus"
"PixelZone"
"PixelCanvas"
"1bit"
"Our main canvas, a huge map of the world. Place everywhere you like"
"Moon canvas. Safe space for art. No flags or large text (unless part of art)"
"Place Voxels on a 3D canvas with others"
"Special canvas to spread awareness of SARS-CoV2"
"Mirror of PixelZone"
"Mirror of PixelCanvas"
"Black and White canvas"

154
package-lock.json generated
View File

@ -3562,6 +3562,12 @@
"integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
"dev": true
},
"easy-stack": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.1.tgz",
"integrity": "sha512-wK2sCs4feiiJeFXn3zvY0p41mdU5VUgbgs1rNsc/y5ngFUijdWd+iIN8eoyuZHKB8xN6BL4PdWmzqFmxNg6V2w==",
"dev": true
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@ -3651,6 +3657,15 @@
"integrity": "sha512-46+j5QxbPWza0PB1i15nZx0xQ4I/EfQxg9J8Had3b408SV63nEtor2e+oiY63amTo9KTuh2a3XLObNwduxYwwA==",
"dev": true
},
"errno": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz",
"integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==",
"dev": true,
"requires": {
"prr": "~1.0.1"
}
},
"error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@ -4306,6 +4321,12 @@
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
},
"event-pubsub": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/event-pubsub/-/event-pubsub-4.3.0.tgz",
"integrity": "sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ==",
"dev": true
},
"events": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz",
@ -5477,6 +5498,21 @@
"resolved": "https://registry.npmjs.org/js-file-download/-/js-file-download-0.4.12.tgz",
"integrity": "sha512-rML+NkoD08p5Dllpjo0ffy4jRHeY6Zsapvr/W86N7E0yuzAO6qa5X9+xog6zQNlH102J7IXljNY2FtS6Lj3ucg=="
},
"js-message": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.7.tgz",
"integrity": "sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==",
"dev": true
},
"js-queue": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/js-queue/-/js-queue-2.0.2.tgz",
"integrity": "sha512-pbKLsbCfi7kriM3s1J4DDCo7jQkI58zPLHi0heXPzPlj0hjUsm+FesPUbE0DSbIVIK503A36aUBoCN7eMFedkA==",
"dev": true,
"requires": {
"easy-stack": "^1.0.1"
}
},
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@ -5524,6 +5560,15 @@
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
"json-stable-stringify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
"integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
"dev": true,
"requires": {
"jsonify": "~0.0.0"
}
},
"json-stable-stringify-without-jsonify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
@ -5538,6 +5583,12 @@
"minimist": "^1.2.5"
}
},
"jsonify": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
"integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
"dev": true
},
"jsx-ast-utils": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.1.0.tgz",
@ -5834,12 +5885,30 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
},
"lodash.assign": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
"integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=",
"dev": true
},
"lodash.clonedeep": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
"integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=",
"dev": true
},
"lodash.endswith": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/lodash.endswith/-/lodash.endswith-4.2.1.tgz",
"integrity": "sha1-/tWawXOO0+I27dcGTsRWRIs3vAk=",
"dev": true
},
"lodash.flatten": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
"integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=",
"dev": true
},
"lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
@ -6312,6 +6381,17 @@
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz",
"integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg=="
},
"node-ipc": {
"version": "9.1.3",
"resolved": "https://registry.npmjs.org/node-ipc/-/node-ipc-9.1.3.tgz",
"integrity": "sha512-8RS4RZyS/KMKKYG8mrje+cLxwATe9dBCuOiqKFSWND4oOuKytfuKCiR9yinvhoXF/nGdX/WnbywaUee+9U87zA==",
"dev": true,
"requires": {
"event-pubsub": "4.3.0",
"js-message": "1.0.7",
"js-queue": "2.0.2"
}
},
"node-modules-regexp": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz",
@ -6850,6 +6930,59 @@
"semver": "^5.1.0"
}
},
"parallel-webpack": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/parallel-webpack/-/parallel-webpack-2.6.0.tgz",
"integrity": "sha512-aOOLfQ40yWWRt8214F0zNWp0DWbeCs7tJaEur0/XUlYU8Yht1sMTYt+eNrbY4VkM4O/SRSme7cdZJTtIantiOw==",
"dev": true,
"requires": {
"ajv": "^4.9.2",
"bluebird": "^3.0.6",
"chalk": "^1.1.1",
"interpret": "^1.0.1",
"lodash.assign": "^4.0.8",
"lodash.endswith": "^4.0.1",
"lodash.flatten": "^4.2.0",
"minimist": "^1.2.0",
"node-ipc": "^9.1.0",
"pluralize": "^1.2.1",
"supports-color": "^3.1.2",
"worker-farm": "^1.3.1"
},
"dependencies": {
"ajv": {
"version": "4.11.8",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
"integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=",
"dev": true,
"requires": {
"co": "^4.6.0",
"json-stable-stringify": "^1.0.1"
}
},
"has-flag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
"integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
"dev": true
},
"interpret": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
"integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
"dev": true
},
"supports-color": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
"integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
"dev": true,
"requires": {
"has-flag": "^1.0.0"
}
}
}
},
"parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@ -7123,6 +7256,12 @@
"resolved": "https://registry.npmjs.org/plural-forms/-/plural-forms-0.5.3.tgz",
"integrity": "sha512-t/hkjsTeDwaK9n/z6tUiSHySTC8sPnTiS5YF3Y5p4L+eomzXh7O0vEemkjwb68/82w0Rjw4uED3X84X7vXf9lg=="
},
"pluralize": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz",
"integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=",
"dev": true
},
"postcss": {
"version": "8.1.10",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.1.10.tgz",
@ -7287,6 +7426,12 @@
"ipaddr.js": "1.9.1"
}
},
"prr": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
"integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
"dev": true
},
"pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
@ -10090,6 +10235,15 @@
"typical": "^5.0.0"
}
},
"worker-farm": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
"integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==",
"dev": true,
"requires": {
"errno": "~0.1.7"
}
},
"wrap-ansi": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",

View File

@ -11,7 +11,7 @@
"scripts": {
"build": "babel-node scripts/run prebuild && npm run webpack",
"clean": "babel-node scripts/run clean",
"webpack": "webpack --config webpack.config.web.babel.js && webpack --config webpack.config.client.babel.js",
"webpack": "webpack --config ./webpack.config.web.babel.js && parallel-webpack --config ./webpack.config.client.babel.js",
"babel-node": "cd $INIT_CWD && babel-node",
"lint": "cd $INIT_CWD && eslint --ext .jsx --ext .js",
"lint:src": "eslint --ext .jsx --ext .js src",
@ -133,6 +133,7 @@
"json-loader": "^0.5.4",
"mkdirp": "^1.0.4",
"npm-check": "^5.9.2",
"parallel-webpack": "^2.6.0",
"react-hot-loader": "^4.13.0",
"react-svg-loader": "^3.0.3",
"rimraf": "^3.0.2",

View File

@ -82,6 +82,14 @@ function ChatMessage({
return (<span className={className}>{txt}</span>);
} if (type === 'c') {
return (<a href={`./${txt}`}>{txt}</a>);
} if (type === 'l') {
return (
<a
href={txt}
target="_blank"
rel="noopener noreferrer"
>{txt}</a>
);
} if (type === 'p') {
return (
<span

View File

@ -219,20 +219,33 @@ export class ChatProvider {
}
}
async sendMessage(user, message, channelId: number = 0) {
/*
* @param user User object
* @param message string of message
* @param channelId integer of channel
* @param ttag for translating return string
* @return error message if unsuccessful, otherwise null
*/
async sendMessage(
user,
message,
channelId,
ttag,
) {
const { id } = user;
const { t } = ttag;
const name = user.getName();
if (!user.userlvl && await cheapDetector(user.ip)) {
logger.info(
`${name} / ${user.ip} tried to send chat message with proxy`,
);
return 'You can not send chat messages with proxy';
return t`You can not send chat messages with proxy`;
}
if (!name || !id) {
// eslint-disable-next-line max-len
return 'Couldn\'t send your message, pls log out and back in again.';
return t`Couldn\'t send your message, pls log out and back in again.`;
}
if (message.charAt(0) === '/' && user.userlvl) {
@ -244,40 +257,41 @@ export class ChatProvider {
}
const waitLeft = user.rateLimiter.tick();
if (waitLeft) {
const waitTime = Math.floor(waitLeft / 1000);
// eslint-disable-next-line max-len
return `You are sending messages too fast, you have to wait ${Math.floor(waitLeft / 1000)}s :(`;
return t`You are sending messages too fast, you have to wait ${waitTime}s :(`;
}
if (!this.userHasChannelAccess(user, channelId)) {
return 'You don\'t have access to this channel';
return t`You don\'t have access to this channel`;
}
const country = user.regUser.flag || 'xx';
const displayCountry = (name.endsWith('berg') || name.endsWith('stein'))
let displayCountry = (name.endsWith('berg') || name.endsWith('stein'))
? 'il'
: country;
if (!user.regUser.verified) {
return 'Your mail has to be verified in order to chat';
/*
* hard coded flag for Manchukuo_1940
* TODO make it possible to modify user flags
*/
if (user.id === 2927) {
displayCountry = 'bt';
}
if (message.length > 4
&& message === message.toUpperCase()
&& message !== message.toLowerCase()
) {
return 'Stop shouting';
if (!user.regUser.verified) {
return t`Your mail has to be verified in order to chat`;
}
const muted = await ChatProvider.checkIfMuted(user);
if (muted === -1) {
return 'You are permanently muted, join our guilded to apppeal the mute';
return t`You are permanently muted, join our guilded to apppeal the mute`;
}
if (muted > 0) {
if (muted > 120) {
const timeMin = Math.round(muted / 60);
return `You are muted for another ${timeMin} minutes`;
return t`You are muted for another ${timeMin} minutes`;
}
return `You are muted for another ${muted} seconds`;
return t`You are muted for another ${muted} seconds`;
}
for (let i = 0; i < this.filters.length; i += 1) {
@ -285,7 +299,7 @@ export class ChatProvider {
const count = (message.match(filter.regexp) || []).length;
if (count >= filter.matches) {
this.mute(name, channelId, 30);
return 'Ow no! Spam protection decided to mute you';
return t`Ow no! Spam protection decided to mute you`;
}
}
@ -294,21 +308,17 @@ export class ChatProvider {
message = message.replace(subsitute.regexp, subsitute.replace);
}
if (message.includes('http')) {
return 'no shitty links pls';
}
if (message.length > 200) {
// eslint-disable-next-line max-len
return 'You can\'t send a message this long :(';
return t`You can\'t send a message this long :(`;
}
if (message.match(this.cyrillic) && channelId === this.enChannelId) {
return 'Please use int channel';
return t`Please use int channel`;
}
if (this.mutedCountries.includes(country)) {
return 'Your country is temporary muted from chat';
return t`Your country is temporary muted from chat`;
}
if (user.last_message && user.last_message === message) {
@ -316,7 +326,7 @@ export class ChatProvider {
if (user.message_repeat >= 4) {
this.mute(name, channelId, 60);
user.message_repeat = 0;
return 'Stop flooding.';
return t`Stop flooding.`;
}
} else {
user.message_repeat = 0;

View File

@ -8,14 +8,17 @@
* splits chat message into array of what it represents
* [[type, text],[type, text], ...]
* type:
* 'l': external link
* 't': text
* 'p': ping
* 'c': coordinates
* 'c': coordinates or ppfun link
* 'm': mention of somebody else
* nameRegExp has to be in the form of:
new RegExp(`(^|\\s+)(@${ownName})(\\s+|$)`, 'g');
*/
const linkRegExp = /(#[a-z]*,-?[0-9]*,-?[0-9]*(,-?[0-9]+)?)/gi;
// eslint-disable-next-line
const linkRegExp = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi;
const ppLinkRegExp = /(#[a-z]*,-?[0-9]*,-?[0-9]*(,-?[0-9]+)?)/gi;
const linkRegExpFilter = (val, ind) => ((ind % 3) !== 2);
const mentionRegExp = /(^|\s)(@\S+)/g;
const spaceFilter = (val, ind) => (val !== ' ' && (ind !== 0 | val !== ''));
@ -49,10 +52,11 @@ function splitChatMessage(message, nameRegExp = null) {
return null;
}
let arr = [['t', message.trim()]];
arr = splitChatMessageRegexp(arr, linkRegExp, 'c', linkRegExpFilter);
arr = splitChatMessageRegexp(arr, ppLinkRegExp, 'c', linkRegExpFilter);
if (nameRegExp) {
arr = splitChatMessageRegexp(arr, nameRegExp, 'p', spaceFilter);
}
arr = splitChatMessageRegexp(arr, linkRegExp, 'l', linkRegExpFilter);
arr = splitChatMessageRegexp(arr, mentionRegExp, 'm', spaceFilter);
return arr;
}

View File

@ -340,6 +340,7 @@ class SocketServer extends WebSocketEvents {
user,
message,
channelId,
user.ttag,
);
if (errorMsg) {
ws.send(JSON.stringify([

View File

@ -7,6 +7,7 @@ import express from 'express';
import session from '../core/session';
import passport from '../core/passport';
import User from '../data/models/User';
import { expressTTag } from '../core/ttag';
import { getIPFromRequest } from '../utils/ip';
const router = express.Router();
@ -16,6 +17,8 @@ router.use(session);
router.use(passport.initialize());
router.use(passport.session());
router.use(expressTTag);
function authenticateClient(req) {
return new Promise(
@ -26,6 +29,7 @@ function authenticateClient(req) {
const user = (req.user) ? req.user
: new User(null, getIPFromRequest(req));
user.setCountry(countryCode);
user.ttag = req.ttag;
resolve(user);
});
}),

View File

@ -113,7 +113,7 @@ export function buildWebpackClientConfig(development, analyze, locale) {
path.resolve(__dirname, 'src'),
],
options: {
cacheDirectory: development,
cacheDirectory: true,
babelrc: false,
presets: [
['@babel/preset-env', {
@ -194,7 +194,18 @@ export function buildWebpackClientConfig(development, analyze, locale) {
chunkModules: false,
},
cache: true,
/*
* this does not much tbqh
cache: {
type: 'filesystem',
cacheDirectory: path.resolve(
__dirname,
'node_modules',
'.cache',
'webpack',
),
},
*/
};
}