MediaWiki:Common.js: Perbedaan antara revisi
Tidak ada ringkasan suntingan Tanda: Dikembalikan Suntingan perangkat seluler Suntingan peramban seluler |
Tidak ada ringkasan suntingan Tanda: Pengembalian manual Suntingan perangkat seluler Suntingan peramban seluler |
||
| (144 revisi perantara oleh 2 pengguna tidak ditampilkan) | |||
| Baris 1: | Baris 1: | ||
/* Script Estimasi Waktu Baca - Spesialis Mobile (Minerva) & Desktop */ | /* Script Estimasi Waktu Baca - Spesialis Mobile (Minerva) & Desktop */ | ||
$(document).ready(function() { | $(document).ready(function() { | ||
// Hanya jalan di halaman artikel asli | // Hanya jalan di halaman artikel asli dan BUKAN di Halaman Utama | ||
if (mw.config.get('wgIsArticle') && mw.config.get('wgAction') === 'view' && mw.config.get('wgNamespaceNumber') === 0) { | if (mw.config.get('wgIsArticle') && mw.config.get('wgAction') === 'view' && mw.config.get('wgNamespaceNumber') === 0 && !mw.config.get('wgIsMainPage')) { | ||
function hitungWaktuBaca() { | function hitungWaktuBaca() { | ||
| Baris 15: | Baris 15: | ||
// Bikin elemen tampilannya | // Bikin elemen tampilannya | ||
var icon = '🕒'; // Emoji jam biar simpel dan ringan | var icon = '🕒'; // Emoji jam biar simpel dan ringan | ||
var label = (readingTime <= 1) ? ' | var label = (readingTime <= 1) ? '- 1 menit' : readingTime + ' menit'; | ||
var html = '<div id="reading-time-auto" style="font-size: 0.9em; color: #54595d; margin-bottom: 15px; display: flex; align-items: center; font-family: sans-serif;">'; | var html = '<div id="reading-time-auto" style="font-size: 0.9em; color: #54595d; margin-bottom: 15px; display: flex; align-items: center; font-family: sans-serif;">'; | ||
html += '<span style="margin-right: 5px;">' + icon + '</span>'; | html += '<span style="margin-right: 5px;">' + icon + '</span>'; | ||
html += '<span>Estimasi waktu baca: <b>' + label + '</b></span>'; | html += '<span>Estimasi waktu baca : <b>' + label + '</b></span>'; | ||
html += '</div>'; | html += '</div>'; | ||
| Baris 36: | Baris 36: | ||
} | } | ||
}); | }); | ||
/* Script Tombol Back to Top (Spesial Mobile) */ | /* Script Tombol Back to Top (Spesial Mobile) */ | ||
| Baris 59: | Baris 58: | ||
}); | }); | ||
}); | }); | ||
/* 3. Anti-Ghosting pada Link Kosong (Redlinks) */ | /* 3. Anti-Ghosting pada Link Kosong (Redlinks) */ | ||
| Baris 139: | Baris 67: | ||
} | } | ||
}); | }); | ||
}); | }); | ||
| Baris 375: | Baris 78: | ||
// Tambah atau hapus di dalam kurung siku ini. Gunakan koma sebagai pemisah. | // Tambah atau hapus di dalam kurung siku ini. Gunakan koma sebagai pemisah. | ||
var protectedPages = [ | var protectedPages = [ | ||
"MediaWiki:", | "MediaWiki:Common.js", | ||
" | "Istimewa:Versi" | ||
]; | ]; | ||
| Baris 481: | Baris 181: | ||
// Ubah judul tab browser | // Ubah judul tab browser | ||
document.title = "Akses Dilindungi - Mippedia bahasa Indonesia, ensiklopedia umum"; | document.title = "Akses Dilindungi - Mippedia bahasa Indonesia, ensiklopedia umum"; | ||
} | } | ||
}); | }); | ||
| Baris 1.001: | Baris 654: | ||
/* ========================================================== | /* ========================================================== | ||
🔵 MIPPEDIA ULTIMATE VERIFICATION SYSTEM (V3 - HIGH SECURITY) | |||
Fitur: Identitas Rahasia, Tombol Tolak, & Auto-Purge Data | |||
========================================================== */ | |||
$(document).ready(function() { | |||
var user = mw.config.get('wgUserName'); | |||
var pageName = mw.config.get('wgPageName'); | |||
var ns = mw.config.get('wgNamespaceNumber'); | |||
var isAdmin = mw.config.get('wgUserGroups').includes('sysop'); | |||
var api = new mw.Api(); | |||
var vFile = 'Verified_Badge.png'; | |||
// --- 1. POP-UP TERVERIFIKASI --- | |||
function showVerifiedPopup() { | |||
api.parse('[[Berkas:' + vFile + '|60px|link=|middle]]').done(function(renderedImage) { | |||
var modalHtml = '<div id="mippedia-v-modal" style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.75);z-index:99999;display:flex;align-items:center;justify-content:center;">' + | |||
'<div style="background:#fff;padding:30px;border-radius:20px;width:85%;max-width:320px;text-align:center;box-shadow:0 15px 35px rgba(0,0,0,0.5);position:relative;">' + | |||
'<div style="margin-bottom:15px;">' + renderedImage + '</div>' + | |||
'<h2 style="margin:0 0 10px 0;color:#1a1a1a;font-family:sans-serif;font-size:20px;font-weight:bold;">Akun Terverifikasi</h2>' + | |||
'<p style="color:#555;line-height:1.5;font-size:13px;margin-bottom:20px;font-family:sans-serif;">Mippedia telah mengonfirmasi bahwa identitas pemilik akun ini adalah asli. Lencana ini menandakan kredibilitas tinggi di dalam komunitas kami.</p>' + | |||
'<button id="close-v-modal" style="background:#0095f6;color:#fff;border:none;padding:12px 0;width:100%;border-radius:10px;cursor:pointer;font-weight:bold;font-size:14px;">Mengerti</button>' + | |||
'</div></div>'; | |||
$('body').append(modalHtml); | |||
$('#close-v-modal').click(function() { $('#mippedia-v-modal').remove(); }); | |||
}); | |||
} | |||
// --- 2. LOGIKA CENTANG BIRU GLOBAL --- | |||
function applyGlobalBadge($element) { | |||
if ($element.data('has-badge') || $element.next('.mippedia-badge-global').length) return; | |||
api.parse('[[Berkas:' + vFile + '|13px|link=|middle]]').done(function(renderedImage) { | |||
if ($element.next('.mippedia-badge-global').length) return; | |||
var cleanImage = $(renderedImage).find('img').first(); | |||
var $badge = $('<span class="mippedia-badge-global" style="margin-left: 4px; display: inline-flex; align-items: center; vertical-align: middle; position: relative; top: -1px; cursor: pointer;"></span>').append(cleanImage); | |||
$badge.click(function(e) { e.preventDefault(); showVerifiedPopup(); }); | |||
$element.after($badge); | |||
$element.data('has-badge', true); | |||
}); | |||
} | |||
api.get({ action: 'query', list: 'categorymembers', cmtitle: 'Category:Pengguna_Terverifikasi', cmlimit: 'max' }).done(function(data) { | |||
var verifiedUsers = data.query.categorymembers.map(function(member) { return member.title.replace('Pengguna:', ''); }); | |||
function scanLinks() { | |||
$('a.mw-userlink').each(function() { | |||
var username = $(this).text().trim(); | |||
if (verifiedUsers.includes(username)) { applyGlobalBadge($(this)); } | |||
}); | |||
} | |||
scanLinks(); | |||
mw.hook('wikipage.content').add(scanLinks); | |||
var currentTitle = mw.config.get('wgTitle'); | |||
if ((ns === 2 || ns === 3) && verifiedUsers.includes(currentTitle)) { | |||
if (!$('#firstHeading').find('.mippedia-profile-badge').length) { | |||
api.parse('[[Berkas:' + vFile + '|22px|link=|middle]]').done(function(renderedImage) { | |||
var cleanImage = $(renderedImage).find('img').first(); | |||
var $pBadge = $('<span class="mippedia-profile-badge" style="margin-left: 6px; display: inline-flex; align-items: center; vertical-align: middle; cursor: pointer;"></span>').append(cleanImage); | |||
$pBadge.click(showVerifiedPopup); | |||
$('#firstHeading').append($pBadge); | |||
}); | |||
} | |||
} | |||
}); | |||
// --- 3. AUTO-FILL TEKS PERMINTAAN (DENGAN FORM IDENTITAS RAHASIA) --- | |||
if (mw.config.get('wgAction') === 'edit' && sessionStorage.getItem('mippedia_verify_req')) { | |||
var identityTemplate = | |||
"\n\n\n" + | |||
"<div class='sysop-show' style='background:#fff5f5; border:1px solid #ff0000; padding:10px;'>\n" + | |||
"=== Data Identitas Pemohon ===\n" + | |||
"* '''Foto KTP/ID:''' [[Berkas:Isi_Nama_File_Di_Sini.jpg|thumb|150px]]\n" + | |||
"* '''Foto Selfie dengan KTP:''' [[Berkas:Isi_Nama_File_Di_Sini.jpg|thumb|150px]]\n" + | |||
"* '''Nama Lengkap:''' \n" + | |||
"* '''Tautan Media Sosial:''' \n" + | |||
"</div>\n" + | |||
""; | |||
var savedText = sessionStorage.getItem('mippedia_verify_req'); | |||
$('#wpTextbox1').val(savedText + "\n\n**Persyaratan Verifikasi:** \n(Tulis alasan mengapa akun lo layak dapet centang biru, boys!) " + identityTemplate + "\n\n<div class='mippedia-status'>'''Status: 🕒 Sedang diverifikasi'''</div>\n\n--" + user); | |||
sessionStorage.removeItem('mippedia_verify_req'); | |||
} | |||
// --- 4. SEMBUNYIKAN DATA PRIVASI DARI NON-ADMIN --- | |||
if (!isAdmin) { | |||
$('.sysop-show').hide(); | |||
} | |||
// --- 5. TOMBOL MINTA VERIFIKASI --- | |||
if (ns === 2 && user && mw.config.get('wgTitle') === user) { | |||
if (!$('#ca-verify-request').length) { | |||
var $verifyLink = $('<li>').attr({'id': 'ca-verify-request', 'class': 'mw-list-item'}).append( | |||
$('<a>').attr({'href': '#', 'title': 'Minta Verifikasi'}).css({ | |||
'display': 'flex', 'align-items': 'center', 'padding': '6px 12px' | |||
}).append( | |||
$('<span>').html('🔵 Verifikasi').css({'color': '#0095f6', 'font-weight': 'bold', 'margin-left': '2px'}) | |||
) | |||
); | |||
$verifyLink.click(function(e) { | |||
e.preventDefault(); | |||
sessionStorage.setItem('mippedia_verify_req', "Halo Pengurus Mippedia,\n\nSaya mengajukan permohonan verifikasi identitas akun untuk profil [[" + pageName + "]] sesuai dengan kebijakan komunitas."); | |||
window.location.href = mw.util.getUrl("Pembicaraan_Pengguna:" + user, { action: 'edit', section: 'new', preloadtitle: 'Permintaan Verifikasi Profil Pengguna' }); | |||
}); | |||
$('#p-cactions ul, #p-views ul').append($verifyLink); | |||
} | |||
} | |||
// --- 6. PANEL ADMIN VERIFIKASI (APPROVE & REJECT) --- | |||
if (ns === 3 && isAdmin && $('#mw-content-text').text().includes("Sedang diverifikasi")) { | |||
var targetUserPage = "Pengguna:" + mw.config.get('wgTitle'); | |||
api.get({ action: 'query', prop: 'revisions', titles: pageName, rvprop: 'user|content', rvlimit: 1 }).done(function(res) { | |||
var pg = res.query.pages[Object.keys(res.query.pages)[0]]; | |||
if (!pg || !pg.revisions) return; | |||
var requester = pg.revisions[0].user; | |||
var oldContent = pg.revisions[0]['*']; | |||
if (!$('#mw-content-text').text().includes("Permintaan Verifikasi Profil Pengguna")) return; | |||
var $panel = $('<div style="background:#f0f7ff; border:2px solid #0095f6; padding:15px; border-radius:12px; margin-bottom:15px; display:flex; flex-direction:column; gap:10px;">' + | |||
'<div><b style="color:#0095f6;">🔵 ADMIN VERIFICATION PANEL</b><br><small>Memproses permohonan: <b>'+requester+'</b></small></div></div>'); | |||
var $btnGroup = $('<div style="display:flex; gap:10px;"></div>'); | |||
var $btnApprove = $('<button>').text('✅ SETUJUI').css({'background':'#0095f6','color':'#fff','padding':'8px 15px','border':'none','border-radius':'6px','cursor':'pointer','font-weight':'bold'}); | |||
var $btnReject = $('<button>').text('❌ TOLAK').css({'background':'#ff4d4d','color':'#fff','padding':'8px 15px','border':'none','border-radius':'6px','cursor':'pointer','font-weight':'bold'}); | |||
// LOGIKA SETUJUI | |||
$btnApprove.click(function() { | |||
$(this).prop('disabled', true).text('Approving...'); | |||
sessionStorage.setItem('is_system_verify', 'true'); | |||
api.postWithToken('edit', { action: 'edit', title: targetUserPage, appendtext: '\n[[Category:Pengguna_Terverifikasi]]', summary: 'Akun Terverifikasi' | |||
}).then(function() { | |||
// HAPUS DATA PRIVASI OTOMATIS SAAT DISETUJUI | |||
var cleanText = oldContent.replace(/<div class='sysop-show'[\s\S]*?<\/div>/g, "''(Data identitas telah dihapus otomatis demi keamanan tingkat tinggi)''"); | |||
var newText = cleanText.replace("Status: 🕒 Sedang diverifikasi", "Status: ✅ '''Akun Terverifikasi''' 🔵"); | |||
return api.postWithToken('edit', { action: 'edit', title: pageName, text: newText, summary: 'Approved & Purged Identity Data' }); | |||
}).then(function() { | |||
var msg = "\n== Selamat! Profil Anda Terverifikasi ==\nHalo [["+requester+"]],\n\nKabar gembira! Tim Pengurus Mippedia telah meninjau data identitas Anda dan memutuskan untuk **MENYETUJUI** permohonan verifikasi Anda. Akun Anda kini memiliki lencana centang biru 🔵 sebagai tanda kredibilitas asli.\n\nData identitas yang Anda kirimkan telah kami hapus secara otomatis dari sistem kami demi menjaga keamanan privasi Anda. Terima kasih telah berkontribusi di Mippedia! --[[Pengguna:Admin|Admin]]"; | |||
return api.postWithToken('edit', { action: 'edit', title: "Pembicaraan_Pengguna:"+requester, section: 'new', text: msg }); | |||
}).done(function() { | |||
sessionStorage.removeItem('is_system_verify'); | |||
location.reload(); | |||
}); | |||
}); | |||
// LOGIKA TOLAK | |||
$btnReject.click(function() { | |||
$(this).prop('disabled', true).text('Rejecting...'); | |||
// HAPUS DATA PRIVASI OTOMATIS SAAT DITOLAK | |||
var cleanText = oldContent.replace(/<div class='sysop-show'[\s\S]*?<\/div>/g, "''(Data identitas telah dihapus otomatis demi keamanan tingkat tinggi)''"); | |||
var newText = cleanText.replace("Status: 🕒 Sedang diverifikasi", "Status: ❌ '''Permintaan Ditolak'''"); | |||
api.postWithToken('edit', { action: 'edit', title: pageName, text: newText, summary: 'Rejected & Purged Identity Data' | |||
}).then(function() { | |||
var msg = "\n== Informasi: Permintaan Verifikasi Belum Disetujui ==\nHalo [["+requester+"]],\n\nMohon maaf, setelah melakukan peninjauan terhadap data yang Anda kirimkan, Tim Pengurus Mippedia memutuskan untuk **BELUM DAPAT MENYETUJUI** permohonan verifikasi Anda saat ini. Hal ini bisa disebabkan oleh data yang kurang jelas atau tidak memenuhi kriteria verifikasi kami.\n\nJangan khawatir, data identitas sensitif yang Anda kirimkan sudah kami hapus secara otomatis demi keamanan Anda. Anda dapat mengajukan permohonan kembali di masa mendatang dengan data yang lebih lengkap. --[[Pengguna:Admin|Admin]]"; | |||
return api.postWithToken('edit', { action: 'edit', title: "Pembicaraan_Pengguna:"+requester, section: 'new', text: msg }); | |||
}).done(function() { | |||
location.reload(); | |||
}); | |||
}); | |||
$btnGroup.append($btnApprove, $btnReject); | |||
$panel.append($btnGroup); | |||
$('#mw-content-text').prepend($panel); | |||
}); | |||
} | |||
}); | |||
/* ========================================================== | |||
🛡️ MIPPEDIA CORE SYSTEM - NEURAL ENGINE V12 | |||
Update: Brain Upgrade - Semantic Search & Anti-Duplicate | |||
Semua fitur asli (Patroli, Promo, Kategori) tetap UTUH. | |||
========================================================== */ | |||
mw.hook('postEdit').add(function() { | |||
var rawUser = mw.config.get('wgUserName'); | |||
var userName = rawUser ? rawUser.replace(/_/g, ' ') : 'Anonim'; | |||
var isPatroli = (userName === 'Mippedia Patroli'); | |||
if (mw.config.get('wgNamespaceNumber') !== 0) return; | |||
var api = new mw.Api(); | |||
var pageTitle = mw.config.get('wgPageName').replace(/_/g, ' '); | |||
api.get({ | |||
action: 'query', | |||
titles: pageTitle, | |||
prop: 'revisions|categories|links', | |||
rvprop: 'content', | |||
clshow: '!hidden', | |||
pllimit: 'max' | |||
}).done(function(resData) { | |||
var page = resData.query.pages[Object.keys(resData.query.pages)[0]]; | |||
if (!page || !page.revisions) return; | |||
var rawContent = page.revisions[0]['*']; | |||
var content = rawContent; | |||
var summaryParts = []; | |||
// --- 1. GLOBAL ENGINE: MAINTENANCE (FITUR ASLI) --- | |||
if ((!page.categories || page.categories.length === 0) && !/\{\{Butuh Kategori/i.test(content) && !/\[\[Kategori:/i.test(content)) { | |||
content = '{{Butuh Kategori|date=April 2026}}\n' + content; | |||
summaryParts.push('+Cat'); | |||
} | |||
// --- UPGRADE ENGINE: DETEKSI SMART STUB PARAMETER & POSISI BAWAH --- | |||
var wordCount = rawContent.trim().split(/\s+/).length; | |||
if (wordCount < 200 && !/\{\{Stub/i.test(content) && !/\{\{Artikel Rintisan/i.test(content)) { | |||
var lowerContent = rawContent.toLowerCase(); | |||
var stubParam = ''; | |||
// Mapping Otak Pintar berdasarkan Kata Kunci Semantik (19 Parameter) | |||
if (/\b(lahir|wafat|tokoh|pria|wanita|biografi|sosok|pahlawan|presiden|menteri)\b/i.test(lowerContent)) { | |||
stubParam = 'biografi tokoh'; | |||
} else if (/\b(musik|lagu|album|konser|penyanyi|band|vokal|gitar|single|nada)\b/i.test(lowerContent)) { | |||
stubParam = 'musik'; | |||
} else if (/\b(geografi|negara|kota|desa|kecamatan|kabupaten|provinsi|pulau|gunung|sungai)\b/i.test(lowerContent)) { | |||
stubParam = 'geografi'; | |||
} else if (/\b(teknologi|komputer|aplikasi|software|hardware|internet|digital|android|sistem|gawai)\b/i.test(lowerContent)) { | |||
stubParam = 'teknologi'; | |||
} else if (/\b(sejarah|kerajaan|perang|prasasti|arkeo|masa lalu|kuno|dinasti|peristiwa|abad)\b/i.test(lowerContent)) { | |||
stubParam = 'sejarah'; | |||
} else if (/\b(olahraga|atlet|sepak|bola|stadion|juara|klub|tanding|liga|olimpiade)\b/i.test(lowerContent)) { | |||
stubParam = 'olahraga'; | |||
} else if (/\b(film|bioskop|aktor|aktris|sutradara|drama|sinema|serial|movie|tayang)\b/i.test(lowerContent)) { | |||
stubParam = 'film'; | |||
} else if (/\b(perusahaan|pt|perbangkan|bisnis|saham|industri|korporasi|merek|ceo|didirikan)\b/i.test(lowerContent)) { | |||
stubParam = 'perusahaan'; | |||
} else if (/\b(ilmu pengetahuan|sains|kimia|fisika|matematika|biologi|riset|laboratorium|teori|molekul)\b/i.test(lowerContent)) { | |||
stubParam = 'ilmu pengetahuan'; | |||
} else if (/\b(seni|lukisan|patung|pameran|budaya|teater|rupa|desain|kriya|estetika)\b/i.test(lowerContent)) { | |||
stubParam = 'seni'; | |||
} else if (/\b(politik|partai|pemilu|dpr|pemerintah|kebijakan|demokrasi|suara|kampanye|negara)\b/i.test(lowerContent)) { | |||
stubParam = 'politik'; | |||
} else if (/\b(militer|tni|tentara|perang|senjata|pasukan|jenderal|alutsista|batalyon|operasi)\b/i.test(lowerContent)) { | |||
stubParam = 'militer'; | |||
} else if (/\b(transportasi|kereta|pesawat|mobil|kapal|bandara|stasiun|pelabuhan|rute|kendaraan)\b/i.test(lowerContent)) { | |||
stubParam = 'transportasi'; | |||
} else if (/\b(literatur|buku|novel|puisi|sastra|penulis|penerbit|komik|cerpen|fiksi)\b/i.test(lowerContent)) { | |||
stubParam = 'literatur'; | |||
} else if (/\b(makanan|kuliner|resep|masakan|minuman|rasa|koki|restoran|hidangan|bahan)\b/i.test(lowerContent)) { | |||
stubParam = 'makanan'; | |||
} else if (/\b(kesehatan|medis|dokter|penyakit|obat|rumah sakit|klinik|terapi|virus|gejala)\b/i.test(lowerContent)) { | |||
stubParam = 'kesehatan'; | |||
} else if (/\b(astronomi|bintang|planet|galaksi|teleskop|antariksa|nasa|komet|orbit|luar angkasa)\b/i.test(lowerContent)) { | |||
stubParam = 'astronomi'; | |||
} else if (/\b(agama|ibadah|kitab|tuhan|nabi|gereja|masjid|pura|vihara|iman)\b/i.test(lowerContent)) { | |||
stubParam = 'agama'; | |||
} else if (/\b(bahasa|dialek|aksara|kamus|linguistik|kata|kalimat|suku|ucapan|fonem)\b/i.test(lowerContent)) { | |||
stubParam = 'bahasa'; | |||
} else if (/\b(hukum|undang|pasal|pengadilan|hakim|jaksa|pengacara|pidana|perdata|legal)\b/i.test(lowerContent)) { | |||
stubParam = 'hukum'; | |||
} | |||
// Gabungkan teks template Stub pilihan di baris paling bawah artikel | |||
var stubTag = stubParam ? '{{Stub|' + stubParam + '}}' : '{{Stub}}'; | |||
content = content.trim() + '\n\n' + stubTag; | |||
summaryParts.push('+SmartStub(' + (stubParam || 'umum') + ')'); | |||
} | |||
var promoList = ['memang hebat', 'terpercaya sekali', 'terbaik di dunia', 'hubungi nomor kami', 'harga murah', 'kualitas terjamin']; | |||
if (promoList.some(p => rawContent.toLowerCase().indexOf(p) !== -1) && !/\{\{Hapus/i.test(content)) { | |||
content = '{{Hapus|Deteksi kalimat promosi otomatis}}\n' + content; | |||
summaryParts.push('+Promo'); | |||
} | |||
// --- 2. SUPER INTELLIGENCE RELATED (UPGRADE OTAK V12) --- | |||
var currentRelatedMatch = content.match(/\{\{#related:.*?\}\}/g) || []; | |||
if (currentRelatedMatch.length < 3) { | |||
content = content.replace(/\n*\{\{#related:.*?\}\}/g, ''); | |||
api.get({ | |||
action: 'query', | |||
list: 'search', | |||
srsearch: pageTitle, | |||
srlimit: 15, | |||
srprop: '' | |||
}).done(function(searchRes) { | |||
var candidates = {}; | |||
if (searchRes.query && searchRes.query.search) { | |||
searchRes.query.search.forEach(function(item, index) { | |||
if (item.title === pageTitle) return; | |||
candidates[item.title] = (15 - index); | |||
}); | |||
} | |||
if (page.links) { | |||
page.links.forEach(function(link) { | |||
if (link.title === pageTitle) return; | |||
candidates[link.title] = (candidates[link.title] || 0) + 5; | |||
}); | |||
} | |||
var sortedTitles = Object.keys(candidates).sort(function(a, b) { | |||
return candidates[b] - candidates[a]; | |||
}); | |||
var finalRelated = sortedTitles.filter(t => t.indexOf(':') === -1).slice(0, 3); | |||
if (finalRelated.length > 0) { | |||
var relatedTags = '\n\n' + finalRelated.map(t => '{{#related: ' + t + '}}').join('\n'); | |||
content += relatedTags; | |||
summaryParts.push('NeuralRelated'); | |||
} | |||
runPatroliAndSave(); | |||
}); | |||
} else { | |||
runPatroliAndSave(); | |||
} | |||
function runPatroliAndSave() { | |||
// --- 3. PATROLI ENGINE (FITUR ASLI - TETAP BERFUNGSI) --- | |||
if (isPatroli) { | |||
var placeholders = []; | |||
content = content.replace(/(\{\{[\s\S]*?\}\}|==+.*?==+|\[\[Kategori:.*?\]\]|<ref[\s\S]*?<\/ref>|^.*?adalah)/gi, function(match) { | |||
placeholders.push(match); | |||
return '___MIP_SKIP_' + (placeholders.length - 1) + '___'; | |||
}); | |||
api.get({ action: 'query', list: 'allpages', apnamespace: 0, aplimit: 'max' }).done(function(apData) { | |||
var allTitles = apData.query.allpages.map(p => p.title); | |||
var lowerTitles = allTitles.map(t => t.toLowerCase()); | |||
var tokens = content.split(/(\s+|\[\[|\]\])/); | |||
var inLink = false; | |||
for (var i = 0; i < tokens.length; i++) { | |||
if (tokens[i] === '[[' ) { inLink = true; continue; } | |||
if (tokens[i] === ']]' ) { inLink = false; continue; } | |||
if (inLink || tokens[i].trim().length < 3 || tokens[i].includes('___MIP_SKIP_')) continue; | |||
var wordsInToken = tokens[i].match(/\b\w+\b/g); | |||
if (wordsInToken) { | |||
wordsInToken.forEach(function(word) { | |||
var idx = lowerTitles.indexOf(word.toLowerCase()); | |||
if (idx !== -1 && allTitles[idx] !== pageTitle) { | |||
tokens[i] = tokens[i].replace(new RegExp('\\b' + word + '\\b', 'g'), '[[' + allTitles[idx] + '|' + word + ']]'); | |||
} | |||
}); | |||
} | |||
} | |||
content = tokens.join(''); | |||
content = content.replace(/___MIP_SKIP_(\d+)___/g, function(match, id) { return placeholders[id]; }); | |||
content = content.replace(/\[\[([^|\]:]+)\]\]/g, function(match, p1) { | |||
return lowerTitles.includes(p1.toLowerCase()) ? match : p1; | |||
}); | |||
saveAction(); | |||
}); | |||
} else { | |||
saveAction(); | |||
} | |||
} | |||
function saveAction() { | |||
// --- 4. EKSEKUSI --- | |||
if (content.trim() !== rawContent.trim()) { | |||
api.postWithToken('edit', { | |||
action: 'edit', | |||
title: pageTitle, | |||
text: content, | |||
summary: 'Mippedia Neural Engine V12: ' + summaryParts.join(', '), | |||
bot: true, markasbot: true | |||
}).done(function() { location.reload(); }); | |||
} | |||
} | |||
}); | |||
}); | |||
/* ========================================================== | |||
🚀 MIPPEDIA DATA BUTTON ONLY (Otomatis) | |||
Hanya memunculkan tombol jika data tersedia di pusat. | |||
========================================================== */ | ========================================================== */ | ||
$(document).ready(function() { | $(document).ready(function() { | ||
var pageName = mw.config.get('wgPageName'); | var pageName = mw.config.get('wgPageName'); | ||
var | var namespace = mw.config.get('wgNamespaceNumber'); | ||
var | var dataDomain = 'https://data.mippedia.org'; | ||
// Jalankan hanya di namespace artikel | |||
if (namespace === 0) { | |||
// Cek apakah halaman tersebut ada di Mippedia Data | |||
$.ajax({ | |||
url: dataDomain + '/api.php', | |||
data: { | |||
action: 'query', | |||
titles: pageName, | |||
format: 'json', | |||
origin: '*' | |||
}, | |||
dataType: 'jsonp', | |||
success: function(res) { | |||
var pages = res.query.pages; | |||
var isExist = false; | |||
// Cek apakah ID halaman > 0 (artinya halaman ada) | |||
for (var id in pages) { | |||
if (parseInt(id) > 0) { | |||
isExist = true; | |||
break; | |||
} | |||
} | |||
// Jika data ditemukan, munculkan tombol melayang | |||
if (isExist) { | |||
injectFloatingDataBtn(pageName, dataDomain); | |||
} | |||
} | |||
}); | }); | ||
} | } | ||
function injectFloatingDataBtn(name, domain) { | |||
if ($('#mippedia-data-btn').length) return; | |||
var | |||
var $btn = $('<a>', { | |||
id: 'mippedia-data-btn', | |||
href: domain + '/wiki/' + encodeURIComponent(name), | |||
target: '_blank', | |||
style: 'position: absolute; right: 10px; top: -32px; background: #36c; color: #fff; padding: 4px 10px; border-radius: 4px; font-weight: bold; font-size: 10px; text-decoration: none; z-index: 1000; box-shadow: 0 2px 4px rgba(0,0,0,0.1);', | |||
text: 'DATA' | |||
}); | |||
// Target: Area menu aksi (dekat ikon pensil) | |||
// Mendukung skin Mobile (Minerva) dan Desktop | |||
var $target = $('.page-actions-menu, .mw-editsection-visualeditor, #ca-edit, .minerva__tab-container').first(); | |||
if ($target.length) { | |||
$target.css('position', 'relative').append($btn); | |||
$('. | } else { | ||
// Fallback jika header tidak standar | |||
$('#firstHeading').css('position', 'relative').append($btn); | |||
} | |||
} | |||
}); | |||
/* ========================================================== | |||
🚀 MIPPEDIA COMMAND CENTER: AUTO-SYNC ENGINE (V4) | |||
Status: Global Login User | Auto-Purge | High Reliability | |||
========================================================== */ | |||
(function($, mw) { | |||
"use strict"; | |||
var conf = mw.config.get(['wgNamespaceNumber', 'wgAction', 'wgPageName', 'wgIsMainPage', 'wgUserName']); | |||
// Filter: Hanya artikel, hanya saat baca, hanya user yang sudah login | |||
if (conf.wgNamespaceNumber !== 0 || conf.wgAction !== 'view' || conf.wgIsMainPage || conf.wgUserName === null) return; | |||
$(document).ready(function() { | |||
var currentTitle = conf.wgPageName; | |||
// Penentuan subdomain (id, en, concise) | |||
var hostParts = window.location.hostname.split('.'); | |||
var langKey = hostParts[0] === 'mippedia' || hostParts[0] === 'www' ? 'id' : hostParts[0]; | |||
$.ajax({ | |||
url: 'https://data.mippedia.org/api.php', | |||
data: { | |||
action: 'query', | |||
prop: 'revisions', | |||
titles: 'MediaWiki:ShortDesc-Data.json', | |||
rvprop: 'content', | |||
format: 'json', | |||
origin: '*' | |||
}, | |||
dataType: 'jsonp', | |||
success: function(res) { | |||
try { | |||
var pages = res.query.pages; | |||
var pageId = Object.keys(pages)[0]; | |||
if (pageId === "-1") return; | |||
var fullData = JSON.parse(pages[pageId].revisions[0]['*']); | |||
var targetDesc = (fullData[currentTitle] && fullData[currentTitle][langKey]) ? fullData[currentTitle][langKey].trim() : ""; | |||
syncMetadata(currentTitle, targetDesc); | |||
} catch (e) { | |||
console.log("Mippedia System: Data sync not required or entry missing."); | |||
} | } | ||
} | } | ||
}); | }); | ||
function syncMetadata(title, dataCenterDesc) { | |||
var api = new mw.Api(); | |||
api.get({ | |||
action: 'query', | |||
prop: 'revisions', | |||
titles: title, | |||
var | rvprop: 'content', | ||
formatversion: 2 | |||
}).done(function(data) { | |||
var content = data.query.pages[0].revisions[0].content; | |||
var shortDescPattern = /\{\{SHORTDESC:.*?\}\}\n?/gi; | |||
var hasLocalDesc = shortDescPattern.test(content); | |||
var localMatch = content.match(/\{\{SHORTDESC:(.*?)\}\}/i); | |||
' | var currentLocalDesc = localMatch ? localMatch[1].trim() : ""; | ||
// AKSI 1: HAPUS (Jika di pusat kosong/dihapus, tapi di artikel lokal masih ada) | |||
if (dataCenterDesc === "" && hasLocalDesc) { | |||
console.log("Mippedia: Purging metadata..."); | |||
saveEdit(title, content.replace(shortDescPattern, ""), "Purge out-of-sync metadata"); | |||
} | |||
// AKSI 2: UPDATE/TAMBAH (Jika data di pusat ada dan beda dengan lokal) | |||
else if (dataCenterDesc !== "" && dataCenterDesc !== currentLocalDesc) { | |||
console.log("Mippedia: Syncing with Data Center..."); | |||
var cleanedContent = content.replace(shortDescPattern, ""); | |||
// Menaruh di paling atas agar terbaca Extension ShortDescription | |||
var newContent = '{{SHORTDESC:' + dataCenterDesc + '}}\n' + cleanedContent; | |||
saveEdit(title, newContent, "Sync metadata: " + dataCenterDesc); | |||
} | |||
}); | |||
} | |||
function saveEdit(title, text, summary) { | |||
// Menggunakan token user yang sedang login saat ini | |||
new mw.Api().postWithEditToken({ | |||
action: 'edit', | |||
title: title, | |||
text: text, | |||
summary: '🤖 ' + summary, | |||
minor: true // Menandai sebagai suntingan kecil | |||
// Parameter 'bot: true' DIHAPUS agar bisa dijalankan semua pengguna login | |||
}).done(function() { | |||
console.log("Mippedia: " + title + " synced successfully."); | |||
}); | }); | ||
} | } | ||
}); | }); | ||
})(jQuery, mediaWiki); | |||
/* ========================================================== | |||
🚀 MIPPEDIA METADATA GUARD - RADAR SYSTEM (V5) | |||
Status: Professional Messaging | Hybrid Mobile/Desktop | |||
========================================================== */ | |||
(function($, mw) { | |||
"use strict"; | |||
var ns = mw.config.get('wgNamespaceNumber'); | |||
if (ns !== 0 || mw.config.get('wgIsMainPage')) return; | |||
var shortDescRegex = /\{\{SHORTDESC:.*?\}\}/gi; | |||
var originalShortDesc = null; | |||
function validateAndBlock(e) { | |||
var $textbox = $('#wpTextbox1, textarea.previewable-render, .editor-container textarea, textarea[name="wpTextbox1"]'); | |||
if (!$textbox.length) return true; | |||
var | |||
var currentContent = $textbox.val() || ""; | |||
var currentMatch = currentContent.match(shortDescRegex); | |||
var currentShortDesc = currentMatch ? currentMatch[0] : ""; | |||
if (originalShortDesc === null) { | |||
originalShortDesc = currentShortDesc; | |||
return true; | |||
} | |||
if (originalShortDesc !== currentShortDesc) { | |||
// --- PESAN PROFESIONAL BARU --- | |||
window.alert( | |||
"MIPPEDIA SYSTEM NOTIFICATION\n" + | |||
"────────────────────────────\n\n" + | |||
"Suntingan anda tidak bisa di lanjutkan untuk di terbitkan, Karena sinkronisasi otomatis terdeteksi tidak valid.\n\n" + | |||
"Untuk menjaga integritas metadata, deskripsi singkat (ShortDescription) wajib dikelola melalui repositori Mippedia Data.\n\n" + | |||
"Harap urungkan perubahan manual pada kode {{SHORTDESC}} untuk melanjutkan proses penyimpanan." | |||
); | |||
e.preventDefault(); | e.preventDefault(); | ||
e.stopPropagation(); | |||
e.stopImmediatePropagation(); | |||
} | return false; | ||
} | |||
return true; | |||
} | } | ||
// Radar untuk menangkap elemen editor saat muncul (terutama di Mobile) | |||
var observer = new MutationObserver(function() { | |||
var $textbox = $('#wpTextbox1, .editor-container textarea, textarea[name="wpTextbox1"]'); | |||
if ($textbox.length && originalShortDesc === null) { | |||
var content = $textbox.val() || ""; | |||
var match = content.match(shortDescRegex); | |||
originalShortDesc = match ? match[0] : ""; | |||
} | |||
}); | |||
observer.observe(document.body, { childList: true, subtree: true }); | |||
// Event listener untuk tombol simpan di berbagai platform | |||
$(document).on('click mousedown touchstart', | |||
'#wpSave, .mw-ui-button.primary, button.submit, .editor-save, .save-button, button[type="submit"]', | |||
function(e) { | |||
return validateAndBlock(e); | |||
} | |||
); | |||
window.addEventListener('submit', function(e) { | |||
if (!validateAndBlock(e)) e.preventDefault(); | |||
}, true); | |||
})(jQuery, mediaWiki); | |||
$(function() { | |||
$('.ambox-learn-more').on('click', function(e) { | |||
e.preventDefault(); | |||
var $parentBox = $(this).closest('.ambox'); | |||
$parentBox.toggleClass('ambox-active'); | |||
$parentBox.find('.ambox-text-long').slideToggle('fast'); | |||
// Ubah teks tombol pas dibuka | |||
if ($parentBox.hasClass('ambox-active')) { | |||
$(this).text('Sembunyikan'); | |||
} else { | |||
$(this).text('Pelajari selengkapnya'); | |||
} | |||
}); | |||
}); | }); | ||