diff --git a/README.md b/README.md
index d09e98f4..b33c7ba2 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ Official repository of [pixelplanet.fun](http://www.pixelplanet.fun).
> **TRANSLATORS NEEDED** If you want to help us translate pixelplanet.fun, look into [i18n](./i18n)
-Just to the 2nd anniversary of r/space, pixelplanet takes pixelgames to a new level. Place pixels, create pixelart and fight faction wars on pixelplanet.fun.
+To the 2nd anniversary of r/space, pixelplanet takes pixelgames to a new level. Place pixels, create pixelart and fight faction wars on pixelplanet.fun.
Pixelplanet is a 65k x 65k large canvas that is a map of the world and can also be seen as 3d globe, you can place pixels where ever you want, build an island, take over another country with a flag or just create pixelart.
30 well chosen colors (decided by polls within the community) are available and you can place a pixel every 3s on an empty space, and 5s on an already set pixel. But pixels can be stacked up to a minute, so you don't have to wait every time.
@@ -63,7 +63,7 @@ git config --global url.https://github.com/.insteadOf git://github.com/
- mysql or mariadb ([setup own user](https://www.digitalocean.com/community/tutorials/how-to-create-a-new-user-and-grant-permissions-in-mysql) and [create database](https://www.w3schools.com/SQl/sql_create_db.asp) for pixelplanet) for storing additional data like IP blacklist
### Configuration
-Configuration takes place in the environment variables that are defined in ecosystem.yml
+Configuration takes place in the environment variables that are defined in ecosystem.yml.
#### Neccessary Configuration
@@ -79,32 +79,24 @@ Configuration takes place in the environment variables that are defined in ecosy
#### Optional Configuration
-| Variable | Description | Example |
-|-------------------|:--------------------------------------|-------------------------|
-| ASSET_SERVER | URL for assets | "http://localhost" |
-| USE_PROXYCHECK | Check users for Proxies | 0 |
-| APISOCKET_KEY | Key for API Socket for SpecialAccess™ | "SDfasife3" |
-| ADMIN_IDS | Ids of users with Admin rights | "1,12,3" |
-| CAPTCHA_TIME | time in minutes between captchas | 30 |
-| | 0: always captcha -1: never captcha | |
-| SESSION_SECRET | random sting for express sessions | "ayylmao" |
-| LOG_MYSQL | if sql queries should get logged | 0 |
-| USE_XREALIP | see ngins / CDN section | 1 |
-| BACKUP_URL | url of backup server (see Backup) | "http://localhost" |
-| BACKUP_DIR | mounted directory of backup server | "/mnt/backup/" |
-| GMAIL_USER | gmail username if used for mails | "ppfun@gmail.com" |
-| GMAIL_PW | gmail password if used for mails | "lolrofls" |
-| HOURLY_EVENT | run hourly void event on main canvas | 1 |
+| Variable | Description | Example |
+|-------------------|:--------------------------------------|---------------------------|
+| ASSET_SERVER | URL for assets | "http://localhost" |
+| USE_PROXYCHECK | Check users for Proxies | 0 |
+| APISOCKET_KEY | Key for API Socket for SpecialAccess™ | "SDfasife3" |
+| ADMIN_IDS | Ids of users with Admin rights | "1,12,3" |
+| CAPTCHA_TIME | time in minutes between captchas | 30 |
+| | 0: always captcha -1: never captcha | |
+| SESSION_SECRET | random sting for express sessions | "ayylmao" |
+| LOG_MYSQL | if sql queries should get logged | 0 |
+| USE_XREALIP | see ngins / CDN section | 1 |
+| BACKUP_URL | url of backup server (see Backup) | "http://localhost" |
+| BACKUP_DIR | mounted directory of backup server | "/mnt/backup/" |
+| HOURLY_EVENT | run hourly void event on main canvas | 1 |
+| USE_MAILER | enable to use mail sevicse | 0 |
+| MAIL_ADDRESS | email address for sending mails | "noreply@pixelplanet.fun" |
-Notes:
-
-- HOST / PORT is the host on which the ppfun server is listening. In example: If you have a reverse proxy on the same machine, HOST should still be unset or localhost, because it's where the proxy forwards to.
-- to be able to use USE_PROXYCHECK, you have to have an account on proxycheck.io or getipintel or another checker setup and you might set some proxies in`proxies.json` that get used for making proxycheck requests. Look into `src/isProxy.js` to see how things work, but keep in mind that this isn't neccessarily how pixelplanet.fun uses it.
-- Admins are users with 0cd and access to `Admintools`in their User Menu for image-upload and whatever
-- You can find out the id of a user by looking into the logs (i.e. `info: {ip} / {id} wants to place 2 in (1701, -8315)`) when he places a pixel or by checking the MySql Users database
-- If you use gmail as mail transport, make sure that less-secure apps are allowed to access it in your settings [here](https://myaccount.google.com/lesssecureapps)
-
-#### Social Media
+#### Social Media Configuration
| Variable | Description |
|-----------------------|:-------------------------|
@@ -122,33 +114,45 @@ Notes:
Notes:
-- The HTML for SocialMedia logins is in src/componets/UserAreaModal.js , delete stuff from there if you don't need it
-- The HTML for the Help Screen is in src/components/HelpModal.js
+- HOST / PORT is the host on which the ppfun server is listening. In example: If you have a reverse proxy on the same machine, HOST should still be unset or localhost, because it's where the proxy forwards to.
+- to be able to use USE_PROXYCHECK, you have to have an account on proxycheck.io or getipintel or another checker setup and you might set some proxies in`proxies.json` that get used for making proxycheck requests. Look into `src/isProxy.js` to see how things work, but keep in mind that this isn't neccessarily how pixelplanet.fun uses it.
+- Admins are users with 0cd and access to `Admintools`in their User Menu for image-upload and whatever
+- You can find out the id of a user by looking into the logs (i.e. `info: {ip} / {id} wants to place 2 in (1701, -8315)`) when he places a pixel or by checking the MySql Users database
+- pixelplanet uses the unix command sendmail for sending verification and password reset mails. If you don't want to set up your own mail server, look into [ssmtp](https://wiki.archlinux.org/title/SSMTP), which provides a sendmail interface that forwards to other providers like gmail.
+- default configuartion values can be seen in `src/core/config.js`
+Notes:
+- The HTML for SocialMedia logins is in src/componets/UserAreaModal.js , delete stuff from there if you don't need it. The HTML for the Help Screen is in src/components/HelpModal.js
Canvas specific configuartion like colors and cooldown is in `canvases.json` for all canvases. The titles and descriptions of the canvases are in `src/canvasesDesc.js` for translation reasons. Changing them requires a rebuild.
Meaning of some values:
+#### Neccessary canvases Configuration
+
| Key | Description |
|--------|:----------------------------------------------------------------|
| ident | Unique character used in the url |
| size | canvas size, power of 2 and between 256 and 65536 |
| bcd | Base cooldown for unset pixels |
-| pcd | Cooldown for placing on set pixels (defaults to same as bcd) |
| cds | Stack time of Cooldown |
+| sd | Start-date of the canvas (for historical view) |
+
+#### Optional canvases Configuration
+
+| Key | Description |
+|--------|:----------------------------------------------------------------|
+| pcd | Cooldown for placing on set pixels (defaults to same as bcd) |
| cli | Number of leading colors on the palette to ignore (default: 0) |
+| req | requieremt to place on the canvas (default: unset) |
| ranked | If pixels on canvas count on player statistic (default: false) |
-| req | requieremt to place on the canvas |
-| sd | Start-date of the canvas for historical view |
| v | If 3D voxel canvas (boolean) (default: false) |
| hid | Hidden canvases, can be just seen by pressing P (default: false)|
-Values that have defaults and `req` are optional.
-The canvas size limit can be surpassed by changing the websocket packages in src/socket/packages/ to send chunk coordinates in 16bit.
-If `req` is 0, the canvas is only available for registered Useers. If it is a number >0 it is the amount of total pixels placed before a player is allowed to play there. If it is `top`, then it is only accessible for the Top10 players of the previous day.
-The colors that are ignored via `cli` are used for making the canvas (blue ocean and white continents) and to know if the pixel is already set by a user or not.
-If you want to add a new canvas, be sure that you additionally create `public/loading${canvasId}.png`, `public/assets3d/normal${canvasId}.jpg`, `public/preview${canvasId}.png` and `public/assets3d/specular${canvasId}.jpg`, check out the existing ones to see what those files are for.
+Notes:
-The default configuration values can be seen in `src/core/config.js` and for the canvases in `src/core/constats.js`
+- The canvas size limit can be surpassed by changing the websocket packages in src/socket/packages/ to send chunk coordinates in 16bit.
+- If `req` is 0, the canvas is only available for registered Useers. If it is a number >0 it is the amount of total pixels placed before a player is allowed to play there. If it is `top`, then it is only accessible for the Top10 players of the previous day.
+- The colors that are ignored via `cli` are used for making the canvas (blue ocean and white continents) and to know if the pixel is already set by a user or not.
+- If you want to add a new canvas, be sure that you additionally create `public/loading${canvasId}.png`, `public/assets3d/normal${canvasId}.jpg`, `public/preview${canvasId}.png` and `public/assets3d/specular${canvasId}.jpg`, check out the existing ones to see what those files are for.
#### Styles
@@ -163,10 +167,6 @@ To add more css styles, create a new css file in `src/styles` based on `src/styl
pm2 start ecosystem.yml
```
-Notes:
-
-- pixelplanet uses the unix command sendmail for sending verification and password reset mails if no GMAIL account is given. If you are on windows, this might not work.
-
### Logging
General logs are in `~/pm2/log/`, you can view them with
@@ -187,9 +187,9 @@ Pixel placing logs are in `./log/pixels.log`and proxycheck logs in `./log/proxie
pm2 stop ppfun-server
```
-### If using Cloudflare / Reverse Proxy
+### If using reverse Proxy
-If USE\_XREALIP is set, we take the IP from the X-Real-Ip header. Use this if you have pixelplanet running behind nginx and cloudflare. Use the nginx set\_realip module to give us the client ip on the X-Real-Ip header (and set it up so that just cloudflare are trusted proxy IPs, or else players could fake their IP). And be sure to also set X-Forwarded-Host, X-Forwarded-Port and set X-Forwarded-Proto, because we use it for CORS and redirecion.
+If USE\_XREALIP is set, we take the IP from the X-Real-Ip header. Use this if you have pixelplanet running behind a reverse proxy like nginx (recommended). Use the nginx set\_realip module to give us the client ip on the X-Real-Ip header (and set it up so that just cloudflare are trusted proxy IPs, if you use them, or else players could fake their IP). And be sure to also set X-Forwarded-Host, X-Forwarded-Port and set X-Forwarded-Proto, because we use it for CORS and redirecion.
### Auto-Start
To have the canvas with all it's components autostart at systemstart,
@@ -225,13 +225,14 @@ If command is defined, it will be executed after every backup (just one command,
You can run it with pm2, just like pixelplanet. An example ecosystem-backup.example.yml file will be located in the dist directory.
Note:
+
- You do not have to run backups or historical view, it's optional.
-### Hourly Event
+## Hourly Event
Hourly event is an MMORPG style event that launches once in two hours where users have to fight against a growing void that starts at a random position at the main canvas. If they complete it successfully, the whole canvas will have half cooldown for a few minutes.
-### Historical view
+## Historical view
![historicalview](promotion/historicalview.gif)
@@ -249,7 +250,6 @@ If v is set and true for a canvas in the canvas.json, it will be a 3D voxel canv
## Development
Run `npm run lint:src` to check for code errors and warnings or `npm run lint -- ./your/file.js` to check a single file.
-Please do not produce too many additional warnings.
[ttag](https://github.com/ttag-org/ttag/) is used for handling translations. For server-side rendering the `Accept-Language` header gets checked and the first locale used and on-the-fly translated (`src/core/ttag.js` provides the functions for it). On the client-side a seperate bundle for every language gets provided.
The language definitions in `i18n/template.pot` and `i18n/template-ssr.pot` get updated when doing a dev build with
@@ -258,4 +258,4 @@ npm run build:dev
```
which also only builds the default local in a development environment for debugging.
-You can use `npm run babel-node ./your/script.js` to execute a script with local babel.
+You can use `npm run babel-node ./utils/script.js` to execute a script with local babel (path always relative to the root directory).
diff --git a/src/core/ChatProvider.js b/src/core/ChatProvider.js
index 63744aa9..0f1d4576 100644
--- a/src/core/ChatProvider.js
+++ b/src/core/ChatProvider.js
@@ -15,6 +15,7 @@ import { cheapDetector } from './isProxy';
import { DailyCron } from '../utils/cron';
import ttags from './ttag';
+import { USE_MAILER } from './config';
import {
CHAT_CHANNELS,
EVENT_USER_NAME,
@@ -415,7 +416,7 @@ export class ChatProvider {
displayCountry = 'bt';
}
- if (!user.regUser.verified) {
+ if (USE_MAILER && !user.regUser.verified) {
return t`Your mail has to be verified in order to chat`;
}
diff --git a/src/core/config.js b/src/core/config.js
index 0f54dffd..eb20cb52 100644
--- a/src/core/config.js
+++ b/src/core/config.js
@@ -12,8 +12,9 @@ if (process.env.BROWSER) {
export const PORT = process.env.PORT || 8080;
export const HOST = process.env.HOST || 'localhost';
-export const GMAIL_USER = process.env.GMAIL_USER || null;
-export const GMAIL_PW = process.env.GMAIL_PW || null;
+export const USE_MAILER = parseInt(process.env.USE_MAILER, 10) || false;
+export const MAIL_ADDRESS = process.env.MAIL_ADDRESS
+ || 'donotreply@pixelplanet.fun';
const TILE_FOLDER_REL = process.env.TILE_FOLDER || 'tiles';
export const TILE_FOLDER = path.join(__dirname, `./${TILE_FOLDER_REL}`);
@@ -51,13 +52,6 @@ export const APISOCKET_KEY = process.env.APISOCKET_KEY || null;
export const ADMIN_IDS = (process.env.ADMIN_IDS)
? process.env.ADMIN_IDS.split(',').map((z) => parseInt(z, 10)) : [];
-export const analytics = {
- // https://analytics.google.com/
- google: {
- trackingId: process.env.GOOGLE_TRACKING_ID, // UA-XXXXX-X
- },
-};
-
export const auth = {
// https://developers.facebook.com/
facebook: {
diff --git a/src/core/mail.js b/src/core/mail.js
index 978227dc..29eb7b2d 100644
--- a/src/core/mail.js
+++ b/src/core/mail.js
@@ -10,44 +10,52 @@ import logger from './logger';
import { HOUR, MINUTE } from './constants';
import { DailyCron, HourlyCron } from '../utils/cron';
import { getTTag } from './ttag';
-import { GMAIL_USER, GMAIL_PW } from './config';
+import { USE_MAILER, MAIL_ADDRESS } from './config';
import { RegUser } from '../data/sql';
-/*
- * define mail transport
- * using unix command sendmail
- */
-const transporter = (GMAIL_USER && GMAIL_PW)
- ? nodemailer.createTransport({
- service: 'gmail',
- auth: {
- user: GMAIL_USER,
- pass: GMAIL_PW,
- },
- })
- : nodemailer.createTransport({
- sendmail: true,
- newline: 'unix',
- path: '/usr/sbin/sendmail',
- });
-const address = (GMAIL_USER && GMAIL_PW)
- ? GMAIL_USER
- : 'donotreply@pixelplanet.fun';
-
-
// TODO make code expire
class MailProvider {
constructor() {
- this.clearCodes = this.clearCodes.bind(this);
+ this.enabled = !!USE_MAILER;
+ if (this.enabled) {
+ this.transporter = nodemailer.createTransport({
+ sendmail: true,
+ newline: 'unix',
+ path: '/usr/sbin/sendmail',
+ });
- this.verifyCodes = {};
- HourlyCron.hook(this.clearCodes);
- DailyCron.hook(MailProvider.cleanUsers);
+ this.clearCodes = this.clearCodes.bind(this);
+
+ this.verifyCodes = {};
+ HourlyCron.hook(this.clearCodes);
+ DailyCron.hook(MailProvider.cleanUsers);
+ }
+ }
+
+ sendMail(to, subject, html) {
+ if (!this.enabled) {
+ return;
+ }
+ this.transporter.sendMail({
+ from: `PixelPlanet <${MAIL_ADDRESS}>`,
+ to,
+ replyTo: MAIL_ADDRESS,
+ subject,
+ html,
+ }, (err) => {
+ if (err) {
+ logger.error(err);
+ }
+ });
}
sendVerifyMail(to, name, host, lang) {
+ if (!this.enabled) {
+ return null;
+ }
+
const { t } = getTTag(lang);
const pastMail = this.verifyCodes[to];
@@ -62,30 +70,27 @@ class MailProvider {
return t`We already sent you a verification mail, you can request another one in ${minLeft} minutes.`;
}
}
+
logger.info(`Sending verification mail to ${to} / ${name}`);
const code = this.setCode(to);
const verifyUrl = `${host}/api/auth/verify?token=${code}`;
- transporter.sendMail({
- from: `PixelPlanet <${address}>`,
- to,
- replyTo: address,
- subject: t`Welcome ${name} to PixelPlanet, plese verify your mail`,
- // text: `Hello,\nwelcome to our little community of pixelplacers, to use your account, you have to verify your mail. You can do that here:\n ${verifyUrl} \nHave fun and don't hesitate to contact us if you encouter any problems :)\nThanks`,
- html: `${t`Hello ${name}`},
+ const subject = t`Welcome ${name} to PixelPlanet, plese verify your mail`;
+ const html = `${t`Hello ${name}`},
${t`welcome to our little community of pixelplacers, to use your account, you have to verify your mail. You can do that here: `} ${t`Click to Verify`}. ${t`Or by copying following url:`}
${verifyUrl}\n
${t`Have fun and don't hesitate to contact us if you encouter any problems :)`}
${t`Thanks`}
-
`,
- }, (err) => {
- if (err) {
- logger.error(err);
- }
- });
+
`;
+ this.sendMail(to, subject, html);
return null;
}
async sendPasswdResetMail(to, ip, host, lang) {
const { t } = getTTag(lang);
+
+ if (!this.enabled) {
+ return t`Mail is not configured on the server`;
+ }
+
const pastMail = this.verifyCodes[to];
if (pastMail) {
if (Date.now() < pastMail.timestamp + 15 * MINUTE) {
@@ -102,6 +107,7 @@ class MailProvider {
);
return t`Couldn't find this mail in our database`;
}
+
/*
* not sure if this is needed yet
* does it matter if spaming password reset mails or verifications mails?
@@ -115,21 +121,12 @@ class MailProvider {
logger.info(`Sending Password reset mail to ${to}`);
const code = this.setCode(to);
const restoreUrl = `${host}/reset_password?token=${code}`;
- transporter.sendMail({
- from: `PixelPlanet <${address}>`,
- to,
- replyTo: address,
- subject: t`You forgot your password for PixelPlanet? Get a new one here`,
- // text: `Hello,\nYou requested to get a new password. You can change your password within the next 30min here:\n ${restoreUrl} \nHave fun and don't hesitate to contact us if you encouter any problems :)\nIf you did not request this mail, please just ignore it (the ip that requested this mail was ${ip}).\nThanks`,
- html: `${t`Hello`},
+ const subject = t`You forgot your password for PixelPlanet? Get a new one here`;
+ const html = `${t`Hello`},
${t`You requested to get a new password. You can change your password within the next 30min here: `} ${t`Reset Password`}. ${t`Or by copying following url:`}
${restoreUrl}\n
${t`If you did not request this mail, please just ignore it (the ip that requested this mail was ${ip}).`}
- ${t`Thanks`}
\n
`,
- }, (err) => {
- if (err) {
- logger.error(err & err.stack);
- }
- });
+ ${t`Thanks`}
\n
`;
+ this.sendMail(to, subject, html);
return null;
}
@@ -212,7 +209,6 @@ class MailProvider {
[Sequelize.Op.lt]:
Sequelize.literal('CURRENT_TIMESTAMP - INTERVAL 4 DAY'),
},
- // NOTE: this means that minecraft verified accounts do not get deleted
verified: 0,
},
});
diff --git a/src/core/me.js b/src/core/me.js
index e1fc6b25..37b0455b 100644
--- a/src/core/me.js
+++ b/src/core/me.js
@@ -7,6 +7,7 @@
*/
// eslint-disable-next-line import/no-unresolved
import { getLocalicedCanvases } from '../canvasesDesc';
+import { USE_MAILER } from './config';
import chatProvider from './ChatProvider';
@@ -18,7 +19,7 @@ export default async function getMe(user, lang = 'default') {
} = userdata;
if (!name) userdata.name = null;
const messages = [];
- if (name && !mailVerified) {
+ if (USE_MAILER && name && !mailVerified) {
messages.push('not_verified');
}
if (messages.length > 0) {