משתמש:שרדינגר/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}">●</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 = "ⓘ";
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 = "ⓘ";
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);
});
});
});
});
});
}
})();