לדלג לתוכן

משתמש:מוטי/ייבוא.js

מתוך המכלול, האנציקלופדיה היהודית

לתשומת ליבך: לאחר הפרסום, ייתכן שיהיה צורך לנקות את זיכרון המטמון (cache) של הדפדפן כדי להבחין בשינויים.

  • פיירפוקס / ספארי: להחזיק את המקש Shift בעת לחיצה על טעינה מחדש (Reload) או ללחוץ על צירוף המקשים Ctrl-F5 או Ctrl-R (במחשב מק: ⌘-R).
  • גוגל כרום: ללחוץ על צירוף המקשים Ctrl-Shift-R (במחשב מק: ⌘-Shift-R).
  • אדג': להחזיק את המקש Ctrl בעת לחיצה על רענן (Refresh) או ללחוץ על צירוף המקשים Ctrl-F5.
//<nowiki>
mw.loader
  .using([
    "mediawiki.api",
    "mediawiki.ForeignApi",
    "mediawiki.util",
    "oojs-ui-windows",
    "oojs-ui-core",
    "ext.gadget.mw-import",
  ])
  .then(() => {
    mw.messages.set({
      "": "הערות לבדיקה:",
      "checkty-whait-title": "ממתין לתוצאות הבדיקה...",
      "update-success": "העדכון או הייבוא הסתיים בהצלחה! ",
      images: "לא לשכוח לבדוק תמונות!",
      "no-images": "אין תמונות בערך זה.",
      "No-Words": "הבדיקה הסתיימה בהצלחה",
      "checkty-page-doesnt-exist": " (הדף אינו קיים)",
      "checkty-search": "חיפוש",
      "checkty-language-check": 'בערך זה מופיע הביטוי "$1" פעם אחת או יותר. ',
      aspaklaria: "הערך עבר סינון! העדכון מוגבל לעורכי אספקלריה בלבד.",
      block: "הייבוא או העדכון נחסם על ידי ספק הרשת",
    });
    const api = new mw.Api();
    const isUpdate = mw.config.get("wgArticleId") > 0;
    const Template = /(\{\{מיון ויקיפדיה\|דף=)(.*)(\|גרסה=)(\d*)/;
    const edited =
      /\{\{(נערך במכלול|נבמ)\}\}|\[\[קטגוריה:המכלול: ערכים ששוכתבו או הורחבו במכלול\]\]/;
    const sectionParam = mw.util.getParamValue("section");
    const isSection =
      sectionParam && sectionParam !== "0" ? sectionParam : null;
    const textBox = $("#wpTextbox1");
    const summaryBox = $("#wpSummary");
    const updatemassage = $("<div>", { text: mw.msg("update-success") });
    const noimages = $("<div>", { text: mw.msg("no-images") });
    const images = $("<div>", { text: mw.msg("images") });
    const setOf =
      "<div><span>" +
      '<input type="checkbox" id="tionary" name="tionary">' +
      '<label for="tionary"> בוט ייבוא</label></span>' +
      '<span><select id="selectbut" disabled>' +
      '<option value="" selected disabled hidden>בחר סיווג...</option>' +
      '<option value="ספורט">ספורט</option>' +
      '<option value="סרטים">סרטים</option>' +
      '<option value="טלוויזיה">טלוויזיה</option>' +
      '<option value="שחקנים">שחקנים</option>' +
      '<option value="שירים">שירים</option>' +
      '<option value="מוזיקה">מוזיקה</option>' +
      '<option value="מוזיקאים">מוזיקאים</option>' +
      '<option value="ספרות">ספרות</option>' +
      '<option value="סופרים">סופרים</option>' +
      '<option value="תרבות ובידור">תרבות ובידור</option>' +
      //'<option value="אלבומים">אלבומים</option>' +
      //'<option value="משחקי מחשב">משחקי מחשב</option>' +
      "</select></div>";

    let PageName = mw.config.get("wgPageName");
    if (isUpdate) {
      PageName = PageName.replace(/^רבי_/, "")
        .replace(/^הרב_/, "")
        .replace(/_/g, " ")
        .replace(/ה"קדושה"/g, "הקדושה")
        .replace(/ה"קדוש"/g, "הקדוש")
        .replace(/ה"קדושים"/g, "הקדושים")
        .replace(/א-ל/g, "אל")
        .replace("המכלול:", "ויקיפדיה:");
    } else {
      PageName = PageName.replace(/_/g, " ");
    }
    if ($("#wikiPageName").length > 0) {
      PageName = $("#wikiPageName").text();
    }
    if (
      mw.config.get("wgAction") === "edit" ||
      mw.config.get("wgAction") === "submit"
    ) {
      $("#mw-editpage-watch").before(setOf);
      $("#tionary").on("change", function () {
        $("#selectbut").prop("disabled", !this.checked);
      });
      if (
        textBox &&
        Template.exec(textBox.val()) &&
        Template.exec(textBox.val())[4] != null
      ) {
        PageName = Template.exec(textBox.val())[2];
      }
    }
    const parseParams = {
      page: PageName,
      exist: isUpdate && mw.config.get("aspaklaryaLockdown") !== "edit-full",
      currentPage: mw.config.get("wgPageName"),
    };

    const level = getLevel(mw.config.get("wgUserGroups"));
    function getLevel(groupsUesr) {
      return groupsUesr.indexOf("sysop") !== -1
        ? 20
        : groupsUesr.indexOf("bot") !== -1
        ? 18
        : groupsUesr.indexOf("aspaklarya2") !== -1
        ? 16
        : groupsUesr.indexOf("aspaklaryaEditor") !== -1
        ? 14
        : groupsUesr.indexOf("patroller") !== -1
        ? 12
        : groupsUesr.indexOf("wikiupdate") !== -1
        ? 10
        : groupsUesr.indexOf("wikimport") !== -1
        ? 8
        : 0;
    }

    const ApiParse = new mw.import();
    const ForeignApi = new mw.ForeignApi(ApiParse.urlImport, { anonymous: true });

    function checkifexist() {
      ForeignApi.get({
        titles: PageName,
      }).done((result) => {
        if (result && result.query && result.query.pages) {
          if (result.query.pages["-1"]) {
            console.log("הדף לא קיים בוויקיפדיה העברית");
          } else {
            const stringButton = isUpdate ? "עדכון" : "ייבוא";
            const Btn1 = new OO.ui.ButtonInputWidget({
              label: stringButton,
              title: stringButton,
              id: "wpImportWidget",
            });
            if (isUpdate) {
              if (level < 10) return;
            } else {
              if (level > 15 && mw.config.get("wgAction") === "edit") {
                const apiToCheck = `${ApiParse.urlImport}?action=parse&page=${encodeURIComponent(
                  PageName
                )}&format=json&prop=text&section=0&origin=*`;

                fetch(apiToCheck)
                  .then((response) => response.json())
                  .then(({ parse }) => {
                    if (parse) {
                      const { text } = parse;
                      const rawa = text["*"].replace("/wiki/", "/");
                      const box3 = $($.parseHTML(rawa));
                      const box2 = $(
                        '<div class="warningbox mw-warning-with-logexcerpt mw-content-rtl" dir="rtl" lang="he"></div>'
                      ).html(box3);
                      $(
                        "#mw-content-text > div.mw-newarticletext.plainlinks"
                      ).html(box2);
                    }
                  });
              }
            }
            if (level > 7) {
              $("#wpDiffWidget").after(
                Btn1.$element.click(async () => {
                  if (isUpdate) {
                    const history = await getHistory();
                    displayDataEdits(history);
                  } else {
                    getArticle();
                  }
                })
              );
              mw.hook("userjs.import.addButten").fire(isUpdate);
            }
          }
        }
      });
    }
    function getArticle() {
      // Create results container if not exists
      if (!$("#checktyResults").length) {
        $(".editButtons").after(`
          <div id="checktyResults">
            <div class="checktyResultsTitle">פינת ההודעות</div>
          </div>
        `);
      }

      // Check for previous edits
      if (edited.test(textBox.val())) {
        alert("ערך זה נערך במכלול! נא לשמר עריכות מקומיות.");
      }

      // Process form parameters
      const isShort = document.getElementById("tionary")?.checked === true;
      const select = document.getElementById("selectbut")?.value;

      if (isShort) {
        parseParams.bot = select;
      }

      if (isSection && isUpdate) {
        parseParams.sectionNum = isSection;
        parseParams.sectionTitle = summaryBox.val().replace(/\/|\*/g, "");
      }

      // Fire import hooks and process API call
      mw.hook("userjs.import.starttingImport").fire(parseParams);

      ApiParse.importWikitext(parseParams)
        .then((result) => {
          if (!result) return;

          if (parseParams.form) {
            return ApiParse.openForm(
              parseParams.page,
              result.text,
              result.summary,
              parseParams.exist,
              parseParams.section
            );
          }

          // Reset parameters
          Object.assign(parseParams, {
            sectionTitle: null,
            sectionNum: undefined,
            form: false,
            bot: false,
          });

          mw.hook("userjs.import.gettingData").fire(result);

          if (!textBox) return;

          // Update text and summary
          textBox.val(result.text);
          mw.hook("userjs.import.loadTextForBox").fire(result.text);
          summaryBox.val(result.summary);

          // Add change tags
          const changeTag = isUpdate ? "update" : "wikiimport";
          const elm = $("#editform input[name=wpChangeTags]");

          if (elm.length === 0) {
            $("#editform").append(
              `<input type="hidden" name="wpChangeTags" value="${changeTag}">`
            );
          } else {
            elm.val(`${elm.val()},${changeTag}`);
          }

          writeMsg(updatemassage, "check");
          check();
        })
        .catch((error) => {
          console.error(error);
          mw.notify(error, { type: "warn" });
        });
    }
    function setDataWithExpiry(key, value) {
      const now = new Date();
      const item = {
        value,
        expiry: now.getTime() + 30 * 60 * 1000, // 30 minutes from now
      };
      localStorage.setItem(key, JSON.stringify(item));
    }

    function getDataWithExpiry(key) {
      const itemStr = localStorage.getItem(key);
      if (!itemStr) {
        return null;
      }
      const item = JSON.parse(itemStr);
      const now = new Date();
      if (now.getTime() > item.expiry) {
        localStorage.removeItem(key);
        return null;
      }
      return item.value;
    }

    async function getChecks() {
      try {
        const checksFromStorage = getDataWithExpiry("checks");

        if (checksFromStorage) {
          console.log("Checks loaded from localStorage");
          return checksFromStorage.map((source) => new RegExp(source, "i"));
        }

        console.log("Fetching checks from API");
        const { parse } = await api.get({
          action: "parse",
          page: "המכלול:בודק מילים חשודות",
          prop: "wikitext",
        });

        if (!(parse && parse.wikitext)) return;

        const genrealWarningWords = parse.wikitext["*"]
          .split("-----")[1]
          .split("\n*");

        const checks = genrealWarningWords
          .filter((line) => line.includes("//"))
          .map((line) => line.split("//")[0].trim());

        setDataWithExpiry("checks", checks);

        return checks.map((source) => new RegExp(source, "i"));
      } catch (error) {
        console.error("Error in getChecks:", error);
        return [];
      }
    }
    async function check() {
      if (!$("#checktyResults").length)
        $(".editButtons").after(
          '<div id="checktyResults"><div class="checktyResultsTitle">הערות לבדיקה</div></div>'
        );
      const txt = textBox.val();
      const pic =
        /(jpg|pdf|ogg|webm|png|jpeg|Jpg|JPG|svg|svg\.png|gif|gallery)/;
      const tst = pic.test(txt);

      if (tst) {
        writeMsg(images, "alert");
      } else {
        writeMsg(noimages, "check");
      }
      try {
        const checks = await getChecks();
        const checkWarnings = $("<div>");
        checks.forEach((regex) => {
          const m = regex.exec(txt);
          if (m) {
            checkWarnings.append(createSearchLink(m[0]));
            checkWarnings.append(
              "&nbsp;-&nbsp;" +
                (m[0].split(" ").length < 4 && !regex.source.includes("\\]")
                  ? mw.msg("checkty-language-check", m[0])
                  : "") +
                "<br/>"
            );
          }
        });
        if (checkWarnings.html().length) writeMsg(checkWarnings, "alert");
        writeMsg($("<div>").text(mw.msg("No-Words")), "check");
      } catch (error) {
        console.error(error);
      }
    }
    function writeMsg(msg, icon) {
      var x;
      if (msg instanceof Array) {
        if (msg.length === 0) return;
        msg = "<div>" + msg.join("<br/>") + "</div>";
      }
      x = $(msg).css("display", "none").addClass("checktyMsg");
      if (icon) {
        var iconWidget = new OO.ui.IconWidget({
          icon: icon,
        });
        x.prepend(iconWidget.$element);
      }
      $("#checktyResults").append(x);
      x.show("slow");
      return x;
    }
    function createSearchLink(v) {
      var highlightStr = highlightString;
      var searchLink = $('<a href="#">חיפוש</a>')
        .data({ search: v })
        .click(function (e) {
          highlightStr($(this).data("search"));
          e.preventDefault();
        });
      return searchLink;
    }

    function highlightString(toFind) {
      const HALF_EDIT_BOX_HEIGHT = 200;
      const text = textBox.val();

      if (toFind instanceof RegExp) {
        const match = toFind.exec(text);
        if (!match) return;
        toFind = match[0];
      }

      const currentPos = textBox.textSelection("getCaretPosition");
      let nextPlace = text.indexOf(toFind, currentPos + 1);
      if (nextPlace === -1) {
        nextPlace = text.indexOf(toFind);
      }
      if (nextPlace === -1) return;

      textBox.val(text.substring(0, nextPlace)).focus().scrollTop(1000000);

      const curScrollTop = textBox.scrollTop();

      textBox
        .val(text)
        .scrollTop(curScrollTop > 0 ? curScrollTop + HALF_EDIT_BOX_HEIGHT : 0)
        .focus()
        .textSelection("setSelection", {
          start: nextPlace,
          end: nextPlace + toFind.length,
        });
    }

    /**
     * 
     * @param {string} htmlNode html selector or html element
     */
    async function aspaklaryaColor(htmlNode) {
      let data = getDataWithExpiry("aspaklaryaColor");
      if (!data) {
        data = await $.get(
          "https://www.hamichlol.org.il/w/index.php?title=" +
            encodeURI("המכלול:בדיקת מילים חשודות") +
            "&action=raw"
        );
        setDataWithExpiry("aspaklaryaColor", data);
      }
    
      const nodes = $(htmlNode)
        .find("*")
        .contents()
        .filter(function () {
          return this.nodeType === 3;
        });
      const theWords = data.split("<!--  -->");

      const colors = {
        1: "#ff5555", // אדום כהה
        3: "#ffcccc", // אדום בהיר
        5: "#00ff00", // ירוק
        // 5: "#99ff99", // ירוק
        7: "#ccccff", // כחול
        9: "#eeee99", // צהוב
        11: "#9370bd", // סגול
      };

      let run = 0;
      for (const index in colors) {
        wrapText(
          nodes,
          "background-Color:" + colors[index],
          theWords[index]
        );
      }

      /**
       *
       * @param {NodeList} nodes
       * @param {string} style
       * @param {string} theWords
       * @returns
       */
      function wrapText(nodes, style, theWords) {

        if (!theWords) return;

        theWords = theWords.trim();
        if (!theWords) return;

        const pattern = new RegExp(theWords, "g");
        Array.from(nodes).forEach((node) => {
          if (
            node.parentNode === null ||
            !node.nodeValue.match(new RegExp(theWords))?.[0]
          ) {
            return;
          }
          const text = node.nodeValue;

          const regex = new RegExp(pattern.source, pattern.flags);
          regex.lastIndex = 0;

          /**
           * @type {RegExpExecArray|null}
           */
          let match;
          let lastIndex = 0;
          const frag = document.createDocumentFragment();

          while ((match = regex.exec(text)) !== null) {
            run++;
            const matchText = match[0];
            const matchStart = match.index;
            const matchEnd = regex.lastIndex;

            // Prevent infinite loop on empty match
            if (matchStart === matchEnd) {
              regex.lastIndex++;
              continue;
            }

            // Text before match
            if (lastIndex < matchStart) {
              frag.appendChild(
                document.createTextNode(text.slice(lastIndex, matchStart))
              );
            }

            // Matched text
            const span = document.createElement("span");
            span.style = style;
            span.textContent = matchText;
            frag.appendChild(span);

            lastIndex = matchEnd;
          }

          // Remaining text after last match
          if (lastIndex < text.length) {
            frag.appendChild(document.createTextNode(text.slice(lastIndex)));
          }
          //   console.log(`Wrapping text: "${text}" with style: ${style}`,text.match(pattern));
          node.parentNode.replaceChild(frag, node);
        });
      }
      console.log(`Total words wrapped: ${run}`);
    }
    async function getHistory() {
      if (!$("#checktyResults").length) {
        $(".editButtons").after(
          '<div id="checktyResults"><div class="checktyResultsTitle">פינת ההודעות</div></div>'
        );
      }

      const localpagename = mw.config.get("wgPageName");
      const params = {
        prop: "info|revisions",
        indexpageids: true,
        titles: localpagename,
        utf8: 1,
        rvprop: "ids|timestamp|flags|comment|user|size|tags",
        rvdir: "newer",
        rvlimit: "max",
      };

      try {
        const data = await api.get(params);
        const revisions = data.query.pages[data.query.pageids[0]].revisions;
        if (!revisions) return;

        return analyzeRevisions(revisions);
      } catch (error) {
        console.error("Error fetching history:", error);
      }
    }

    function analyzeRevisions(revisions) {
      return revisions.reduce(
        (acc, rev, index, array) => {
          const comment = rev.comment;
          const size = rev.size;

          if (index > 0) {
            const prevSize = array[index - 1].size;
            const diff = size - prevSize;

            if (!/מוויקיפדיה|מויקיפדיה|החלפת טקסט/.test(comment)) {
              acc.edits++;
              acc.plussize += diff;
            } else {
              acc.wikiup += diff;
            }
          }

          if (/הסרת תוכן|גיור מונח/.test(comment)) {
            acc.aspak.push({ תקציר: comment });
          }

          if (/הסרת תמונה|החלפת תמונה|תמונה חילופית|, תמונה/.test(comment)) {
            acc.potos.push({ תקציר: comment });
          }

          if (/החלפות אוטומטיות/.test(comment)) {
            acc.autoReplace.push({ תקציר: comment });
          }

          return acc;
        },
        {
          edits: 0,
          plussize: 0,
          wikiup: 0,
          aspak: [],
          potos: [],
          autoReplace: [],
        }
      );
    }

    function displayDataEdits(stats) {
      const { edits, plussize, wikiup, aspak, potos, autoReplace } = stats;

      if (plussize !== 0) {
        writeMsg(
          $("<div>").text(
            `ערך זה נערך במכלול ${edits} פעמים. גודל העריכות המקומיות המשוקלל הוא: ${plussize} בתים`
          )
        );
      }

      if (!aspak.length) {
        getArticle();
      } else if (level >= 10) {
        writeMsg($("<div>").text("הערך עבר סינון תוכן!"), "alert");
        getArticle();
      } else {
        writeMsg($("<div>").text(mw.msg("aspaklaria")), "alert");
      }

      if (potos.length) {
        writeMsg($("<div>").text("הערך עבר טיפול בתמונות!"), "alert");
      }

      if (autoReplace.length) {
        writeMsg($("<div>").text("הערך עבר החלפות סינון אוטומטיות"), "alert");
      }
    }

    function editDiffrents() {
      aspaklaryaColor(document.querySelectorAll(
        "td.diff-addedline.diff-side-added.diff-side-added"
      ));

      importScript("משתמש:בוט גאון הירדן/ספירת העומר.js");
    }

    if ($.inArray(mw.config.get("wgAction"), ["edit", "submit"]) + 1)
      $(function () {
        if (
          $.inArray(mw.config.get("wgNamespaceNumber"), ["2", "3", "4", "6"]) +
          1
        ) {
          return;
        }
        if (location.href.indexOf("&submit") === -1) {
          checkifexist();
        }
        var Btn2 = new OO.ui.ButtonInputWidget({
          label: "בדיקת מילים",
          title: "בדיקת מילים",
          accessKey: "a",
        });
        $("#wpDiffWidget").after(Btn2.$element.click(check));
        const isPreviewMode = document.querySelector(".previewnote") !== null;
        const btn = $(
          `<button id ="${isPreviewMode ? "colorWOrds" : "editDiffrents"}">${
            isPreviewMode ? "צביעת מילים" : "תצוגת הבדלים מתקדמת"
          }</button>`
        );

        btn.on("click", function () {
          if (isPreviewMode) return aspaklaryaColor("#wikiPreview > .mw-parser-output");
          editDiffrents();
        });
        $("#bodyContent").prepend(btn);
      });

    function alertDataEdits(data) {
      const { edits, plussize, wikiup, aspak, potos } = data;
      if (!aspak.length && !potos.length) {
        return getArticle();
      }
      const container = $("<div>");
      const msg = mw.util.messageBox(
        `הערך נערך במכלול ${edits} פעמים. גודל העריכות המקומיות המשוקלל הוא : ${plussize} בתים `,
        "info"
      );

      let warnText = "";
      if (aspak.length && potos.length) {
        warnText = "הערך עבר סינון תוכן ותמונות!";
      } else if (aspak.length) {
        warnText = "הערך עבר סינון תוכן!";
      } else if (potos.length) {
        warnText = "שים לב, הערך עבר טיפול בתמונות!";
      }
      if (warnText.length) {
        warnText = warnText;
      }

      const warnBox = mw.util.messageBox(warnText, "warning");
      /*$(".vector-body-before-content").append(msg, boxMassags); */
      container.append(warnBox, msg);
      OO.ui
        .alert(container, {
          title: "עריכות מקומיות",
          actions: [
            {
              action: "accept",
              label: "אישור",
              flags: "primary",
            },
          ],
        })
        .done(() => {
          /*
          if (aspak.length && level < 14) {
            return;
          } else {*/
          return getArticle();
          //}
        });
    }

    if (
      mw.config.get("wgPageName") != "עמוד_ראשי" &&
      mw.config.get("wgPageContentModel") != "flow-board" &&
      (mw.config.get("wgNamespaceNumber") === 0 ||
        mw.config.get("wgNamespaceNumber") === 10) &&
      level > 9 &&
      mw.config.get("wgAction") === "view"
    ) {
      var btnUpDate = mw.util.addPortletLink(
        "p-views",
        "#",
        "עדכון",
        "wikiUpdate",
        null,
        null,
        "#ca-history"
      ); //הפרמטר הרביעי מיועד לצורך הסתרה בקוד הסינון בקומונס
      $(btnUpDate).click(async function () {
        const aspSpecLinks = {
          sport: "ספורט",
          musicion: "מוזיקאים",
          music: "מוזיקה",
          player: "שחקנים",
          television: "טלוויזיה",
          sofrim: "סופרים",
          singers: "זמרים",
          movie: "קולנוע",
          books: "ספרות",
          gaming: "משחקי מחשב",
          balet: "בלט",
          tarbut: "תרבות ובידור",
          albums: "אלבומים",
          film: "סרטים",
          songs: "שירים",
        };
        if ($("#wikiPageName").length > 0) {
          parseParams.page = $("#wikiPageName").text();
        }
        parseParams.form = true;
        const bot = $("#asp-measege").text();
        if (bot) parseParams.bot = aspSpecLinks[bot];
        const history = await getHistory();
        alertDataEdits(history);
      });
      $(".mw-editsection").each(function (i) {
        $(this)
          .find("a:not(.mw-editsection-visualeditor)")
          .after(
            $("<span> | </span>"),
            $("<a>", {
              id: i,
              class: "updatesection",
              text: "עדכון",
              herf: "#",
              "data-title": $(this).siblings(".mw-headline").text(),
            })
          );
      });
      $(".updatesection").click(async function () {
        parseParams.sectionNum = $(this).attr("id");
        parseParams.sectionTitle = $(this).attr("data-title");
        parseParams.form = true;
        const history = await getHistory();
        alertDataEdits(history);
      });
    }
    const tagsElement = $('#editform input[name="wpChangeTags"]');
    if (
      /עדכון (פסקה )?מוויקיפדיה|ייבוא מוויקיפדיה העברית/.test(summaryBox.val())
    ) {
      if (!tagsElement[0]) {
        $("#editform").append(
          `<input type="hidden" name="wpChangeTags" value="${
            /עדכון/.test(summaryBox.val()) ? "update" : "wikiimport"
          }">`
        );
      }
    }
  });
//</nowiki>