User:GlaMainBot/gallery.js
Jump to navigation
Jump to search
Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: press Ctrl-F5, Mozilla: hold down Shift while clicking Reload (or press Ctrl-Shift-R), Opera/Konqueror: press F5, Safari: hold down Shift + Alt while clicking Reload, Chrome: hold down Shift while clicking Reload.
Documentation for this user script can be added at User:GlaMainBot/gallery. |
(function ($, mw) {
"use strict";
mw.loader.using(["mediawiki.util", "mediawiki.api"]).then(function () {
const api = new mw.Api();
console.log("GlaMainBot gallery.js loaded");
const nameToFileName = (name) => {
name = name.replace(/ /g, "_");
name = name
.split(".")
.map((x, i, arr) => (i === arr.length - 1 ? x.toLowerCase() : x))
.join(".");
return name;
};
const fileNameToName = (name, names) => {
return names.find((x) => nameToFileName(x) === name);
};
const glamaingallery = document.querySelectorAll(".glamaingallery");
const bulkUpload = (links) => {
if (document.getElementById("bulkUploadContainer")) {
return;
}
const names = links.map((x) => {
const url = new URL(x.href);
return url.searchParams.get("wpDestFile");
});
const fileList = (files) => {
return files
.map(([name, color]) => {
color = color ? color : "black";
return `<a href="/wiki/File:${fileNameToName(
name,
names
)}" target="_blank" style="color: ${color}">${name}</a>`;
})
.join("<br>");
};
const fileNames = names.map(nameToFileName);
const container = document.createElement("div");
container.id = "bulkUploadContainer";
container.style.position = "fixed";
container.style.top = "50%";
container.style.left = "50%";
container.style.transform = "translate(-50%, -50%)";
container.style.zIndex = "1000";
container.style.backgroundColor = "white";
container.style.padding = "20px";
container.style.border = "1px solid black";
container.style.width = "100%";
container.style.maxWidth = "400px";
container.innerHTML = `
<form method="post">
<h2>Bulk upload</h2>
<input type="file" name="file" multiple style="display: block; margin-bottom: 10px">
<small style="display: block; margin-bottom: 10px; font-size: 10px;">Only files with the following names are allowed: <br><span></span></small>
<input type="text" name="comment" placeholder="Removed watermark" style="display: block; margin-bottom: 10px">
<input type="submit" value="Upload" disabled style="display: block; margin-bottom: 10px">
<pre style="font-size: 10px; display: block; white-space: pre-wrap; margin-bottom: 10px"></pre>
<button type="button" onclick="this.closest('div').remove()" style="display: block; margin-bottom: 10px">Close</button>
</form>
`;
document.body.appendChild(container);
const form = container.querySelector("form");
const input = form.querySelector("input[type=file]");
const commentInput = form.querySelector("input[name=comment]");
const small = form.querySelector("small");
const span = small.querySelector("span");
const submit = form.querySelector("input[type=submit]");
const pre = form.querySelector("pre");
pre.textContent =
"Note: If the file is not in the list, it will be ignored\n";
span.innerHTML = fileList(fileNames.map((x) => [x, ""]));
let files = [];
input.addEventListener("change", (e) => {
const allFiles = Array.from(e.target.files);
files = allFiles.filter((x) => fileNames.includes(x.name));
const notAllowedFiles = allFiles.filter(
(x) => !fileNames.includes(x.name)
);
span.innerHTML = fileList([
...fileNames.map((x) => [
x,
files.map((x) => x.name).includes(x) ? "green" : "",
]),
...notAllowedFiles.map((x) => [x.name, "red"]),
]);
submit.value = `Upload (${files.length}/${allFiles.length})`;
submit.disabled = files.length === 0;
pre.textContent += `Selected ${files.length} files\n`;
});
form.addEventListener("submit", (e) => {
e.preventDefault();
if (submit.disabled || files.length === 0) {
return;
}
input.disabled = true;
submit.disabled = true;
const comment = commentInput.value
? commentInput.value
: commentInput.placeholder;
pre.textContent += `Uploading ${files.length} files...\n`;
const fileColors = fileNames.map((x) => [x, ""]);
const setFileColor = (name, color) => {
fileColors[fileColors.findIndex((x) => x[0] === name)][1] = color;
span.innerHTML = fileList(fileColors);
};
span.innerHTML = fileList(fileColors);
const successes = [];
const upload = (i) => {
if (i >= files.length) {
pre.textContent += `Uploaded ${successes.length}/${files.length} files\n`;
for (const success of successes) {
window.open(success, "_blank");
}
return;
}
const file = files[i];
pre.textContent += `Uploading ${file.name} (${i + 1}/${files.length})...\n`;
const formData = new FormData();
formData.append("token", mw.user.tokens.get("csrfToken"));
formData.append("action", "upload");
formData.append("format", "json");
formData.append("file", file);
formData.append("filename", fileNameToName(file.name, names));
formData.append("comment", comment);
formData.append("ignorewarnings", 1);
fetch("/w/api.php", {
method: "POST",
body: formData,
})
.then((x) => x.json())
.then((response) => {
console.debug(`Upload response for ${file.name}`, response);
if (
response &&
response.upload &&
response.upload.result === "Success"
) {
pre.textContent += `Uploaded ${file.name} (${i + 1}/${files.length})\n`;
setFileColor(file.name, "green");
successes.push(response.upload.imageinfo.descriptionurl);
} else {
pre.textContent += `Failed to upload ${file.name} (${i + 1}/${files.length})\n`;
if (
response &&
response.upload &&
response.upload.warnings
) {
pre.textContent += `${file.name} warnings: ${result.upload.warnings.join(", ")}\n`;
}
setFileColor(file.name, "red");
}
upload(i + 1);
})
.catch((e) => {
console.error(e);
pre.textContent += `${file.name} error: ${e}\n`;
setFileColor(file.name, "red");
upload(i + 1);
});
};
upload(0);
});
input.click();
};
glamaingallery.forEach((glamaingallery) => {
const items = glamaingallery.querySelectorAll(
"li.gallerybox div.gallerytext"
);
items.forEach((item) => {
const links = item.querySelectorAll("a");
links.forEach((link) => {
const url = link.getAttribute("href");
if (url.includes("croptool") || url.includes("Special:Upload")) {
link.setAttribute("target", "_blank");
}
});
});
const bulkLinks = Array.from(
glamaingallery.querySelectorAll(".gallerytext .plainlinks a")
);
for (const link of bulkLinks) {
const bulkLink = link.cloneNode(true);
bulkLink.textContent = "+6";
link.after(bulkLink);
link.after(document.createTextNode(" "));
bulkLink.addEventListener("click", (e) => {
e.preventDefault();
const sameLinks = bulkLinks.filter(
(x) => x.textContent === link.textContent
);
const links = sameLinks.slice(
sameLinks.indexOf(link),
sameLinks.indexOf(link) + 7
);
if (link.href.includes("Special:Upload")) {
bulkUpload(links);
return;
}
links.forEach((el) => {
window.open(el.getAttribute("href") || "", "_blank");
});
});
}
});
});
})(jQuery, mw);