לדלג לתוכן

משתמש:שרדינגר/lastseen.js

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

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

  • פיירפוקס / ספארי: להחזיק את המקש Shift בעת לחיצה על טעינה מחדש (Reload) או ללחוץ על צירוף המקשים Ctrl-F5 או Ctrl-R (במחשב מק: ⌘-R).
  • גוגל כרום: ללחוץ על צירוף המקשים Ctrl-Shift-R (במחשב מק: ⌘-Shift-R).
  • אדג': להחזיק את המקש Ctrl בעת לחיצה על רענן (Refresh) או ללחוץ על צירוף המקשים Ctrl-F5.
(function () {
    var username = mw.config.get('wgRelevantUserName');
    var wikiLanguage = mw.config.get('wgContentLanguage');

    // פונקציה להצגת רשימת הערכים שנוצרו
    function createArticleList(pages) {
        const listContainer = document.createElement('ul');
        listContainer.style.display = "none";
        pages.forEach(page => {
            const listItem = document.createElement('li');
            const link = document.createElement('a');
            link.href = mw.util.getUrl(page);
            link.textContent = page;
            listItem.appendChild(link);
            listContainer.appendChild(listItem);
        });
        return listContainer;
    }

    // פונקציה להחלפה בין הצגת והסתרת רשימת הערכים
    function toggleArticleList(event) {
        const articleList = event.target.nextElementSibling;
        if (articleList.style.display === "none" || articleList.style.display === "") {
            articleList.style.display = "block";
        } else {
            articleList.style.display = "none";
        }
    }

    // פונקציה לבדוק אם המשתמש כותב בתשלום
    function checkPaidEditing() {
        return new Promise(function(resolve) {
            var userPageParams = {
                "action": "query",
                "format": "json",
                "prop": "revisions",
                "titles": "User:" + username,
                "rvprop": "content",
                "rvslots": "main"
            };
            $.getJSON('/w/api.php', userPageParams, function(res) {
                var pages = res.query.pages;
                var userPageContent = Object.values(pages)[0].revisions[0].slots.main['*'];
                var isPaidEditor = userPageContent.includes("כותב בתשלום") || userPageContent.includes("כותבת בתשלום");
                resolve(isPaidEditor);
            });
        });
    }

    // פונקציה לבדיקת זכויות הצבעה 
    function checkVotingEligibility(gender) {
        return new Promise(function (resolve) {
            var reasons = [];
            var userContributionCount = 0;
            var seniorityDays = 0;
            var checkSeniority = new Date();
            checkSeniority.setDate(checkSeniority.getDate() - 365);

            var contributionsParams = {
                action: "query",
                list: "usercontribs",
                ucuser: username,
                uclimit: 500,
                ucnamespace: "0|6|8|10|12|14|100",
                ucdir: "newer",
                ucstart: new Date(new Date().setDate(new Date().getDate() - 90)).toISOString()
            };

            api.get(contributionsParams).done(function (data) {
                userContributionCount = data.query.usercontribs.length;
                if (userContributionCount < 100) {
                    reasons.push(gender === 'female' ? "אין לה 100 עריכות ב-90 הימים האחרונים" : "אין לו 100 עריכות ב-90 הימים האחרונים");
                }

                api.get({
                    action: 'query',
                    list: 'usercontribs',
                    ucuser: username,
                    uclimit: 1,
                    ucdir: 'newer'
                }).done(function (seniorityData) {
                    var firstEdit = new Date(seniorityData.query.usercontribs[0].timestamp);
                    if (firstEdit > checkSeniority) {
                        reasons.push(gender === 'female' ? "אין לה ותק של 365 ימים" : "אין לו ותק של 365 ימים");
                    }

                    checkPaidEditing().then(function(isPaidEditor) {
                        if (isPaidEditor) {
                            reasons.push(gender === 'female' ? "היא כותבת בתשלום" : "הוא כותב בתשלום");
                        }

                        if (reasons.length > 0) {
                            resolve(gender === 'female' ? "המשתמשת אינה זכאית להצביע כי " + reasons.join(", ") : "המשתמש אינו זכאי להצביע כי " + reasons.join(", "));
                        } else {
                            resolve(gender === 'female' ? "המשתמשת זכאית להצביע." : "המשתמש זכאי להצביע.");
                        }
                    });
                });
            });
        });
    }

    if (username) {
        var api = new mw.Api();

        mw.loader.using(['mediawiki.api', 'mediawiki.util', 'mediawiki.language.months']).then(function () {
            // קוד לפעולה לפי מגדר המשתמש
            api.get({
                action: 'query',
                list: 'users',
                ususers: username,
                usprop: 'gender|blockinfo'
            }).done(function (data) {
                var userInfo = data.query.users[0];
                var userGender = userInfo.gender;

                var messages = {
                    'he': {
                        male: "המשתמש " + username + " ביצע את <a href='https://" + wikiLanguage + ".wikipedia.org/wiki/Special:Contributions/" + encodeURIComponent(username) + "'>העריכה</a> האחרונה שלו לפני ",
                        female: "המשתמשת " + username + " ביצעה את <a href='https://" + wikiLanguage + ".wikipedia.org/wiki/Special:Contributions/" + encodeURIComponent(username) + "'>העריכה</a> האחרונה שלה לפני "
                    },
                    'en': {
                        male: "User " + username + " made his last <a href='https://" + wikiLanguage + ".wikipedia.org/wiki/Special:Contributions/" + encodeURIComponent(username) + "'>edit</a> ",
                        female: "User " + username + " made her last <a href='https://" + wikiLanguage + ".wikipedia.org/wiki/Special:Contributions/" + encodeURIComponent(username) + "'>edit</a> "
                    }
                };

                var noEditMessages = {
                    'he': {
                        male: "המשתמש " + username + " עדיין לא ביצע עריכה",
                        female: "המשתמשת " + username + " עדיין לא ביצעה עריכה"
                    },
                    'en': {
                        male: "User " + username + " has not edited yet",
                        female: "User " + username + " has not edited yet"
                    }
                };

                var genderKey = userGender === 'female' ? 'female' : 'male';
                var message = messages[wikiLanguage][genderKey] || messages['en'][genderKey];
                var noEditMessage = noEditMessages[wikiLanguage][genderKey] || noEditMessages['en'][genderKey];

                var tooltipFullExplanation = {
                    'he': "ירוק: המשתמש ערך לאחרונה לפני פחות מ־20 דקות\nכתום: המשתמש ערך לאחרונה לפני יותר מ־20 דקות, אך לפני פחות משלושה חודשים\nאדום: המשתמש ערך לאחרונה לפני יותר משלושה חודשים\nאפור: המשתמש מעולם לא ערך באתר, או שמועד העריכה האחרונה לא ידוע",
                    'en': "Green: The user edited less than 20 minutes ago\nOrange: The user edited more than 20 minutes ago, but within the last three months\nRed: The user edited more than three months ago\nGray: The user has never edited, or the last edit date is unknown"
                };

                var tooltipMessage = tooltipFullExplanation[wikiLanguage] || tooltipFullExplanation['en'];

                function convertTimeDifferenceToSeconds(date) {
                    var now = new Date();
                    return Math.floor((now - date) / 1000);
                }

                function determineUnits(diffInSeconds) {
                    var units = [];
                    if (diffInSeconds > 2 * 24 * 60 * 60) {
                        units.push("years", "months", "days");
                    } else if (diffInSeconds > 24 * 60 * 60) {
                        units.push("days", "hours");
                    } else if (diffInSeconds > 2 * 60) {
                        units.push("days", "hours", "minutes");
                    } else {
                        units.push("days", "hours", "minutes", "seconds");
                    }
                    return units.join(", ");
                }

                function formatRelativeTimeUsingLua(diffInSeconds, lastEditDate) {
                    var units = determineUnits(diffInSeconds);
                    var tooltipTime = lastEditDate.toLocaleDateString() + ' ' + lastEditDate.getHours() + ':' + lastEditDate.getMinutes().toString().padStart(2, '0');
                    return api.post({
                        action: 'expandtemplates',
                        text: "{{#invoke:משך זמן|sumHMS|" + diffInSeconds + "|units=" + units + "}}"
                    }).then(function (response) {
                        return {
                            relativeTime: response.expandtemplates['*'].replace(/וגם/g, 'ו-').replace(/\s{2,}/g, ' ').trim(),
                            tooltipTime: tooltipTime
                        };
                    });
                }

                function getRecencyIcon(timeDiff, hasEdits) {
                    var iconColor;
                    if (!hasEdits) {
                        iconColor = "gray";
                    } else if (timeDiff <= 20 * 60 * 1000) {
                        iconColor = "green";
                    } else if (timeDiff <= 90 * 24 * 60 * 60 * 1000) {
                        iconColor = "orange";
                    } else {
                        iconColor = "red";
                    }
                    return `<span style="color:${iconColor}; font-size: 24px; cursor: help; vertical-align: middle;" title="${tooltipMessage}">&#9679;</span>`;
                }

                var apiUrl = "https://" + wikiLanguage + ".wikipedia.org/w/api.php?action=query&list=usercontribs&ucuser=" + encodeURIComponent(username) + "&uclimit=1&ucdir=older&format=json&origin=*";

                $.getJSON(apiUrl, function (data) {
                    var displayTime, icon;
                    if (data.query && data.query.usercontribs && data.query.usercontribs.length > 0) {
                        var lastEditTime = new Date(data.query.usercontribs[0].timestamp);
                        var now = new Date();
                        icon = getRecencyIcon(now - lastEditTime, true);

                        var timeDifferenceInSeconds = convertTimeDifferenceToSeconds(lastEditTime);

                        formatRelativeTimeUsingLua(timeDifferenceInSeconds, lastEditTime).then(function (result) {
                            displayTime = `${message}<span title="${result.tooltipTime}" style="border-bottom: 1px dashed; cursor: pointer; font-size: inherit;" onclick="toggleExactTime(this, '${result.tooltipTime}')">${result.relativeTime}</span>`;

                            var infoBox = document.createElement('div');
                            infoBox.className = "user-info-box";
                            infoBox.style.padding = "6px 10px";
                            infoBox.style.marginBottom = "8px";
                            infoBox.style.backgroundColor = "#f5f5f5";
                            infoBox.style.borderLeft = "4px solid #ccc";
                            infoBox.style.borderRadius = "4px";
                            infoBox.style.boxShadow = "0 1px 3px rgba(0,0,0,0.1)";
                            infoBox.style.display = "block";
                            infoBox.style.maxWidth = "550px";
                            infoBox.style.fontSize = "smaller";

                            var contentContainer = document.createElement('div');
                            contentContainer.style.display = "flex";
                            contentContainer.style.alignItems = "center";
                            contentContainer.innerHTML = `${icon} <span style="margin-left: 8px;">${displayTime}</span>`;

                            infoBox.appendChild(contentContainer);

                            var infoIcon = document.createElement('span');
                            infoIcon.style.cursor = "pointer";
                            infoIcon.style.fontSize = "larger"; 
                            infoIcon.style.fontWeight = "bold"; 
                            infoIcon.style.color = "blue";
                            infoIcon.innerHTML = "&#9432;";
                            infoIcon.style.marginLeft = "8px";

                            var infoDisplayed = false;

                            infoIcon.onclick = function () {
                                if (infoDisplayed) {
                                    var additionalInfo = infoBox.querySelector('.additional-info');
                                    if (additionalInfo) {
                                        additionalInfo.remove();
                                    }
                                    infoDisplayed = false;
                                } else {
                                    loadAdditionalUserInfo(infoBox);
                                    infoDisplayed = true;
                                }
                            };

                            contentContainer.appendChild(infoIcon);

                            var firstHeading = document.getElementById('firstHeading');
                            if (firstHeading) {
                                firstHeading.parentNode.insertBefore(infoBox, firstHeading.nextSibling);
                            }
                        });
                    } else {
                        displayTime = noEditMessage;
                        icon = getRecencyIcon(Infinity, false);

                        var infoBox = document.createElement('div');
                        infoBox.className = "user-info-box";
                        infoBox.style.padding = "6px 10px";
                        infoBox.style.marginBottom = "8px";
                        infoBox.style.backgroundColor = "#f5f5f5";
                        infoBox.style.borderLeft = "4px solid #ccc";
                        infoBox.style.borderRadius = "4px";
                        infoBox.style.boxShadow = "0 1px 3px rgba(0,0,0,0.1)";
                        infoBox.style.display = "block";
                        infoBox.style.maxWidth = "550px";
                        infoBox.style.fontSize = "smaller";

                        var contentContainer = document.createElement('div');
                        contentContainer.style.display = "flex";
                        contentContainer.style.alignItems = "center";
                        contentContainer.innerHTML = `${icon} <span style="margin-left: 8px;">${displayTime}</span>`;

                        infoBox.appendChild(contentContainer);

                        var infoIcon = document.createElement('span');
                        infoIcon.style.cursor = "pointer";
                        infoIcon.style.fontSize = "larger"; 
                        infoIcon.style.fontWeight = "bold"; 
                        infoIcon.style.color = "blue";
                        infoIcon.innerHTML = "&#9432;";
                        infoIcon.style.marginLeft = "8px";

                        var infoDisplayed = false;

                        infoIcon.onclick = function () {
                            if (infoDisplayed) {
                                var additionalInfo = infoBox.querySelector('.additional-info');
                                if (additionalInfo) {
                                    additionalInfo.remove();
                                }
                                infoDisplayed = false;
                            } else {
                                loadAdditionalUserInfo(infoBox);
                                infoDisplayed = true;
                            }
                        };

                        contentContainer.appendChild(infoIcon);

                        var firstHeading = document.getElementById('firstHeading');
                        if (firstHeading) {
                            firstHeading.parentNode.insertBefore(infoBox, firstHeading.nextSibling);
                        }
                    }
                });
            });
        });
    }

    window.toggleExactTime = function (element, exactTime) {
        var nextElement = element.nextElementSibling;
        if (nextElement && nextElement.classList.contains('exact-time')) {
            nextElement.remove();
        } else {
            var exactTimeElement = document.createElement('div');
            exactTimeElement.classList.add('exact-time');
            exactTimeElement.style.fontSize = 'smaller';
            exactTimeElement.style.color = '#555';
            exactTimeElement.textContent = exactTime;
            element.parentNode.insertBefore(exactTimeElement, element.nextSibling);
        }
    };

    function loadAdditionalUserInfo(infoBox) {
        var api = new mw.Api();

        function getUserStats(username) {
            return api.get({
                action: 'query',
                list: 'users',
                ususers: username,
                usprop: 'editcount|registration|gender|blockinfo'
            });
        }

        function formatRegistrationDate(timestamp) {
            const date = new Date(timestamp);
            const monthName = mw.language.months.names ? mw.language.months.names[date.getMonth()] : '';
            const monthNameGen = mw.language.months.genitive ? mw.language.months.genitive[date.getMonth()] : '';
            const year = date.getFullYear();
            const day = date.getDate();

            if (mw.user.options.get('date') === 'mdy') {
                return `${monthName} ${day}, ${year}`;
            } else {
                return `${day} ${monthNameGen} ${year}`;
            }
        }

        function getUserContribs(username) {
            return api.get({
                action: 'query',
                list: 'usercontribs',
                ucuser: username,
                uclimit: 'max',
                ucprop: 'timestamp'
            });
        }

        function calculateAverageTimeBetweenEdits(contribs) {
            if (contribs.length < 2) {
                return null;
            }

            let totalDiff = 0;

            for (let i = 1; i < contribs.length; i++) {
                const prevEditTime = new Date(contribs[i - 1].timestamp).getTime();
                const currentEditTime = new Date(contribs[i].timestamp).getTime();
                totalDiff += prevEditTime - currentEditTime;
            }

            const averageDiff = totalDiff / (contribs.length - 1);
            return Math.floor(averageDiff / 1000);
        }

        function formatAverageTimeWithLua(averageTimeInSeconds) {
            return api.post({
                action: 'expandtemplates',
                text: `{{#invoke:משך זמן|sumHMS|${averageTimeInSeconds}}}`
            }).then(function (response) {
                return response.expandtemplates['*'].replace(/וגם/g, 'ו-').replace(/\s{2,}/g, ' ').trim();
            });
        }

        function getCreatedPages(username) {
            return new Promise(function (resolve, reject) {
                var pages = [];
                var continueToken = "";

                function findPagesCreated() {
                    var params = {
                        action: "query",
                        list: "usercontribs",
                        ucuser: username,
                        ucprop: "flags|title|timestamp|comment|tags",
                        ucshow: "new",
                        uclimit: 500,
                        ucnamespace: 0 
                    };

                    if (continueToken) {
                        params.uccontinue = continueToken;
                    }

                    api.get(params).done(function (data) {
                        pages = pages.concat(data.query.usercontribs.filter(function (contrib) {
                            return !(/הועבר(ה)?|העביר(ה)? את הדף|הפניה|העברה/i.test(contrib.comment)) &&
                                !contrib.tags.includes("mw-new-redirect") &&
                                !(/הפניה/i.test(contrib.comment)) &&
                                !(/תוכן תרגום/i.test(contrib.comment)) &&
                                !(/פירושונים/i.test(contrib.title));
                        }).map(function (contrib) {
                            return contrib.title;
                        }));

                        if (data.continue && data.continue.uccontinue) {
                            continueToken = data.continue.uccontinue;
                            setTimeout(findPagesCreated, 3000);
                        } else {
                            resolve(pages);
                        }
                    }).fail(function (error) {
                        reject(error);
                    });
                }

                findPagesCreated();
            });
        }

        function checkUserBlockHistory(username) {
            return api.get({
                action: 'query',
                list: 'blocks',
                bkusers: username,
                bkprop: 'flags|user|partial'
            }).then(function (data) {
                if (data.query.blocks.length > 0) {
                    const blockInfo = data.query.blocks[0];
                    const isPartial = blockInfo.partial !== undefined;
                    return { wasBlocked: true, isPartial: isPartial };
                } else {
                    return { wasBlocked: false };
                }
            });
        }

        var username = mw.config.get('wgRelevantUserName');
        getUserStats(username).done(async function (userData) {
            const user = userData.query.users[0];
            const totalEdits = user.editcount;
            const registrationDate = user.registration ? await formatRegistrationDate(user.registration) : 'לא זמין';
            const gender = user.gender;

            const textMap = {
                male: {
                    edits: "עריכות",
                    createdPages: "ערכים שיצר המשתמש",
                    blockedNow: "משתמש זה חסום כרגע",
                    partialBlockNow: "משתמש זה חסום חלקית כעת"
                },
                female: {
                    edits: "עריכות",
                    createdPages: "ערכים שיצרה המשתמשת",
                    blockedNow: "משתמשת זו חסומה כרגע",
                    partialBlockNow: "משתמשת זו חסומה חלקית כעת"
                },
                unknown: {
                    edits: "עריכות",
                    createdPages: "ערכים שיצר המשתמש",
                    blockedNow: "משתמש זה חסום כרגע",
                    partialBlockNow: "משתמש זה חסום חלקית כעת"
                }
            };

            const genderText = textMap[gender] || textMap.unknown;

            getUserContribs(username).done(function (contribData) {
                const contribs = contribData.query.usercontribs;
                const averageTimeInSeconds = calculateAverageTimeBetweenEdits(contribs);

                const additionalInfo = document.createElement('div');
                additionalInfo.className = "additional-info";
                additionalInfo.style.padding = "6px 0";
                additionalInfo.style.borderTop = "1px solid #ccc";
                additionalInfo.style.marginTop = "8px";
                additionalInfo.style.fontSize = "smaller";
                additionalInfo.innerHTML = `
                    <p>תאריך יצירת החשבון: ${registrationDate}</p>
                    <p>${genderText.edits}: ${totalEdits}</p>
                    <p class="created-pages">${genderText.createdPages}: מבצע חישוב...</p>
                `;
                infoBox.appendChild(additionalInfo);

                getCreatedPages(username).then(function (pages) {
                    const uniquePages = [...new Set(pages)].sort();
                    const createdPagesCount = uniquePages.length;

                    const createdPagesElement = additionalInfo.querySelector('.created-pages');
                    createdPagesElement.innerHTML = `${genderText.createdPages}: ${createdPagesCount} <small>(הנתון עשוי להיות לא מדויק)</small> <a href="javascript:void(0);" class="toggle-article-list">להצגה</a>`;

                    const articleList = createArticleList(uniquePages);
                    createdPagesElement.appendChild(articleList);

                    additionalInfo.querySelector('.toggle-article-list').addEventListener('click', toggleArticleList);

                    checkUserBlockHistory(username).then(function (blockInfo) {
                        if (averageTimeInSeconds !== null) {
                            formatAverageTimeWithLua(averageTimeInSeconds).then(function (formattedTime) {
                                const avgTimeParagraph = document.createElement('p');
                                avgTimeParagraph.textContent = `זמן ממוצע בין עריכות: ${formattedTime}`;
                                additionalInfo.appendChild(avgTimeParagraph);
                            });
                        } else {
                            const noAvgTimeParagraph = document.createElement('p');
                            noAvgTimeParagraph.textContent = 'לא ניתן לחשב זמן ממוצע בין עריכות';
                            additionalInfo.appendChild(noAvgTimeParagraph);
                        }

                        if (blockInfo.wasBlocked) {
                            const blockLogUrl = `${mw.config.get('wgServer')}${mw.config.get('wgScriptPath')}/index.php?title=Special:Log/block&page=User:${encodeURIComponent(username)}`;
                            const blockedParagraph = document.createElement('p');
                            blockedParagraph.style.color = 'red';
                            blockedParagraph.innerHTML = `<a href="${blockLogUrl}" style="color: red; text-decoration: none;">${blockInfo.isPartial ? genderText.partialBlockNow : genderText.blockedNow}</a>.`;
                            additionalInfo.appendChild(blockedParagraph);
                        }

                        checkVotingEligibility(gender).then(function (votingMessage) {
                            const votingParagraph = document.createElement('p');
                            votingParagraph.textContent = votingMessage;
                            additionalInfo.appendChild(votingParagraph);
                        });
                    });
                });
            });
        });
    }
})();