Lompat ke isi

MediaWiki:Common.js

Dari Mippedia bahasa Indonesia ringkas, ensiklopedia umum
Revisi sejak 20 April 2026 21.48 oleh Admin (bicara | kontrib)
(beda) ← Revisi sebelumnya | Revisi terkini (beda) | Revisi selanjutnya → (beda)

Catatan: Setelah menerbitkan, Anda mungkin perlu melewati tembolok peramban web Anda untuk melihat perubahan.

  • Firefox/Safari: Tekan dan tahan Shift sembari mengeklik Reload, atau tekan Ctrl-F5 atau Ctrl-R (⌘-R di Mac)
  • Google Chrome: Tekan Ctrl-Shift-R (⌘-Shift-R di Mac)
  • Edge: Tahan Ctrl sembari mengeklik Refresh, atau tekan Ctrl-F5
/* Script Estimasi Waktu Baca - Spesialis Mobile (Minerva) & Desktop */
$(document).ready(function() {
    // Hanya jalan di halaman artikel asli
    if (mw.config.get('wgIsArticle') && mw.config.get('wgAction') === 'view' && mw.config.get('wgNamespaceNumber') === 0) {
        
        function hitungWaktuBaca() {
            // Ambil teks dari konten utama
            var content = $('#mw-content-text').text();
            
            // Hitung jumlah kata (asumsi rata-rata orang baca 200 kata per menit)
            var wordsPerMinute = 200;
            var textLength = content.split(/\s+/).length; // Pecah berdasarkan spasi
            var readingTime = Math.ceil(textLength / wordsPerMinute);
            
            // Bikin elemen tampilannya
            var icon = '🕒'; // Emoji jam biar simpel dan ringan
            var label = (readingTime <= 1) ? 'Kurang dari 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;">';
            html += '<span style="margin-right: 5px;">' + icon + '</span>';
            html += '<span>Estimasi waktu baca: <b>' + label + '</b></span>';
            html += '</div>';

            // PENEMPELAN TARGET:
            // Di Minerva (HP), judul biasanya ada di .page-heading
            // Di Vector (Desktop), judul ada di #firstHeading
            if ($('.page-heading').length) {
                $('.page-heading').after(html); // Target Mobile
            } else if ($('#firstHeading').length) {
                $('#firstHeading').after(html); // Target Desktop
            }
        }

        // Jalankan fungsi
        hitungWaktuBaca();
    }
});


/* Script Tombol Back to Top (Spesial Mobile) */
$(document).ready(function() {
    // Bikin tombolnya lewat JS biar gak ribet edit CSS/HTML
    var btnHtml = '<div id="backToTop" style="display:none; position:fixed; bottom:80px; right:20px; z-index:9999; background:#36c; color:#fff; width:45px; height:45px; border-radius:50%; text-align:center; line-height:45px; font-size:24px; cursor:pointer; box-shadow: 0 4px 6px rgba(0,0,0,0.3); opacity: 0.8;">↑</div>';
    $('body').append(btnHtml);

    // Fungsi munculin tombol pas di-scroll
    $(window).scroll(function() {
        if ($(this).scrollTop() > 300) {
            $('#backToTop').fadeIn();
        } else {
            $('#backToTop').fadeOut();
        }
    });

    // Fungsi pas tombol diklik
    $('#backToTop').click(function() {
        $('html, body').animate({scrollTop: 0}, 600);
        return false;
    });
});


/* Smart Glossary Pop-up (Pratinjau Link Ringan) */
$(document).ready(function() {
    if (mw.config.get('wgIsArticle') && mw.config.get('wgAction') === 'view') {
        
        var timer;
        // Targetkan link di dalam konten artikel saja
        $('#mw-content-text a').on('mouseenter touchstart', function(e) {
            var $link = $(this);
            var title = $link.attr('title');
            
            // Jangan jalan kalau link-nya bukan artikel (misal link luar atau redlink)
            if (!title || $link.hasClass('new') || $link.hasClass('external')) return;

            timer = setTimeout(function() {
                $.getJSON(mw.util.wikiScript('api'), {
                    action: 'query',
                    prop: 'extracts',
                    exintro: true,
                    exsentences: 2, // Ambil 2 kalimat aja biar singkat
                    titles: title,
                    explaintext: true,
                    format: 'json'
                }, function(data) {
                    var pages = data.query.pages;
                    var pageId = Object.keys(pages)[0];
                    var extract = pages[pageId].extract;

                    if (extract) {
                        // Hapus pop-up lama kalau ada
                        $('.wiki-preview').remove();

                        var preview = $('<div class="wiki-preview" style="position:absolute; background:#fff; color:#202122; border:1px solid #a2a9b1; padding:12px; border-radius:8px; box-shadow:0 4px 12px rgba(0,0,0,0.2); z-index:10001; font-size:13px; max-width:250px; line-height:1.4; opacity:0; transition:opacity 0.3s ease;"></div>');
                        preview.text(extract);
                        
                        $('body').append(preview);

                        // Atur posisi pop-up di deket link
                        var offset = $link.offset();
                        preview.css({
                            top: offset.top + 25,
                            left: Math.min(offset.left, $(window).width() - 270),
                            opacity: 1
                        });

                        // Hilang kalau klik di mana aja atau setelah 5 detik
                        setTimeout(function() { $('.wiki-preview').fadeOut(function() { $(this).remove(); }); }, 5000);
                    }
                });
            }, 600); // Delay 0.6 detik biar gak ganggu kalau cuma scrolling lewat
        }).on('mouseleave', function() {
            clearTimeout(timer);
        });

        $(document).on('mousedown touchstart', function() {
            $('.wiki-preview').remove();
        });
    }
});

/* 3. Notifikasi Link Luar */
$(document).ready(function() {
    $('a.external').click(function(e) {
        var url = $(this).attr('href');
        if (!confirm('Anda akan meninggalkan Mippedia menuju situs luar:\n' + url + '\n\nLanjutkan?')) {
            e.preventDefault();
        }
    });
});


/* 3. Anti-Ghosting pada Link Kosong (Redlinks) */
$(document).ready(function() {
    $('a.new').click(function(e) {
        var confirmCreate = confirm("Halaman ini belum tersedia di Mippedia.\n\nApakah Anda ingin berkontribusi membuatnya?");
        if (!confirmCreate) {
            e.preventDefault();
        }
    });
});

/* 2. Auto-Night Shift (Berdasarkan Jam Lokal) */
$(document).ready(function() {
    var hour = new Date().getHours();
    if (hour >= 21 || hour < 6) { // Jam 9 malem sampe 6 pagi
        $("<style id='night-shift'>").prop("type", "text/css").html(`
            body::after {
                content: "";
                position: fixed;
                top: 0; left: 0;
                width: 100vw; height: 100vh;
                background: rgba(255, 165, 0, 0.05); /* Filter orange tipis */
                pointer-events: none;
                z-index: 99999;
            }
        `).appendTo("head");
    }
});

/* 3. Smooth Fade-In saat Ganti Halaman */
$(document).ready(function() {
    $('body').css({'opacity': '0', 'transition': 'opacity 0.5s ease'});
    setTimeout(function() { $('body').css('opacity', '1'); }, 100);
});

/* ==========================================================
   🛡️ MIPPEDIA SHIELD: PROTEKSI HALAMAN SENSITIF (FULL CODE)
   Hanya untuk Pengurus, Birokrat, dan Pengawas.
   ========================================================== */
$(document).ready(function() {
    
    // 1. DAFTAR HALAMAN YANG MAU DIKUNCI
    // Tambah atau hapus di dalam kurung siku ini. Gunakan koma sebagai pemisah.
    var protectedPages = [
        "MediaWiki:Common.css",
        "MediaWiki:Common.js",
        "Istimewa:Versi"
    ];

    // 2. CEK STATUS USER & HALAMAN
    var userGroups = mw.config.get('wgUserGroups') || [];
    // Daftar grup yang KEBAL proteksi (bisa akses halaman)
    var isStaff = userGroups.some(r => ["sysop", "bureaucrat", "steward", "interface-admin"].includes(r));
    
    var currentPage = mw.config.get('wgPageName');
    // Cek apakah halaman saat ini masuk dalam daftar proteksi
    var shouldProtect = protectedPages.some(prefix => currentPage.startsWith(prefix.replace(/ /g, '_')));

    // 3. EKSEKUSI PROTEKSI (Hanya jika user BUKAN staff)
    if (shouldProtect && !isStaff) {
        
        // Hapus total konten asli agar tidak bisa diintip/disunting
        $('body').addClass('mippedia-locked').html('');

        // Inject CSS khusus untuk tampilan Mobile-Friendly & Auto-Center
        $('<style>').prop('type', 'text/css').html(`
            html, body { 
                margin: 0 !important; 
                padding: 0 !important; 
                height: 100% !important; 
                width: 100% !important; 
                overflow: hidden !important; 
                background: #f8f9fa !important;
            }
            #protection-wrapper {
                display: flex;
                align-items: center;
                justify-content: center;
                min-height: 100vh;
                width: 100vw;
                padding: 20px;
                box-sizing: border-box;
                font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
            }
            .protection-card {
                width: 100%;
                max-width: 400px;
                background: #ffffff;
                padding: 40px 25px;
                border-radius: 30px;
                box-shadow: 0 15px 50px rgba(54, 102, 204, 0.15);
                border: 1px solid #eef0f2;
                text-align: center;
            }
            .shield-icon { font-size: 70px; display: block; margin-bottom: 20px; }
            .lock-title { color: #1a1a1a; font-size: 24px; font-weight: 800; margin: 0 0 15px 0; }
            .lock-desc { color: #5f6368; font-size: 15px; line-height: 1.6; margin-bottom: 25px; }
            .admin-notice { 
                background: #fff5f5; 
                color: #d93025; 
                padding: 12px; 
                border-radius: 12px; 
                font-size: 13px; 
                font-weight: 700; 
                margin-bottom: 30px; 
                border: 1px solid #fadbd8;
            }
            .btn-back { 
                background: #36c; 
                color: #fff; 
                border: none; 
                padding: 16px; 
                border-radius: 18px; 
                font-weight: 700; 
                font-size: 16px;
                width: 100%; 
                cursor: pointer; 
                box-shadow: 0 4px 12px rgba(51, 102, 204, 0.3);
            }
            .link-home { display: block; margin-top: 20px; color: #70757a; font-size: 14px; text-decoration: none; }
            .footer-ver { margin-top: 40px; font-size: 10px; color: #bdc1c6; font-weight: bold; letter-spacing: 2px; }
        `).appendTo('head');

        // Tampilkan layar kunci
        var shieldHTML = `
            <div id="protection-wrapper">
                <div class="protection-card">
                    <span class="shield-icon">🛡️</span>
                    <h2 class="lock-title">Akses Dibatasi</h2>
                    <p class="lock-desc">
                        Halaman ini telah dilindungi oleh <b>Mippedia Community</b> untuk menjaga stabilitas sistem.
                    </p>
                    <div class="admin-notice">
                        Hanya Administrator & Birokrat yang dapat mengakses halaman ini.
                    </div>
                    <button class="btn-back" onclick="window.history.back()">
                        Kembali ke Halaman Sebelumnya
                    </button>
                    <a href="/" class="link-home">Kembali ke Beranda</a>
                    <div class="footer-ver">MIPPEDIA COMMUNITY SECURE v2.0</div>
                </div>
            </div>
        `;

        $('body').append(shieldHTML);
        
        // Ubah judul tab browser
        document.title = "Akses Dilindungi - Mippedia bahasa Indonesia, ensiklopedia umum";
    }
});

/* ==========================================================
   🛡️ MIPPEDIA FILE VERIFICATION SYSTEM v3.1 (PRECISION)
   Fix: Kotak lebih ramping & Ikon lebih proporsional
   ========================================================== */
$(document).ready(function() {
    if (mw.config.get('wgNamespaceNumber') === 6) {
        
        var $content = $('#mw-content-text');
        var pageText = $content.text();
        var badgeTitle = "";
        var badgeStyle = "";

        if (pageText.includes("Aset Resmi")) {
            badgeTitle = "ASET RESMI";
            badgeStyle = "border: 1px solid #36c; background: #f0f7ff;";
        } else if (pageText.includes("Terverifikasi")) {
            badgeTitle = "TERVERIFIKASI";
            badgeStyle = "border: 1px solid #00af89; background: #e6fffb;";
        }

        if (badgeTitle !== "") {
            // Ukuran gambar dinaikin ke 24px biar lebih jelas centangnya
            var fileName = "Verified_Badge.png"; 
            
            new mw.Api().parse('[[Berkas:' + fileName + '|24px|link=]]')
                .done(function(renderedImage) {
                    var badgeHTML = `
                        <div id="mippedia-sleek-badge" style="display: inline-flex; align-items: center; border-radius: 8px; padding: 2px 8px; margin: 5px 0 12px 0; height: 32px; box-sizing: border-box; font-family: sans-serif; vertical-align: middle; ${badgeStyle}">
                            <div style="margin-right: 6px; display: flex; align-items: center; justify-content: center; width: 24px;">${renderedImage}</div>
                            <span style="font-weight: 800; font-size: 11px; letter-spacing: 0.5px; color: #1a1a1a; text-transform: uppercase; white-space: nowrap; line-height: 1;">${badgeTitle}</span>
                        </div>
                    `;

                    $('#firstHeading').after(badgeHTML);
                    $('.mippedia-hidden-key').hide(); 
                });

            $content.find(':contains("Aset Resmi"), :contains("Terverifikasi")').each(function() {
                var $this = $(this);
                if ($this.children().length === 0 && ($this.text().trim() === "Aset Resmi" || $this.text().trim() === "Terverifikasi")) {
                    $this.addClass('mippedia-hidden-key').css('display', 'none');
                }
            });
        }
    }
});

/* ==========================================================
   🛡️ MIPPEDIA VERIFICATION SYSTEM v8.0 (ANTI-GAGAL)
   ========================================================== */
$(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 $content = $('#mw-content-text');

    // --- 1. AUTO-FILL TEKS (PENGGUNA) ---
    if (mw.config.get('wgAction') === 'edit' && sessionStorage.getItem('mippedia_req_text')) {
        var savedText = sessionStorage.getItem('mippedia_req_text');
        $('#wpTextbox1').val(savedText + "\n\n**Alasan saya:** \n(Tulis alasan lo di sini, boys!) \n\n<div class='mippedia-status'>'''Status: 🕒 Sedang diajukan'''</div>\n\n--" + user);
        sessionStorage.removeItem('mippedia_req_text');
    }

    // --- 2. TOMBOL MINTA (HALAMAN BERKAS) ---
    if (ns === 6) {
        if (!$content.text().includes("Aset Resmi")) {
            var $reqBtn = $('<button>').html('<span>📩</span> Minta Verifikasi').css({
                'background': '#36c', 'color': '#fff', 'border': 'none', 'padding': '5px 15px', 
                'border-radius': '20px', 'font-size': '11px', 'font-weight': '800', 'cursor': 'pointer', 'margin': '10px 0'
            });
            $reqBtn.click(function() {
                if (!user) { window.location.href = mw.util.getUrl('Istimewa:Masuk_log', { returnto: pageName }); return; }
                var talkPage = "Pembicaraan_Berkas:" + mw.config.get('wgTitle');
                sessionStorage.setItem('mippedia_req_text', "Halo Pengurus Mippedia,\n\nSaya memohon verifikasi untuk berkas [[:" + pageName + "]].");
                window.location.href = mw.util.getUrl(talkPage, { action: 'edit', section: 'new', preloadtitle: 'Permintaan Verifikasi Berkas' });
            });
            setTimeout(function() { $('#firstHeading').after($reqBtn); }, 600);
        }
    }

    // --- 3. PANEL ADMIN & AUTOMATION (HALAMAN PEMBICARAAN) ---
    if (ns === 7) {
        var api = new mw.Api();
        var filePage = pageName.replace('Pembicaraan_Berkas:', 'Berkas:');
        var fullContent = $content.text();
        var isPending = fullContent.includes("Status: 🕒 Sedang diajukan");

        // Ambil User Pengaju
        api.get({ action: 'query', prop: 'revisions', titles: pageName, rvprop: 'user', rvlimit: 1, rvdir: 'newer' }).done(function(data) {
            var pages = data.query.pages;
            var requester = "";
            for (var id in pages) { requester = pages[id].revisions[0].user; }

            // Tombol Coba Lagi buat Pengaju
            if (fullContent.includes("Status: ❌ Ditolak") && user === requester) {
                var $retryBtn = $('<button>').text('🔄 Coba Lagi').css({'background':'#36c','color':'#fff','border':'none','padding':'4px 10px','border-radius':'4px','cursor':'pointer','display':'block','margin-top':'10px'});
                $retryBtn.click(function() { window.location.href = mw.util.getUrl(filePage); });
                $('.mippedia-status').append($retryBtn);
            }

            // PANEL ADMIN
            if (isAdmin && isPending) {
                var $panel = $('<div id="admin-panel" style="background:#f0f5ff; border:2px solid #36c; padding:15px; border-radius:10px; margin:15px 0;">' +
                    '<div style="font-weight:bold; color:#36c; margin-bottom:10px;">🛡️ ADMIN CONTROL</div></div>');
                
                var $btnApprove = $('<button>').text('✅ SETUJUI').css({'background':'#00af89','color':'#fff','border':'none','padding':'8px 15px','margin-right':'10px','cursor':'pointer'});
                var $btnReject = $('<button>').text('❌ TOLAK').css({'background':'#d33','color':'#fff','border':'none','padding':'8px 15px','cursor':'pointer'});

                $btnApprove.click(function() {
                    $btnApprove.prop('disabled', true).text('Processing...');
                    
                    // STEP 1: Nulis "Aset Resmi" di Berkas
                    api.postWithToken('edit', { action: 'edit', title: filePage, appendtext: '\nAset Resmi', summary: 'Verifikasi Disetujui' }).done(function() {
                        // STEP 2: Ganti teks status di halaman diskusi
                        api.get({ action: 'query', prop: 'revisions', titles: pageName, rvprop: 'content' }).done(function(res) {
                            var content = res.query.pages[Object.keys(res.query.pages)[0]].revisions[0]['*'];
                            var newText = content.replace("Status: 🕒 Sedang diajukan", "Status: ✅ '''Disetujui'''");
                            api.postWithToken('edit', { action: 'edit', title: pageName, text: newText, summary: 'Update Status: Disetujui' }).done(function() {
                                // STEP 3: Kirim notif ke User
                                var msg = "\n== Notifikasi Verifikasi ==\nHalo [[" + requester + "]], permohonan Anda untuk [[:" + filePage + "]] telah '''DISETUJUI'''. --[[Pengguna:Admin|Admin]] ([[Pembicaraan Pengguna:Admin|bicara]]) 10 April 2026 16.37 (UTC)";
                                api.postWithToken('edit', { action: 'edit', title: "Pembicaraan_Pengguna:" + requester, section: 'new', text: msg }).done(function() {
                                    location.reload();
                                });
                            });
                        });
                    });
                });

                $btnReject.click(function() {
                    var alasan = prompt("Alasan penolakan:");
                    if (!alasan) return;
                    $btnReject.prop('disabled', true).text('Processing...');

                    api.get({ action: 'query', prop: 'revisions', titles: pageName, rvprop: 'content' }).done(function(res) {
                        var content = res.query.pages[Object.keys(res.query.pages)[0]].revisions[0]['*'];
                        var newText = content.replace("Status: 🕒 Sedang diajukan", "Status: ❌ '''Ditolak'''\n\n''Alasan: " + alasan + "''");
                        api.postWithToken('edit', { action: 'edit', title: pageName, text: newText, summary: 'Update Status: Ditolak' }).done(function() {
                            var msg = "\n== Notifikasi Verifikasi ==\nHalo [[" + requester + "]], permohonan Anda untuk [[:" + filePage + "]] '''DITOLAK''' karena: ''" + alasan + "''. --[[Pengguna:Admin|Admin]] ([[Pembicaraan Pengguna:Admin|bicara]]) 10 April 2026 16.37 (UTC)";
                            api.postWithToken('edit', { action: 'edit', title: "Pembicaraan_Pengguna:" + requester, section: 'new', text: msg }).done(function() {
                                location.reload();
                            });
                        });
                    });
                });

                $panel.append($btnApprove, $btnReject);
                $('#mw-content-text').prepend($panel);
            }
        });
    }
});

/* ==========================================================
   🛡️ MIPPEDIA AUTO-PROTECTION SYSTEM (ADAPTIVE & AUTO-NOTIF)
   Fitur: Request Protect, Auto-Lock, & Pesan Otomatis ke User
   ========================================================== */
$(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 $content = $('#mw-content-text');

    // --- 1. AUTO-FILL TEKS PERLINDUNGAN ---
    if (mw.config.get('wgAction') === 'edit' && sessionStorage.getItem('mippedia_protect_text')) {
        var savedText = sessionStorage.getItem('mippedia_protect_text');
        $('#wpTextbox1').val(savedText + "\n\n**Alasan Perlindungan:** \n(Tulis alasan kenapa berkas ini perlu dikunci, boys!) \n\n<div class='mippedia-status'>'''Status: 🕒 Sedang diajukan'''</div>\n\n--" + user);
        sessionStorage.removeItem('mippedia_protect_text');
    }

    // --- 2. TOMBOL DINAMIS (DI HALAMAN BERKAS) ---
    if (ns === 6 && user) { // Khusus user login
        var api = new mw.Api();
        api.get({ action: 'query', prop: 'info', titles: pageName, inprop: 'protection' }).done(function(data) {
            var page = data.query.pages[Object.keys(data.query.pages)[0]];
            var protections = page.protection;
            
            var isFull = false;
            var isSemi = false;

            protections.forEach(function(p) {
                if (p.type === 'edit') {
                    if (p.level === 'sysop') isFull = true;
                    if (p.level === 'autoconfirmed') isSemi = true;
                }
            });

            // Jika Full, tombol hilang. Jika Semi, tombol minta Penuh.
            if (isFull) return;
            var btnLabel = isSemi ? '🔒 Minta Perlindungan Penuh' : '🔒 Minta Perlindungan';
            var reqType = isSemi ? 'Perlindungan Penuh' : 'Perlindungan';

            var $protBtn = $('<button>').html('<span></span> ' + btnLabel).css({
                'background': '#d33', 'color': '#fff', 'border': 'none', 'padding': '5px 15px', 
                'border-radius': '20px', 'font-size': '11px', 'font-weight': '800', 'cursor': 'pointer', 'margin': '10px 5px'
            });

            $protBtn.click(function() {
                var talkPage = "Pembicaraan_Berkas:" + mw.config.get('wgTitle');
                sessionStorage.setItem('mippedia_protect_text', "Halo Pengurus Mippedia,\n\nSaya memohon " + reqType + " untuk berkas [[:" + pageName + "]] guna menghindari penyalahgunaan.");
                window.location.href = mw.util.getUrl(talkPage, { action: 'edit', section: 'new', preloadtitle: 'Permintaan Perlindungan Berkas' });
            });

            setTimeout(function() { $('#firstHeading').after($protBtn); }, 650);
        });
    }

    // --- 3. PANEL ADMIN PERLINDUNGAN (DI HALAMAN PEMBICARAAN) ---
    if (ns === 7) {
        var api = new mw.Api();
        var filePage = pageName.replace('Pembicaraan_Berkas:', 'Berkas:');
        var isPending = $content.text().includes("Status: 🕒 Sedang diajukan");

        api.get({ action: 'query', prop: 'revisions', titles: pageName, rvprop: 'user', rvlimit: 1, rvdir: 'newer' }).done(function(data) {
            var pages = data.query.pages;
            var requester = "";
            for (var id in pages) { requester = pages[id].revisions[0].user; }

            if (isAdmin && isPending && $content.text().includes("Permintaan Perlindungan")) {
                var $panel = $('<div style="background:#fff0f0; border:2px solid #d33; padding:15px; border-radius:10px; margin:15px 0;">' +
                    '<div style="font-weight:bold; color:#d33; margin-bottom:10px;">🛡️ ADMIN PROTECTION CONTROL</div>' +
                    '<p style="font-size:11px;">Pilih tingkat perlindungan untuk berkas ini:</p></div>');
                
                var $btnSemi = $('<button>').text('SEMI-PROT').attr('title', 'Hanya user terdaftar').css({'background':'#faad14','color':'#fff','border':'none','padding':'8px 12px','margin-right':'8px','cursor':'pointer','font-weight':'bold'});
                var $btnFull = $('<button>').text('FULL-PROT').attr('title', 'Hanya pengurus').css({'background':'#d33','color':'#fff','border':'none','padding':'8px 12px','margin-right':'8px','cursor':'pointer','font-weight':'bold'});
                var $btnReject = $('<button>').text('TOLAK').css({'background':'#555','color':'#fff','border':'none','padding':'8px 12px','cursor':'pointer'});

                // FUNGSI EKSEKUSI PROTEKSI (Tetap menjaga sistem kirim pesan otomatis ke user)
                function executeProtect(level, levelName) {
                    var editRight = (level === 'sysop') ? 'sysop' : 'autoconfirmed';

                    api.postWithToken('csrf', {
                        action: 'protect',
                        title: filePage,
                        protections: 'edit=' + editRight + '|move=' + editRight,
                        expiry: 'infinite',
                        reason: 'Permintaan disetujui: ' + levelName
                    }).done(function() {
                        api.get({ action: 'query', prop: 'revisions', titles: pageName, rvprop: 'content' }).done(function(res) {
                            var content = res.query.pages[Object.keys(res.query.pages)[0]].revisions[0]['*'];
                            var newText = content.replace("Status: 🕒 Sedang diajukan", "Status: ✅ '''Dilindungi (" + levelName + ")'''");
                            
                            api.postWithToken('edit', { action: 'edit', title: pageName, text: newText, summary: 'Status: Protection Granted' }).done(function() {
                                // FITUR OTOMATIS KIRIM PESAN (TIDAK DIBUANG)
                                var msg = "\n== Notifikasi Perlindungan ==\nHalo [[" + requester + "]], permohonan perlindungan untuk [[:" + filePage + "]] telah '''DISETUJUI''' dengan tingkat '''" + levelName + "'''. --[[Pengguna:Admin|Admin]] ([[Pembicaraan Pengguna:Admin|bicara]]) 10 April 2026 17.37 (UTC)";
                                api.postWithToken('edit', { action: 'edit', title: "Pembicaraan_Pengguna:" + requester, section: 'new', text: msg }).done(function() {
                                    location.reload();
                                });
                            });
                        });
                    });
                }

                $btnSemi.click(function() { executeProtect('autoconfirmed', 'Semi Perlindungan'); });
                $btnFull.click(function() { executeProtect('sysop', 'Perlindungan Penuh'); });
                $btnReject.click(function() {
                    var alasan = prompt("Alasan penolakan:");
                    if (!alasan) return;
                    api.get({ action: 'query', prop: 'revisions', titles: pageName, rvprop: 'content' }).done(function(res) {
                        var content = res.query.pages[Object.keys(res.query.pages)[0]].revisions[0]['*'];
                        var newText = content.replace("Status: 🕒 Sedang diajukan", "Status: ❌ '''Ditolak'''\n\n''Alasan: " + alasan + "''");
                        api.postWithToken('edit', { action: 'edit', title: pageName, text: newText, summary: 'Status: Protection Rejected' }).done(function() {
                            // FITUR OTOMATIS KIRIM PESAN PENOLAKAN
                            var msg = "\n== Notifikasi Perlindungan ==\nHalo [[" + requester + "]], permohonan perlindungan untuk [[:" + filePage + "]] '''DITOLAK''' karena: ''" + alasan + "''. --[[Pengguna:Admin|Admin]] ([[Pembicaraan Pengguna:Admin|bicara]]) 10 April 2026 17.37 (UTC)";
                            api.postWithToken('edit', { action: 'edit', title: "Pembicaraan_Pengguna:" + requester, section: 'new', text: msg }).done(function() {
                                location.reload();
                            });
                        });
                    });
                });

                $panel.append($btnSemi, $btnFull, $btnReject);
                $('#mw-content-text').prepend($panel);
            }
        });
    }
});

/* ==========================================================
   🛡️ MIPPEDIA ARTICLE PROTECTION SYSTEM (PERFECT ALIGNMENT)
   Fokus: Posisi Sejajar, Teks Tebal, & Warna Standar
   ========================================================== */
$(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 $content = $('#mw-content-text');

    // --- 1. AUTO-FILL TEKS PERLINDUNGAN ---
    if (mw.config.get('wgAction') === 'edit' && sessionStorage.getItem('mippedia_art_protect')) {
        var savedText = sessionStorage.getItem('mippedia_art_protect');
        $('#wpTextbox1').val(savedText + "\n\n**Alasan Perlindungan:** \n(Tulis alasan lo, boys!) \n\n<div class='mippedia-status'>'''Status: 🕒 Sedang diajukan'''</div>\n\n--" + user);
        sessionStorage.removeItem('mippedia_art_protect');
    }

    // --- 2. TOMBOL DINAMIS (POSISI PRESISI & TEKS TEBAL) ---
    if (ns === 0 && user) {
        var api = new mw.Api();
        api.get({ action: 'query', prop: 'info', titles: pageName, inprop: 'protection' }).done(function(data) {
            var page = data.query.pages[Object.keys(data.query.pages)[0]];
            var protections = page.protection;
            var isFull = protections.some(p => p.type === 'edit' && p.level === 'sysop');
            var isSemi = protections.some(p => p.type === 'edit' && p.level === 'autoconfirmed');

            if (isFull) return;

            var btnLabel = isSemi ? 'Proteksi Penuh' : 'Proteksi';
            var reqType = isSemi ? 'Perlindungan Penuh' : 'Perlindungan';

            // Membuat item list dengan padding supaya tidak terlalu ke kiri
            var $protLink = $('<li>').attr({
                'id': 'ca-protect-request',
                'class': 'mw-list-item'
            }).append(
                $('<a>').attr({'href': '#', 'title': 'Minta perlindungan'}).css({
                    'display': 'flex',
                    'align-items': 'center',
                    'padding': '6px 12px' // Memberi ruang agar tidak mepet ke kiri
                }).append(
                    $('<span>').html('🔒 ' + btnLabel).css({
                        'color': '#202122', 
                        'font-weight': 'bold', // Tulisan jadi tebal
                        'margin-left': '2px'  // Jarak halus setelah ikon
                    })
                )
            );

            $protLink.click(function(e) {
                e.preventDefault();
                var talkPage = "Pembicaraan:" + mw.config.get('wgTitle');
                sessionStorage.setItem('mippedia_art_protect', "Halo Pengurus,\n\nSaya memohon " + reqType + " untuk [[" + pageName + "]].");
                window.location.href = mw.util.getUrl(talkPage, { action: 'edit', section: 'new', preloadtitle: 'Permintaan Perlindungan Artikel' });
            });

            // Menyisipkan ke menu
            $('#p-cactions ul, #p-views ul').append($protLink);
        });
    }

    // --- 3. PANEL ADMIN (LOGIKA BERANTAI ANTI-MACET) ---
    if (ns === 1 && isAdmin && $content.text().includes("Sedang diajukan")) {
        var api = new mw.Api();
        var articlePage = pageName.replace('Pembicaraan:', '');
        
        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]];
            var requester = pg.revisions[0].user;
            var oldContent = pg.revisions[0]['*'];

            var $panel = $('<div style="background:#fff0f0; border:2px solid #d33; padding:15px; border-radius:10px; margin-bottom:15px;">' +
                '<b>🛡️ ADMIN CONTROL</b><br><small>Request by: '+requester+'</small></div>');
            
            var $btnOk = $('<button>').text('✅ SETUJUI').css({'background':'#d33','color':'#fff','padding':'5px 12px','border':'none','cursor':'pointer','font-weight':'bold'});
            var $btnNo = $('<button>').text('❌ TOLAK').css({'background':'#555','color':'#fff','padding':'5px 12px','border':'none','cursor':'pointer','margin-left':'10px'});

            $btnOk.click(function() {
                var level = oldContent.includes("Penuh") ? "sysop" : "autoconfirmed";
                $(this).prop('disabled', true).text('Processing Step 1/3...');

                api.postWithToken('csrf', {
                    action: 'protect', title: articlePage, protections: 'edit='+level+'|move='+level, expiry: 'infinite', reason: 'Approved'
                }).then(function() {
                    $btnOk.text('Processing Step 2/3...');
                    var newText = oldContent.replace("Status: 🕒 Sedang diajukan", "Status: ✅ '''Dilindungi ("+level+")'''");
                    return api.postWithToken('edit', { action: 'edit', title: pageName, text: newText, summary: 'Status Updated' });
                }).then(function() {
                    $btnOk.text('Processing Step 3/3...');
                    var msg = "\n== Notifikasi ==\nHalo [["+requester+"]], permohonan perlindungan [["+articlePage+"]] udah disetujui, boys! --[[Pengguna:Admin|Admin]] ([[Pembicaraan Pengguna:Admin|bicara]]) 10 April 2026 19.40 (UTC)";
                    return api.postWithToken('edit', { action: 'edit', title: "Pembicaraan_Pengguna:"+requester, section: 'new', text: msg });
                }).done(function() {
                    location.reload();
                });
            });

            $btnNo.click(function() {
                var alasan = prompt("Alasan:");
                if (!alasan) return;
                $(this).prop('disabled', true).text('Rejecting...');
                var newText = oldContent.replace("Status: 🕒 Sedang diajukan", "Status: ❌ '''Ditolak'''\n\nAlasan: " + alasan);
                api.postWithToken('edit', { action: 'edit', title: pageName, text: newText, summary: 'Rejected' }).then(function() {
                    var msg = "\n== Notifikasi ==\nSori [["+requester+"]], permintaan lo ditolak: " + alasan + " --[[Pengguna:Admin|Admin]] ([[Pembicaraan Pengguna:Admin|bicara]]) 10 April 2026 19.40 (UTC)";
                    return api.postWithToken('edit', { action: 'edit', title: "Pembicaraan_Pengguna:"+requester, section: 'new', text: msg });
                }).done(function() {
                    location.reload();
                });
            });

            $panel.append($btnOk, $btnNo);
            $('#mw-content-text').prepend($panel);
        });
    }
});

/* ==========================================================
   🛡️ MIPPEDIA USER PAGE PROTECTION SYSTEM
   Khusus Namespace Pengguna - Versi Stabil, Rapi & Otomatis
   ========================================================== */
$(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 $content = $('#mw-content-text');

    // --- 1. AUTO-FILL TEKS PERLINDUNGAN ---
    if (mw.config.get('wgAction') === 'edit' && sessionStorage.getItem('mippedia_user_protect')) {
        var savedText = sessionStorage.getItem('mippedia_user_protect');
        $('#wpTextbox1').val(savedText + "\n\n**Alasan Perlindungan:** \n(Tulis alasan kenapa halaman pengguna ini perlu dikunci, boys!) \n\n<div class='mippedia-status'>'''Status: 🕒 Sedang diajukan'''</div>\n\n--" + user);
        sessionStorage.removeItem('mippedia_user_protect');
    }

    // --- 2. TOMBOL DINAMIS (KHUSUS NAMESPACE PENGGUNA / NS 2) ---
    if (ns === 2 && user) { 
        var api = new mw.Api();
        api.get({ action: 'query', prop: 'info', titles: pageName, inprop: 'protection' }).done(function(data) {
            var page = data.query.pages[Object.keys(data.query.pages)[0]];
            var protections = page.protection;
            var isFull = protections.some(p => p.type === 'edit' && p.level === 'sysop');
            var isSemi = protections.some(p => p.type === 'edit' && p.level === 'autoconfirmed');

            if (isFull) return;

            var btnLabel = isSemi ? 'Proteksi Penuh' : 'Proteksi Profil';
            var reqType = isSemi ? 'Perlindungan Penuh' : 'Perlindungan';

            var $protLink = $('<li>').attr({
                'id': 'ca-protect-user-request',
                'class': 'mw-list-item'
            }).append(
                $('<a>').attr({'href': '#', 'title': 'Minta perlindungan halaman pengguna'}).css({
                    'display': 'flex',
                    'align-items': 'center',
                    'padding': '6px 12px'
                }).append(
                    $('<span>').html('🔒 ' + btnLabel).css({
                        'color': '#202122', 
                        'font-weight': 'bold',
                        'margin-left': '2px'
                    })
                )
            );

            $protLink.click(function(e) {
                e.preventDefault();
                // Halaman Pengguna pake Pembicaraan Pengguna: (Namespace 3)
                var talkPage = "Pembicaraan_Pengguna:" + mw.config.get('wgTitle');
                sessionStorage.setItem('mippedia_user_protect', "Halo Pengurus,\n\nSaya memohon " + reqType + " untuk halaman pengguna [[" + pageName + "]] guna menghindari vandalisme profil.");
                window.location.href = mw.util.getUrl(talkPage, { action: 'edit', section: 'new', preloadtitle: 'Permintaan Perlindungan Halaman Pengguna' });
            });

            $('#p-cactions ul, #p-views ul').append($protLink);
        });
    }

    // --- 3. PANEL ADMIN (HALAMAN PEMBICARAAN PENGGUNA / NS 3) ---
    if (ns === 3 && isAdmin && $content.text().includes("Sedang diajukan")) {
        var api = new mw.Api();
        // Target perlindungan adalah halaman pengguna utamanya
        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]];
            var requester = pg.revisions[0].user;
            var oldContent = pg.revisions[0]['*'];

            if (!$content.text().includes("Permintaan Perlindungan Halaman Pengguna")) return;

            var $panel = $('<div style="background:#fff0f0; border:2px solid #d33; padding:15px; border-radius:10px; margin-bottom:15px;">' +
                '<b>🛡️ ADMIN USER-PAGE CONTROL</b><br><small>Request by: '+requester+'</small></div>');
            
            var $btnOk = $('<button>').text('✅ SETUJUI').css({'background':'#d33','color':'#fff','padding':'5px 12px','border':'none','cursor':'pointer','font-weight':'bold'});
            var $btnNo = $('<button>').text('❌ TOLAK').css({'background':'#555','color':'#fff','padding':'5px 12px','border':'none','cursor':'pointer','margin-left':'10px'});

            $btnOk.click(function() {
                var level = oldContent.includes("Penuh") ? "sysop" : "autoconfirmed";
                $(this).prop('disabled', true).text('Step 1/3...');

                // STEP 1: PROTEKSI
                api.postWithToken('csrf', {
                    action: 'protect', title: targetUserPage, protections: 'edit='+level+'|move='+level, expiry: 'infinite', reason: 'User Page Protection: Approved'
                }).then(function() {
                    // STEP 2: UPDATE STATUS
                    $btnOk.text('Step 2/3...');
                    var newText = oldContent.replace("Status: 🕒 Sedang diajukan", "Status: ✅ '''Dilindungi ("+level+")'''");
                    return api.postWithToken('edit', { action: 'edit', title: pageName, text: newText, summary: 'Protection Status Updated' });
                }).then(function() {
                    // STEP 3: NOTIFIKASI OTOMATIS (KE USER)
                    $btnOk.text('Step 3/3...');
                    var msg = "\n== Notifikasi Perlindungan Profil ==\nHalo [["+requester+"]], permohonan perlindungan untuk halaman pengguna lo [["+targetUserPage+"]] udah disetujui dan aktif, boys! --[[Pengguna:Admin|Admin]] ([[Pembicaraan Pengguna:Admin|bicara]]) 10 April 2026 19.48 (UTC)";
                    return api.postWithToken('edit', { action: 'edit', title: "Pembicaraan_Pengguna:"+requester, section: 'new', text: msg });
                }).done(function() {
                    location.reload();
                });
            });

            $btnNo.click(function() {
                var alasan = prompt("Alasan penolakan:");
                if (!alasan) return;
                $(this).prop('disabled', true).text('Rejecting...');
                var newText = oldContent.replace("Status: 🕒 Sedang diajukan", "Status: ❌ '''Ditolak'''\n\nAlasan: " + alasan);
                api.postWithToken('edit', { action: 'edit', title: pageName, text: newText, summary: 'Protection Rejected' }).then(function() {
                    var msg = "\n== Notifikasi ==\nHalo [["+requester+"]], permintaan perlindungan profil lo belum bisa disetujui karena: " + alasan + " --[[Pengguna:Admin|Admin]] ([[Pembicaraan Pengguna:Admin|bicara]]) 10 April 2026 19.48 (UTC)";
                    return api.postWithToken('edit', { action: 'edit', title: "Pembicaraan_Pengguna:"+requester, section: 'new', text: msg });
                }).done(function() {
                    location.reload();
                });
            });

            $panel.append($btnOk, $btnNo);
            $('#mw-content-text').prepend($panel);
        });
    }
});

/* ==========================================================
   🔵 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 === 'Admin');
    
    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 - JANGAN DIHAPUS) ---
        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');
        }
        var wordCount = rawContent.trim().split(/\s+/).length;
        if (wordCount < 700 && !/\{\{Artikel Rintisan/i.test(content)) {
            content = '\n' + content;
            summaryParts.push('+Stub');
        }
        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) ---
        // Cek jumlah related saat ini
        var currentRelatedMatch = content.match(/\{\{#related:.*?\}\}/g) || [];
        
        // Jika kurang dari 3, kita jalankan otak pencarian canggih
        if (currentRelatedMatch.length < 3) {
            // Hapus yang lama dulu agar tidak ada duplikat atau "pake yang bekas"
            content = content.replace(/\n*\{\{#related:.*?\}\}/g, '');

            // Langkah A: Ambil kandidat dari Search Engine (Ranking Skor)
            api.get({
                action: 'query',
                list: 'search',
                srsearch: pageTitle, // Gunakan judul sebagai basis pencarian semantic
                srlimit: 15,
                srprop: ''
            }).done(function(searchRes) {
                var candidates = {};

                // Masukkan hasil pencarian ke pool skor
                if (searchRes.query && searchRes.query.search) {
                    searchRes.query.search.forEach(function(item, index) {
                        if (item.title === pageTitle) return;
                        candidates[item.title] = (15 - index); // Skor berdasarkan urutan relevansi
                    });
                }

                // Langkah B: Tambah skor jika artikel ada di daftar Link Internal
                if (page.links) {
                    page.links.forEach(function(link) {
                        if (link.title === pageTitle) return;
                        candidates[link.title] = (candidates[link.title] || 0) + 5; // Bonus skor link
                    });
                }

                // Langkah C: Urutkan berdasarkan skor tertinggi (yang paling nyambung)
                var sortedTitles = Object.keys(candidates).sort(function(a, b) {
                    return candidates[b] - candidates[a];
                });

                // Ambil TOP 3
                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 = [];
                // Lindungi Brankas: Template, Header, Kategori, Ref, dan Kalimat Pembuka
                content = content.replace(/(\{\{[\s\S]*?\}\}|==+.*?==+|\[\[Kategori:.*?\]\]|<ref[\s\S]*?<\/ref>|^.*?adalah)/gi, function(match) {
                    placeholders.push(match);
                    return '___MIP_SKIP_' + (placeholders.length - 1) + '___';
                });

                // Proses Auto-Link (Wajib ambil daftar AllPages dulu)
                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('');
                    
                    // Kembalikan dari Brankas
                    content = content.replace(/___MIP_SKIP_(\d+)___/g, function(match, id) { return placeholders[id]; });

                    // Bersihkan Link Merah
                    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() {
    var pageName = mw.config.get('wgPageName');
    var namespace = mw.config.get('wgNamespaceNumber');
    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 $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, 
                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 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.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);