add protection or rectangles without image to admintools
This commit is contained in:
parent
1d081991ba
commit
a69711d838
|
@ -9,8 +9,13 @@ import { connect } from 'react-redux';
|
|||
|
||||
import type { State } from '../reducers';
|
||||
|
||||
const keptState = {
|
||||
coords: null,
|
||||
tlcoords: null,
|
||||
brcoords: null,
|
||||
};
|
||||
|
||||
async function submitAction(
|
||||
async function submitImageAction(
|
||||
action,
|
||||
canvas,
|
||||
coords,
|
||||
|
@ -32,6 +37,26 @@ async function submitAction(
|
|||
callback(await resp.text());
|
||||
}
|
||||
|
||||
async function submitProtAction(
|
||||
action,
|
||||
canvas,
|
||||
tlcoords,
|
||||
brcoords,
|
||||
callback,
|
||||
) {
|
||||
const data = new FormData();
|
||||
data.append('protaction', action);
|
||||
data.append('canvasid', canvas);
|
||||
data.append('ulcoor', tlcoords);
|
||||
data.append('brcoor', brcoords);
|
||||
const resp = await fetch('./admintools', {
|
||||
credentials: 'include',
|
||||
method: 'POST',
|
||||
body: data,
|
||||
});
|
||||
callback(await resp.text());
|
||||
}
|
||||
|
||||
async function submitIPAction(
|
||||
action,
|
||||
callback,
|
||||
|
@ -56,8 +81,11 @@ function Admintools({
|
|||
const [selectedCanvas, selectCanvas] = useState(canvasId);
|
||||
const [imageAction, selectImageAction] = useState('build');
|
||||
const [iPAction, selectIPAction] = useState('ban');
|
||||
const [protAction, selectProtAction] = useState('protect');
|
||||
const [coords, selectCoords] = useState(keptState.coords);
|
||||
const [tlcoords, selectTLCoords] = useState(keptState.tlcoords);
|
||||
const [brcoords, selectBRCoords] = useState(keptState.brcoords);
|
||||
const [resp, setResp] = useState(null);
|
||||
const [coords, selectCoords] = useState('X_Y');
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
|
||||
let descAction;
|
||||
|
@ -156,8 +184,11 @@ function Admintools({
|
|||
maxWidth: '15em',
|
||||
}}
|
||||
type="text"
|
||||
placeholder="X_Y"
|
||||
onChange={(evt) => {
|
||||
selectCoords(evt.target.value.trim());
|
||||
const co = evt.target.value.trim();
|
||||
selectCoords(co);
|
||||
keptState.coords = co;
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
|
@ -168,7 +199,7 @@ function Admintools({
|
|||
return;
|
||||
}
|
||||
setSubmitting(true);
|
||||
submitAction(
|
||||
submitImageAction(
|
||||
imageAction,
|
||||
selectedCanvas,
|
||||
coords,
|
||||
|
@ -181,6 +212,111 @@ function Admintools({
|
|||
>
|
||||
{(submitting) ? '...' : 'Submit'}
|
||||
</button>
|
||||
|
||||
<br />
|
||||
<div className="modaldivider" />
|
||||
<h3 className="modaltitle">Pixel Protection</h3>
|
||||
<p className="modalcotext">
|
||||
Set protection of areas
|
||||
(if you need finer grained control,
|
||||
use protect with image upload and alpha layers)
|
||||
</p>
|
||||
<p className="modalcotext">Choose Canvas:
|
||||
<select
|
||||
onChange={(e) => {
|
||||
const sel = e.target;
|
||||
selectCanvas(sel.options[sel.selectedIndex].value);
|
||||
}}
|
||||
>
|
||||
{
|
||||
Object.keys(canvases).map((canvas) => ((canvases[canvas].v)
|
||||
? null
|
||||
: (
|
||||
<option
|
||||
selected={canvas === selectedCanvas}
|
||||
value={canvas}
|
||||
>
|
||||
{
|
||||
canvases[canvas].title
|
||||
}
|
||||
</option>
|
||||
)))
|
||||
}
|
||||
</select>
|
||||
</p>
|
||||
<select
|
||||
onChange={(e) => {
|
||||
const sel = e.target;
|
||||
selectProtAction(sel.options[sel.selectedIndex].value);
|
||||
}}
|
||||
>
|
||||
{['protect', 'unprotect'].map((opt) => (
|
||||
<option
|
||||
value={opt}
|
||||
selected={protAction === opt}
|
||||
>
|
||||
{opt}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<p className="modalcotext">
|
||||
Top-left corner (X_Y):
|
||||
<input
|
||||
value={tlcoords}
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: '100%',
|
||||
maxWidth: '15em',
|
||||
}}
|
||||
type="text"
|
||||
placeholder="X_Y"
|
||||
onChange={(evt) => {
|
||||
const co = evt.target.value.trim();
|
||||
selectTLCoords(co);
|
||||
keptState.tlcoords = co;
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
<p className="modalcotext">
|
||||
Bottom-right corner (X_Y):
|
||||
<input
|
||||
value={brcoords}
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: '100%',
|
||||
maxWidth: '15em',
|
||||
}}
|
||||
type="text"
|
||||
placeholder="X_Y"
|
||||
onChange={(evt) => {
|
||||
const co = evt.target.value.trim();
|
||||
selectBRCoords(co);
|
||||
keptState.brcoords = co;
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
if (submitting) {
|
||||
return;
|
||||
}
|
||||
setSubmitting(true);
|
||||
submitProtAction(
|
||||
protAction,
|
||||
selectedCanvas,
|
||||
tlcoords,
|
||||
brcoords,
|
||||
(ret) => {
|
||||
setSubmitting(false);
|
||||
setResp(ret);
|
||||
},
|
||||
);
|
||||
}}
|
||||
>
|
||||
{(submitting) ? '...' : 'Submit'}
|
||||
</button>
|
||||
|
||||
<br />
|
||||
<div className="modaldivider" />
|
||||
<h3 className="modaltitle">IP Actions</h3>
|
||||
|
|
|
@ -200,6 +200,7 @@ export async function protectCanvasArea(
|
|||
y + height - 1,
|
||||
);
|
||||
|
||||
let totalPxlCnt = 0;
|
||||
let chunk;
|
||||
for (let cx = ucx; cx <= lcx; cx += 1) {
|
||||
for (let cy = ucy; cy <= lcy; cy += 1) {
|
||||
|
@ -234,10 +235,12 @@ export async function protectCanvasArea(
|
|||
if (ret) {
|
||||
// eslint-disable-next-line max-len
|
||||
logger.info(`Set protection for ${pxlCnt} pixels in chunk ${cx}, ${cy}.`);
|
||||
totalPxlCnt += pxlCnt;
|
||||
}
|
||||
}
|
||||
chunk = null;
|
||||
}
|
||||
}
|
||||
logger.info('Setting protection for area done.');
|
||||
return totalPxlCnt;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,10 @@ import { Blacklist, Whitelist } from '../data/models';
|
|||
import { MINUTE } from '../core/constants';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import canvases from './canvases.json';
|
||||
import { imageABGR2Canvas } from '../core/Image';
|
||||
import {
|
||||
imageABGR2Canvas,
|
||||
protectCanvasArea,
|
||||
} from '../core/Image';
|
||||
|
||||
|
||||
const router = express.Router();
|
||||
|
@ -147,7 +150,7 @@ async function executeIPAction(action: string, ips: string): boolean {
|
|||
* @param action what to do with the image
|
||||
* @param file imagefile
|
||||
* @param coords coord sin X_Y format
|
||||
* @param canvasid numerical canvas id
|
||||
* @param canvasid numerical canvas id as string
|
||||
* @return [ret, msg] http status code and message
|
||||
*/
|
||||
async function executeImageAction(
|
||||
|
@ -156,12 +159,21 @@ async function executeImageAction(
|
|||
coords: string,
|
||||
canvasid: string,
|
||||
) {
|
||||
if (!coords) {
|
||||
return [403, 'Coordinates not defined'];
|
||||
}
|
||||
if (!canvasid) {
|
||||
return [403, 'canvasid not defined'];
|
||||
}
|
||||
|
||||
const splitCoords = coords.trim().split('_');
|
||||
if (splitCoords.length !== 2) {
|
||||
return [403, 'Invalid Coordinate Format'];
|
||||
}
|
||||
const [x, y] = splitCoords.map((z) => Math.floor(Number(z)));
|
||||
|
||||
const canvas = canvases[canvasid];
|
||||
|
||||
let error = null;
|
||||
if (Number.isNaN(x)) {
|
||||
error = 'x is not a valid number';
|
||||
|
@ -169,21 +181,15 @@ async function executeImageAction(
|
|||
error = 'y is not a valid number';
|
||||
} else if (!action) {
|
||||
error = 'No imageaction given';
|
||||
} else if (!canvasid) {
|
||||
error = 'No canvas specified';
|
||||
} else if (!canvases[canvasid]) {
|
||||
} else if (!canvas) {
|
||||
error = 'Invalid canvas selected';
|
||||
} else if (canvas.v) {
|
||||
error = 'Can not upload Image to 3D canvas';
|
||||
}
|
||||
if (error !== null) {
|
||||
return [403, error];
|
||||
}
|
||||
|
||||
const canvas = canvases[canvasid];
|
||||
|
||||
if (canvas.v) {
|
||||
return [403, 'Can not upload Image to 3D canvas'];
|
||||
}
|
||||
|
||||
const canvasMaxXY = canvas.size / 2;
|
||||
const canvasMinXY = -canvasMaxXY;
|
||||
if (x < canvasMinXY || y < canvasMinXY
|
||||
|
@ -208,6 +214,8 @@ async function executeImageAction(
|
|||
wipe, protect,
|
||||
);
|
||||
|
||||
// eslint-disable-next-line max-len
|
||||
logger.info(`ADMINTOOLS: Loaded image wth ${pxlCount} pixels to ${x}/${y}`);
|
||||
return [
|
||||
200,
|
||||
`Successfully loaded image wth ${pxlCount} pixels to ${x}/${y}`,
|
||||
|
@ -217,6 +225,100 @@ async function executeImageAction(
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute actions for protecting areas
|
||||
* @param action what to do
|
||||
* @param ulcoor coords of upper-left corner in X_Y format
|
||||
* @param brcoord coords of bottom-right corner in X_Y format
|
||||
* @param canvasid numerical canvas id as string
|
||||
* @return [ret, msg] http status code and message
|
||||
*/
|
||||
async function executeProtAction(
|
||||
action: string,
|
||||
ulcoor: string,
|
||||
brcoor: string,
|
||||
canvasid: number,
|
||||
) {
|
||||
if (!ulcoor || !brcoor) {
|
||||
return [403, 'Not all coordinates defined'];
|
||||
}
|
||||
if (!canvasid) {
|
||||
return [403, 'canvasid not defined'];
|
||||
}
|
||||
|
||||
let splitCoords = ulcoor.trim().split('_');
|
||||
if (splitCoords.length !== 2) {
|
||||
return [403, 'Invalid Coordinate Format for top-left corner'];
|
||||
}
|
||||
const [x, y] = splitCoords.map((z) => Math.floor(Number(z)));
|
||||
splitCoords = brcoor.trim().split('_');
|
||||
if (splitCoords.length !== 2) {
|
||||
return [403, 'Invalid Coordinate Format for bottom-right corner'];
|
||||
}
|
||||
const [u, v] = splitCoords.map((z) => Math.floor(Number(z)));
|
||||
|
||||
const canvas = canvases[canvasid];
|
||||
|
||||
let error = null;
|
||||
if (Number.isNaN(x)) {
|
||||
error = 'x of top-left corner is not a valid number';
|
||||
} else if (Number.isNaN(y)) {
|
||||
error = 'y of top-left corner is not a valid number';
|
||||
} else if (Number.isNaN(u)) {
|
||||
error = 'x of bottom-right corner is not a valid number';
|
||||
} else if (Number.isNaN(v)) {
|
||||
error = 'y of bottom-right corner is not a valid number';
|
||||
} else if (u < x || v < y) {
|
||||
error = 'Corner coordinates are alligned wrong';
|
||||
} else if (!action) {
|
||||
error = 'No imageaction given';
|
||||
} else if (!canvas) {
|
||||
error = 'Invalid canvas selected';
|
||||
} else if (!canvases[canvasid]) {
|
||||
error = 'Invalid canvas selected';
|
||||
} else if (action !== 'protect' && action !== 'unprotect') {
|
||||
error = 'Invalid action (must be protect or unprotect)';
|
||||
}
|
||||
if (error !== null) {
|
||||
return [403, error];
|
||||
}
|
||||
|
||||
const canvasMaxXY = canvas.size / 2;
|
||||
const canvasMinXY = -canvasMaxXY;
|
||||
if (x < canvasMinXY || y < canvasMinXY
|
||||
|| x >= canvasMaxXY || y >= canvasMaxXY) {
|
||||
return [403, 'Coordinates of top-left corner are outside of canvas'];
|
||||
}
|
||||
if (u < canvasMinXY || v < canvasMinXY
|
||||
|| u >= canvasMaxXY || v >= canvasMaxXY) {
|
||||
return [403, 'Coordinates of bottom-right corner are outside of canvas'];
|
||||
}
|
||||
|
||||
const width = u - x + 1;
|
||||
const height = v - y + 1;
|
||||
const protect = action === 'protect';
|
||||
const pxlCount = await protectCanvasArea(
|
||||
canvasid,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
protect,
|
||||
);
|
||||
logger.info(
|
||||
// eslint-disable-next-line max-len
|
||||
`ADMINTOOLS: Set protect to ${protect} for ${pxlCount} pixels at ${x} / ${y} with dimension ${width}x${height}`,
|
||||
);
|
||||
return [
|
||||
200,
|
||||
(protect)
|
||||
// eslint-disable-next-line max-len
|
||||
? `Successfully protected ${pxlCount} pixels at ${x} / ${y} with dimension ${width}x${height}`
|
||||
// eslint-disable-next-line max-len
|
||||
: `Soccessfully unprotected ${pxlCount} pixels at ${x} / ${y} with dimension ${width}x${height}`,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check for POST parameters,
|
||||
|
@ -237,6 +339,18 @@ router.post('/', upload.single('image'), async (req, res, next) => {
|
|||
const ret = await executeIPAction(req.body.ipaction, req.body.ip);
|
||||
res.status(200).send(ret);
|
||||
return;
|
||||
} if (req.body.protaction) {
|
||||
const {
|
||||
protaction, ulcoor, brcoor, canvasid,
|
||||
} = req.body;
|
||||
const [ret, msg] = await executeProtAction(
|
||||
protaction,
|
||||
ulcoor,
|
||||
brcoor,
|
||||
canvasid,
|
||||
);
|
||||
res.status(ret).send(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
next();
|
||||
|
|
Loading…
Reference in New Issue
Block a user