forked from ppfun/pixelplanet
use lua scripting in redis for setting pixels
This commit is contained in:
parent
9166adab13
commit
100bdb17b5
123
src/core/draw.js
123
src/core/draw.js
|
@ -7,6 +7,7 @@ import {
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import logger, { pixelLogger } from './logger';
|
import logger, { pixelLogger } from './logger';
|
||||||
import RedisCanvas from '../data/redis/RedisCanvas';
|
import RedisCanvas from '../data/redis/RedisCanvas';
|
||||||
|
import allowPlace from '../data/redis/allowPlace';
|
||||||
import {
|
import {
|
||||||
setPixelByOffset,
|
setPixelByOffset,
|
||||||
setPixelByCoords,
|
setPixelByCoords,
|
||||||
|
@ -68,6 +69,7 @@ export async function drawByOffsets(
|
||||||
let retCode = 0;
|
let retCode = 0;
|
||||||
let pxlCnt = 0;
|
let pxlCnt = 0;
|
||||||
let rankedPxlCnt = 0;
|
let rankedPxlCnt = 0;
|
||||||
|
let needProxycheck = 0;
|
||||||
const { ip } = user;
|
const { ip } = user;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -91,8 +93,6 @@ export async function drawByOffsets(
|
||||||
const canvasSize = canvas.size;
|
const canvasSize = canvas.size;
|
||||||
const is3d = !!canvas.v;
|
const is3d = !!canvas.v;
|
||||||
|
|
||||||
wait = await user.getWait(canvasId);
|
|
||||||
|
|
||||||
const tileSize = (is3d) ? THREE_TILE_SIZE : TILE_SIZE;
|
const tileSize = (is3d) ? THREE_TILE_SIZE : TILE_SIZE;
|
||||||
/*
|
/*
|
||||||
* canvas/chunk validation
|
* canvas/chunk validation
|
||||||
|
@ -134,38 +134,34 @@ export async function drawByOffsets(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (pixels.length) {
|
const clrIgnore = canvas.cli || 0;
|
||||||
const [offset, color] = pixels.pop();
|
const factor = (isAdmin || (user.userlvl > 0 && pixels[0][1] < clrIgnore))
|
||||||
|
? 0.0 : coolDownFactor;
|
||||||
|
const bcd = canvas.bcd * factor;
|
||||||
|
const pcd = (canvas.pcd) ? canvas.pcd * factor : bcd;
|
||||||
|
const pxlOffsets = [];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* validate pixels
|
||||||
|
*/
|
||||||
|
for (let u = 0; u < pixels.length; u += 1) {
|
||||||
|
const [offset, color] = pixels[u];
|
||||||
|
pxlOffsets.push(offset);
|
||||||
|
|
||||||
const [x, y, z] = getPixelFromChunkOffset(i, j, offset, canvasSize, is3d);
|
const [x, y, z] = getPixelFromChunkOffset(i, j, offset, canvasSize, is3d);
|
||||||
|
|
||||||
// eslint-disable-next-line no-await-in-loop
|
|
||||||
const setColor = await RedisCanvas.getPixelByOffset(
|
|
||||||
canvasId,
|
|
||||||
i, j,
|
|
||||||
offset,
|
|
||||||
);
|
|
||||||
|
|
||||||
pixelLogger.info(
|
pixelLogger.info(
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
`${startTime} ${user.ip} ${user.id} ${canvasId} ${x} ${y} ${z} ${color} ${setColor}`,
|
`${startTime} ${user.ip} ${user.id} ${canvasId} ${x} ${y} ${z} ${color}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const clrIgnore = canvas.cli || 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* pixel validation
|
|
||||||
*/
|
|
||||||
const maxSize = (is3d) ? tileSize * tileSize * THREE_CANVAS_HEIGHT
|
const maxSize = (is3d) ? tileSize * tileSize * THREE_CANVAS_HEIGHT
|
||||||
: tileSize * tileSize;
|
: tileSize * tileSize;
|
||||||
if (offset >= maxSize) {
|
if (offset >= maxSize) {
|
||||||
// z out of bounds or weird stuff
|
// z out of bounds or weird stuff
|
||||||
throw new Error(4);
|
throw new Error(4);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* admins and mods can place unset pixels
|
// admins and mods can place unset pixels
|
||||||
*/
|
|
||||||
if (color >= canvas.colors.length
|
if (color >= canvas.colors.length
|
||||||
|| (color < clrIgnore
|
|| (color < clrIgnore
|
||||||
&& user.userlvl === 0
|
&& user.userlvl === 0
|
||||||
|
@ -175,59 +171,46 @@ export async function drawByOffsets(
|
||||||
throw new Error(5);
|
throw new Error(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setColor & 0x80
|
/* 3D Canvas Minecraft Avatars */
|
||||||
/* 3D Canvas Minecraft Avatars */
|
// && x >= 96 && x <= 128 && z >= 35 && z <= 100
|
||||||
// && x >= 96 && x <= 128 && z >= 35 && z <= 100
|
// 96 - 128 on x
|
||||||
// 96 - 128 on x
|
// 32 - 128 on z
|
||||||
// 32 - 128 on z
|
if (canvas.v && i === 19 && j >= 17 && j < 20 && !isAdmin) {
|
||||||
|| (canvas.v && i === 19 && j >= 17 && j < 20 && !isAdmin)
|
|
||||||
) {
|
|
||||||
// protected pixel
|
// protected pixel
|
||||||
throw new Error(8);
|
throw new Error(8);
|
||||||
}
|
}
|
||||||
|
|
||||||
coolDown = ((setColor & 0x3F) >= clrIgnore && canvas.pcd)
|
|
||||||
? canvas.pcd : canvas.bcd;
|
|
||||||
/*
|
|
||||||
* admins have no cooldown
|
|
||||||
* mods have no cooldown when placing unset pixels
|
|
||||||
*/
|
|
||||||
if (isAdmin || (user.userlvl > 0 && color < clrIgnore)) {
|
|
||||||
coolDown = 0.0;
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* cooldown changes like from event
|
|
||||||
*/
|
|
||||||
coolDown *= coolDownFactor;
|
|
||||||
}
|
|
||||||
|
|
||||||
wait += coolDown;
|
|
||||||
if (wait > canvas.cds) {
|
|
||||||
// cooldown stack used
|
|
||||||
wait -= coolDown;
|
|
||||||
coolDown = canvas.cds - wait - coolDown;
|
|
||||||
throw new Error(9);
|
|
||||||
}
|
|
||||||
|
|
||||||
setPixelByOffset(canvasId, color, i, j, offset);
|
|
||||||
|
|
||||||
pxlCnt += 1;
|
|
||||||
/*
|
|
||||||
* hardcode to not count pixels in antarctica
|
|
||||||
* do not count 0cd pixels
|
|
||||||
*/
|
|
||||||
// eslint-disable-next-line eqeqeq
|
// eslint-disable-next-line eqeqeq
|
||||||
if (canvas.ranked && (canvasId != 0 || y < 14450) && coolDown) {
|
if (canvas.ranked && (canvasId != 0 || y < 14450) && pcd) {
|
||||||
|
pixels[u].push(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[retCode, pxlCnt, wait, coolDown, needProxycheck] = await allowPlace(
|
||||||
|
ip,
|
||||||
|
user.id,
|
||||||
|
canvasId,
|
||||||
|
i, j,
|
||||||
|
clrIgnore,
|
||||||
|
bcd, pcd,
|
||||||
|
canvas.cds,
|
||||||
|
pxlOffsets,
|
||||||
|
);
|
||||||
|
|
||||||
|
for (let u = 0; u < pxlCnt; u += 1) {
|
||||||
|
const [offset, color, ranked] = pixels[u];
|
||||||
|
setPixelByOffset(canvasId, color, i, j, offset);
|
||||||
|
if (ranked) {
|
||||||
rankedPxlCnt += 1;
|
rankedPxlCnt += 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const duration = Date.now() - startTime;
|
const duration = Date.now() - startTime;
|
||||||
if (duration > 1000) {
|
if (duration > 1000) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
`Long response time of ${duration}ms for placing ${pxlCnt} pixels for user ${user.id || user.ip}`,
|
`Long response time of ${duration}ms for placing ${pxlCnt} pixels for user ${user.id || user.ip}`,
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
retCode = parseInt(e.message, 10);
|
retCode = parseInt(e.message, 10);
|
||||||
|
@ -236,11 +219,8 @@ export async function drawByOffsets(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pxlCnt && wait) {
|
if (rankedPxlCnt) {
|
||||||
await user.setWait(wait, canvasId);
|
await user.incrementPixelcount(rankedPxlCnt);
|
||||||
if (rankedPxlCnt) {
|
|
||||||
await user.incrementPixelcount(rankedPxlCnt);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retCode !== 13) {
|
if (retCode !== 13) {
|
||||||
|
@ -253,6 +233,7 @@ export async function drawByOffsets(
|
||||||
pxlCnt,
|
pxlCnt,
|
||||||
rankedPxlCnt,
|
rankedPxlCnt,
|
||||||
retCode,
|
retCode,
|
||||||
|
needProxycheck,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,16 +92,15 @@ async function withCache(f, ip) {
|
||||||
status: 4,
|
status: 4,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// get from cache, if there
|
|
||||||
const ipKey = getIPv6Subnet(ip);
|
const ipKey = getIPv6Subnet(ip);
|
||||||
const cache = await getCacheAllowed(ipKey);
|
|
||||||
if (cache) {
|
|
||||||
return cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
// else make asynchronous ipcheck and assume no proxy in the meantime
|
|
||||||
// do not check ip that currently gets checked
|
|
||||||
if (checking.indexOf(ipKey) === -1) {
|
if (checking.indexOf(ipKey) === -1) {
|
||||||
|
// get from cache, if there
|
||||||
|
const cache = await getCacheAllowed(ipKey);
|
||||||
|
if (cache) {
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
// else make asynchronous ipcheck and assume no proxy in the meantime
|
||||||
|
// do not check ip that currently gets checked
|
||||||
checking.push(ipKey);
|
checking.push(ipKey);
|
||||||
withoutCache(f, ip)
|
withoutCache(f, ip)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
|
|
43
src/data/redis/allowPlace.js
Normal file
43
src/data/redis/allowPlace.js
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* redis script for user pixel placement
|
||||||
|
* this does not set any pixels itself, see lua/placePixel.lua
|
||||||
|
*/
|
||||||
|
import client from './client';
|
||||||
|
import { getIPv6Subnet } from '../../utils/ip';
|
||||||
|
import { PREFIX as CAPTCHA_PREFIX } from './captcha';
|
||||||
|
import { PREFIX as ALLOWED_PREFIX } from './isAllowedCache';
|
||||||
|
import { CAPTCHA_TIME } from '../../core/config';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gets pixels and chunk coords and checks if
|
||||||
|
* and how many a user can set and sets the cooldown accordingly
|
||||||
|
* @param ip ip of request
|
||||||
|
* @param id userId
|
||||||
|
* @param clrIgnore, bcd, pcd, cds incormations about canvas
|
||||||
|
* @param i, j chunk coordinates
|
||||||
|
* @param pxls Array with offsets of pixels
|
||||||
|
* @return see lua/placePixel.lua
|
||||||
|
*/
|
||||||
|
export default function allowPlace(
|
||||||
|
ip,
|
||||||
|
id,
|
||||||
|
canvasId,
|
||||||
|
i, j,
|
||||||
|
clrIgnore,
|
||||||
|
bcd,
|
||||||
|
pcd,
|
||||||
|
cds,
|
||||||
|
pxls,
|
||||||
|
) {
|
||||||
|
const ipn = getIPv6Subnet(ip);
|
||||||
|
const isalKey = `${ALLOWED_PREFIX}:${ipn}`;
|
||||||
|
const captKey = (CAPTCHA_TIME >= 0) ? `${CAPTCHA_PREFIX}:${ipn}` : 'nope';
|
||||||
|
const ipCdKey = `cd:${canvasId}:ip:${ipn}`;
|
||||||
|
const idCdKey = (id) ? `cd:${canvasId}:id:${id}` : 'nope';
|
||||||
|
const chunkKey = `ch:${canvasId}:${i}:${j}`;
|
||||||
|
return client.placePxl(
|
||||||
|
isalKey, captKey, ipCdKey, idCdKey, chunkKey,
|
||||||
|
clrIgnore, bcd, pcd, cds,
|
||||||
|
...pxls,
|
||||||
|
);
|
||||||
|
}
|
|
@ -13,6 +13,8 @@ import {
|
||||||
|
|
||||||
const TTL_CACHE = CAPTCHA_TIME * 60; // seconds
|
const TTL_CACHE = CAPTCHA_TIME * 60; // seconds
|
||||||
|
|
||||||
|
export const PREFIX = 'human';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* chars that are so similar that we allow them to get mixed up
|
* chars that are so similar that we allow them to get mixed up
|
||||||
* left: captcha text
|
* left: captcha text
|
||||||
|
@ -119,7 +121,7 @@ export async function checkCaptchaSolution(
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
if (!onetime) {
|
if (!onetime) {
|
||||||
const solvkey = `human:${ipn}`;
|
const solvkey = `${PREFIX}:${ipn}`;
|
||||||
await client.set(solvkey, '', {
|
await client.set(solvkey, '', {
|
||||||
EX: TTL_CACHE,
|
EX: TTL_CACHE,
|
||||||
});
|
});
|
||||||
|
@ -148,7 +150,7 @@ export async function needCaptcha(ip) {
|
||||||
if (CAPTCHA_TIME < 0) {
|
if (CAPTCHA_TIME < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const key = `human:${getIPv6Subnet(ip)}`;
|
const key = `${PREFIX}:${getIPv6Subnet(ip)}`;
|
||||||
const ttl = await client.ttl(key);
|
const ttl = await client.ttl(key);
|
||||||
if (ttl > 0) {
|
if (ttl > 0) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -167,7 +169,7 @@ export async function forceCaptcha(ip) {
|
||||||
if (CAPTCHA_TIME < 0) {
|
if (CAPTCHA_TIME < 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const key = `human:${getIPv6Subnet(ip)}`;
|
const key = `${PREFIX}:${getIPv6Subnet(ip)}`;
|
||||||
const ret = await client.del(key);
|
const ret = await client.del(key);
|
||||||
return (ret > 0);
|
return (ret > 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,19 +2,31 @@
|
||||||
* redis client
|
* redis client
|
||||||
* REDIS_URL can be url or path to unix socket
|
* REDIS_URL can be url or path to unix socket
|
||||||
*/
|
*/
|
||||||
|
import fs from 'fs';
|
||||||
import { createClient } from 'redis';
|
import { createClient, defineScript } from 'redis';
|
||||||
|
|
||||||
import { REDIS_URL } from '../../core/config';
|
import { REDIS_URL } from '../../core/config';
|
||||||
|
|
||||||
|
const scripts = {
|
||||||
|
placePxl: defineScript({
|
||||||
|
NUMBER_OF_KEYS: 5,
|
||||||
|
SCRIPT: fs.readFileSync('./workers/placePixel.lua'),
|
||||||
|
transformArguments(...args) {
|
||||||
|
return args.map((a) => ((typeof a === 'string') ? a : a.toString()));
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
const client = createClient(REDIS_URL.startsWith('redis://')
|
const client = createClient(REDIS_URL.startsWith('redis://')
|
||||||
? {
|
? {
|
||||||
url: REDIS_URL,
|
url: REDIS_URL,
|
||||||
|
scripts,
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
socket: {
|
socket: {
|
||||||
path: REDIS_URL,
|
path: REDIS_URL,
|
||||||
},
|
},
|
||||||
|
scripts,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
import client from './client';
|
import client from './client';
|
||||||
|
|
||||||
const PREFIX = 'isal';
|
export const PREFIX = 'isal';
|
||||||
const CACHE_DURATION = 14 * 24 * 3600;
|
const CACHE_DURATION = 14 * 24 * 3600;
|
||||||
|
|
||||||
export function cacheAllowed(ip, status) {
|
export function cacheAllowed(ip, status) {
|
||||||
|
|
110
src/data/redis/lua/placePixel.lua
Normal file
110
src/data/redis/lua/placePixel.lua
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
-- Checking requirements and calculating cooldown of user wthin
|
||||||
|
-- redis itself. Does not set pixels directly. Pixels are set in batches
|
||||||
|
-- in RedisCanvas.js
|
||||||
|
-- This script will get copied into the dist/workers directory from webpack
|
||||||
|
-- Keys:
|
||||||
|
-- isAlloweed: 'isal:ip' (proxycheck, blacklist, whitelist)
|
||||||
|
-- isHuman 'human:ip' (captcha needed when expired)
|
||||||
|
-- ipCD: 'cd:canvasId:ip:ip'
|
||||||
|
-- uCD: 'cd:canvasId:id:userId'
|
||||||
|
-- chunk: 'ch:canvasId:i:j'
|
||||||
|
-- Args:
|
||||||
|
-- clrIgnore: integer number of what colors are considered unset
|
||||||
|
-- bcd: number baseColldown (fixed to cdFactor and 0 if admin)
|
||||||
|
-- pcd: number set pixel cooldown (fixed to cdFactor and 0 if admin)
|
||||||
|
-- cds: max cooldown of canvas
|
||||||
|
-- off1, chonk offset of first pixel
|
||||||
|
-- off2, chonk offset of second pixel
|
||||||
|
-- ..., infinie pixels possible
|
||||||
|
-- Returns:
|
||||||
|
-- {
|
||||||
|
-- 1: pixel return status code (check ui/placePixel.js)
|
||||||
|
-- 2: amount of successfully set pixels
|
||||||
|
-- 3: total cooldown of user
|
||||||
|
-- 4: info about placed pixel cooldown (addition of last pixel)
|
||||||
|
-- 5: if we have to update isAllowed( proxycheck)
|
||||||
|
-- }
|
||||||
|
local ret = {0, 0, 0, 0, 0}
|
||||||
|
-- check if isAllowed
|
||||||
|
local ia = redis.call('get', KEYS[1])
|
||||||
|
if not ia then
|
||||||
|
ret[5] = 1
|
||||||
|
else
|
||||||
|
ia = tonumber(ia)
|
||||||
|
if ia > 0 then
|
||||||
|
if ia == 1 then
|
||||||
|
-- proxy
|
||||||
|
ret[1] = 11
|
||||||
|
elseif ia == 2 then
|
||||||
|
-- banned
|
||||||
|
ret[1] = 14
|
||||||
|
elseif ia == 3 then
|
||||||
|
-- range banned
|
||||||
|
ret[1] = 15
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- check if captcha is needed
|
||||||
|
if KEYS[2] ~= "nope" and not redis.call('get', KEYS[2]) then
|
||||||
|
-- captcha
|
||||||
|
ret[1] = 10
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
-- get cooldown of user
|
||||||
|
local cd = redis.call('pttl', KEYS[3])
|
||||||
|
if cd < 0 then
|
||||||
|
cd = 0
|
||||||
|
end
|
||||||
|
if KEYS[4] ~= "nope" then
|
||||||
|
local icd = redis.call('pttl', KEYS[4])
|
||||||
|
if icd > cd then
|
||||||
|
cd = icd
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- set pixels
|
||||||
|
local pxlcd = 0
|
||||||
|
local pxlcnt = 0
|
||||||
|
local cli = tonumber(ARGV[1])
|
||||||
|
local bcd = tonumber(ARGV[2])
|
||||||
|
local pcd = tonumber(ARGV[3])
|
||||||
|
local cds = tonumber(ARGV[4])
|
||||||
|
for c = 5,#ARGV do
|
||||||
|
local off = tonumber(ARGV[c]) * 8
|
||||||
|
local clr = tonumber(ARGV[c + 1])
|
||||||
|
-- get color of pixel on canvas
|
||||||
|
local sclr = redis.call('bitfield', KEYS[5], 'get', 'u8', off)
|
||||||
|
sclr = sclr[1]
|
||||||
|
-- check if protected (protected is last bit in u8)
|
||||||
|
if sclr >= 128 then
|
||||||
|
-- pixel protected
|
||||||
|
ret[1] = 8
|
||||||
|
break
|
||||||
|
end
|
||||||
|
-- calculate cooldown of pixel
|
||||||
|
pxlcd = bcd
|
||||||
|
if sclr >= cli then
|
||||||
|
pxlcd = pcd
|
||||||
|
end
|
||||||
|
cd = cd + pxlcd
|
||||||
|
if cd > cds then
|
||||||
|
cd = cd - pxlcd
|
||||||
|
pxlcd = cds - cd - pxlcd
|
||||||
|
-- pixelstack used up
|
||||||
|
ret[1] = 9
|
||||||
|
break
|
||||||
|
end
|
||||||
|
pxlcnt = pxlcnt + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if pxlcnt > 0 and cd > 0 then
|
||||||
|
redis.call('set', KEYS[3], '', 'px', cd)
|
||||||
|
if KEYS[4] ~= "nope" then
|
||||||
|
redis.call('set', KEYS[4], '', 'px', cd)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ret[2] = pxlcnt
|
||||||
|
ret[3] = cd
|
||||||
|
ret[4] = pxlcd
|
||||||
|
return ret
|
|
@ -23,7 +23,6 @@ import socketEvents from './SocketEvents';
|
||||||
import chatProvider, { ChatProvider } from '../core/ChatProvider';
|
import chatProvider, { ChatProvider } from '../core/ChatProvider';
|
||||||
import authenticateClient from './authenticateClient';
|
import authenticateClient from './authenticateClient';
|
||||||
import { drawByOffsets } from '../core/draw';
|
import { drawByOffsets } from '../core/draw';
|
||||||
import { needCaptcha } from '../data/redis/captcha';
|
|
||||||
import isIPAllowed from '../core/isAllowed';
|
import isIPAllowed from '../core/isAllowed';
|
||||||
|
|
||||||
|
|
||||||
|
@ -495,39 +494,6 @@ class SocketServer {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let failureRet = null;
|
|
||||||
// check if captcha needed
|
|
||||||
if (await needCaptcha(ip)) {
|
|
||||||
// need captcha
|
|
||||||
failureRet = PixelReturn.dehydrate(10);
|
|
||||||
} else {
|
|
||||||
// (re)check for Proxy
|
|
||||||
const allowed = await isIPAllowed(ip);
|
|
||||||
if (!allowed.allowed) {
|
|
||||||
// proxy
|
|
||||||
let failureStatus = 11;
|
|
||||||
if (allowed.status === 2) {
|
|
||||||
// banned
|
|
||||||
failureStatus = 14;
|
|
||||||
} else if (allowed.status === 3) {
|
|
||||||
// range banned
|
|
||||||
failureStatus = 15;
|
|
||||||
}
|
|
||||||
failureRet = PixelReturn.dehydrate(failureStatus);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (failureRet !== null) {
|
|
||||||
const now = Date.now();
|
|
||||||
if (limiter && limiter[0] > now) {
|
|
||||||
limiter[0] += 1000;
|
|
||||||
} else {
|
|
||||||
rateLimit.set(ip, [now + 1000, false]);
|
|
||||||
}
|
|
||||||
ws.send(failureRet);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// receive pixels here
|
|
||||||
const {
|
const {
|
||||||
i, j, pixels,
|
i, j, pixels,
|
||||||
} = PixelUpdate.hydrate(buffer);
|
} = PixelUpdate.hydrate(buffer);
|
||||||
|
@ -537,12 +503,27 @@ class SocketServer {
|
||||||
pxlCnt,
|
pxlCnt,
|
||||||
rankedPxlCnt,
|
rankedPxlCnt,
|
||||||
retCode,
|
retCode,
|
||||||
|
needProxycheck,
|
||||||
} = await drawByOffsets(
|
} = await drawByOffsets(
|
||||||
ws.user,
|
ws.user,
|
||||||
canvasId,
|
canvasId,
|
||||||
i, j,
|
i, j,
|
||||||
pixels,
|
pixels,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (needProxycheck) {
|
||||||
|
isIPAllowed(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retCode > 9 && retCode !== 13) {
|
||||||
|
const now = Date.now();
|
||||||
|
if (limiter && limiter[0] > now) {
|
||||||
|
limiter[0] += 1000;
|
||||||
|
} else {
|
||||||
|
rateLimit.set(ip, [now + 1000, false]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ws.send(PixelReturn.dehydrate(
|
ws.send(PixelReturn.dehydrate(
|
||||||
retCode,
|
retCode,
|
||||||
wait,
|
wait,
|
||||||
|
|
|
@ -19,10 +19,10 @@ export default {
|
||||||
},
|
},
|
||||||
dehydrate(
|
dehydrate(
|
||||||
retCode,
|
retCode,
|
||||||
wait = 0,
|
wait,
|
||||||
coolDown = 0,
|
coolDown,
|
||||||
pxlCnt = 0,
|
pxlCnt,
|
||||||
rankedPxlCnt = 0,
|
rankedPxlCnt,
|
||||||
) {
|
) {
|
||||||
// Server (sender)
|
// Server (sender)
|
||||||
const buffer = Buffer.allocUnsafe(1 + 1 + 4 + 2 + 1 + 1);
|
const buffer = Buffer.allocUnsafe(1 + 1 + 4 + 2 + 1 + 1);
|
||||||
|
|
|
@ -159,6 +159,10 @@ module.exports = ({
|
||||||
from: path.resolve('deployment', 'captchaFonts'),
|
from: path.resolve('deployment', 'captchaFonts'),
|
||||||
to: path.resolve('dist', 'captchaFonts'),
|
to: path.resolve('dist', 'captchaFonts'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
from: path.resolve('src', 'data', 'redis', 'lua', 'placePixel.lua'),
|
||||||
|
to: path.resolve('dist', 'workers', 'placePixel.lua'),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in New Issue
Block a user