Давайте поиграем в игру.Скрипт, блокирующий во всех ваших репозиториях и организациях лиц, аффилиированных (форки, звёзды и лица, внёсшие коммиты) с репозиторием по вашему выбору. После этого заблокированные лица не смогут отправить в ваши репозитории сообщения об ошибках и даже патчи нужные им (но и вы не сможете в их репозитории), и возможно, подумают о своём поведении. Подобные скрипты - палки о двух концах. Применив его, будьте готовы к тому, что сначала вас забанят во влиятельных организациях, дальше все друг друга перебанят, а потом - опенсорс-сообществу конец. Вас предупредили. Скрипт лицензирован под CC0, разрешается распространять.
Получаете в настройках личный токен, заносите его в скрипт, ставите скрипт. Можете занести випов в белый список. В репозиториях появляются 2 кнопки. Заходите в нежелательный репозиторий, жмёте красную кнопку, дожидаетесь конца. Синяя позволяет передумать.
Жить или умереть FOSS-сообществу в текущем виде - выбор за вами! Приятных вам игр.
// ==UserScript==
// @name GitHammer
// @include /https:\/\/github.com\/[\w_-]+&...)?)?/
// @grant GM.xmlHttpRequest
// @version 0.1
// @author Anonymous
// @run-at document-idle
// @license CC0
// @description A banhammer that blocks affiliates of some GitHub repos.
// ==/UserScript==
'use strict';
let whitelist = [];
const GH_PERSONAL_TOKEN = ""; // Set it
const concurrency = 16;
const delay = 100;
const m = window.location.pathname.split("/"),
p = `${"https://api.github.com/repos"}/${m[1]+"/"+m[2]}`;
let q = d => d.login,
r = [
[`${p}/contributors`, q],
[`${p}/forks`, d => d.owner.login],
[`${p}/stargazers`, q]
];
function v() {
return new Promise(d => {
setTimeout(d, delay)
})
}
function w(d, a) {
a = Math.ceil(d.length / a);
let b = [];
for (let e = 0, c = a; c < d.length + a; e = c, c += a) b.push(d.slice(e, c));
return b
}
function x(d, a) {
var b = w(d, concurrency);
d = [];
for (let e of b) {
b = Promise.resolve("a");
for (let c of e) b = b.then(g => a(c, g));
d.push(b)
}
return Promise.all(d)
}
function y(d, a) {
a.method || (a.method = "GET");
a.url = d;
return new Promise((b, e) => {
a.onload = c => {
b({
text: () => Promise.resolve(c.responseText),
json: () => {
try {
return Promise.resolve(JSON.parse(c.responseText))
} catch (g) {
return Promise.reject(g)
}
}
})
};
a.onerror = c => {
e(c)
};
GM.xmlHttpRequest(a)
})
}
function z(d, a, b, e, c, g, f = null) {
function t(h) {
c.value = k + "\n" + h;
h = JSON.parse(h);
if (h.length) {
if (1 == h.length && !h[0]) return e;
for (let n of h) c.value = b, h = b(n), g.has(h) || e.add(h);
c.value = k + "\n" + JSON.stringify([...e.values()]);
++k;
return u(k).then(t)
}
return e
}
function u(h) {
return d(a + h, f).then(n => n.text())
}
f || (f = {});
a += "?per_page=100&page=";
let k = 1;
return u(k).then(t)
}
const A = z.bind(null, y),
B = z.bind(null, fetch);
function C(d) {
return A("https://api.github.com/user/blocks", q, new Set, d, new Set(whitelist), {
headers: {
Authorization: "token " + GH_PERSONAL_TOKEN
}
})
}
function D(d, a, b, e, c) {
e.value = 0;
e.max = c.size;
c = [...c.values()];
b.value = `collected (${c.length}): ${JSON.stringify(c)}`;
x(c, g => y(`${d}/${g}`, {
method: a,
headers: {
Authorization: "token " + GH_PERSONAL_TOKEN
},
credentials: "include"
}).then(f => f.text()).then(f => {
e.value++;
b.value = "(un) blocked " + g + "\n" + f;
return v()
}, f => {
b.value = f
})).then(() => {
b.value = "AORABTU!"
})
}
let E = D.bind(null, "https://api.github.com/user/blocks", "PUT"),
F = D.bind(null, "https://api.github.com/user/blocks", "DELETE");
function G(d, a) {
let b = new Set,
e = [];
for (let [c, g] of r) e.push(B(c, g, b, d, a));
return Promise.all(e).then(() => b)
}
function H() {
let d = document.createElement("progress");
d.style.width = "100%";
d.style.width = "100%";
let a = document.createElement("div"),
b = document.createElement("textarea");
b.style.height = b.style.width = "100%";
b.style.background = "transparent";
b.style.color = "green";
b.style.fontFamily = "monotype";
b.readOnly = !0;
a.style.background = "black";
a.style.top = "10%";
a.style.left = "10%";
a.style.width = "80%";
a.style.height = "90%";
a.style.position = "fixed";
a.appendChild(d);
a.appendChild(b);
document.body.appendChild(a);
return [b,
d
]
}
let d = document.querySelector("a[data-hotkey=t]"),
a = document.createElement("div"),
b = document.createElement("div");
b.className = a.className = d.className;
a.textContent = "4TGJ";
b.textContent = "unban";
a.style.background = "red";
b.style.background = "navy";
b.style.color = a.style.color = "white";
b.style.textDecoration = a.style.textDecoration = "bold";
b.style.fontFamily = a.style.fontFamily = "monotype";
d.parentElement.insertBefore(a, d);
a.parentElement.insertBefore(b, a);
a.addEventListener("click", function(e) {
e.target.style.display = "none";
let [c, g] = H();
if(!GH_PERSONAL_TOKEN){
c.value = "Get a personal token and edit it into GH_PERSONAL_TOKEN";
return;
}
C(c).then(f => {
c.value = `Already blocked (${f.size}):` + JSON.stringify([...f]);
G(c, f).then(E.bind(null, c, g))
})
}, !0);
b.addEventListener("click", function(e) {
e.target.style.display = "none";
let [c, g] = H();
if(!GH_PERSONAL_TOKEN){
c.value = "Get a personal token and edit it into GH_PERSONAL_TOKEN";
return;
}
C(c).then(f => {
c.value = `Blocked (${f.size}):` + JSON.stringify([...f]);
F(c, g, f)
})
}, !0)