משתמש:ממוני גבך/כמה חסר לזכות הצבעה.js
מראה
לתשומת ליבך: לאחר הפרסום, ייתכן שיהיה צורך לנקות את זיכרון המטמון (cache) של הדפדפן כדי להבחין בשינויים.
- פיירפוקס / ספארי: להחזיק את המקש Shift בעת לחיצה על טעינה מחדש (Reload) או ללחוץ על צירוף המקשים Ctrl-F5 או Ctrl-R (במחשב מק: ⌘-R).
- גוגל כרום: ללחוץ על צירוף המקשים Ctrl-Shift-R (במחשב מק: ⌘-Shift-R).
- אדג': להחזיק את המקש Ctrl בעת לחיצה על רענן (Refresh) או ללחוץ על צירוף המקשים Ctrl-F5.
/**
* סקריפט לבדיקת חוסר בעריכות לזכות הצבעה במכלול
* בודק 100 עריכות ב-90 הימים האחרונים במרחבי התוכן המשיקים בלבד.
* מרחבי תוכן: ראשי (0), קבצים (6), תבניות (10), קטגוריות (14), פורטלים (100), יחידות (828).
* החרגות: דפי שיחה אינם נספרים. תבניות "תיבת משתמש" אינן נספרות.
*/
(function () {
const REQUIRED_EDITS = 100;
const DAYS_LIMIT = 90;
// מזהי מרחבי השם המשיקים (מרחבי תוכן בלבד - זוגיים)
const NAMESPACES_MAP = {
0: 'ערכים',
6: 'קבצים',
10: 'תבניות',
14: 'קטגוריות',
100: 'פורטלים',
828: 'יחידות'
};
const CONTENT_NAMESPACES = Object.keys(NAMESPACES_MAP).join('|');
async function checkVotingRights() {
let targetUser = mw.config.get('wgRelevantUserName') || mw.config.get('wgUserName');
if (!targetUser) {
mw.notify('לא נמצא משתמש לבדיקה.');
return;
}
showInitialModal(targetUser);
const dateLimit = new Date();
dateLimit.setDate(dateLimit.getDate() - DAYS_LIMIT);
const ucend = dateLimit.toISOString();
try {
const response = await $.ajax({
url: mw.util.wikiScript('api'),
data: {
action: 'query',
list: 'usercontribs',
ucuser: targetUser,
ucnamespace: CONTENT_NAMESPACES,
uclimit: 'max',
ucend: ucend,
ucprop: 'timestamp|title|ns|revid|tags',
format: 'json'
}
});
if (!response.query || !response.query.usercontribs) {
throw new Error("מבנה נתונים לא תקין");
}
// סינון וסיווג עריכות
const stats = { 0: 0, 6: 0, 10: 0, 14: 0, 100: 0, 828: 0 };
const filteredEdits = response.query.usercontribs.filter(edit => {
// החרגת תיבות משתמש במרחב תבנית
if (edit.ns === 10 && edit.title.includes('תיבת משתמש')) {
return false;
}
// ספירה לסטטיסטיקה
if (stats[edit.ns] !== undefined) {
stats[edit.ns]++;
}
return true;
});
const editsCount = filteredEdits.length;
const hasMore = !!response.continue;
updateModalWithResults(targetUser, editsCount, filteredEdits, hasMore, stats);
} catch (error) {
console.error("Error fetching contributions:", error);
$('#vote-checker-content').html('<p style="color: #d33;">אירעה שגיאה במשיכת הנתונים. ודאו שאתם מחוברים.</p>');
}
}
function showInitialModal(username) {
$('#vote-checker-modal, #modal-overlay').remove();
const modalHtml = `
<div id="modal-overlay" style="position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.2); z-index:9999;"></div>
<div id="vote-checker-modal" style="position:fixed; top:50%; left:50%; transform:translate(-50%, -50%); background:#fff; color:#202122; border:1px solid #a2a9b1; padding:0; z-index:10000; box-shadow:0 4px 15px rgba(0,0,0,0.15); border-radius:4px; min-width:450px; text-align:right; font-family: system-ui, -apple-system, sans-serif; direction: rtl;">
<div style="background:#f8f9fa; border-bottom:1px solid #a2a9b1; padding:12px 15px; font-weight:bold; display:flex; justify-content:space-between; align-items:center; border-radius:4px 4px 0 0;">
<span style="font-size:1.1em;">בדיקת זכות הצבעה (מרחבים משיקים)</span>
<span id="close-vote-modal-x" style="cursor:pointer; font-size:22px; color:#72777d; line-height:1;">×</span>
</div>
<div id="vote-checker-content" style="padding:20px 15px; max-height: 500px; overflow-y: auto;">
<div style="display:flex; align-items:center; gap:12px;">
<img src="https://upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif" alt="טוען...">
<span>מנתח עריכות עבור <b>${username}</b>...</span>
</div>
</div>
<div style="padding:12px 15px; background:#f8f9fa; border-top:1px solid #a2a9b1; text-align:left; border-radius:0 0 4px 4px;">
<button id="close-vote-modal-btn" style="padding:6px 16px; cursor:pointer; background:#36c; color:#fff; border:1px solid #36c; border-radius:2px; font-weight:bold; font-size:13px;">סגור</button>
</div>
</div>
`;
$('body').append(modalHtml);
$('#close-vote-modal-btn, #close-vote-modal-x, #modal-overlay').on('click', function() {
$('#vote-checker-modal, #modal-overlay').remove();
});
}
function updateModalWithResults(username, count, filteredEdits, hasMore, stats) {
let titleColor = "#36c";
const isEligible = count >= REQUIRED_EDITS || hasMore;
const countDisplay = hasMore ? "מעל 500" : count;
// בניית רשימת עריכות
const recentEditsList = filteredEdits.map((edit, index) => {
const time = new Date(edit.timestamp).toLocaleTimeString('he-IL', {hour: '2-digit', minute:'2-digit'});
const date = new Date(edit.timestamp).toLocaleDateString('he-IL', {day: '2-digit', month:'2-digit'});
// הקישור מוביל כעת ישירות לערך עצמו
const pageUrl = mw.util.getUrl(edit.title);
return `
<li style="font-size: 0.85em; border-bottom: 1px solid #eee; padding: 4px 0; display: flex; justify-content: space-between; align-items: center;">
<span style="color: #72777d; min-width: 90px; font-size: 0.9em;">${index + 1}. ${date} ${time}</span>
<a href="${pageUrl}" target="_blank" style="text-decoration: none; color: #36c; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 280px; flex-grow: 1; text-align: right; margin-right: 10px;" title="מעבר לדף: ${edit.title}">
${edit.title}
</a>
</li>
`;
}).join('');
let statsHtml = `
<div id="vote-details" style="display:none; margin-top:15px; padding:10px; background:#f1f3f5; border-radius:4px; font-size:0.9em;">
<div style="font-weight:bold; border-bottom:1px solid #ccc; margin-bottom:8px; padding-bottom:3px;">סיכום לפי מרחבים:</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 5px; margin-bottom: 15px;">
${Object.entries(NAMESPACES_MAP).map(([id, name]) => `
<div style="display:flex; justify-content:space-between; background: #fff; padding: 4px 8px; border: 1px solid #e2e2e2; border-radius: 2px;">
<span>${name}:</span>
<span style="font-weight:bold;">${stats[id]}</span>
</div>
`).join('')}
</div>
<div style="font-weight:bold; border-bottom:1px solid #ccc; margin-bottom:8px; padding-bottom:3px;">רשימת העריכות שנספרו (לחיצה למעבר לערך):</div>
<div style="max-height: 250px; overflow-y: auto; background: #fff; padding: 5px 10px; border: 1px solid #e2e2e2; border-radius: 2px;">
<ul style="list-style:none; padding:0; margin:0;">
${recentEditsList || '<li>לא נמצאו עריכות בטווח הזמן.</li>'}
</ul>
</div>
<div style="text-align: center; color: #72777d; font-size: 0.8em; margin-top: 8px;">סה"כ מוצגות ${filteredEdits.length} עריכות</div>
</div>
`;
let message = "";
if (isEligible) {
titleColor = "#14866d";
message = `
<div style="color:${titleColor}; font-weight:bold; margin-bottom:12px; font-size:1.2em; border-right:4px solid ${titleColor}; padding-right:10px;">נמצאה זכות הצבעה!</div>
למשתמש יש <b>${countDisplay}</b> עריכות במרחבי התוכן ב-90 הימים האחרונים.
`;
} else {
titleColor = "#d33";
const missing = REQUIRED_EDITS - count;
message = `
<div style="color:${titleColor}; font-weight:bold; margin-bottom:12px; font-size:1.2em; border-right:4px solid ${titleColor}; padding-right:10px;">אין זכות הצבעה כרגע</div>
נמצאו רק <b>${count}</b> עריכות במרחבי התוכן ב-90 הימים האחרונים.
<br>חסרות עוד <b>${missing}</b> עריכות להשלמת המכסה.
`;
}
message += `
<div style="margin-top:15px; font-size:0.9em; color:#54595d;">
<button id="toggle-stats" style="background:#eaecf0; border:1px solid #a2a9b1; color:#202122; cursor:pointer; padding:4px 12px; border-radius:2px; font-size:0.9em; font-weight: bold;">הצג פירוט וכל העריכות שנספרו</button>
</div>
${statsHtml}
`;
$('#vote-checker-content').html(message);
$('#toggle-stats').on('click', function() {
const isVisible = $('#vote-details').is(':visible');
$(this).text(isVisible ? 'הצג פירוט וכל העריכות שנספרו' : 'הסתר פירוט עריכות');
$('#vote-details').slideToggle();
});
}
$(document).ready(function () {
const link = mw.util.addPortletLink(
'p-tb',
'#',
'כמה חסר לזכות הצבעה',
't-check-missing-edits',
'בדיקה כמה עריכות חסרות במרחבי התוכן ב-90 הימים האחרונים'
);
if (link) {
$(link).on('click', function (e) {
e.preventDefault();
checkVotingRights();
});
}
});
})();