User:Bot doubleredirects/Gadget-DoubleRedirectFixer.js: Difference between revisions

No edit summary
No edit summary
 
(4 intermediate revisions by the same user not shown)
Line 1: Line 1:
  const BOT_USERS = [6163];
// Credit: HaMiklolah (Improved version - allows execution for any logged-in user)
  const api = new mw.Api();
(() => {
    const api = new mw.Api();


  const getRedirectContent = async (title) => {
    /**
    return api.get({
    * Gets the content of the redirect page.
      prop: "revisions",
    * @param {string} title - The page title.
      titles: title,
    * @returns {Promise<string|null>} The page content or null if an error occurred.
      rvprop: "content",
    */
      rvslots: "*",
    const getRedirectContent = async (title) => {
      formatversion: "2",
        try {
    });
            const response = await api.get({
  };
                prop: "revisions",
                titles: title,
                rvprop: "content",
                rvslots: "*",
                formatversion: "2",
            });
            const page = response.query?.pages?.[0];
            return page?.revisions?.[0]?.slots?.main?.content ?? null;
        } catch (error) {
            console.error("Error getting redirect content for " + title + ":", error);
            return null;
        }
    };


  const getRedirectTarget = async (title) => {
    /**
    const { query } = await api.get({
    * Gets the final redirect target.
      titles: title,
    * @param {string} title - The title of the redirect page.
      redirects: true,
    * @returns {Promise<string|null>} The redirect target or null if not found.
    });
    */
    const getRedirectTarget = async (title) => {
        try {
            const { query } = await api.get({
                titles: title,
                redirects: true, // Allows MediaWiki to follow redirects
            });


    if (query?.pages) {
            if (query?.pages) {
      const page = Object.values(query.pages).find((page) => !page.missing);
                // Find the page that is not missing (the final target)
      return page?.title ?? null;
                const page = Object.values(query.pages).find((p) => !p.missing);
    }
                return page?.title ?? null;
    return null;
            }
  };
            return null;
        } catch (error) {
            console.error("Error getting redirect target for " + title + ":", error);
            return null;
        }
    };


  const extractAnchorFromContent = (content) => {
    /**
    const match = content.match(/\[\[.*?(?:#(.+?))?\]\]/);
    * Extracts the anchor from redirect content (e.g., [[Target_Page#anchor]]).
    return match?.[1] ? `#${match[1]}` : "";
    * @param {string} content - The content of the redirect page.
  };
    * @returns {string} The anchor with '#' if it exists, otherwise an empty string.
    */
    const extractAnchorFromContent = (content) => {
        // Regex adjusted to look for '#REDIRECT'
        const match = content.match(/#REDIRECT\s*\[\[[^\]]+?(?:#(.+?))?\]\]/i); // 'i' for case-insensitive
        return match?.[1] ? "#" + match[1] : "";
    };


  const getNamespacePrefix = async (title) => {
    /**
    const { query } = await api.get({
    * Gets the namespace prefix of a page (e.g., "MediaWiki:", "File:").
      titles: title,
    * @param {string} title - The page title.
      prop: "info",
    * @returns {Promise<string>} The namespace prefix or an empty string.
    });
    */
    const getNamespacePrefix = async (title) => {
        try {
            const { query } = await api.get({
                titles: title,
                prop: "info",
            });


    if (query?.pages) {
            if (query?.pages) {
      const page = Object.values(query.pages)[0];
                const page = Object.values(query.pages)[0];
      if (page.ns) {
                if (page.ns !== undefined) {
        const namespacePrefixes = {
                    // Standard MediaWiki namespaces. Adjust '4' if Chabadpedia uses a different name for NS 4.
          4: "המכלול:",
                    const namespacePrefixes = {
          6: "קובץ:",
                        0: "", // Main/Article namespace
          10: "תבנית:",
                        1: "Talk:",
          12: "עזרה:",
                        2: "User:",
        };
                        3: "User talk:",
        return namespacePrefixes[page.ns] ?? "";
                        4: "Chabadpedia:", // Common for English wikis, could also be "Project:" or "Wikipedia:"
      }
                        5: "Chabadpedia talk:",
    }
                        6: "File:",
    return "";
                        7: "File talk:",
  };
                        8: "MediaWiki:",
                        9: "MediaWiki talk:",
                        10: "Template:",
                        11: "Template talk:",
                        12: "Help:",
                        13: "Help talk:",
                        14: "Category:",
                        15: "Category talk:",
                        // Add more custom namespaces here if applicable, using their numerical IDs.
                    };
                    return namespacePrefixes[page.ns] ?? "";
                }
            }
            return "";
        } catch (error) {
            console.error("Error getting namespace prefix for " + title + ":", error);
            return "";
        }
    };


  const createRedirect = async (title, target) => {
    /**
    try {
    * Creates/fixes a redirect.
      await api.postWithEditToken({
    * @param {string} title - The title of the page to become a redirect.
        action: "edit",
    * @param {string} target - The redirect target.
        format: "json",
    */
        tags: "doubleredirect-bot",
    const createRedirect = async (title, target) => {
        bot: true,
        try {
        title: title,
            await api.postWithEditToken({
        text: `#הפניה [[${target}]]`,
                action: "edit",
      });
                format: "json",
      mw.notify(`\nstatus:${title} succes`);
                title: title,
    } catch (error) {
                // Changed from #הפניה to #REDIRECT
      console.error(error);
                text: "#REDIRECT [[" + target + "]]",
    }
                // Localized summary
  };
                summary: "Bot: Fixing double redirect to [[" + target + "]]",
            });
            // Localized success notification
            mw.notify(title + ": Redirect successfully fixed to " + target, { type: 'success', title: 'Success' });
        } catch (error) {
            console.error("Error creating redirect for " + title + " to " + target + ":", error);
            // Localized error notifications
            if (error.code === 'badtags') {
                mw.notify(title + ": Error: Permission denied to use edit tags. Please contact a system administrator.", { type: 'error', title: 'Permission Error' });
            } else {
                mw.notify(title + ": Failed to fix redirect. See console for details.", { type: 'error', title: 'Error' });
            }
        }
    };


  const processRedirect = async (title) => {
    /**
    try {
    * Processes a single double redirect: finds the final target and fixes it.
      const contentData = await getRedirectContent(title);
    * @param {string} title - The page title of the double redirect.
      const content =
    */
        contentData.query.pages[0].revisions[0].slots.main.content;
    const processRedirect = async (title) => {
      const anchor = extractAnchorFromContent(content);
        try {
            const content = await getRedirectContent(title);
            if (content === null) {
                mw.notify(title + ": Could not retrieve redirect page content.", { type: 'warn' });
                return;
            }


      const finalTarget = await getRedirectTarget(title);
            const anchor = extractAnchorFromContent(content);
      if (!finalTarget) return;
            const finalTarget = await getRedirectTarget(title);


      const namespace = await getNamespacePrefix(finalTarget);
            if (!finalTarget) {
      const fullTarget = namespace + finalTarget + anchor;
                mw.notify(title + ": No final redirect target found.", { type: 'warn' });
                return;
            }


      if (title === finalTarget) {
            const namespace = await getNamespacePrefix(finalTarget);
        alert("הפניה מעגלית");
            const fullTarget = namespace + finalTarget + anchor;
        return;
      }


      console.log("Creating redirect to:", fullTarget);
            // Check to prevent circular redirects or unnecessary fixes
      await createRedirect(title, fullTarget);
            if (title.replace(/_/g, " ") === finalTarget.replace(/_/g, " ") && !anchor) {
    } catch (error) {
                mw.notify(title + ": Redirect is already valid. No fix needed.", { type: 'info' });
      console.error("Error processing redirect:", error);
                return;
    }
            }
  };


  const init = async () => {
            if (title.replace(/_/g, " ") === fullTarget.replace(/_/g, " ")) {
    const userGroups = mw.config.get("wgUserGroups");
                mw.notify(title + ": Circular or valid redirect. No fix needed.", { type: 'info' });
    const userId = mw.config.get("wgUserId");
                return;
    const pageName = mw.config.get("wgPageName");
            }


    if (!userGroups.includes("bot") && !BOT_USERS.includes(userId)) return;
            console.log("Creating new redirect: " + title + " --> " + fullTarget);
    if (pageName !== "מיוחד:הפניות_כפולות") return;
            await createRedirect(title, fullTarget);


    const num = prompt("? כמה הפניות כפולות להציג", 0);
        } catch (error) {
    if (!num) return;
            console.error("Error processing double redirect for " + title + ":", error);
            mw.notify(title + ": An error occurred while processing the redirect. See console for details.", { type: 'error', title: 'Error' });
        }
    };


     try {
     /**
      const { query } = await api.get({
    * The main function that runs the script.
        list: "querypage",
    */
        qppage: "DoubleRedirects",
    const init = async () => {
        qplimit: num,
        const pageName = mw.config.get("wgPageName");
      });


      const redirects = query.querypage.results;
         // Ensure the script runs only on the Special:DoubleRedirects page
      for (const redirect of redirects) {
         if (pageName !== "Special:DoubleRedirects") {
         const title = redirect.title.replace(/_/g, " ");
            console.log("This script only runs on Special:DoubleRedirects.");
         await processRedirect(title);
            return;
      }
        }
    } catch (error) {
      console.error("Error fetching redirects:", error);
    }
  };


  $(init);
        const numInput = prompt("How many double redirects to display and fix? (Recommended to start with a small number, e.g., 10)", "0");
        const num = parseInt(numInput, 10);
 
        if (isNaN(num) || num <= 0) {
            mw.notify("Invalid input. Please enter a positive integer.", { type: 'error' });
            return;
        }
 
        try {
            mw.notify("Starting check for " + num + " double redirects...", { type: 'info' });
 
            // Get the list of double redirects via API
            const { query } = await api.get({
                list: "querypage",
                qppage: "DoubleRedirects",
                qplimit: num,
            });
 
            const redirects = query.querypage.results;
            if (redirects.length === 0) {
                mw.notify("No double redirects found to fix.", { type: 'info' });
                return;
            }
 
            // Loop through each redirect and fix it
            for (const redirect of redirects) {
                const title = redirect.title.replace(/_/g, " ");
                await processRedirect(title);
            }
            mw.notify("Finished processing double redirects.", { type: 'success', title: 'Finished' });
 
        } catch (error) {
            console.error("Error fetching double redirects:", error);
            mw.notify("An error occurred while fetching the list of double redirects.", { type: 'error', title: 'General Error' });
        }
    };
 
    // Run the script when the page is loaded
    $(init);
})();
})();