您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Banlist collaborative desktop & mobile avec overlay et boutons adaptés
当前为
// ==UserScript== // @name SM Fake Profiles Manager // @namespace http://tampermonkey.net/ // @version 4.1 // @description Banlist collaborative desktop & mobile avec overlay et boutons adaptés // @match *://sexemodel.com/* // @match *://www.sexemodel.com/* // @match *://m.sexemodel.com/* // @grant none // ==/UserScript== (function() { 'use strict'; const AIRTABLE_TOKEN = "patpbe8APun8JckNM.bd007388d8f9807a82733510209428202ea2a43af6d5b805b667933cd45a64bf"; const AIRTABLE_BASE = "appUf8jMiwrXzpsP7"; const AIRTABLE_TABLE = "BanList"; let bannedList = []; async function fetchBanListFromAirtable() { try { const url = `https://api.airtable.com/v0/${AIRTABLE_BASE}/${AIRTABLE_TABLE}?pageSize=100`; const res = await fetch(url, { headers: { Authorization: `Bearer ${AIRTABLE_TOKEN}` } }); if (!res.ok) throw new Error(`HTTP ${res.status}`); const data = await res.json(); return data.records .filter(r => r.fields.Active === true) .map(r => ({ airtableId: r.id, id: r.fields.ProfilID, name: r.fields.ProfilName || "", date: r.createdTime })); } catch (e) { console.warn("⚠️ Erreur Airtable : ", e); return []; } } function showQuickNotif(message) { const notif = document.createElement('div'); notif.textContent = message; Object.assign(notif.style, { position: 'fixed', top: '20px', right: '20px', background: '#4caf50', color: '#fff', padding: '10px 15px', borderRadius: '5px', fontWeight: 'bold', zIndex: '999999', boxShadow: '0 2px 6px rgba(0,0,0,0.3)' }); document.body.appendChild(notif); setTimeout(() => notif.remove(), 700); } async function pushBanToAirtable(profilID, profilName) { try { const url = `https://api.airtable.com/v0/${AIRTABLE_BASE}/${AIRTABLE_TABLE}`; const record = { fields: { ProfilID: profilID, ProfilName: profilName, Active: true } }; const res = await fetch(url, { method: 'POST', headers: { Authorization: `Bearer ${AIRTABLE_TOKEN}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ records: [record] }) }); const json = await res.json(); if (json.error) { console.error("❌ Erreur Airtable :", json.error); alert("❌ Erreur Airtable : " + json.error.message); } else { bannedList.push({ airtableId: json.records[0].id, id: profilID, name: profilName, date: json.records[0].createdTime }); document.querySelectorAll(`a[href*="${profilID}"]`).forEach(a => { const card = a.closest('div'); if (card) card.style.display = 'none'; }); showQuickNotif(`✅ Profil banni : ${profilName}`); } } catch (e) { console.error("❌ Exception Airtable :", e); alert("❌ Erreur connexion Airtable"); } } async function deactivateBan(airtableRecordId) { try { const url = `https://api.airtable.com/v0/${AIRTABLE_BASE}/${AIRTABLE_TABLE}`; const res = await fetch(url, { method: 'PATCH', headers: { Authorization: `Bearer ${AIRTABLE_TOKEN}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ records: [{ id: airtableRecordId, fields: { Active: false } }] }) }); const json = await res.json(); if (json.error) { console.error("❌ Erreur déban Airtable :", json.error); alert("❌ Erreur déban Airtable : " + json.error.message); } else { showQuickNotif('🔄 Profil débanni'); } } catch (e) { console.error("❌ Exception déban :", e); alert("❌ Erreur connexion Airtable (déban)"); } } function isBanned(id) { return bannedList.some(item => item.id === id); } const style = document.createElement('style'); style.textContent = ` .fakeBtnThumbnail, .fakeBtnProfile { background:#e00;color:#fff;font-weight:bold;border:2px solid #fff; border-radius:5px;cursor:pointer;font-size:14px; box-shadow:0 0 5px rgba(0,0,0,0.5);z-index:9999;position:absolute; } .fakeBtnThumbnail { top:5px; right:5px; padding:3px 6px; font-size:12px; } .fakeBtnThumbnail:hover, .fakeBtnProfile:hover {background:#c00;} .fakeBtnProfile { position:relative; display:inline-block; margin:5px; padding:5px 8px; } #banConfirmPanel { position:fixed;top:0;left:0;right:0;bottom:0; background:rgba(0,0,0,0.5); display:flex;justify-content:center;align-items:center;z-index:10001; } #banConfirmPanel .inner { background:#fff;padding:20px;border-radius:8px;text-align:center;min-width:250px; } #banManager { position:fixed;top:0;left:0;width:100%;height:100%; background:rgba(0,0,0,0.6); display:flex;justify-content:center;align-items:center; z-index:10002; } #banManager .content { background:#fff;max-height:80%;overflow:auto;width:90%;padding:15px;border-radius:8px; } #banManager h3{margin-top:0;text-align:center;} #banManager ul{padding:0;list-style:none;} #banManager li{margin-bottom:8px;font-size:14px;display:flex;justify-content:space-between;align-items:center;} #banManager button{margin-left:10px;} `; document.head.appendChild(style); function showConfirmPanel(profileID, profileName) { const old = document.getElementById('banConfirmPanel'); if (old) old.remove(); const panel = document.createElement('div'); panel.id = 'banConfirmPanel'; panel.innerHTML = ` <div class="inner"> <p>Confirmer le ban du profil :</p> <p><b>${profileName}</b> (ID: ${profileID})</p> <button id="confirmBan">✅ Confirmer</button> <button id="cancelBan">❌ Annuler</button> </div>`; document.body.appendChild(panel); panel.querySelector('#confirmBan').onclick = async () => { await pushBanToAirtable(profileID, profileName); panel.remove(); }; panel.querySelector('#cancelBan').onclick = () => panel.remove(); } function showBanManager() { const existing = document.getElementById('banManager'); if (existing) { existing.remove(); return; } const panel = document.createElement('div'); panel.id = 'banManager'; panel.innerHTML = ` <div class="content"> <h3>Banlist collaborative</h3> <ul id="banListItems"></ul> <div style="text-align:center;margin-top:10px;"> <button id="closeBanManager">Fermer</button> </div> </div>`; document.body.appendChild(panel); const list = panel.querySelector('#banListItems'); if (bannedList.length === 0) { const li = document.createElement('li'); li.textContent = "Aucun profil banni pour le moment."; list.appendChild(li); } else { bannedList.forEach(item => { const li = document.createElement('li'); li.innerHTML = `<span>${item.name || "(sans nom)"} [${item.id}]<br><small>${new Date(item.date).toLocaleString()}</small></span>`; const btn = document.createElement('button'); btn.textContent = 'Déban'; btn.onclick = async () => { await deactivateBan(item.airtableId); li.remove(); }; li.appendChild(btn); list.appendChild(li); }); } panel.querySelector('#closeBanManager').onclick = () => panel.remove(); } function addFakeButtonsToListing() { const links = document.querySelectorAll('a[href*="/escort/"]'); const seen = new Set(); links.forEach(link => { const m = link.href.match(/\/escort\/([^\/]+)-(\d+)/); if (!m) return; const name = decodeURIComponent(m[1]).replace(/-/g, ' '); const id = m[2]; if (seen.has(id)) return; seen.add(id); const card = link.closest('div'); if (!card) return; if (isBanned(id)) { card.style.display = 'none'; return; } if (getComputedStyle(card).position === 'static') card.style.position = 'relative'; const btn = document.createElement('button'); btn.textContent = 'FAKE'; btn.className = 'fakeBtnThumbnail'; btn.onclick = (e) => { e.preventDefault(); e.stopPropagation(); showConfirmPanel(id, name); }; card.appendChild(btn); }); } function addFakeButtonToProfile(id) { let nameText = "(inconnu)"; const bcDesktop = document.querySelector('.breadcrumbs a.element.active'); const bcMobile = document.querySelector('.breadcrumb a.active'); if (bcDesktop && bcDesktop.textContent.trim()) { nameText = bcDesktop.textContent.trim(); } else if (bcMobile && bcMobile.textContent.trim()) { nameText = bcMobile.textContent.trim(); } else { const h1 = document.querySelector('h1') || document.querySelector('h2'); if (h1 && h1.innerText && h1.innerText.trim()) { nameText = h1.innerText.trim(); } } // Sur mobile, placer au-dessus de la photo si possible let container = document.querySelector('.main-photo') || document.querySelector('.vprof__photo') || document.querySelector('h1'); if (!container) container = document.querySelector('h1'); if (!container) return; const btn = document.createElement('button'); btn.textContent = 'FAKE'; btn.className = 'fakeBtnProfile'; btn.style.display = 'block'; btn.style.margin = '5px auto'; btn.onclick = () => showConfirmPanel(id, nameText); // si c'est une photo, insérer avant if (container.parentNode) { container.parentNode.insertBefore(btn, container); } } function addGlobalUI() { const panel = document.createElement('div'); panel.style.position = 'fixed'; panel.style.top = '50px'; panel.style.right = '10px'; panel.style.background = 'rgba(255,255,255,0.9)'; panel.style.padding = '8px'; panel.style.border = '1px solid #ccc'; panel.style.zIndex = '10000'; panel.style.opacity = '0.6'; panel.style.fontSize = '12px'; panel.innerHTML = `<button id="manageList">📋 Gérer banlist</button>`; panel.onmouseenter = () => panel.style.opacity = '1'; panel.onmouseleave = () => panel.style.opacity = '0.6'; document.body.appendChild(panel); panel.querySelector('#manageList').onclick = showBanManager; } (async () => { bannedList = await fetchBanListFromAirtable(); const profileMatch = window.location.pathname.match(/\/escort\/([^\/]+)-(\d+)/); if (profileMatch) { const id = profileMatch[2]; if (isBanned(id)) { document.body.innerHTML = '<div style="padding:2em;font-size:16px;background:#fee;">Ce profil est marqué comme fake.</div>'; } else { addFakeButtonToProfile(id); } } else { addFakeButtonsToListing(); } addGlobalUI(); })(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址