@צדיק-וטוב-לו-0 כבר לא צריך רשימה שחורה לצנזור פרסומות:
עכשיו יש בתפריט ההגדרות כפתור חדש בשם "הסתר פרסומות".
ברגע שהוא מסומן, הסקריפט מזהה כל פוסט שאין בו אפשרות להוספת אימוג'י, ומצנזר אותו אוטומטית.
מצורף בספוילר סקריפט עבור Tampermonkey והוראות.
Spoiler
תוכלו לגשת להגדרות דרך תפריט התוסף (לחיצה על סמל ה-Tampermonkey בדפדפן ⟵ "הגדרות צנזורה (גיזרה צרה)"), והחלון ייפתח בתוך הדף עצמו.
מדריך מקיף לשימוש וכתיבת סקריפטים לתוסף הפופולארי - Tampermonkey
// ==UserScript==
// @name גיזרה צרה
// @namespace http://tampermonkey.net/
// @version 1.1.0
// @description מסתיר פוסטים באתר הגיזרה שמכילים מילים שבחרת, ואפשרות לחסימת פרסומות אוטומטית.
// @author Gemini נטפרי
// @match https://hagizra.news/*
// @match https://*.hagizra.news/*
// @grant GM_addStyle
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @run-at document-start
// ==/UserScript==
(() => {
'use strict';
/* ---------- הגדרות ומצבים ---------- */
const TARGETS = 'app-message, app-breaking-ticker .ticker-track > *';
const DEFAULTS = {
enabled: true,
hideAds: true, // הגדרה חדשה: הסתרת פרסומות לפי היעדר אימוג'י
words: [],
mode: 'collapse', // 'hide' | 'collapse' | 'blur'
wholeWord: false
};
let settings = GM_getValue('hgz_settings', DEFAULTS);
let matchers = [];
let version = 0;
function saveSettings(patch) {
settings = { ...settings, ...patch };
GM_setValue('hgz_settings', settings);
version++;
buildMatchers();
scheduleScan();
}
/* ---------- עיצוב CSS שמוזרק לעמוד ---------- */
GM_addStyle(`
.hgz-censored.hgz-mode-hide { display: none !important; }
.hgz-censored.hgz-mode-collapse { display: block !important; }
.hgz-censored.hgz-mode-collapse > *:not(.hgz-notice) { display: none !important; }
.hgz-censored.hgz-mode-blur > *:not(.hgz-notice) {
filter: blur(7px) saturate(0.4) !important;
pointer-events: none !important;
user-select: none !important;
}
.hgz-notice {
display: flex !important; align-items: center; gap: 8px; direction: rtl;
margin: 4px 8px 4px auto; padding: 6px 12px; max-width: 480px;
border: 1px dashed #d1d5db; border-radius: 12px;
background: #f9fafb; color: #6b7280; font-size: 12px;
font-family: inherit; line-height: 1.4;
}
.hgz-mode-blur .hgz-notice { position: relative; z-index: 5; }
.hgz-notice-icon { font-size: 13px; line-height: 1; }
.hgz-notice-text { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hgz-notice-btn {
flex: none; border: 1px solid #e5e7eb; border-radius: 999px;
background: #ffffff; color: #374151; font-size: 11px;
padding: 3px 10px; cursor: pointer; transition: 0.15s;
}
.hgz-notice-btn:hover { background: #111827; color: #ffffff; border-color: #111827; }
.hgz-revealed > .hgz-notice { opacity: 0.65; border-style: solid; }
/* עיצוב חלון ההגדרות */
#hgz-modal-backdrop { display: none; position: fixed; z-index: 999998; inset: 0; background: rgba(0,0,0,0.5); }
#hgz-modal {
display: none; position: fixed; z-index: 999999; left: 50%; top: 50%;
transform: translate(-50%, -50%); background: #fff; border-radius: 12px;
box-shadow: 0 10px 25px rgba(0,0,0,0.2); width: 340px; max-width: 90vw;
direction: rtl; font-family: "Segoe UI", Rubik, Arial, sans-serif; color: #111827;
}
#hgz-modal .hgz-head {
display: flex; justify-content: space-between; align-items: center;
padding: 12px 14px; border-bottom: 1px solid #e5e7eb; background: #f9fafb; border-radius: 12px 12px 0 0;
}
#hgz-modal .hgz-head h1 { margin: 0; font-size: 16px; font-weight: bold; }
#hgz-modal .hgz-close-btn { background: none; border: none; font-size: 24px; cursor: pointer; color: #6b7280; line-height: 1; }
#hgz-modal .hgz-block { padding: 12px 14px; border-bottom: 1px solid #e5e7eb; }
#hgz-modal .hgz-label { display: block; margin-bottom: 7px; font-size: 12px; font-weight: 600; color: #6b7280; }
#hgz-modal input[type="text"], #hgz-modal select {
width: 100%; padding: 8px 10px; border: 1px solid #e5e7eb; border-radius: 8px; box-sizing: border-box; font-family: inherit;
}
#hgz-modal .hgz-flex-row { display: flex; gap: 8px; }
#hgz-modal .hgz-btn-add { background: #111827; color: white; border: none; padding: 8px 14px; border-radius: 8px; cursor: pointer; font-weight: bold; }
#hgz-modal .hgz-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
#hgz-modal .hgz-chip {
background: #f3f4f6; padding: 4px 10px; border-radius: 999px; font-size: 12px;
display: flex; align-items: center; gap: 6px; border: 1px solid #e5e7eb;
}
#hgz-modal .hgz-chip button { border: none; background: none; cursor: pointer; color: #6b7280; padding: 0; font-size: 14px; line-height: 1; }
#hgz-modal .hgz-chip button:hover { color: #c62828; }
#hgz-modal .hgz-check-row { display: flex; align-items: center; gap: 8px; font-size: 13px; margin-top: 8px; cursor: pointer; }
#hgz-modal .hgz-check-row em { color: #6b7280; font-style: normal; font-size: 11px; }
@media (prefers-color-scheme: dark) {
.hgz-notice { border-color: #374151; background: #1f2937; color: #9ca3af; }
.hgz-notice-btn { background: #111827; border-color: #374151; color: #e5e7eb; }
.hgz-notice-btn:hover { background: #e5e7eb; color: #111827; }
#hgz-modal { background: #111827; color: #e5e7eb; }
#hgz-modal .hgz-head { background: #1f2937; border-color: #374151; }
#hgz-modal .hgz-block { border-color: #374151; }
#hgz-modal input[type="text"], #hgz-modal select { background: #0b1220; color: #e5e7eb; border-color: #374151; }
#hgz-modal .hgz-btn-add { background: #e5e7eb; color: #111827; }
#hgz-modal .hgz-chip { background: #1f2937; border-color: #374151; }
}
`);
/* ---------- נירמול טקסט והתאמה ---------- */
const NIQQUD = /[\u0591-\u05C7]/g;
const MARKS = /[\u200B-\u200F\u202A-\u202E\u2066-\u2069]/g;
function norm(s) {
return String(s).replace(NIQQUD, '').replace(MARKS, '').replace(/[׳'‘’]/g, "'").replace(/[״"“”]/g, '"').replace(/\s+/g, ' ').toLowerCase().trim();
}
const escapeRe = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
function buildMatchers() {
matchers = [];
for (const raw of settings.words) {
const label = String(raw || '').trim();
const w = norm(label);
if (!w) continue;
try {
const re = settings.wholeWord
? new RegExp('(?<![\\p{L}\\p{N}])[ובלכמשה]{0,2}' + escapeRe(w) + '(?![\\p{L}\\p{N}])', 'u')
: new RegExp(escapeRe(w), 'u');
matchers.push({ word: label, re });
} catch (_) {}
}
}
function findHit(text) {
for (const m of matchers) if (m.re.test(text)) return m.word;
return null;
}
/* ---------- צנזור / שחרור ---------- */
function noticeFor(el, word) {
let notice = el.querySelector(':scope > .hgz-notice');
if (!notice) {
notice = document.createElement('div');
notice.className = 'hgz-notice';
notice.dir = 'rtl';
const icon = document.createElement('span');
icon.className = 'hgz-notice-icon';
icon.textContent = '🚫';
const text = document.createElement('span');
text.className = 'hgz-notice-text';
const btn = document.createElement('button');
btn.type = 'button';
btn.className = 'hgz-notice-btn';
btn.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
toggleReveal(el);
});
notice.append(icon, text, btn);
el.appendChild(notice);
}
const label = word ? 'פוסט צונזר · "' + word + '"' : 'פוסט צונזר';
const textEl = notice.querySelector('.hgz-notice-text');
if (textEl.textContent !== label) textEl.textContent = label;
return notice;
}
function setRevealUI(el, revealed) {
const btn = el.querySelector(':scope > .hgz-notice .hgz-notice-btn');
if (btn) btn.textContent = revealed ? 'הסתר' : 'הצג בכל זאת';
}
function censor(el, word) {
el.classList.remove('hgz-mode-hide', 'hgz-mode-collapse', 'hgz-mode-blur');
el.classList.add('hgz-censored', 'hgz-mode-' + settings.mode);
el.dataset.hgzWord = word || '';
if (settings.mode !== 'hide') {
noticeFor(el, word);
setRevealUI(el, false);
}
}
function uncensor(el) {
el.classList.remove('hgz-censored', 'hgz-revealed', 'hgz-mode-hide', 'hgz-mode-collapse', 'hgz-mode-blur');
delete el.dataset.hgzWord;
const notice = el.querySelector(':scope > .hgz-notice');
if (notice) notice.remove();
el.__hgzRevealedAt = -1;
}
function toggleReveal(el) {
const revealed = el.classList.toggle('hgz-revealed');
el.classList.toggle('hgz-censored', !revealed);
el.__hgzRevealedAt = revealed ? version : -1;
setRevealUI(el, revealed);
}
/* ---------- סריקה ---------- */
function ownText(el) {
const notice = el.querySelector(':scope > .hgz-notice');
if (!notice) return el.textContent || '';
let out = '';
for (const node of el.childNodes) if (node !== notice) out += node.textContent || '';
return out;
}
function processOne(el) {
if (el.classList.contains('hgz-notice')) return;
if (el.__hgzRevealedAt === version) return;
const text = ownText(el);
const key = version + '|' + text.length;
if (el.__hgzKey === key) return;
el.__hgzKey = key;
// בדיקה חכמה לפרסומות (היעדר כפתור סמיילי) - רלוונטי רק לפוסטים ולא למבזקים
if (settings.hideAds && el.tagName.toLowerCase() === 'app-message') {
const hasEmoji = el.querySelector('ng-icon[name="heroFaceSmile"]');
if (!hasEmoji) {
censor(el, 'פרסומת');
return;
}
}
const hit = findHit(norm(text));
if (hit) censor(el, hit);
else if (el.classList.contains('hgz-censored') || el.classList.contains('hgz-revealed')) uncensor(el);
}
function clearAllScanned() {
document.querySelectorAll('.hgz-censored, .hgz-revealed').forEach(uncensor);
document.querySelectorAll(TARGETS).forEach((el) => { el.__hgzKey = null; });
}
function countCensored() {
return document.querySelectorAll('.hgz-censored').length;
}
function scan() {
if (!document.body) return;
if (!settings.enabled || (matchers.length === 0 && !settings.hideAds)) {
if (countCensored() || document.querySelector('.hgz-revealed')) clearAllScanned();
return;
}
document.querySelectorAll(TARGETS).forEach(processOne);
}
let pending = false;
function scheduleScan() {
if (pending) return;
pending = true;
requestAnimationFrame(() => {
pending = false;
scan();
});
}
const observer = new MutationObserver(scheduleScan);
/* ---------- ממשק משתמש להגדרות (Modal) ---------- */
function initUI() {
if (document.getElementById('hgz-modal')) return;
const backdrop = document.createElement('div');
backdrop.id = 'hgz-modal-backdrop';
const modal = document.createElement('div');
modal.id = 'hgz-modal';
modal.innerHTML = `
<div class="hgz-head">
<h1>🚫 גיזרה צרה - הגדרות</h1>
<button class="hgz-close-btn" id="hgz-close">×</button>
</div>
<div class="hgz-block">
<label class="hgz-check-row" style="margin-top:0;">
<input type="checkbox" id="hgz-enabled"> <strong>הפעל תוסף</strong>
</label>
<label class="hgz-check-row">
<input type="checkbox" id="hgz-hideAds"> <strong>הסתר פרסומות</strong> <em>(מזהה פוסטים ללא אימוג'י)</em>
</label>
</div>
<div class="hgz-block">
<label class="hgz-label">מילים לצנזור</label>
<form class="hgz-flex-row" id="hgz-addForm">
<input type="text" id="hgz-wordInput" placeholder="הקלד מילה או ביטוי ולחץ Enter" autocomplete="off" spellcheck="false">
<button type="submit" class="hgz-btn-add">הוסף</button>
</form>
<div class="hgz-chips" id="hgz-chips"></div>
</div>
<div class="hgz-block" style="border-bottom:none;">
<label class="hgz-label">מה לעשות עם פוסט שנתפס?</label>
<select id="hgz-mode">
<option value="collapse">לכווץ לשורה קטנה (אפשר לפתוח)</option>
<option value="hide">להעלים לגמרי</option>
<option value="blur">לטשטש</option>
</select>
<label class="hgz-check-row">
<input type="checkbox" id="hgz-wholeWord">
<span>מילה שלמה בלבד <em>(כולל תחיליות)</em></span>
</label>
</div>
`;
document.body.appendChild(backdrop);
document.body.appendChild(modal);
const elEnabled = document.getElementById('hgz-enabled');
const elHideAds = document.getElementById('hgz-hideAds');
const elInput = document.getElementById('hgz-wordInput');
const elForm = document.getElementById('hgz-addForm');
const elChips = document.getElementById('hgz-chips');
const elMode = document.getElementById('hgz-mode');
const elWholeWord = document.getElementById('hgz-wholeWord');
const elClose = document.getElementById('hgz-close');
function renderChips() {
elChips.innerHTML = '';
settings.words.forEach(word => {
const chip = document.createElement('div');
chip.className = 'hgz-chip';
chip.innerHTML = `<span>${word}</span> <button type="button" title="הסר">×</button>`;
chip.querySelector('button').addEventListener('click', () => {
saveSettings({ words: settings.words.filter(w => w !== word) });
renderChips();
});
elChips.appendChild(chip);
});
}
function loadToUI() {
elEnabled.checked = settings.enabled;
elHideAds.checked = settings.hideAds;
elMode.value = settings.mode;
elWholeWord.checked = settings.wholeWord;
renderChips();
}
elForm.addEventListener('submit', (e) => {
e.preventDefault();
const parts = elInput.value.split(/[,\n]/);
const added = [...settings.words];
let changed = false;
for (const p of parts) {
const w = p.trim().replace(/\s+/g, ' ');
if (w && !added.some((x) => x.toLowerCase() === w.toLowerCase())) {
added.push(w);
changed = true;
}
}
if (changed) {
saveSettings({ words: added });
renderChips();
}
elInput.value = '';
});
elEnabled.addEventListener('change', () => saveSettings({ enabled: elEnabled.checked }));
elHideAds.addEventListener('change', () => saveSettings({ hideAds: elHideAds.checked }));
elMode.addEventListener('change', () => saveSettings({ mode: elMode.value }));
elWholeWord.addEventListener('change', () => saveSettings({ wholeWord: elWholeWord.checked }));
function closeModal() {
backdrop.style.display = 'none';
modal.style.display = 'none';
}
elClose.addEventListener('click', closeModal);
backdrop.addEventListener('click', closeModal);
window.hgzOpenSettings = function() {
loadToUI();
backdrop.style.display = 'block';
modal.style.display = 'block';
elInput.focus();
};
}
GM_registerMenuCommand("הגדרות צנזורה (גיזרה צרה)", () => {
initUI();
window.hgzOpenSettings();
});
/* ---------- אתחול ---------- */
function start() {
buildMatchers();
observer.observe(document.body, { childList: true, subtree: true, characterData: true });
scheduleScan();
}
if (document.body) start();
else document.addEventListener('DOMContentLoaded', start, { once: true });
})();