diff --git a/src/components/SocialSettings.jsx b/src/components/SocialSettings.jsx
index a5978ce..81aca0c 100644
--- a/src/components/SocialSettings.jsx
+++ b/src/components/SocialSettings.jsx
@@ -3,32 +3,52 @@
*/
import React from 'react';
-import { useDispatch, useSelector } from 'react-redux';
+import { useDispatch, useSelector, shallowEqual } from 'react-redux';
import { t } from 'ttag';
import {
setBlockingDm,
+ setPrivatize,
setUserBlock,
} from '../store/actions/thunks';
import SettingsItem from './SettingsItem';
+const selectBlocks = (state) => [
+ state.chat.blocked,
+ state.user.blockDm,
+ state.user.priv,
+ state.fetching.fetchingApi,
+];
+
const SocialSettings = ({ done }) => {
- const blocked = useSelector((state) => state.chat.blocked);
- const blockDm = useSelector((state) => state.user.blockDm);
- const fetching = useSelector((state) => state.fetching.fetchingApi);
+ const [
+ blocked,
+ blockDm,
+ priv,
+ fetching,
+ ] = useSelector(selectBlocks, shallowEqual);
const dispatch = useDispatch();
return (
{
if (!fetching) {
dispatch(setBlockingDm(!blockDm));
}
}}
- />
+ >{t`Block all Private Messages`}
+ {
+ if (!fetching) {
+ dispatch(setPrivatize(!priv));
+ }
+ }}
+ >{t`Don't show me in global stats`}
day.filter(
+ (r) => histStats.users.some((u) => u.id === r.id),
+ ));
const ret = {
prevTop,
pDailyStats,
+ histStats,
};
if (socketEvents.amIImportant()) {
// only main shard sends to others
diff --git a/src/core/chartSettings.js b/src/core/chartSettings.js
index f1ebd2f..da4a8b6 100644
--- a/src/core/chartSettings.js
+++ b/src/core/chartSettings.js
@@ -246,8 +246,7 @@ export function getHistChartData(histStats) {
const labels = [];
let ts = Date.now();
let c = stats.length;
- // skipping todays dataset
- while (c > 1) {
+ while (c) {
const dAmount = stats.length - c;
c -= 1;
// x label
diff --git a/src/data/User.js b/src/data/User.js
index e985bd2..0acc086 100644
--- a/src/data/User.js
+++ b/src/data/User.js
@@ -241,6 +241,7 @@ class User {
name: null,
mailVerified: false,
blockDm: false,
+ priv: false,
mailreg: false,
};
}
@@ -256,6 +257,7 @@ class User {
name: regUser.name,
mailVerified: regUser.mailVerified,
blockDm: regUser.blockDm,
+ priv: regUser.priv,
totalPixels,
dailyTotalPixels,
ranking,
diff --git a/src/data/redis/ranks.js b/src/data/redis/ranks.js
index 03e55dd..b245a7a 100644
--- a/src/data/redis/ranks.js
+++ b/src/data/redis/ranks.js
@@ -194,17 +194,11 @@ export async function getDailyPixelStats() {
export async function getTopDailyHistory() {
const stats = [];
const users = [];
- let ts;
- let key;
- for (let c = 0; c < 14; c += 1) {
- if (!ts) {
- ts = Date.now();
- key = DAILY_RANKED_KEY;
- } else {
- ts -= 1000 * 3600 * 24;
- const dateKey = getDateKeyOfTs(ts);
- key = `${DAY_STATS_RANKS_KEY}:${dateKey}`;
- }
+ let ts = Date.now();
+ for (let c = 0; c < 13; c += 1) {
+ ts -= 1000 * 3600 * 24;
+ const dateKey = getDateKeyOfTs(ts);
+ const key = `${DAY_STATS_RANKS_KEY}:${dateKey}`;
// eslint-disable-next-line no-await-in-loop
let dData = await client.zRangeWithScores(key, 0, 9, {
REV: true,
diff --git a/src/data/sql/RegUser.js b/src/data/sql/RegUser.js
index 388dbcf..1f125c4 100644
--- a/src/data/sql/RegUser.js
+++ b/src/data/sql/RegUser.js
@@ -28,11 +28,14 @@ const RegUser = sequelize.define('User', {
allowNull: false,
},
- // currently just moderator
- roles: {
- type: DataTypes.TINYINT,
+ /*
+ * if account is private,
+ * exclude it from statistics etc.
+ */
+ priv: {
+ type: DataTypes.BOOLEAN,
allowNull: false,
- defaultValue: 0,
+ defaultValue: false,
},
// null if external oauth authentification
@@ -41,6 +44,13 @@ const RegUser = sequelize.define('User', {
allowNull: true,
},
+ // currently just moderator
+ roles: {
+ type: DataTypes.TINYINT,
+ allowNull: false,
+ defaultValue: 0,
+ },
+
// mail and Minecraft verified
verified: {
type: DataTypes.TINYINT,
@@ -205,6 +215,7 @@ export async function populateRanking(rawRanks) {
],
where: {
id: uids,
+ priv: false,
},
raw: true,
});
@@ -216,7 +227,7 @@ export async function populateRanking(rawRanks) {
dat.age = age;
}
}
- return rawRanks;
+ return rawRanks.filter((r) => r.name);
}
export default RegUser;
diff --git a/src/routes/api/index.js b/src/routes/api/index.js
index f0b633f..26765cf 100644
--- a/src/routes/api/index.js
+++ b/src/routes/api/index.js
@@ -14,6 +14,7 @@ import startDm from './startdm';
import leaveChan from './leavechan';
import block from './block';
import blockdm from './blockdm';
+import privatize from './privatize';
import modtools from './modtools';
import baninfo from './baninfo';
import getiid from './getiid';
@@ -94,6 +95,8 @@ router.post('/block', block);
router.post('/blockdm', blockdm);
+router.post('/privatize', privatize);
+
router.get('/chathistory', chatHistory);
router.get('/me', me);
diff --git a/src/routes/api/privatize.js b/src/routes/api/privatize.js
new file mode 100644
index 0000000..70f567f
--- /dev/null
+++ b/src/routes/api/privatize.js
@@ -0,0 +1,40 @@
+/*
+ *
+ * block all private messages
+ *
+ */
+import logger from '../../core/logger';
+
+async function privatize(req, res) {
+ const { priv } = req.body;
+ const { user } = req;
+
+ const errors = [];
+ if (typeof priv !== 'boolean') {
+ errors.push('Not defined if setting or unsetting private');
+ }
+ if (!user || !user.regUser) {
+ errors.push('You are not logged in');
+ }
+ if (errors.length) {
+ res.status(400);
+ res.json({
+ errors,
+ });
+ return;
+ }
+
+ logger.info(
+ `User ${user.getName()} set private status to ${priv}`,
+ );
+
+ await user.regUser.update({
+ priv,
+ });
+
+ res.json({
+ status: 'ok',
+ });
+}
+
+export default privatize;
diff --git a/src/store/actions/fetch.js b/src/store/actions/fetch.js
index ac1166f..fff4df3 100644
--- a/src/store/actions/fetch.js
+++ b/src/store/actions/fetch.js
@@ -151,6 +151,25 @@ export async function requestBlock(userId, block) {
return t`Unknown Error`;
}
+/*
+ * set / unset provile as private
+ * @param priv
+ * @return error string or null if successful
+ */
+export async function requestPrivatize(priv) {
+ const res = await makeAPIPOSTRequest(
+ '/api/privatize',
+ { priv },
+ );
+ if (res.errors) {
+ return res.errors[0];
+ }
+ if (res.status === 'ok') {
+ return null;
+ }
+ return t`Unknown Error`;
+}
+
/*
* start new DM channel with user
* @param query Object with either userId or userName: string
diff --git a/src/store/actions/index.js b/src/store/actions/index.js
index 9339fba..969df1e 100644
--- a/src/store/actions/index.js
+++ b/src/store/actions/index.js
@@ -475,6 +475,13 @@ export function blockingDm(blockDm) {
};
}
+export function privatize(priv) {
+ return {
+ type: 's/SET_PRIVATE',
+ priv,
+ };
+}
+
export function removeChatChannel(cid) {
return {
type: 's/REMOVE_CHAT_CHANNEL',
diff --git a/src/store/actions/thunks.js b/src/store/actions/thunks.js
index cb93a02..dd8a903 100644
--- a/src/store/actions/thunks.js
+++ b/src/store/actions/thunks.js
@@ -5,6 +5,7 @@ import {
requestStartDm,
requestBlock,
requestBlockDm,
+ requestPrivatize,
requestLeaveChan,
requestRankings,
requestChatMessages,
@@ -19,6 +20,7 @@ import {
blockUser,
unblockUser,
blockingDm,
+ privatize,
removeChatChannel,
} from './index';
@@ -127,9 +129,7 @@ export function setUserBlock(
};
}
-export function setBlockingDm(
- block,
-) {
+export function setBlockingDm(block) {
return async (dispatch) => {
dispatch(setApiFetching(true));
const res = await requestBlockDm(block);
@@ -147,6 +147,25 @@ export function setBlockingDm(
};
}
+export function setPrivatize(priv) {
+ return async (dispatch) => {
+ dispatch(setApiFetching(true));
+ const res = await requestPrivatize(priv);
+ if (res) {
+ dispatch(pAlert(
+ 'Setting User Private Error',
+ res,
+ 'error',
+ 'OK',
+ ));
+ } else {
+ dispatch(privatize(priv));
+ }
+ dispatch(setApiFetching(false));
+ };
+}
+
+
export function setLeaveChannel(
cid,
) {
diff --git a/src/store/reducers/user.js b/src/store/reducers/user.js
index 8328c7c..a81f20d 100644
--- a/src/store/reducers/user.js
+++ b/src/store/reducers/user.js
@@ -10,6 +10,8 @@ const initialState = {
mailreg: false,
// blocking all Dms
blockDm: false,
+ // privile is private
+ priv: false,
// if user is using touchscreen
isOnMobile: false,
// small notifications for received cooldown
@@ -92,6 +94,7 @@ export default function user(
name,
mailreg,
blockDm,
+ priv,
userlvl,
} = action;
const messages = (action.messages) ? action.messages : [];
@@ -102,6 +105,7 @@ export default function user(
messages,
mailreg,
blockDm,
+ priv,
userlvl,
};
}
@@ -114,6 +118,7 @@ export default function user(
messages: [],
mailreg: false,
blockDm: false,
+ priv: false,
userlvl: 0,
};
}
@@ -134,6 +139,14 @@ export default function user(
};
}
+ case 's/SET_PRIVATE': {
+ const { priv } = action;
+ return {
+ ...state,
+ priv,
+ };
+ }
+
case 'SET_NOTIFICATION': {
return {
...state,