]> git.aero2k.de Git - dfde/quickmods.git/blob - quickmod.user.js
d5c53e481f2cef76fc4b6b691b85597662904223
[dfde/quickmods.git] / quickmod.user.js
1 // ==UserScript==
2 // @name          debianforum.de-quickmod-additions
3 // @namespace     org.free.for.all
4 // @include       https://debianforum.de/forum/viewtopic.php*
5 // @match         https://debianforum.de/forum/viewtopic.php*
6 // @author        Thorsten Sperber
7 // @author        JTH
8 // @version       1.2
9 // ==/UserScript==
10
11 const ARCHIVFORUMID = 35;
12 const boardurl = "/forum/";
13
14 let mod_user_id;
15
16 function ellipsify(str, maxlen) {
17         const ell = str.length > maxlen ? " […]" : "";
18     return str.substring(0, maxlen - ell.length) + ell;
19 }
20
21 function get_thread_id() {
22     return new URL(document.head.querySelector("link[rel=canonical]").href).searchParams.get("t");
23 }
24
25 function get_forum_id() {
26     return new URLSearchParams(document.querySelector('a[href*="f="]').search).get("f");
27 }
28
29 function redirect_to_new_topic(redirDoc) {
30     const links = redirDoc.querySelectorAll("#message a");
31     window.location = links[links.length-1].href;
32 }
33
34 function remove_post_handler(event) {
35     const post = event.currentTarget.closest('.post');
36     const post_id = post.id.slice(1);
37     const username = post.querySelector(".author .username,.author .username-coloured").text;
38     const thread_title = document.querySelector('.topic-title a').text;
39     const content = ellipsify(post.querySelector(".content").innerText, 250);
40     if (localStorage.getItem("deleteWithoutConfirmation") ?? window.confirm(`Folgenden Beitrag von „${username}“ im Thema „${ellipsify(thread_title, 100)}“ wirklich als Spam archivieren?\n\n„${content}“`)) {
41         send_mcp_request_archival(post_id, get_thread_id(), thread_title);
42     }
43 }
44
45 async function send_mcp_request_confirmation(post_id, confirmDoc) {
46     const form = confirmDoc.querySelector("form#confirm");
47     const data = new FormData(form);
48     const confirmInput = form.elements["confirm"];
49     data.set(confirmInput.name, confirmInput.value); // Press "Yes"
50     /* Have to use explicit getAttribute() below since there is an input with
51      * name="action" which would be accessed with `form.action` :-/
52      */
53     const resp = await fetch(form.getAttribute("action"),
54         { body: new URLSearchParams(data), method: "POST" });
55     if (resp.ok) {
56         if (localStorage.getItem("redirectToNewTopic") ?? true) {
57             const respTxt = await resp.text();
58             const respDoc = new DOMParser().parseFromString(respTxt, "text/html");
59             if (!respDoc.querySelector("parsererror")) {
60                 redirect_to_new_topic(respDoc);
61             }
62         } else {
63             // hide the freshly archived post
64             document.querySelector('.post#p' + post_id).style.display = "none";
65         }
66     }
67 }
68
69 async function send_mcp_request_archival(post_id, thread_id, thread_title) {
70     const url = boardurl + "mcp.php?f=" + get_forum_id() + "&t=" + thread_id + "&i=main&mode=topic_view&action=split&start=0";
71     const data = new URLSearchParams({
72         "action": "split_all",
73         "mcp_topic_submit": "Absenden",
74         "post_id_list[]": post_id,
75         "posts_per_page": "15",
76         "st": "0",
77         "sk": "t",
78         "sd": "a",
79         "icon": "1",
80         "subject": thread_title.toLowerCase().includes("spam") ? thread_title : "[spam] " + thread_title,
81         "to_forum_id": ARCHIVFORUMID,
82         "to_topic_id": "0",
83         "st_old": "0",
84         "post_ids[0]": post_id
85     });
86     const resp = await fetch(url, { body: data, method: "POST" });
87     if (resp.ok) {
88         const respTxt = await resp.text();
89         const respDoc = new DOMParser().parseFromString(respTxt, "text/html");
90         if (!respDoc.querySelector("parsererror")) {
91             send_mcp_request_confirmation(post_id, respDoc);
92         }
93     }
94 }
95
96 function add_buttons() {
97     const postbuttons = document.querySelectorAll(".postbody .post-buttons");
98     postbuttons.forEach(function(el) {
99         // well...
100         el.style.maxWidth = '41%';
101
102         const del_post_btn_outer = document.createElement('li');
103         const del_post_btn = document.createElement('a');
104         del_post_btn.className = 'button button-icon-only';
105         del_post_btn.innerHTML = '<i class="icon fa-fire-extinguisher fa-fw" aria-hidden="true"></i><span class="sr-only">Abfall</span>';
106
107         del_post_btn.addEventListener("click", remove_post_handler);
108
109         del_post_btn_outer.append(del_post_btn);
110         el.insertBefore(del_post_btn_outer, el.querySelector('.dropdown-container'));
111     });
112 }
113
114 function find_mod_user_id() {
115     const profile_link = document.querySelector("#username_logged_in a[title^='Profil']");
116     return Number.parseInt(new URLSearchParams(profile_link?.search).get("u"));
117 }
118
119 mod_user_id ??= find_mod_user_id();
120 if (Number.isInteger(mod_user_id)) {
121     add_buttons();
122 } else {
123     console.error("mod_user_id unset and could not find user ID");
124 }