github-easy-mirror/script.user.js

253 lines
7.8 KiB
JavaScript
Raw Normal View History

2024-10-18 00:06:15 +02:00
// ==UserScript==
// @name incest mirror :)
// @description kiss your sister
2024-10-24 15:05:54 +02:00
// @version 1.0.1
2024-10-18 00:06:15 +02:00
2024-10-24 15:06:40 +02:00
// @include *://github.com/*
2024-10-18 00:06:15 +02:00
// @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>';
2024-10-24 14:59:38 +02:00
if (!GM) {
2024-10-18 00:06:15 +02:00
alert("This script requires GreaseMonkey!");
return;
}
2024-10-24 14:59:38 +02:00
var config = {}
2024-10-21 18:34:44 +02:00
2024-10-18 00:06:15 +02:00
async function api(url, data) {
return new Promise((resolve, reject) => {
GM.xmlHttpRequest({
method: "POST",
2024-10-24 14:59:38 +02:00
url: `${config.instance}/api/v1/${url}`,
2024-10-18 00:06:15 +02:00
data: JSON.stringify(data),
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
2024-10-24 14:59:38 +02:00
"Authorization": `token ${config.token}`,
2024-10-18 00:06:15 +02:00
},
onload: (response) => {
resolve(response);
}
});
});
}
2024-10-24 14:59:38 +02:00
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;
}
}
2024-10-18 00:06:15 +02:00
(async () => {
2024-10-24 14:59:38 +02:00
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;
}
2024-10-18 00:06:15 +02:00
function main() {
var container = document.querySelector(".pagehead-actions");
2024-10-24 14:59:38 +02:00
if (!container)
2024-10-18 00:06:15 +02:00
return;
var mirrorButton = container.querySelector("#mirror");
2024-10-24 14:59:38 +02:00
if (mirrorButton != null)
2024-10-18 00:06:15 +02:00
return;
mirrorButton = container.children[container.children.length - 1].cloneNode(true);
mirrorButton.id = "mirror";
var starCount = mirrorButton.querySelector("#repo-stars-counter-star");
2024-10-24 14:59:38 +02:00
if (starCount)
2024-10-18 00:06:15 +02:00
starCount.parentNode.removeChild(starCount);
var dropDown = mirrorButton.querySelector("details");
2024-10-24 14:59:38 +02:00
dropDown.querySelector("details-menu").removeAttribute("src");
2024-10-18 00:06:15 +02:00
2024-10-24 14:59:38 +02:00
var title = dropDown.querySelector(".SelectMenu-title");
title.textContent = "Mirror Settings";
2024-10-18 00:06:15 +02:00
2024-10-24 14:59:38 +02:00
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]
}
2024-10-18 00:06:15 +02:00
2024-10-24 14:59:38 +02:00
var list = dropDown.querySelector(".SelectMenu-list");
list.className += " flex-1 overflow-y-auto px-3 py-2 mb-0";
list.innerHTML = "";
2024-10-21 18:34:44 +02:00
2024-10-24 14:59:38 +02:00
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,
2024-10-21 18:34:44 +02:00
"repo_name": repo,
2024-10-18 00:06:15 +02:00
"mirror": true,
"repo_owner": "mirrors",
2024-10-24 14:59:38 +02:00
"description": "Mirror of " + address,
2024-10-18 00:06:15 +02:00
"private": false,
"issues": false,
2024-10-24 14:59:38 +02:00
"pull_requests": false,
...data
}
var res = await api("repos/migrate", _data);
2024-10-24 15:00:36 +02:00
try {
2024-10-24 15:05:54 +02:00
var resp = JSON.parse(res.responseText);
2024-10-24 15:00:36 +02:00
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) {
2024-10-24 15:05:54 +02:00
console.log(res);
alert(err);
2024-10-21 18:34:44 +02:00
}
2024-10-18 00:06:15 +02:00
};
2024-10-24 14:59:38 +02:00
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);
2024-10-18 00:06:15 +02:00
mirrorButton.innerHTML = "";
mirrorButton.appendChild(newButton);
2024-10-24 14:59:38 +02:00
mirrorButton.appendChild(dropDown);
2024-10-18 00:06:15 +02:00
container.prepend(mirrorButton);
}
setInterval(main, 1);
})();