Skip to content

Instantly share code, notes, and snippets.

@Mortimal
Last active April 12, 2017 19:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Mortimal/22dce0eaccd79ec52b90171f6b01451a to your computer and use it in GitHub Desktop.
Save Mortimal/22dce0eaccd79ec52b90171f6b01451a to your computer and use it in GitHub Desktop.
function Botnet(t) {
t.ignore = t.ignore || [], t.dir = t.dir || 0, t.pixelize = t.pixelize || !1, this.image = t
}
function launchBot(t) {
function e() {
(App.cooldown - (new Date).getTime()) / 1e3 > 0 ? setTimeout(e, WAIT_DELAY) : (i || setTimeout(a, FORCE_DELAY), setTimeout(e, DRAW_DELAY))
}
function a() {
t.board.data = updateBoardData(t.board);
for (var e = 0, a = 0; a < t.template.data.width; a++)
for (var i = 0; i < t.template.data.height; i++) {
var c = o(a, i);
null != c && e++
}
switch (l = Math.ceil(100 - e / n * 100), p(), t.image.dir) {
case 0:
for (var i = t.template.data.height - 1 ; i > 0; i--)
for (var a = t.template.data.width - 1; a > 0; a--) {
var c = o(a, i);
if (null != c) return void r(c)
}
break;
case 1:
for (var i = t.template.data.height - 1 ; i > 0; i--)
for (var a = t.template.data.width - 1; a > 0; a--) {
var c = o(a, i);
if (null != c) return void r(c)
}
break;
case 2:
for (var i = t.template.data.height - 1 ; i > 0; i--)
for (var a = t.template.data.width - 1; a > 0; a--) {
var c = o(a, i);
if (null != c) return void r(c)
}
break;
case 3:
for (var i = t.template.data.height - 1 ; i > 0; i--)
for (var a = t.template.data.width - 1; a > 0; a--) {
var c = o(a, i);
if (null != c) return void r(c)
}
break;
case 4:
for (var i = t.template.data.height - 1 ; i > 0; i--)
for (var a = t.template.data.width - 1; a > 0; a--) {
var c = o(a, i);
if (null != c) return void r(c)
}
break;
case 5:
for (var i = t.template.data.height - 1 ; i > 0; i--)
for (var a = t.template.data.width - 1; a > 0; a--) {
var c = o(a, i);
if (null != c) return void r(c)
}
break;
default:
console.warn("Unknown direction index")
}
}
function o(e, a) {
var o = e + t.image.x,
r = a + t.image.y,
n = getPixel(t.template.data, e, a),
i = getPixel(t.board.data, o, r);
if (n[3] <= 127) return null;
for (var l = 0; l < t.image.ignore.length; l++)
if (pixelEquals(t.image.ignore[l], n)) return null;
if (t.image.pixelize && (n = nearesColors(n)), !pixelEquals(n, i)) {
var c = getColorIndex(n);
return -1 == c && console.warn("Incorrect color !"), {
x: o,
y: r,
color: c
}
}
return null
}
function r(t) {
console.log("Place.."), App.switchColor(t.color), App.attemptPlace(t.x, t.y), App.alert("Placed at [" + t.x + ", " + t.y + "] Color " + t.color)
}
var n = countPoints(t.template.data),
i = !1,
l = 0,
c = App.socket.onmessage;
App.socket.onmessage = function(t) {
if ("captcha_required" == JSON.parse(t.data).type)
if (i = !0, "granted" !== Notification.permission) Notification.requestPermission();
else {
var e = new Notification("Pxls.space", {
body: "Введіть капчу!"
});
e.onclick = function() {
window.focus()
}
}
c(t)
};
var d = recaptchaCallback;
recaptchaCallback = function(t) {
console.log("Captcha OK"), i = !1, d(t)
};
var p = function() {
function e() {
o.find("#filledpercent").text("Filled " + l + "%")
}
var o, r = !1;
return function() {
return $("head").append("<style>.botpanel {\tbox-shadow: 0 0 15px rgba(0,0,0,0.9);\tbackground-color: rgba(0,0,0,0.8);\tborder-radius: 3px;\tbottom: 110px;\topacity: 0.8;\ttransition: opacity 0.3s ease-in-out;}.botpanel:hover {\topacity: 1.0;}.botpanel button, .botpanel select {\tbackground-color: #109254;\tborder: none;\tcolor: white;\tpadding: 3px 15px;\ttext-align: center;\ttext-decoration: none;\tdisplay: inline-block;\tfont-size: 14px;\tborder-radius: 3px;\twidth: 100%;\tmargin: 2px;\tcursor: pointer;}.botpanel a {\tcolor: #109254;}</style>"), o = $("#ui"), o.append('<div class="online botpanel"><a target="_blank" title="[Discord]" href="https://discord.gg/7SCbPUe">Ukraine pxls.space</a><br>' + t.image.title + "<br>[" + t.image.x + ", " + t.image.y + ']<br><span id="filledpercent">Filled ' + l + '%</span><br><button id="restartbot">Restart Bot</button><br><button id="screenshot">Screenshot</button><br><button id="preview">Preview</button><br><select id="selectdir"><option value="0">Random</option><option value="1">Left - Right</option><option value="2">Right - Left</option><option value="3">Top - Bottom</option><option value="4">Bottom - Top</option><option value="5">Chess</option></select></div>'), o.find("#selectdir").val("" + t.image.dir), o.find("#restartbot").click(function() {
a()
}), o.find("#screenshot").click(function() {
var t = document.getElementById("board"),
e = new Image;
e.src = t.toDataURL("image/png");
var a = document.createElement("a");
a.setAttribute("download", "board.png"), a.setAttribute("href", e.src), a.appendChild(e), a.click()
}), o.find("#preview").click(function() {
r = !r, r ? ($(this).css("background-color", "#ff2967"), t.board.context.globalAlpha = .6, t.board.context.drawImage(t.template.canvas, t.image.x, t.image.y), t.board.context.globalAlpha = 1) : ($(this).css("background-color", "#109254"), updateBoardData(t.board))
}), o.find("#selectdir").change(function(e) {
t.image.dir = parseInt($(this).val())
}), e
}()
}();
setTimeout(e, FORCE_DELAY)
}
function updateBoardData(t) {
return jQuery.get("/boarddata", function(e) {
for (var a = t.context, o = new ImageData(App.width, App.height), r = new Uint32Array(o.data.buffer), n = App.palette.map(function(t) {
return t = hexToRgb(t), 4278190080 | t.b << 16 | t.g << 8 | t.r
}), i = 0; i < App.width * App.height; i++) r[i] = n[e.charCodeAt(i)];
a.putImageData(o, 0, 0)
}), t.context.getImageData(0, 0, t.canvas.width, t.canvas.height)
}
function validateTemplate(t) {
for (var e = 0; e < t.width; e++)
for (var a = 0; a < t.height; a++) {
var o = getPixel(t, e, a);
if (!(o[3] <= 127) && getColorIndex(o)) return {
valid: !1,
pixel: o,
x: e,
y: a
}
}
return {
valid: !0
}
}
function countPoints(t) {
counter = 0;
for (var e = 0; e < t.width; e++)
for (var a = 0; a < t.height; a++) counter++;
return counter
}
function getColorIndex(t) {
for (var e = 0; e < palette.length; e++)
if (pixelEquals(palette[e], t)) return e;
return -1
}
function getPixel(t, e, a) {
var o = a * t.width * 4,
r = 4 * e,
n = o + r;
return t.data.slice(n, n + 4)
}
function pixelEquals(t, e) {
return t[0] == e[0] && t[1] == e[1] && t[2] == e[2]
}
function nearesColors(t) {
for (var e = [], a = 0; a < palette.length; a++) {
var o = colorDistance(palette[a], t);
e.push(o)
}
var r = arrayMinIndex(e);
return palette[r]
}
function arrayMinIndex(t) {
for (var e = t[0], a = 0, o = 0; o < t.length; o++) t[o] < e && (e = t[o], a = o);
return a
}
function colorDistance(t, e) {
return Math.abs(t[0] - e[0]) + Math.abs(t[1] - e[1]) + Math.abs(t[2] - e[2])
}
var palette = [
[255, 255, 255],
[228, 228, 228],
[136, 136, 136],
[34, 34, 34],
[255, 167, 209],
[229, 0, 0],
[229, 149, 0],
[160, 106, 66],
[229, 217, 0],
[148, 224, 68],
[2, 190, 1],
[0, 211, 221],
[0, 131, 199],
[0, 0, 234],
[207, 110, 228],
[130, 0, 128]
];
Botnet.prototype.start = function() {
var t = {
image: new Image,
canvas: document.createElement("canvas"),
context: null,
data: null
},
e = {
canvas: document.getElementById("board"),
context: null,
data: null
};
t.context = t.canvas.getContext("2d"), e.context = e.canvas.getContext("2d"), this.template = t, this.board = e;
var a = this;
t.image.onload = function() {
if (t.canvas.width = t.image.width, t.canvas.height = t.image.height, t.context.drawImage(t.image, 0, 0), e.data = updateBoardData(e), t.data = t.context.getImageData(0, 0, t.image.width, t.image.height), !a.image.pixelize) {
var o = validateTemplate(t.data);
if (!o.valid) return void App.alert("Incorrect color " + o.pixel + " at [" + o.x + ", " + o.y + "]");
console.log("Template valid true")
}
App.alert("Title: " + a.image.title), launchBot(a)
}, t.image.crossOrigin = "anonymous", t.image.src = this.image.src
};
var FORCE_DELAY = 1e3,
WAIT_DELAY = 1e3,
DRAW_DELAY = 3e3;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment