255 lines
No EOL
7.9 KiB
JavaScript
255 lines
No EOL
7.9 KiB
JavaScript
// ==UserScript==
|
|
// @name incest mirror :)
|
|
// @description kiss your sister
|
|
// @version 1.0.0
|
|
|
|
// @include https://www.github.com/*
|
|
// @include http://www.github.com/*
|
|
// @include https://github.com/*
|
|
// @include http://github.com/*
|
|
|
|
// @grant GM.setValue
|
|
// @grant GM.getValue
|
|
// @grant GM.xmlHttpRequest
|
|
// ==/UserScript==
|
|
|
|
var mirrorIcon = '<path d="M1 2.5A2.5 2.5 0 0 1 3.5 0h8.75a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0V1.5h-8a1 1 0 0 0-1 1v6.708A2.5 2.5 0 0 1 3.5 9h3.25a.75.75 0 0 1 0 1.5H3.5a1 1 0 0 0 0 2h5.75a.75.75 0 0 1 0 1.5H3.5A2.5 2.5 0 0 1 1 11.5Zm13.23 7.79zl-1.224-1.224v6.184a.75.75 0 0 1-1.5 0V9.066L10.28 10.29a.75.75 0 0 1-1.06-1.061l2.505-2.504a.75.75 0 0 1 1.06 0L15.29 9.23a.75.75 0 0 1-.018 1.042.75.75 0 0 1-1.042.018"></path>';
|
|
|
|
if (!GM) {
|
|
alert("This script requires GreaseMonkey!");
|
|
return;
|
|
}
|
|
|
|
var config = {}
|
|
|
|
async function api(url, data) {
|
|
return new Promise((resolve, reject) => {
|
|
GM.xmlHttpRequest({
|
|
method: "POST",
|
|
url: `${config.instance}/api/v1/${url}`,
|
|
data: JSON.stringify(data),
|
|
headers: {
|
|
"Accept": "application/json",
|
|
"Content-Type": "application/json",
|
|
"Authorization": `token ${config.token}`,
|
|
},
|
|
onload: (response) => {
|
|
resolve(response);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function createFooterElement() {
|
|
// Create footer
|
|
const footer = document.createElement('footer');
|
|
footer.className = 'SelectMenu-footer px-2';
|
|
|
|
// Create button
|
|
const button = document.createElement('button');
|
|
button.type = 'button';
|
|
button.className = 'user-lists-menu-action btn-invisible btn btn-block text-left text-normal rounded-1 px-2';
|
|
|
|
// Create SVG
|
|
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
svg.setAttribute('aria-hidden', 'true');
|
|
svg.setAttribute('height', '16');
|
|
svg.setAttribute('viewBox', '0 0 16 16');
|
|
svg.setAttribute('version', '1.1');
|
|
svg.setAttribute('width', '16');
|
|
svg.setAttribute('data-view-component', 'true');
|
|
svg.setAttribute('class', 'octicon octicon-plus mr-1');
|
|
|
|
// Create path for SVG
|
|
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
|
path.setAttribute('d', 'M7.75 2a.75.75 0 0 1 .75.75V7h4.25a.75.75 0 0 1 0 1.5H8.5v4.25a.75.75 0 0 1-1.5 0V8.5H2.75a.75.75 0 0 1 0-1.5H7V2.75A.75.75 0 0 1 7.75 2Z');
|
|
|
|
// Create text node
|
|
const textNode = document.createTextNode('Mirror repository');
|
|
|
|
// Assemble the elements
|
|
svg.appendChild(path);
|
|
button.appendChild(svg);
|
|
button.appendChild(textNode);
|
|
footer.appendChild(button);
|
|
|
|
return footer;
|
|
}
|
|
|
|
function createCheckbox(labelText, value) {
|
|
const div = document.createElement('div');
|
|
div.className = 'form-checkbox mt-1 mb-0 p-1';
|
|
div.setAttribute('role', 'listitem');
|
|
|
|
const label = document.createElement('label');
|
|
label.className = 'd-flex';
|
|
|
|
const input = document.createElement('input');
|
|
input.type = 'checkbox';
|
|
input.checked = value;
|
|
input.className = 'mx-0 js-user-list-menu-item';
|
|
|
|
const outerSpan = document.createElement('span');
|
|
outerSpan.setAttribute('data-view-component', 'true');
|
|
outerSpan.className = 'Truncate ml-2 text-normal f5';
|
|
|
|
const innerSpan = document.createElement('span');
|
|
innerSpan.setAttribute('data-view-component', 'true');
|
|
innerSpan.className = 'Truncate-text';
|
|
innerSpan.textContent = labelText;
|
|
|
|
outerSpan.appendChild(innerSpan);
|
|
label.appendChild(input);
|
|
label.appendChild(outerSpan);
|
|
div.appendChild(label);
|
|
|
|
return div;
|
|
}
|
|
|
|
function createInput(placeholder, value) {
|
|
const input = document.createElement('input');
|
|
input.className = 'FormControl-input';
|
|
input.placeholder = placeholder ?? '';
|
|
input.value = value ?? '';
|
|
|
|
return input;
|
|
}
|
|
|
|
function createSettingElement(key, [label, value, editable]) {
|
|
if (typeof value === 'boolean') {
|
|
const checkbox = createCheckbox(label, value);
|
|
checkbox.querySelector('input').disabled = !editable;
|
|
checkbox.querySelector('input').name = key;
|
|
return checkbox;
|
|
} else {
|
|
const div = document.createElement('div');
|
|
div.className = "mx-0 mt-2";
|
|
|
|
const labelElement = document.createElement('label');
|
|
labelElement.textContent = label;
|
|
div.appendChild(labelElement);
|
|
|
|
const input = createInput(label, value);
|
|
input.disabled = !editable;
|
|
input.name = key;
|
|
div.appendChild(input);
|
|
|
|
return div;
|
|
}
|
|
}
|
|
|
|
(async () => {
|
|
config.instance = await GM.getValue("instance");
|
|
if (!config.instance) {
|
|
var input = prompt("Enter your Gitea/Forgejo instance (include protocol, no trailing slash)");
|
|
GM.setValue("instance", input);
|
|
config.instance = input;
|
|
}
|
|
|
|
config.token = await GM.getValue("token");
|
|
if (!config.token) {
|
|
var input = prompt(`Enter your git access token\nSee: ${config.instance}/user/settings/applications`);
|
|
GM.setValue("token", input);
|
|
config.token = input;
|
|
}
|
|
|
|
function main() {
|
|
var container = document.querySelector(".pagehead-actions");
|
|
if (!container)
|
|
return;
|
|
|
|
var mirrorButton = container.querySelector("#mirror");
|
|
if (mirrorButton != null)
|
|
return;
|
|
|
|
mirrorButton = container.children[container.children.length - 1].cloneNode(true);
|
|
mirrorButton.id = "mirror";
|
|
|
|
var starCount = mirrorButton.querySelector("#repo-stars-counter-star");
|
|
if (starCount)
|
|
starCount.parentNode.removeChild(starCount);
|
|
|
|
var dropDown = mirrorButton.querySelector("details");
|
|
dropDown.querySelector("details-menu").removeAttribute("src");
|
|
|
|
var title = dropDown.querySelector(".SelectMenu-title");
|
|
title.textContent = "Mirror Settings";
|
|
|
|
var data = {}
|
|
|
|
var address = document.querySelector("meta[name=go-import]").content.split(" ").slice(-1)[0];
|
|
var repo = address.split("/")[4].slice(0, -4);
|
|
|
|
var settings = {
|
|
"repo_owner": ["Owner", "mirrors", true],
|
|
"repo_name": ["Repository Name", repo, true],
|
|
"description": ["Description", "Mirror of " + address, true],
|
|
"mirror": ["Mirror", true, true],
|
|
"private": ["Private", false, true]
|
|
}
|
|
|
|
var list = dropDown.querySelector(".SelectMenu-list");
|
|
list.className += " flex-1 overflow-y-auto px-3 py-2 mb-0";
|
|
list.innerHTML = "";
|
|
|
|
Object.entries(settings).forEach(([key, value]) => {
|
|
const settingElement = list.appendChild(createSettingElement(key, value));
|
|
settingElement.querySelector("input").addEventListener("input", (ev) => {
|
|
var input = ev.target;
|
|
data[input.name] = input.type == "checkbox" ? input.checked : input.value;
|
|
});
|
|
});
|
|
|
|
var callback = async () => {
|
|
mirrorButton.querySelector("button").disabled = true;
|
|
footer.querySelector("button").disabled = true;
|
|
|
|
var _data = {
|
|
"clone_addr": address,
|
|
"repo_name": repo,
|
|
"mirror": true,
|
|
"repo_owner": "mirrors",
|
|
"description": "Mirror of " + address,
|
|
"private": false,
|
|
"issues": false,
|
|
"pull_requests": false,
|
|
...data
|
|
}
|
|
|
|
var res = await api("repos/migrate", _data);
|
|
try {
|
|
var resp = JSON.parse(res);
|
|
|
|
if (resp.message) {
|
|
if (resp.message == "The repository with the same name already exists.") {
|
|
window.open(`${config.instance}/mirrors/${repo}`);
|
|
} else alert(resp.message);
|
|
} else {
|
|
window.open(resp.html_url);
|
|
}
|
|
} catch (err) {
|
|
alert(res);
|
|
}
|
|
};
|
|
|
|
const footer = createFooterElement(repo);
|
|
list.parentNode.appendChild(footer);
|
|
list.parentNode.querySelector("footer button").onclick = callback;
|
|
|
|
var btn = mirrorButton.querySelector(".unstarred button");
|
|
|
|
var newButton = btn.cloneNode(true);
|
|
newButton.querySelector("svg").innerHTML = mirrorIcon;
|
|
newButton.querySelector("span").innerText = "Mirror";
|
|
newButton.onclick = footer.querySelector("button").onclick;
|
|
|
|
btn.parentNode.removeChild(btn);
|
|
mirrorButton.innerHTML = "";
|
|
mirrorButton.appendChild(newButton);
|
|
mirrorButton.appendChild(dropDown);
|
|
|
|
container.prepend(mirrorButton);
|
|
}
|
|
|
|
setInterval(main, 1);
|
|
})(); |