add protection or rectangles without image to admintools

This commit is contained in:
HF 2020-06-22 20:23:55 +02:00
parent 1d081991ba
commit a69711d838
3 changed files with 268 additions and 15 deletions

View File

@ -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&nbsp;
(if you need finer grained control,&nbsp;
use protect with image upload and alpha layers)
</p>
<p className="modalcotext">Choose Canvas:&nbsp;
<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):&nbsp;
<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):&nbsp;
<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>

View File

@ -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;
}

View File

@ -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();