@מתכנת-חובב @לשכת-הרב @יוסי-מחשבים
יצרתי עם ג'מיני תוסף לחסימה של גוגל אבל רק מה שברשימה נחסם, מישהוא יכול להגיד אם הקוד כתוב כמו שצריך ויכול לחסום גם שלא יופיע בחיפוש בכלל?
background
// פונקציה שמחלצת את מזהה הסרטון (Video ID) מתוך הקישור של יוטיוב
function getYouTubeId(url) {
if (!url) return null;
const match = url.match(/(?:watch\?v=|v\/|embed\/|youtu\.be\/)([^&#?]+)/i);
return (match && match[1]) ? match[1] : null;
}
// פונקציה לבדיקת הכתובת וחסימתה
function checkTab(tabId, url) {
if (!url) return;
chrome.storage.local.get(["blocked"], (data) => {
const blocked = data.blocked || [];
const currentUrl = url.toLowerCase();
const currentVideoId = getYouTubeId(currentUrl);
for (const site of blocked) {
const blockedTarget = site.toLowerCase();
// תיקון: בדיקה אם מדובר בסרטון יוטיוב ספציפי
if (blockedTarget.includes("://youtube.com")) {
const blockedVideoId = getYouTubeId(blockedTarget);
// חוסם אך ורק אם מזהה הסרטון הנוכחי זהה למזהה הסרטון שחסמת
if (blockedVideoId && currentVideoId && blockedVideoId === currentVideoId) {
chrome.tabs.update(tabId, { url: "about:blank" });
break;
}
}
// קוד חסימת האתרים הרגיל שלך
else if (currentUrl.includes(blockedTarget)) {
chrome.tabs.update(tabId, { url: "about:blank" });
break;
}
}
});
}
// האזנה לשינויים בכרטיסייה בזמן אמת
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
if (changeInfo.url) {
checkTab(tabId, changeInfo.url);
}
});
content
function hideEverythingRelated() {
// בדיקה שאנחנו אכן בעמוד החיפוש של גוגל
if (!window.location.hostname.includes("google.")) return;
if (!window.location.pathname.includes("/search")) return;
// =========================================================================
// רשימה לבנה: הכנס כאן את כתובות האתרים שאתה רוצה שיישארו פתוחים תמיד!
// =========================================================================
const ALLOWED_SITES = [
"wikipedia.org",
"google.com" // שנה או הוסף כאן את האתרים המותרים שלך
];
chrome.storage.local.get(["blocked"], (data) => {
const blocked = data.blocked || [];
if (blocked.length === 0) return;
// פונקציית עזר לבדיקה האם הקישור שייך לאתר מהרשימה הלבנה
const isUrlWhitelisted = (urlStr) => {
if (!urlStr) return false;
return ALLOWED_SITES.some(allowedSite => urlStr.includes(allowedSite.toLowerCase().trim()));
};
// --- 1. סריקה וחסימה של רכיב ה-AI הראשי של גוגל (AI Overview) ---
// תפיסת התיבות הראשיות שגוגל משתמשת בהן להצגת תשובות ה-AI בחיפוש
const aiOverviews = document.querySelectorAll(
"div.WbY9Mc, div[data-initial-sections], g-card:has(div.f9G6te), div.hdzaWe"
);
aiOverviews.forEach((aiContainer) => {
const aiText = aiContainer.textContent.toLowerCase();
const aiLinks = aiContainer.querySelectorAll("a");
// החרגה של ה-AI אם הוא מכיל קישור מהרשימה הלבנה
let containsWhitelistedLink = false;
aiLinks.forEach(link => {
if (isUrlWhitelisted(link.href)) {
containsWhitelistedLink = true;
}
});
if (containsWhitelistedLink) return;
for (const site of blocked) {
const siteLower = site.toLowerCase().trim();
if (!siteLower) continue;
let cleanSite = siteLower
.replace(/^(https?:\/\/)?(www\.)?/, '')
.split('/')[0];
if (!cleanSite) continue;
// א) בדיקה אם המילה/האתר החסום מופיעים בטקסט שכתב ה-AI
if (aiText.includes(cleanSite)) {
aiContainer.style.setProperty("display", "none", "important");
break;
}
// ב) בדיקה אם ה-AI מפנה לקישור או מקור (Source) שנמצא ברשימת החסימה
let shouldBlockAI = false;
aiLinks.forEach(link => {
if (link.href.toLowerCase().includes(cleanSite)) {
shouldBlockAI = true;
}
});
if (shouldBlockAI) {
aiContainer.style.setProperty("display", "none", "important");
break;
}
}
});
// --- 2. תפיסת כל רכיבי תוצאות הטקסט הרגילות בגוגל ---
const allElements = document.querySelectorAll(
"div.g, div.jtfwS, div.v7W4ed, div.UK9Zve, div.Ww4FFb, div.MjjYud, div.hlcw0c, div.X96gYc"
);
allElements.forEach((element) => {
const elementText = element.textContent.toLowerCase();
const linkElement = element.querySelector("a");
const href = linkElement ? linkElement.href.toLowerCase() : "";
// החרגה: אם האתר ברשימה הלבנה - דלג עליו ואל תחסום בשום מצב
if (isUrlWhitelisted(href)) return;
for (const site of blocked) {
const siteLower = site.toLowerCase().trim();
if (!siteLower) continue;
// תיקון ליוטיוב בתוך גוגל
if (siteLower.includes("youtube.com") || siteLower.includes("youtu.be")) {
const match = siteLower.match(/(?:watch\?v=|v\/|embed\/|youtu\.be\/|shorts\/)([^&#?]+)/i);
if (match && match[1]) {
const videoId = match[1].toLowerCase();
if (href.includes(videoId)) {
element.style.setProperty("display", "none", "important");
break;
}
}
continue;
}
let cleanSite = siteLower
.replace(/^(https?:\/\/)?(www\.)?/, '')
.split('/')[0];
if (!cleanSite) continue;
// חסימה רגילה: אם הקישור או הטקסט של התוצאה מכילים את המילה/אתר החסום
if (href.includes(cleanSite) || elementText.includes(cleanSite)) {
element.style.setProperty("display", "none", "important");
break;
}
}
});
// --- 3. תפיסת קוביות תמונות ממוזערות (Thumbnails) בחיפוש גוגל וחסימתן ---
const imageContainers = document.querySelectorAll("div.image-result, div.O830d, div.mCBkyc, div.Gor6zc, a[data-navigation], div.v7W4ed a");
imageContainers.forEach((imgContainer) => {
const anchor = imgContainer.tagName === "A" ? imgContainer : imgContainer.querySelector("a");
const imgHref = anchor ? anchor.href.toLowerCase() : "";
const imgText = imgContainer.textContent.toLowerCase();
// החרגה: אם התמונה מובילה לאתר ברשימה הלבנה - דלג עליה ואל תחסום
if (isUrlWhitelisted(imgHref)) return;
for (const site of blocked) {
const siteLower = site.toLowerCase().trim();
if (siteLower.includes("youtube.com") || siteLower.includes("youtu.be")) continue;
let cleanSite = siteLower
.replace(/^(https?:\/\/)?(www\.)?/, '')
.split('/')[0];
if (!cleanSite) continue;
if ((imgHref && imgHref.includes(cleanSite)) || imgText.includes(cleanSite)) {
imgContainer.style.setProperty("display", "none", "important");
break;
}
}
});
});
}
// ==================== חסימת סרטונים ושורטס בתוך יוטיוב עם מנגנון החרגות ====================
function hideYoutubeVideosByKeywords() {
if (!window.location.hostname.includes("youtube.com")) return;
chrome.storage.local.get(["blocked"], (data) => {
const blocked = data.blocked || [];
if (blocked.length === 0) return;
const ALLOWED_WORDS = ["עוף", "מתכון", "בישול", "שניצל", "רוטב", "מטבח"];
const titles = document.querySelectorAll("#video-title, #video-title-link, yt-formatted-string#video-title, span#video-title, .title-and-badge #video-title, #shorts-title, #reel-title");
titles.forEach((titleElement) => {
const videoTitle = titleElement.textContent.toLowerCase();
const hasBannedWord = blocked.some(word => videoTitle.includes(word.toLowerCase().trim()));
if (hasBannedWord) {
const hasAllowedWord = ALLOWED_WORDS.some(word => videoTitle.includes(word.toLowerCase()));
if (!hasAllowedWord) {
const videoContainer = titleElement.closest(`
ytd-video-renderer,
ytd-grid-video-renderer,
ytd-compact-video-renderer,
ytd-rich-item-renderer,
ytd-reel-item-renderer,
ytd-item-renderer
`);
if (videoContainer) {
videoContainer.style.setProperty("display", "none", "important");
}
}
}
});
});
}
// פונקציה מאוחדת שמפעילה את שתי החסימות בהתאם לאתר שבו נמצאים
function runAllBlockers() {
hideEverythingRelated();
hideYoutubeVideosByKeywords();
}
// הפעלה מיידית וניטור עמודי האתרים בזמן גלילה
runAllBlockers();
const observer = new MutationObserver(runAllBlockers);
observer.observe(document.body, { childList: true, subtree: true });
manifest
{
"manifest_version": 3,
"name": "My Web Blocker",
"version": "1.0",
"description": "חוסם אתרים מותאם אישית",
"permissions": [
"storage",
"tabs"
],
"host_permissions": [
"<all_urls>"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_popup": "popup.html"
},
"incognito": "spanning",
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": ["content.js"],
"run_at": "document_end"
}
]
}
popup
const inputElement = document.getElementById("site");
const addButton = document.getElementById("add");
const listElement = document.getElementById("blocked-list");
// פונקציה שמציגה את רשימת החסימה ומייצרת כפתור הסרה לכל אחד
function updateList() {
listElement.innerHTML = ""; // ניקוי הרשימה הישנה מהמסך
chrome.storage.local.get(["blocked"], (data) => {
const blocked = data.blocked || [];
blocked.forEach((item) => {
const li = document.createElement("li");
li.textContent = item;
// יצירת כפתור הסרה בעברית
const removeBtn = document.createElement("button");
removeBtn.textContent = "הסרה";
removeBtn.className = "remove-btn";
// הפעלת מנגנון ההסרה בלחיצה
removeBtn.addEventListener("click", () => {
removeItem(item);
});
li.appendChild(removeBtn);
listElement.appendChild(li);
});
});
}
// הפונקציה שמוחקת את הפריט מהזיכרון של התוסף ומבטלת את החסימה
function removeItem(itemToRemove) {
chrome.storage.local.get(["blocked"], (data) => {
let blocked = data.blocked || [];
// סינון הפריט החוצה מהרשימה
blocked = blocked.filter(item => item !== itemToRemove);
chrome.storage.local.set({ blocked: blocked }, () => {
updateList(); // עדכון הרשימה שמוצגת למשתמש
});
});
}
// הוספת אתר או מילת מפתח חדשה ליוטיוב
addButton.addEventListener("click", () => {
let item = inputElement.value.trim();
if (!item) return;
// אם זה נראה כמו קישור, ננקה אותו. אם זו מילה רגילה (או בעברית), נשמור אותה כפי שהיא.
if (item.includes(".") || item.startsWith("http")) {
item = item.replace(/^(https?:\/\/)?(www\.)?/, '').toLowerCase();
} else {
item = item.toLowerCase(); // מילה רגילה ליוטיוב
}
chrome.storage.local.get(["blocked"], (data) => {
let blocked = data.blocked || [];
if (!blocked.includes(item)) {
blocked.push(item);
chrome.storage.local.set({ blocked: blocked }, () => {
inputElement.value = "";
updateList();
});
} else {
alert("פריט זה כבר קיים ברשימת החסימה שלך.");
}
});
});
// טעינת הרשימה מיד עם פתיחת חלונית התוסף
document.addEventListener("DOMContentLoaded", updateList);