fix minor issues
This commit is contained in:
parent
be8f94b368
commit
0e78dea560
|
@ -7,12 +7,12 @@ import { t } from 'ttag';
|
||||||
|
|
||||||
async function submitIPAction(
|
async function submitIPAction(
|
||||||
action,
|
action,
|
||||||
|
vallist,
|
||||||
callback,
|
callback,
|
||||||
) {
|
) {
|
||||||
const data = new FormData();
|
const data = new FormData();
|
||||||
const iplist = document.getElementById('iparea').value;
|
|
||||||
data.append('ip', iplist);
|
|
||||||
data.append('ipaction', action);
|
data.append('ipaction', action);
|
||||||
|
data.append('ip', vallist);
|
||||||
const resp = await fetch('./api/modtools', {
|
const resp = await fetch('./api/modtools', {
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
@ -72,8 +72,9 @@ async function submitMakeMod(
|
||||||
|
|
||||||
|
|
||||||
function Admintools() {
|
function Admintools() {
|
||||||
const [iPAction, selectIPAction] = useState('ban');
|
const [iPAction, selectIPAction] = useState('iidtoip');
|
||||||
const [modName, selectModName] = useState('');
|
const [modName, selectModName] = useState('');
|
||||||
|
const [txtval, setTxtval] = useState('');
|
||||||
const [resp, setResp] = useState(null);
|
const [resp, setResp] = useState(null);
|
||||||
const [modlist, setModList] = useState([]);
|
const [modlist, setModList] = useState([]);
|
||||||
const [submitting, setSubmitting] = useState(false);
|
const [submitting, setSubmitting] = useState(false);
|
||||||
|
@ -114,9 +115,10 @@ function Admintools() {
|
||||||
selectIPAction(sel.options[sel.selectedIndex].value);
|
selectIPAction(sel.options[sel.selectedIndex].value);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{['iidtoip']
|
{['iidtoip', 'iptoiid']
|
||||||
.map((opt) => (
|
.map((opt) => (
|
||||||
<option
|
<option
|
||||||
|
key={opt}
|
||||||
value={opt}
|
value={opt}
|
||||||
>
|
>
|
||||||
{opt}
|
{opt}
|
||||||
|
@ -124,7 +126,12 @@ function Admintools() {
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
<br />
|
<br />
|
||||||
<textarea rows="10" cols="17" id="iparea" /><br />
|
<textarea
|
||||||
|
rows="10"
|
||||||
|
cols="17"
|
||||||
|
value={txtval}
|
||||||
|
onChange={(e) => setTxtval(e.target.value)}
|
||||||
|
/><br />
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -134,9 +141,10 @@ function Admintools() {
|
||||||
setSubmitting(true);
|
setSubmitting(true);
|
||||||
submitIPAction(
|
submitIPAction(
|
||||||
iPAction,
|
iPAction,
|
||||||
|
txtval,
|
||||||
(ret) => {
|
(ret) => {
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
setResp(ret);
|
setTxtval(ret);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
@ -157,6 +165,7 @@ function Admintools() {
|
||||||
<div
|
<div
|
||||||
role="button"
|
role="button"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
|
key={mod[0]}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (submitting) {
|
if (submitting) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -62,10 +62,11 @@ const Alert = () => {
|
||||||
className={(open && render) ? 'Alert show' : 'Alert'}
|
className={(open && render) ? 'Alert show' : 'Alert'}
|
||||||
>
|
>
|
||||||
<h2>{title}</h2>
|
<h2>{title}</h2>
|
||||||
|
{(message) && (
|
||||||
<p className="modaltext">
|
<p className="modaltext">
|
||||||
{message}
|
{message}
|
||||||
</p>
|
</p>
|
||||||
<div>
|
)}
|
||||||
{(Content) ? (
|
{(Content) ? (
|
||||||
<Content close={close} />
|
<Content close={close} />
|
||||||
) : (
|
) : (
|
||||||
|
@ -76,7 +77,6 @@ const Alert = () => {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,9 +3,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
import { t } from 'ttag';
|
import { t } from 'ttag';
|
||||||
|
|
||||||
import useInterval from './hooks/interval';
|
import useInterval from './hooks/interval';
|
||||||
|
import { showHelpModal } from '../store/actions';
|
||||||
import {
|
import {
|
||||||
largeDurationToString,
|
largeDurationToString,
|
||||||
} from '../core/utils';
|
} from '../core/utils';
|
||||||
|
@ -14,17 +16,20 @@ import { requestBanInfo } from '../store/actions/fetch';
|
||||||
|
|
||||||
const BanInfo = ({ close }) => {
|
const BanInfo = ({ close }) => {
|
||||||
const [errors, setErrors] = useState([]);
|
const [errors, setErrors] = useState([]);
|
||||||
const [reason, setReason] = useState('');
|
const [reason, setReason] = useState(null);
|
||||||
|
const [mod, setMod] = useState(null);
|
||||||
const [expireTs, setExpireTs] = useState(0);
|
const [expireTs, setExpireTs] = useState(0);
|
||||||
const [expire, setExpire] = useState(null);
|
const [expire, setExpire] = useState(null);
|
||||||
const [submitting, setSubmitting] = useState(false);
|
const [submitting, setSubmitting] = useState(false);
|
||||||
|
|
||||||
const handleSubmit = async (evt) => {
|
const dispatch = useDispatch();
|
||||||
evt.preventDefault();
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
if (submitting) {
|
if (submitting) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setSubmitting(true);
|
setSubmitting(true);
|
||||||
|
setErrors([]);
|
||||||
const info = await requestBanInfo();
|
const info = await requestBanInfo();
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
if (info.errors) {
|
if (info.errors) {
|
||||||
|
@ -32,37 +37,64 @@ const BanInfo = ({ close }) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const {
|
const {
|
||||||
ts,
|
sleft,
|
||||||
|
mod: newMod,
|
||||||
reason: newReason,
|
reason: newReason,
|
||||||
} = info;
|
} = info;
|
||||||
setExpireTs(ts);
|
if (sleft) {
|
||||||
const tsDate = new Date(ts);
|
const tsDate = new Date(Date.now() + sleft * 1000);
|
||||||
setExpire(tsDate.toLocaleString);
|
setExpireTs(sleft);
|
||||||
|
setExpire(tsDate.toLocaleString());
|
||||||
|
}
|
||||||
|
setMod(newMod);
|
||||||
setReason(newReason);
|
setReason(newReason);
|
||||||
};
|
};
|
||||||
|
|
||||||
useInterval(() => {
|
useInterval(() => {
|
||||||
console.log('do');
|
if (expireTs > 0) {
|
||||||
if (expireTs) {
|
|
||||||
setExpireTs(expireTs - 1);
|
setExpireTs(expireTs - 1);
|
||||||
|
if (expireTs === 1) {
|
||||||
|
handleSubmit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
|
/* eslint-disable max-len */
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div style={{ userSelect: 'text' }}>
|
||||||
|
<p className="modaltext">
|
||||||
|
{t`You are banned. You think it is unjustifed? Check out the `}
|
||||||
|
<span
|
||||||
|
role="button"
|
||||||
|
tabIndex={0}
|
||||||
|
className="modallink"
|
||||||
|
onClick={() => {
|
||||||
|
dispatch(showHelpModal());
|
||||||
|
close();
|
||||||
|
}}
|
||||||
|
>{t`Help`}</span>
|
||||||
|
{t` on how to appeal.`}
|
||||||
|
</p>
|
||||||
{errors.map((error) => (
|
{errors.map((error) => (
|
||||||
<p key={error} className="errormessage">
|
<p key={error} className="errormessage">
|
||||||
<span>{t`Error`}</span>: {error}
|
<span>{t`Error`}</span>: {error}
|
||||||
</p>
|
</p>
|
||||||
))}
|
))}
|
||||||
{(reason) && (
|
{(reason) && (
|
||||||
<>
|
<React.Fragment key="rea">
|
||||||
<h3 className="modaltitle">{t`Reason`}:</h3>
|
<h3 className="modaltitle">{t`Reason`}:</h3>
|
||||||
<p className="modaltext">{reason}</p>
|
<p className="modaltext">{reason}</p>
|
||||||
</>
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
{(expireTs) && (
|
{(mod) && (
|
||||||
<>
|
<React.Fragment key="mod">
|
||||||
|
<h3 className="modaltitle">{t`By Mod`}:</h3>
|
||||||
|
<p className="modaltext">{mod}</p>
|
||||||
|
</React.Fragment>
|
||||||
|
)}
|
||||||
|
{(expireTs > 0) && (
|
||||||
|
<React.Fragment key="exp">
|
||||||
<h3 className="modaltitle">{t`Duration`}:</h3>
|
<h3 className="modaltitle">{t`Duration`}:</h3>
|
||||||
<p className="modaltext">
|
<p className="modaltext">
|
||||||
{t`Your ban expires at `}
|
{t`Your ban expires at `}
|
||||||
|
@ -74,9 +106,17 @@ const BanInfo = ({ close }) => {
|
||||||
{largeDurationToString(expireTs)}
|
{largeDurationToString(expireTs)}
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
</>
|
</React.Fragment>
|
||||||
|
)}
|
||||||
|
{(expireTs < 0) && (
|
||||||
|
<React.Fragment key="nb">
|
||||||
|
<h3 className="modaltitle">{t`Unbanned`}:</h3>
|
||||||
|
<p className="modaltext">{t`Now that you have seen this message, you are no longer banned.`}</p>
|
||||||
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
<p>
|
<p>
|
||||||
|
{(!reason) && (
|
||||||
|
<React.Fragment key="btnr">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
style={{ fontSize: 16 }}
|
style={{ fontSize: 16 }}
|
||||||
|
@ -85,6 +125,8 @@ const BanInfo = ({ close }) => {
|
||||||
{(submitting) ? '...' : t`Why?`}
|
{(submitting) ? '...' : t`Why?`}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
</React.Fragment>
|
||||||
|
)}
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
style={{ fontSize: 16 }}
|
style={{ fontSize: 16 }}
|
||||||
|
|
59
src/components/GetIID.jsx
Normal file
59
src/components/GetIID.jsx
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* show IID
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
import { t } from 'ttag';
|
||||||
|
|
||||||
|
import { notify } from '../store/actions';
|
||||||
|
import copyTextToClipboard from '../utils/clipboard';
|
||||||
|
import {
|
||||||
|
requestIID,
|
||||||
|
} from '../store/actions/fetch';
|
||||||
|
|
||||||
|
const GetIID = () => {
|
||||||
|
const [iid, setIID] = useState('');
|
||||||
|
const [submitting, setSubmitting] = useState(false);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<p>
|
||||||
|
<input
|
||||||
|
style={{
|
||||||
|
display: 'inline-block',
|
||||||
|
width: '100%',
|
||||||
|
maxWidth: '18em',
|
||||||
|
}}
|
||||||
|
readOnly
|
||||||
|
value={iid}
|
||||||
|
/>
|
||||||
|
{(!iid)
|
||||||
|
? (
|
||||||
|
<button
|
||||||
|
key="subtn"
|
||||||
|
type="button"
|
||||||
|
onClick={async () => {
|
||||||
|
setSubmitting(true);
|
||||||
|
const resp = await requestIID();
|
||||||
|
if (resp.iid) {
|
||||||
|
setIID(resp.iid);
|
||||||
|
}
|
||||||
|
setSubmitting(false);
|
||||||
|
}}
|
||||||
|
>{(submitting) ? '...' : t`Get IID`}</button>
|
||||||
|
) : (
|
||||||
|
<button
|
||||||
|
key="cobtn"
|
||||||
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
copyTextToClipboard(iid);
|
||||||
|
dispatch(notify(t`Copied!`));
|
||||||
|
}}
|
||||||
|
>{t`Copy`}</button>
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default React.memo(GetIID);
|
|
@ -43,6 +43,7 @@ function LanguageSelect() {
|
||||||
{
|
{
|
||||||
langs.map(([l]) => (
|
langs.map(([l]) => (
|
||||||
<option
|
<option
|
||||||
|
key={l}
|
||||||
value={l}
|
value={l}
|
||||||
>
|
>
|
||||||
{l.toUpperCase()}
|
{l.toUpperCase()}
|
||||||
|
|
|
@ -14,11 +14,18 @@ async function submitIIDAction(
|
||||||
duration,
|
duration,
|
||||||
callback,
|
callback,
|
||||||
) {
|
) {
|
||||||
|
let time = parseInterval(duration);
|
||||||
|
if (time === 0 && duration !== '0') {
|
||||||
|
callback(t`You must enter an IID`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!iid) {
|
if (!iid) {
|
||||||
callback(t`You must enter an IID`);
|
callback(t`You must enter an IID`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const time = Date.now() + parseInterval(duration);
|
if (time > 0) {
|
||||||
|
time += Date.now();
|
||||||
|
}
|
||||||
const data = new FormData();
|
const data = new FormData();
|
||||||
data.append('iidaction', action);
|
data.append('iidaction', action);
|
||||||
data.append('reason', reason);
|
data.append('reason', reason);
|
||||||
|
@ -61,7 +68,7 @@ function ModIIDtools() {
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
{(iIDAction === 'ban') && (
|
{(iIDAction === 'ban') && (
|
||||||
<>
|
<React.Fragment key="ban">
|
||||||
<p>{t`Reason`}</p>
|
<p>{t`Reason`}</p>
|
||||||
<input
|
<input
|
||||||
maxLength="200"
|
maxLength="200"
|
||||||
|
@ -88,7 +95,7 @@ function ModIIDtools() {
|
||||||
/>
|
/>
|
||||||
{t`(0 = infinite)`}
|
{t`(0 = infinite)`}
|
||||||
</p>
|
</p>
|
||||||
</>
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
<p className="modalcotext">
|
<p className="modalcotext">
|
||||||
{' IID: '}
|
{' IID: '}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import React, { useState, useEffect } from 'react';
|
||||||
import { useSelector, shallowEqual } from 'react-redux';
|
import { useSelector, shallowEqual } from 'react-redux';
|
||||||
import { t } from 'ttag';
|
import { t } from 'ttag';
|
||||||
|
|
||||||
|
import copyTextToClipboard from '../utils/clipboard';
|
||||||
import { parseInterval } from '../core/utils';
|
import { parseInterval } from '../core/utils';
|
||||||
|
|
||||||
const keepState = {
|
const keepState = {
|
||||||
|
@ -341,11 +342,22 @@ function ModWatchtools() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case 'cid': {
|
case 'cid': {
|
||||||
const cid = (cidColumn > 0)
|
const ident = canvases[val] && canvases[val].ident;
|
||||||
? row[cidColumn] : selectedCanvas;
|
|
||||||
const ident = canvases[cid] && canvases[cid].ident;
|
|
||||||
return (<td>{ident}</td>);
|
return (<td>{ident}</td>);
|
||||||
}
|
}
|
||||||
|
case 'uuid': {
|
||||||
|
return (
|
||||||
|
<td>
|
||||||
|
<span
|
||||||
|
role="button"
|
||||||
|
tabIndex={-1}
|
||||||
|
style={{ cursor: 'pointer' }}
|
||||||
|
title={t`Copy to Clipboard`}
|
||||||
|
onClick={() => copyTextToClipboard(val)}
|
||||||
|
>{val}</span>
|
||||||
|
</td>
|
||||||
|
);
|
||||||
|
}
|
||||||
case 'user': {
|
case 'user': {
|
||||||
const seperator = val.lastIndexOf(',');
|
const seperator = val.lastIndexOf(',');
|
||||||
if (seperator === -1) {
|
if (seperator === -1) {
|
||||||
|
|
|
@ -7,8 +7,9 @@ import { c, t, jt } from 'ttag';
|
||||||
import { GiMouse } from 'react-icons/gi';
|
import { GiMouse } from 'react-icons/gi';
|
||||||
import { MdTouchApp } from 'react-icons/md';
|
import { MdTouchApp } from 'react-icons/md';
|
||||||
|
|
||||||
/* eslint-disable max-len */
|
import GetIID from '../GetIID';
|
||||||
|
|
||||||
|
/* eslint-disable max-len */
|
||||||
|
|
||||||
const Help = () => {
|
const Help = () => {
|
||||||
const bindG = <kbd>{c('keybinds').t`G`}</kbd>;
|
const bindG = <kbd>{c('keybinds').t`G`}</kbd>;
|
||||||
|
@ -33,7 +34,6 @@ const Help = () => {
|
||||||
const starhouseLink = <a href="https://twitter.com/starhousedev">starhouse </a>;
|
const starhouseLink = <a href="https://twitter.com/starhousedev">starhouse </a>;
|
||||||
const vinikLink = <a href="https://twitter.com/Vinikdev">Vinikdev</a>;
|
const vinikLink = <a href="https://twitter.com/Vinikdev">Vinikdev</a>;
|
||||||
const guildedLink = <a href="https://pixelplanet.fun/guilded">guilded</a>;
|
const guildedLink = <a href="https://pixelplanet.fun/guilded">guilded</a>;
|
||||||
const getIPLink = <a href="https://www.whatismyip.com/">{t`your IP`}</a>;
|
|
||||||
const mailLink = <a href="mailto:admin@pixelplanet.fun">admin@pixelplanet.fun</a>;
|
const mailLink = <a href="mailto:admin@pixelplanet.fun">admin@pixelplanet.fun</a>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -52,9 +52,10 @@ pixels and 7s on already set pixels.`}<br />
|
||||||
<p className="modaltitle">{t`Map Data`}</p>
|
<p className="modaltitle">{t`Map Data`}</p>
|
||||||
<p className="modaltext">{t`The bare map data that we use, together with converted OpenStreetMap tiles for orientation, \
|
<p className="modaltext">{t`The bare map data that we use, together with converted OpenStreetMap tiles for orientation, \
|
||||||
can be downloaded from mega.nz here: `}<a href="https://mega.nz/#!JpkBwAbJ!EnSLlZmKv3kEBE0HDhakTgAZZycD3ELjduajJxPGaXo">pixelplanetmap.zip</a> (422MB)</p>
|
can be downloaded from mega.nz here: `}<a href="https://mega.nz/#!JpkBwAbJ!EnSLlZmKv3kEBE0HDhakTgAZZycD3ELjduajJxPGaXo">pixelplanetmap.zip</a> (422MB)</p>
|
||||||
<p className="modaltitle">{t`Detected as Proxy?`}</p>
|
<p className="modaltitle">{t`Banned? Detected as Proxy?`}</p>
|
||||||
<div className="modaltext">
|
<div className="modaltext">
|
||||||
<p>{jt`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.`}</p>
|
<p>{jt`If you got detected as proxy, but you are none, or think that you got wrongfully banned, please go to our ${guildedLink} or send us an e-mail to ${mailLink} and include the following IID:`}</p>
|
||||||
|
<GetIID />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="modaltitle">2D {t`Controls`}</h3>
|
<h3 className="modaltitle">2D {t`Controls`}</h3>
|
||||||
<div className="modaltext" style={{ lineHeight: 1.8 }}>
|
<div className="modaltext" style={{ lineHeight: 1.8 }}>
|
||||||
|
|
|
@ -26,7 +26,11 @@ import {
|
||||||
banIP,
|
banIP,
|
||||||
unbanIP,
|
unbanIP,
|
||||||
} from '../data/sql/Ban';
|
} from '../data/sql/Ban';
|
||||||
import { getInfoToIp, getIPofIID } from '../data/sql/IPInfo';
|
import {
|
||||||
|
getInfoToIp,
|
||||||
|
getIPofIID,
|
||||||
|
getIIDofIP,
|
||||||
|
} from '../data/sql/IPInfo';
|
||||||
// eslint-disable-next-line import/no-unresolved
|
// eslint-disable-next-line import/no-unresolved
|
||||||
import canvases from './canvases.json';
|
import canvases from './canvases.json';
|
||||||
import {
|
import {
|
||||||
|
@ -48,31 +52,25 @@ import rollbackCanvasArea from './rollback';
|
||||||
* @return text of success
|
* @return text of success
|
||||||
*/
|
*/
|
||||||
export async function executeIPAction(action, ips, logger = null) {
|
export async function executeIPAction(action, ips, logger = null) {
|
||||||
const ipArray = ips.split('\n');
|
const valueArray = ips.split('\n');
|
||||||
let out = '';
|
let out = '';
|
||||||
for (let i = 0; i < ipArray.length; i += 1) {
|
for (let i = 0; i < valueArray.length; i += 1) {
|
||||||
const ip = ipArray[i].trim();
|
const value = valueArray[i].trim();
|
||||||
|
if (!value) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logger) logger(`${action} ${value}`);
|
||||||
|
|
||||||
if (action === 'iidtoip') {
|
if (action === 'iidtoip') {
|
||||||
const resIp = await getIPofIID(ip);
|
const ip = await getIPofIID(value);
|
||||||
const iidPart = ip.slice(0, ip.indexOf('-'));
|
out += (ip) ? `${ip}\n` : `${value}\n`;
|
||||||
if (resIp) {
|
|
||||||
out += `${iidPart}: ${resIp}\n`;
|
|
||||||
} else {
|
|
||||||
out += `${iidPart}: N/A\n`;
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ip || ip.length < 8 || ip.indexOf(' ') !== -1) {
|
if (action === 'iptoiid') {
|
||||||
out += `Couln't parse ${action} ${ip}\n`;
|
const iid = await getIIDofIP(value);
|
||||||
continue;
|
out += (iid) ? `${iid}\n` : `${value}\n`;
|
||||||
}
|
|
||||||
|
|
||||||
if (logger) logger(`${action} ${ip}`);
|
|
||||||
switch (action) {
|
|
||||||
default:
|
|
||||||
return `Failed to ${action} ${ip}\n`;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
|
@ -98,10 +96,12 @@ export async function executeIIDAction(
|
||||||
}
|
}
|
||||||
const iidPart = iid.slice(0, iid.indexOf('-'));
|
const iidPart = iid.slice(0, iid.indexOf('-'));
|
||||||
|
|
||||||
|
if (logger) logger(`${action} ${iid} ${ip}`);
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case 'status': {
|
case 'status': {
|
||||||
const allowed = await isIPAllowed(ip, true);
|
const allowed = await isIPAllowed(ip, true);
|
||||||
let out = `Allowed to place: ${allowed.allowed}`;
|
let out = `Allowed to place: ${allowed.allowed}\n`;
|
||||||
const info = await getInfoToIp(ip);
|
const info = await getInfoToIp(ip);
|
||||||
out += `Country: ${info.country}\n`
|
out += `Country: ${info.country}\n`
|
||||||
+ `CIDR: ${info.cidr}\n`
|
+ `CIDR: ${info.cidr}\n`
|
||||||
|
@ -119,7 +119,8 @@ export async function executeIIDAction(
|
||||||
if (!ban) {
|
if (!ban) {
|
||||||
out += 'banned: false\n';
|
out += 'banned: false\n';
|
||||||
} else {
|
} else {
|
||||||
out += `reason: ${ban.reason}\n`;
|
out += 'banned: true\n'
|
||||||
|
+ `reason: ${ban.reason}\n`;
|
||||||
if (ban.expires) {
|
if (ban.expires) {
|
||||||
out += `expires: ${ban.expires.toLocaleString()}\n`;
|
out += `expires: ${ban.expires.toLocaleString()}\n`;
|
||||||
}
|
}
|
||||||
|
@ -140,28 +141,27 @@ export async function executeIIDAction(
|
||||||
return `${iidPart} would have gotten captcha anyway`;
|
return `${iidPart} would have gotten captcha anyway`;
|
||||||
}
|
}
|
||||||
case 'ban': {
|
case 'ban': {
|
||||||
if (expire && expire < Date.now()) {
|
const expireTs = parseInt(expire, 10);
|
||||||
|
if (Number.isNaN(expireTs) || (expireTs && expireTs < Date.now())) {
|
||||||
return 'No valid expiration time';
|
return 'No valid expiration time';
|
||||||
}
|
}
|
||||||
if (!reason) {
|
if (!reason || !reason.trim()) {
|
||||||
return 'No reason specified';
|
return 'No reason specified';
|
||||||
}
|
}
|
||||||
const ret = await banIP(ip, reason, expire || null, muid);
|
const ret = await banIP(ip, reason, expireTs || null, muid);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
await cleanCacheForIP(ip);
|
|
||||||
return 'Successfully banned user';
|
return 'Successfully banned user';
|
||||||
}
|
}
|
||||||
return 'User is already banned';
|
return 'Updated existing ban of user';
|
||||||
}
|
}
|
||||||
case 'unban': {
|
case 'unban': {
|
||||||
const ret = await unbanIP(ip);
|
const ret = await unbanIP(ip);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
await cleanCacheForIP(ip);
|
|
||||||
return 'Successfully unbanned user';
|
return 'Successfully unbanned user';
|
||||||
}
|
}
|
||||||
return 'User is not banned';
|
return 'User is not banned';
|
||||||
}
|
}
|
||||||
case 'Whitelist': {
|
case 'whitelist': {
|
||||||
const ret = await whitelistIP(ip);
|
const ret = await whitelistIP(ip);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
await cleanCacheForIP(ip);
|
await cleanCacheForIP(ip);
|
||||||
|
|
|
@ -94,14 +94,12 @@ async function dummy() {
|
||||||
return [false, 'dummy'];
|
return [false, 'dummy'];
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveIPInfo(ip, whoisRet, isProxy, info) {
|
async function saveIPInfo(ip, whoisRet, allowed, info) {
|
||||||
const whoisData = whoisRet || {};
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
IPInfo.upsert({
|
await IPInfo.upsert({
|
||||||
|
...whoisRet,
|
||||||
ip,
|
ip,
|
||||||
...whoisData,
|
proxy: allowed,
|
||||||
isProxy,
|
|
||||||
pcheck: info,
|
pcheck: info,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -136,9 +134,9 @@ async function withoutCache(f, ip) {
|
||||||
allowed = !allowed;
|
allowed = !allowed;
|
||||||
status = (allowed) ? 0 : 1;
|
status = (allowed) ? 0 : 1;
|
||||||
}
|
}
|
||||||
whoisRet = await whois(ip);
|
whoisRet = await whois(ip) || {};
|
||||||
} finally {
|
} finally {
|
||||||
await saveIPInfo(ipKey, whoisRet, allowed, pcInfo);
|
await saveIPInfo(ipKey, whoisRet, status, pcInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -176,16 +174,18 @@ async function withCache(f, ip) {
|
||||||
if (checking.indexOf(ipKey) === -1 && lock > 0) {
|
if (checking.indexOf(ipKey) === -1 && lock > 0) {
|
||||||
lock -= 1;
|
lock -= 1;
|
||||||
checking.push(ipKey);
|
checking.push(ipKey);
|
||||||
try {
|
withoutCache(f, ip)
|
||||||
const result = await withoutCache(f, ip);
|
.then((result) => {
|
||||||
cacheAllowed(ip, result);
|
cacheAllowed(ipKey, result);
|
||||||
} catch (error) {
|
})
|
||||||
|
.catch((error) => {
|
||||||
logger.error('Error %s', error.message || error);
|
logger.error('Error %s', error.message || error);
|
||||||
} finally {
|
})
|
||||||
|
.finally(() => {
|
||||||
const pos = checking.indexOf(ipKey);
|
const pos = checking.indexOf(ipKey);
|
||||||
if (~pos) checking.splice(pos, 1);
|
if (~pos) checking.splice(pos, 1);
|
||||||
lock += 1;
|
lock += 1;
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
allowed: true,
|
allowed: true,
|
||||||
|
|
|
@ -249,15 +249,13 @@ export function durationToString(
|
||||||
export function largeDurationToString(
|
export function largeDurationToString(
|
||||||
ts,
|
ts,
|
||||||
) {
|
) {
|
||||||
let restA = Math.round(ts / 1000);
|
const seconds = ts % 60;
|
||||||
let restB = restA % (3600 * 24);
|
let durs = (ts - seconds) / 60;
|
||||||
const days = restA - restB;
|
const minutes = durs % 60;
|
||||||
restA = restB % 3600;
|
durs = (durs - minutes) / 60;
|
||||||
const hours = restB - restA;
|
const hours = durs % 24;
|
||||||
restB = restA % 60;
|
durs = (durs - hours) / 24;
|
||||||
const minutes = restA - restB;
|
const days = durs;
|
||||||
restA = restB % 60;
|
|
||||||
const seconds = restB - restA;
|
|
||||||
let out = '';
|
let out = '';
|
||||||
if (days) {
|
if (days) {
|
||||||
out += ` ${days}d`;
|
out += ` ${days}d`;
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import { DataTypes } from 'sequelize';
|
import { DataTypes, Op } from 'sequelize';
|
||||||
import sequelize from './sequelize';
|
import sequelize from './sequelize';
|
||||||
|
|
||||||
import RegUser from './RegUser';
|
import RegUser from './RegUser';
|
||||||
|
import { HourlyCron } from '../../utils/cron';
|
||||||
|
import { cleanCacheForIP } from '../redis/isAllowedCache';
|
||||||
|
|
||||||
const Ban = sequelize.define('Blacklist', {
|
const Ban = sequelize.define('Ban', {
|
||||||
ip: {
|
ip: {
|
||||||
type: DataTypes.CHAR(39),
|
type: DataTypes.CHAR(39),
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
|
@ -41,7 +43,38 @@ const Ban = sequelize.define('Blacklist', {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Ban.belongsTo(RegUser, {
|
||||||
|
as: 'mod',
|
||||||
|
foreignKey: 'muid',
|
||||||
|
});
|
||||||
|
|
||||||
|
async function cleanBans() {
|
||||||
|
const expiredIPs = await Ban.findAll({
|
||||||
|
attributes: [
|
||||||
|
'ip',
|
||||||
|
],
|
||||||
|
where: {
|
||||||
|
expires: {
|
||||||
|
[Op.lte]: new Date(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
raw: true,
|
||||||
|
});
|
||||||
|
const ips = [];
|
||||||
|
for (let i = 0; i < expiredIPs.length; i += 1) {
|
||||||
|
ips.push(expiredIPs[i].ip);
|
||||||
|
}
|
||||||
|
await Ban.destroy({
|
||||||
|
where: {
|
||||||
|
ip: ips,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
for (let i = 0; i < ips.length; i += 1) {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await cleanCacheForIP(ips[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HourlyCron.hook(cleanBans);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* check if ip is whitelisted
|
* check if ip is whitelisted
|
||||||
|
@ -61,16 +94,20 @@ export async function isIPBanned(ip) {
|
||||||
* @param ip
|
* @param ip
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
export async function getBanInfo(ip) {
|
export function getBanInfo(ip) {
|
||||||
const ban = await Ban.findByPk(ip, {
|
return Ban.findByPk(ip, {
|
||||||
include: [{
|
attributes: ['reason', 'expires'],
|
||||||
|
include: {
|
||||||
model: RegUser,
|
model: RegUser,
|
||||||
as: 'mod',
|
as: 'mod',
|
||||||
foreignKey: 'muid',
|
attributes: [
|
||||||
attributes: ['id', 'name'],
|
'id',
|
||||||
}],
|
'name',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
raw: true,
|
||||||
|
nest: true,
|
||||||
});
|
});
|
||||||
return ban;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -85,15 +122,14 @@ export async function banIP(
|
||||||
expiresTs,
|
expiresTs,
|
||||||
muid,
|
muid,
|
||||||
) {
|
) {
|
||||||
const expires = (expiresTs) ? new Date(expiresTs) : null;
|
const expires = (expiresTs) ? new Date(expiresTs).toISOString() : null;
|
||||||
const [, created] = await Ban.findOrCreate({
|
const [, created] = await Ban.upsert({
|
||||||
where: { ip },
|
ip,
|
||||||
defaults: {
|
|
||||||
reason,
|
reason,
|
||||||
expires,
|
expires,
|
||||||
muid,
|
muid,
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
await cleanCacheForIP(ip);
|
||||||
return created;
|
return created;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,6 +143,7 @@ export async function unbanIP(ip) {
|
||||||
const count = await Ban.destroy({
|
const count = await Ban.destroy({
|
||||||
where: { ip },
|
where: { ip },
|
||||||
});
|
});
|
||||||
|
await cleanCacheForIP(ip);
|
||||||
return !!count;
|
return !!count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,9 @@ const IPInfo = sequelize.define('IPInfo', {
|
||||||
},
|
},
|
||||||
|
|
||||||
pcheck(value) {
|
pcheck(value) {
|
||||||
|
if (value) {
|
||||||
this.setDataValue('pcheck', value.slice(0, 60));
|
this.setDataValue('pcheck', value.slice(0, 60));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
country(value) {
|
country(value) {
|
||||||
|
@ -101,12 +103,25 @@ export async function getIPofIID(uuid) {
|
||||||
raw: true,
|
raw: true,
|
||||||
});
|
});
|
||||||
} catch {
|
} catch {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
return result && result.ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getIIDofIP(ip) {
|
||||||
|
if (!ip) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (result) {
|
let result = null;
|
||||||
return result.ip;
|
try {
|
||||||
|
result = await IPInfo.findByPk(ip, {
|
||||||
|
attributes: ['uuid'],
|
||||||
|
raw: true,
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
// nothing
|
||||||
}
|
}
|
||||||
return null;
|
return result && result.uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getIdsToIps(ips) {
|
export async function getIdsToIps(ips) {
|
||||||
|
|
|
@ -103,12 +103,4 @@ router.post('/local', passport.authenticate('json'), async (req, res) => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
router.use((err, req, res, next) => {
|
|
||||||
res.status(400);
|
|
||||||
res.json({
|
|
||||||
errors: [err.message],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|
45
src/routes/api/baninfo.js
Normal file
45
src/routes/api/baninfo.js
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
getIPFromRequest,
|
||||||
|
getIPv6Subnet,
|
||||||
|
} from '../../utils/ip';
|
||||||
|
import {
|
||||||
|
getBanInfo,
|
||||||
|
unbanIP,
|
||||||
|
} from '../../data/sql/Ban';
|
||||||
|
|
||||||
|
async function baninfo(req, res, next) {
|
||||||
|
try {
|
||||||
|
const { t } = req.ttag;
|
||||||
|
|
||||||
|
const ip = getIPv6Subnet(
|
||||||
|
getIPFromRequest(req),
|
||||||
|
);
|
||||||
|
|
||||||
|
const info = await getBanInfo(ip);
|
||||||
|
|
||||||
|
if (!info) {
|
||||||
|
throw new Error(t`You are not banned`);
|
||||||
|
}
|
||||||
|
let sleft = (info.expires)
|
||||||
|
? Math.round((info.expires.getTime() - Date.now()) / 1000)
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
if (info.expires && sleft < 3) {
|
||||||
|
await unbanIP(ip);
|
||||||
|
sleft = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
reason: info.reason,
|
||||||
|
sleft,
|
||||||
|
mod: `${info.mod.name} (${info.mod.id})`,
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default baninfo;
|
32
src/routes/api/getiid.js
Normal file
32
src/routes/api/getiid.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
getIPFromRequest,
|
||||||
|
getIPv6Subnet,
|
||||||
|
} from '../../utils/ip';
|
||||||
|
import {
|
||||||
|
getIIDofIP,
|
||||||
|
} from '../../data/sql/IPInfo';
|
||||||
|
|
||||||
|
async function getiid(req, res, next) {
|
||||||
|
try {
|
||||||
|
const ip = getIPv6Subnet(
|
||||||
|
getIPFromRequest(req),
|
||||||
|
);
|
||||||
|
|
||||||
|
const iid = await getIIDofIP(ip);
|
||||||
|
|
||||||
|
if (!iid) {
|
||||||
|
throw new Error('Could not get IID');
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
iid,
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default getiid;
|
|
@ -15,24 +15,26 @@ import leaveChan from './leavechan';
|
||||||
import block from './block';
|
import block from './block';
|
||||||
import blockdm from './blockdm';
|
import blockdm from './blockdm';
|
||||||
import modtools from './modtools';
|
import modtools from './modtools';
|
||||||
|
import baninfo from './baninfo';
|
||||||
|
import getiid from './getiid';
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
router.use(express.json());
|
router.use(express.json());
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
router.use((err, req, res, next) => {
|
router.use((err, req, res, next) => {
|
||||||
if (err) {
|
|
||||||
logger.warn(`Got invalid json from ${req.trueIp} on ${req.originalUrl}`);
|
logger.warn(`Got invalid json from ${req.trueIp} on ${req.originalUrl}`);
|
||||||
res.status(400);
|
res.status(400).json({
|
||||||
res.status(400).json({ errors: [{ msg: 'Invalid Request' }] });
|
errors: [{ msg: 'Invalid Request' }],
|
||||||
} else {
|
});
|
||||||
next();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// captcah doesn't need a user
|
// routes that don't need a user
|
||||||
router.post('/captcha', captcha);
|
router.post('/captcha', captcha);
|
||||||
|
router.get('/baninfo', baninfo);
|
||||||
|
router.get('/getiid', getiid);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get user session
|
* get user session
|
||||||
|
@ -87,4 +89,11 @@ router.get('/me', me);
|
||||||
|
|
||||||
router.use('/auth', auth);
|
router.use('/auth', auth);
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
router.use((err, req, res, next) => {
|
||||||
|
res.status(400).json({
|
||||||
|
errors: [err.message],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|
|
@ -89,6 +89,11 @@ router.post('/', upload.single('image'), async (req, res, next) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const bLogger = (text) => {
|
||||||
|
logger.info(`IID> ${req.user.regUser.name}[${req.user.id}]> ${text}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
if (req.body.cleanerstat) {
|
if (req.body.cleanerstat) {
|
||||||
const ret = CanvasCleaner.reportStatus();
|
const ret = CanvasCleaner.reportStatus();
|
||||||
res.status(200);
|
res.status(200);
|
||||||
|
@ -125,6 +130,7 @@ router.post('/', upload.single('image'), async (req, res, next) => {
|
||||||
reason,
|
reason,
|
||||||
time,
|
time,
|
||||||
req.user.id,
|
req.user.id,
|
||||||
|
bLogger,
|
||||||
);
|
);
|
||||||
res.status(200).send(ret);
|
res.status(200).send(ret);
|
||||||
return;
|
return;
|
||||||
|
@ -186,6 +192,9 @@ router.post('/', upload.single('image'), async (req, res, next) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
|
} catch (err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -209,6 +218,7 @@ router.post('/', async (req, res, next) => {
|
||||||
logger.info(`ADMIN> ${req.user.regUser.name}[${req.user.id}]> ${text}`);
|
logger.info(`ADMIN> ${req.user.regUser.name}[${req.user.id}]> ${text}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
if (req.body.ipaction) {
|
if (req.body.ipaction) {
|
||||||
const ret = await executeIPAction(
|
const ret = await executeIPAction(
|
||||||
req.body.ipaction,
|
req.body.ipaction,
|
||||||
|
@ -236,6 +246,9 @@ router.post('/', async (req, res, next) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
|
} catch (err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
router.use(async (req, res) => {
|
router.use(async (req, res) => {
|
||||||
|
|
|
@ -491,7 +491,7 @@ class SocketServer {
|
||||||
if (await needCaptcha(ip)) {
|
if (await needCaptcha(ip)) {
|
||||||
// need captcha
|
// need captcha
|
||||||
failureRet = PixelReturn.dehydrate(10, 0, 0);
|
failureRet = PixelReturn.dehydrate(10, 0, 0);
|
||||||
}
|
} else {
|
||||||
// (re)check for Proxy
|
// (re)check for Proxy
|
||||||
const allowed = await isIPAllowed(ip);
|
const allowed = await isIPAllowed(ip);
|
||||||
if (!allowed.allowed) {
|
if (!allowed.allowed) {
|
||||||
|
@ -506,6 +506,7 @@ class SocketServer {
|
||||||
}
|
}
|
||||||
failureRet = PixelReturn.dehydrate(failureStatus, 0, 0);
|
failureRet = PixelReturn.dehydrate(failureStatus, 0, 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (failureRet !== null) {
|
if (failureRet !== null) {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
if (limiter && limiter[0] > now) {
|
if (limiter && limiter[0] > now) {
|
||||||
|
|
|
@ -41,7 +41,6 @@ export type Action =
|
||||||
| { type: 'SELECT_CANVAS', canvasId: number }
|
| { type: 'SELECT_CANVAS', canvasId: number }
|
||||||
| { type: 'PLACED_PIXELS', amount: number }
|
| { type: 'PLACED_PIXELS', amount: number }
|
||||||
| { type: 'PIXEL_WAIT' }
|
| { type: 'PIXEL_WAIT' }
|
||||||
| { type: 'PIXEL_FAILURE' }
|
|
||||||
| { type: 'SET_VIEW_COORDINATES', view: Array }
|
| { type: 'SET_VIEW_COORDINATES', view: Array }
|
||||||
| { type: 'SET_SCALE', scale: number, zoompoint: Array }
|
| { type: 'SET_SCALE', scale: number, zoompoint: Array }
|
||||||
| { type: 'REQUEST_BIG_CHUNK', center: Array }
|
| { type: 'REQUEST_BIG_CHUNK', center: Array }
|
||||||
|
|
|
@ -293,3 +293,9 @@ export function requestMe() {
|
||||||
'api/me',
|
'api/me',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function requestIID() {
|
||||||
|
return makeAPIGETRequest(
|
||||||
|
'api/getiid',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -115,6 +115,10 @@ export function toggleOpenMenu() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* requestingPixel is inveted, it has the meaning of
|
||||||
|
* "can i request a pixel"
|
||||||
|
*/
|
||||||
export function setRequestingPixel(requestingPixel) {
|
export function setRequestingPixel(requestingPixel) {
|
||||||
return {
|
return {
|
||||||
type: 'SET_REQUESTING_PIXEL',
|
type: 'SET_REQUESTING_PIXEL',
|
||||||
|
@ -195,12 +199,6 @@ export function pixelWait() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function pixelFailure() {
|
|
||||||
return {
|
|
||||||
type: 'PIXEL_FAILURE',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function receiveOnline(online) {
|
export function receiveOnline(online) {
|
||||||
return {
|
return {
|
||||||
type: 'RECEIVE_ONLINE',
|
type: 'RECEIVE_ONLINE',
|
||||||
|
|
|
@ -94,7 +94,10 @@ export default (store) => (next) => (action) => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'PIXEL_FAILURE': {
|
case 'ALERT': {
|
||||||
|
if (action.alertType !== 'error') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
const oscillatorNode = context.createOscillator();
|
const oscillatorNode = context.createOscillator();
|
||||||
const gainNode = context.createGain();
|
const gainNode = context.createGain();
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ import {
|
||||||
setRequestingPixel,
|
setRequestingPixel,
|
||||||
pAlert,
|
pAlert,
|
||||||
gotCoolDownDelta,
|
gotCoolDownDelta,
|
||||||
pixelFailure,
|
|
||||||
setWait,
|
setWait,
|
||||||
placedPixels,
|
placedPixels,
|
||||||
pixelWait,
|
pixelWait,
|
||||||
|
@ -187,6 +186,7 @@ export function receivePixelReturn(
|
||||||
|
|
||||||
let errorTitle = null;
|
let errorTitle = null;
|
||||||
let msg = null;
|
let msg = null;
|
||||||
|
let type = 'error';
|
||||||
switch (retCode) {
|
switch (retCode) {
|
||||||
case 0:
|
case 0:
|
||||||
store.dispatch(placedPixels(pxlCnt));
|
store.dispatch(placedPixels(pxlCnt));
|
||||||
|
@ -228,13 +228,10 @@ export function receivePixelReturn(
|
||||||
store.dispatch(pixelWait());
|
store.dispatch(pixelWait());
|
||||||
break;
|
break;
|
||||||
case 10:
|
case 10:
|
||||||
store.dispatch(pAlert(
|
errorTitle = 'Captcha';
|
||||||
'Captcha',
|
msg = t`Please prove that you are human`;
|
||||||
t`Please prove that you are human`,
|
type = 'captcha';
|
||||||
'captcha',
|
break;
|
||||||
));
|
|
||||||
store.dispatch(setRequestingPixel(true));
|
|
||||||
return;
|
|
||||||
case 11:
|
case 11:
|
||||||
errorTitle = t`No Proxies Allowed :(`;
|
errorTitle = t`No Proxies Allowed :(`;
|
||||||
msg = t`You are using a Proxy.`;
|
msg = t`You are using a Proxy.`;
|
||||||
|
@ -249,13 +246,9 @@ export function receivePixelReturn(
|
||||||
msg = t`Server got confused by your pixels. Are you playing on multiple devices?`;
|
msg = t`Server got confused by your pixels. Are you playing on multiple devices?`;
|
||||||
break;
|
break;
|
||||||
case 14:
|
case 14:
|
||||||
store.dispatch(pAlert(
|
errorTitle = t`Banned`;
|
||||||
'Banned',
|
type = t`ban`;
|
||||||
t`You are banned.`,
|
break;
|
||||||
'ban',
|
|
||||||
));
|
|
||||||
store.dispatch(setRequestingPixel(true));
|
|
||||||
return;
|
|
||||||
case 15:
|
case 15:
|
||||||
errorTitle = t`Range Banned`;
|
errorTitle = t`Range Banned`;
|
||||||
msg = t`Your Internet Provider is banned from playing this game`;
|
msg = t`Your Internet Provider is banned from playing this game`;
|
||||||
|
@ -265,17 +258,19 @@ export function receivePixelReturn(
|
||||||
msg = t`Couldn't set Pixel`;
|
msg = t`Couldn't set Pixel`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg) {
|
if (msg || errorTitle) {
|
||||||
store.dispatch(pixelFailure());
|
|
||||||
store.dispatch(pAlert(
|
store.dispatch(pAlert(
|
||||||
(errorTitle || t`Error ${retCode}`),
|
(errorTitle || t`Error ${retCode}`),
|
||||||
msg,
|
msg,
|
||||||
'error',
|
type,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dispatch(setRequestingPixel(true));
|
store.dispatch(setRequestingPixel(true));
|
||||||
|
|
||||||
|
if (!msg) {
|
||||||
/* start next request if queue isn't empty */
|
/* start next request if queue isn't empty */
|
||||||
requestFromQueue(store);
|
requestFromQueue(store);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,9 +31,9 @@ class Cron {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkForExecution() {
|
checkForExecution() {
|
||||||
|
this.timeout = setTimeout(this.checkForExecution, HOUR);
|
||||||
const curDate = new Date();
|
const curDate = new Date();
|
||||||
const curTime = curDate.getTime();
|
const curTime = curDate.getTime();
|
||||||
this.timeout = setTimeout(this.checkForExecution, HOUR);
|
|
||||||
if (curTime + 120000 > this.lastRun + this.interval * HOUR) {
|
if (curTime + 120000 > this.lastRun + this.interval * HOUR) {
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
logger.info(`${curDate.toUTCString()}> Run cron events for interval: ${this.interval}h`);
|
logger.info(`${curDate.toUTCString()}> Run cron events for interval: ${this.interval}h`);
|
||||||
|
@ -65,7 +65,7 @@ function initializeDailyCron() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function initializeHourlyCron() {
|
function initializeHourlyCron() {
|
||||||
const cron = new Cron(1, Date.now());
|
const cron = new Cron(1);
|
||||||
return cron;
|
return cron;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user