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

No edit summary
No edit summary
 
(One intermediate revision by the same user not shown)
Line 1: Line 1:
// קרדיט: המכלול (גרסה משופרת - מאפשרת הרצה לכל משתמש מחובר)
// Credit: HaMiklolah (Improved version - allows execution for any logged-in user)
(() => {
(() => {
     const api = new mw.Api();
     const api = new mw.Api();


     /**
     /**
     * מקבל את תוכן דף ההפניה.
     * Gets the content of the redirect page.
     * @param {string} title - שם הדף.
     * @param {string} title - The page title.
     * @returns {Promise<string|null>} תוכן הדף או null אם הייתה שגיאה.
     * @returns {Promise<string|null>} The page content or null if an error occurred.
     */
     */
     const getRedirectContent = async (title) => {
     const getRedirectContent = async (title) => {
Line 20: Line 20:
             return page?.revisions?.[0]?.slots?.main?.content ?? null;
             return page?.revisions?.[0]?.slots?.main?.content ?? null;
         } catch (error) {
         } catch (error) {
             console.error("שגיאה בקבלת תוכן הפניה עבור " + title + ":", error);
             console.error("Error getting redirect content for " + title + ":", error);
             return null;
             return null;
         }
         }
Line 26: Line 26:


     /**
     /**
     * מקבל את יעד ההפניה הסופי.
     * Gets the final redirect target.
     * @param {string} title - שם דף ההפניה.
     * @param {string} title - The title of the redirect page.
     * @returns {Promise<string|null>} יעד ההפניה או null אם לא נמצא.
     * @returns {Promise<string|null>} The redirect target or null if not found.
     */
     */
     const getRedirectTarget = async (title) => {
     const getRedirectTarget = async (title) => {
Line 34: Line 34:
             const { query } = await api.get({
             const { query } = await api.get({
                 titles: title,
                 titles: title,
                 redirects: true, // מאפשר למדיה-וויקי לעקוב אחר הפניות
                 redirects: true, // Allows MediaWiki to follow redirects
             });
             });


             if (query?.pages) {
             if (query?.pages) {
                 // מצא את הדף שאינו חסר (היעד הסופי)
                 // Find the page that is not missing (the final target)
                 const page = Object.values(query.pages).find((p) => !p.missing);
                 const page = Object.values(query.pages).find((p) => !p.missing);
                 return page?.title ?? null;
                 return page?.title ?? null;
Line 44: Line 44:
             return null;
             return null;
         } catch (error) {
         } catch (error) {
             console.error("שגיאה בקבלת יעד ההפניה עבור " + title + ":", error);
             console.error("Error getting redirect target for " + title + ":", error);
             return null;
             return null;
         }
         }
Line 50: Line 50:


     /**
     /**
     * מחלץ את העוגן (anchor) מתוך תוכן הפניה (לדוגמה: [[דף_יעד#עוגן]]).
     * Extracts the anchor from redirect content (e.g., [[Target_Page#anchor]]).
     * @param {string} content - תוכן דף ההפניה.
     * @param {string} content - The content of the redirect page.
     * @returns {string} העוגן עם '#' אם קיים, אחרת מחרוזת ריקה.
     * @returns {string} The anchor with '#' if it exists, otherwise an empty string.
     */
     */
     const extractAnchorFromContent = (content) => {
     const extractAnchorFromContent = (content) => {
         const match = content.match(/#הפניה\s*\[\[[^\]]+?(?:#(.+?))?\]\]/);
        // Regex adjusted to look for '#REDIRECT'
         const match = content.match(/#REDIRECT\s*\[\[[^\]]+?(?:#(.+?))?\]\]/i); // 'i' for case-insensitive
         return match?.[1] ? "#" + match[1] : "";
         return match?.[1] ? "#" + match[1] : "";
     };
     };


     /**
     /**
     * מקבל את קידומת מרחב השם של דף (לדוגמה: "מדיה ויקי:", "קובץ:").
     * Gets the namespace prefix of a page (e.g., "MediaWiki:", "File:").
     * @param {string} title - שם הדף.
     * @param {string} title - The page title.
     * @returns {Promise<string>} קידומת מרחב השם או מחרוזת ריקה.
     * @returns {Promise<string>} The namespace prefix or an empty string.
     */
     */
     const getNamespacePrefix = async (title) => {
     const getNamespacePrefix = async (title) => {
Line 74: Line 75:
                 const page = Object.values(query.pages)[0];
                 const page = Object.values(query.pages)[0];
                 if (page.ns !== undefined) {
                 if (page.ns !== undefined) {
                     // יש להוסיף כאן מרחבי שמות נוספים במידת הצורך
                     // Standard MediaWiki namespaces. Adjust '4' if Chabadpedia uses a different name for NS 4.
                     const namespacePrefixes = {
                     const namespacePrefixes = {
                         4: "chabadpedia:",   // Namespace 4
                        0: "", // Main/Article namespace
                         6: "File:",       // Namespace 6
                        1: "Talk:",
                         10: "Template:",     // Namespace 10
                        2: "User:",
                         12: "Help:",     // Namespace 12
                        3: "User talk:",
                         // ... ניתן להוסיף עוד מרחבי שמות לפי המספרים שלהם בוויקי
                         4: "Chabadpedia:", // Common for English wikis, could also be "Project:" or "Wikipedia:"
                        5: "Chabadpedia talk:",
                         6: "File:",
                        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 namespacePrefixes[page.ns] ?? "";
Line 87: Line 100:
             return "";
             return "";
         } catch (error) {
         } catch (error) {
             console.error("שגיאה בקבלת קידומת מרחב שם עבור " + title + ":", error);
             console.error("Error getting namespace prefix for " + title + ":", error);
             return "";
             return "";
         }
         }
Line 93: Line 106:


     /**
     /**
     * יוצר/מתקן הפניה.
     * Creates/fixes a redirect.
     * @param {string} title - שם הדף שיהפוך להפניה.
     * @param {string} title - The title of the page to become a redirect.
     * @param {string} target - יעד ההפניה.
     * @param {string} target - The redirect target.
     */
     */
     const createRedirect = async (title, target) => {
     const createRedirect = async (title, target) => {
Line 102: Line 115:
                 action: "edit",
                 action: "edit",
                 format: "json",
                 format: "json",
                // **השורות עם "tags" הוסרו לחלוטין כאן.**
                 title: title,
                 title: title,
                 text: "#הפניה [[" + target + "]]",
                // Changed from #הפניה to #REDIRECT
                 summary: "בוט: מתקן הפניה כפולה ל- [[" + target + "]]",
                 text: "#REDIRECT [[" + target + "]]",
                // Localized summary
                 summary: "Bot: Fixing double redirect to [[" + target + "]]",
             });
             });
             mw.notify(title + ": ההפניה תוקנה בהצלחה ל- " + target, { type: 'success', title: 'הצלחה' });
            // Localized success notification
             mw.notify(title + ": Redirect successfully fixed to " + target, { type: 'success', title: 'Success' });
         } catch (error) {
         } catch (error) {
             console.error("שגיאה ביצירת הפניה עבור " + title + " ל- " + target + ":", error);
             console.error("Error creating redirect for " + title + " to " + target + ":", error);
             // בדיקה ספציפית לשגיאת badtags
             // Localized error notifications
             if (error.code === 'badtags') {
             if (error.code === 'badtags') {
                mw.notify(title + ": שגיאה: אין הרשאה להשתמש בתגיות עריכה. אנא פנה למנהל המערכת.", { type: 'error', title: 'שגיאת הרשאה' });
                mw.notify(title + ": Error: Permission denied to use edit tags. Please contact a system administrator.", { type: 'error', title: 'Permission Error' });
             } else {
             } else {
                mw.notify(title + ": נכשל תיקון ההפניה. פרטים בקונסול.", { type: 'error', title: 'שגיאה' });
                mw.notify(title + ": Failed to fix redirect. See console for details.", { type: 'error', title: 'Error' });
             }
             }
         }
         }
Line 120: Line 135:


     /**
     /**
     * מעבד הפניה כפולה יחידה: מוצא את היעד הסופי ומתקן אותה.
     * Processes a single double redirect: finds the final target and fixes it.
     * @param {string} title - שם הדף של ההפניה הכפולה.
     * @param {string} title - The page title of the double redirect.
     */
     */
     const processRedirect = async (title) => {
     const processRedirect = async (title) => {
Line 127: Line 142:
             const content = await getRedirectContent(title);
             const content = await getRedirectContent(title);
             if (content === null) {
             if (content === null) {
                 mw.notify(title + ": לא ניתן לאחזר תוכן דף ההפניה.", { type: 'warn' });
                 mw.notify(title + ": Could not retrieve redirect page content.", { type: 'warn' });
                 return;
                 return;
             }
             }
Line 135: Line 150:


             if (!finalTarget) {
             if (!finalTarget) {
                 mw.notify(title + ": לא נמצא יעד הפניה סופי.", { type: 'warn' });
                 mw.notify(title + ": No final redirect target found.", { type: 'warn' });
                 return;
                 return;
             }
             }
Line 142: Line 157:
             const fullTarget = namespace + finalTarget + anchor;
             const fullTarget = namespace + finalTarget + anchor;


             // בדיקה למניעת הפניות מעגליות או תיקונים מיותרים
             // Check to prevent circular redirects or unnecessary fixes
             if (title.replace(/_/g, " ") === finalTarget.replace(/_/g, " ") && !anchor) {
             if (title.replace(/_/g, " ") === finalTarget.replace(/_/g, " ") && !anchor) {
                 mw.notify(title + ": ההפניה כבר תקינה. אין צורך בתיקון.", { type: 'info' });
                 mw.notify(title + ": Redirect is already valid. No fix needed.", { type: 'info' });
                 return;
                 return;
             }
             }


             if (title.replace(/_/g, " ") === fullTarget.replace(/_/g, " ")) {
             if (title.replace(/_/g, " ") === fullTarget.replace(/_/g, " ")) {
                 mw.notify(title + ": הפניה מעגלית או תקינה. אין צורך בתיקון.", { type: 'info' });
                 mw.notify(title + ": Circular or valid redirect. No fix needed.", { type: 'info' });
                 return;
                 return;
             }
             }


             console.log("יוצר הפניה חדשה: " + title + " --> " + fullTarget);
             console.log("Creating new redirect: " + title + " --> " + fullTarget);
             await createRedirect(title, fullTarget);
             await createRedirect(title, fullTarget);


         } catch (error) {
         } catch (error) {
             console.error("שגיאה בעיבוד הפניה כפולה עבור " + title + ":", error);
             console.error("Error processing double redirect for " + title + ":", error);
             mw.notify(title + ": אירעה שגיאה בעת עיבוד ההפניה. פרטים בקונסול.", { type: 'error', title: 'שגיאה' });
             mw.notify(title + ": An error occurred while processing the redirect. See console for details.", { type: 'error', title: 'Error' });
         }
         }
     };
     };


     /**
     /**
     * הפונקציה הראשית שמפעילה את הסקריפט.
     * The main function that runs the script.
     */
     */
     const init = async () => {
     const init = async () => {
         const pageName = mw.config.get("wgPageName");
         const pageName = mw.config.get("wgPageName");


         // ודא שהסקריפט רץ רק בדף ההפניות הכפולות
         // Ensure the script runs only on the Special:DoubleRedirects page
         if (pageName !== "Special:DoubleRedirects") {
         if (pageName !== "Special:DoubleRedirects") {
             console.log("הסקריפט פועל רק בדף מיוחד:הפניות_כפולות.");
             console.log("This script only runs on Special:DoubleRedirects.");
             return;
             return;
         }
         }


         const numInput = prompt("כמה הפניות כפולות להציג ולתקן? (מומלץ להתחיל עם מספר קטן, לדוגמה: 10)", "0");
         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);
         const num = parseInt(numInput, 10);


         if (isNaN(num) || num <= 0) {
         if (isNaN(num) || num <= 0) {
             mw.notify("קלט לא חוקי. אנא הזן מספר שלם חיובי.", { type: 'error' });
             mw.notify("Invalid input. Please enter a positive integer.", { type: 'error' });
             return;
             return;
         }
         }


         try {
         try {
             mw.notify("מתחיל בדיקת " + num + " הפניות כפולות...", { type: 'info' });
             mw.notify("Starting check for " + num + " double redirects...", { type: 'info' });


             // קבלת רשימת ההפניות הכפולות באמצעות API
             // Get the list of double redirects via API
             const { query } = await api.get({
             const { query } = await api.get({
                 list: "querypage",
                 list: "querypage",
Line 194: Line 209:
             const redirects = query.querypage.results;
             const redirects = query.querypage.results;
             if (redirects.length === 0) {
             if (redirects.length === 0) {
                 mw.notify("לא נמצאו הפניות כפולות לתיקון.", { type: 'info' });
                 mw.notify("No double redirects found to fix.", { type: 'info' });
                 return;
                 return;
             }
             }


             // לולאה על כל הפניה ותיקונה
             // Loop through each redirect and fix it
             for (const redirect of redirects) {
             for (const redirect of redirects) {
                 const title = redirect.title.replace(/_/g, " ");
                 const title = redirect.title.replace(/_/g, " ");
                 await processRedirect(title);
                 await processRedirect(title);
             }
             }
             mw.notify("סיום עיבוד ההפניות הכפולות.", { type: 'success', title: 'סיום' });
             mw.notify("Finished processing double redirects.", { type: 'success', title: 'Finished' });


         } catch (error) {
         } catch (error) {
             console.error("שגיאה באחזור הפניות כפולות:", error);
             console.error("Error fetching double redirects:", error);
             mw.notify("אירעה שגיאה באחזור רשימת ההפניות הכפולות.", { type: 'error', title: 'שגיאה כללית' });
             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);
     $(init);
})();
})();