Yapay zeka mantığıyla çalışan, görsel ve anlamsal tarayıcı hafızası. (TR/EN Otomatik Dil Destekli)
// ==UserScript==
// @name MemoryLens V3sp: Semantic Engine
// @namespace http://tampermonkey.net/
// @version 3.2
// @description Yapay zeka mantığıyla çalışan, görsel ve anlamsal tarayıcı hafızası. (TR/EN Otomatik Dil Destekli)
// @author Mustafa Hakan
// @match *://*/*
// @grant none
// @require https://cdnjs.cloudflare.com/ajax/libs/fuse.js/6.6.2/fuse.min.js
// ==/UserScript==
/* jshint esversion: 8 */
(function() {
'use strict';
const userLang = navigator.language.startsWith('tr') ? 'tr' : 'en';
const TRANSLATIONS = {
tr: {
placeholder: "Zihninde ne var?",
stats: "Hafıza Aktif",
noResult: "Anlamlı bir eşleşme bulunamadı.",
untitled: "Başlıksız İçerik",
noDesc: "İçerik özeti çıkarılamadı.",
readingTime: "dk okuma",
dateSuffix: "kaydedildi"
},
en: {
placeholder: "What's on your mind?",
stats: "Memory Active",
noResult: "No semantic match found.",
untitled: "Untitled Content",
noDesc: "Summary could not be extracted.",
readingTime: "min read",
dateSuffix: "recorded"
}
};
const UI_TEXT = TRANSLATIONS[userLang];
const CONFIG = {
dbName: "MemoryLens_V3",
storeName: "neural_history",
maxTextLength: 7000,
snapshotDelay: 4000
};
const getDB = () => {
return new Promise((res, rej) => {
const req = indexedDB.open(CONFIG.dbName, 1);
req.onupgradeneeded = (e) => {
e.target.result.createObjectStore(CONFIG.storeName, { keyPath: "url" });
};
req.onsuccess = (e) => res(e.target.result);
req.onerror = rej;
});
};
const captureInsight = async () => {
if (document.hidden) return;
const descMeta = document.querySelector('meta[name="description"]');
const ogImage = document.querySelector('meta[property="og:image"]');
const bodyText = document.body.innerText || "";
const words = bodyText.split(/\s+/);
const meta = {
url: window.location.href,
title: document.title || UI_TEXT.untitled,
desc: descMeta ? descMeta.content : "",
image: ogImage ? ogImage.content : "",
icon: `https://www.google.com/s2/favicons?sz=128&domain=${window.location.hostname}`,
text: bodyText.slice(0, CONFIG.maxTextLength).replace(/\s+/g, ' '),
domain: window.location.hostname,
timestamp: Date.now(),
wordCount: words.length,
readingTime: Math.ceil(words.length / 200)
};
try {
const db = await getDB();
const tx = db.transaction(CONFIG.storeName, "readwrite");
tx.objectStore(CONFIG.storeName).put(meta);
} catch (err) {
console.warn("MemoryLens Save Error:", err);
}
};
setTimeout(captureInsight, CONFIG.snapshotDelay);
const injectUI = () => {
if (document.getElementById('ml-v3-root')) return;
const root = document.createElement('div');
root.id = 'ml-v3-root';
root.innerHTML = `
<div id="ml-v3-blur" style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.6);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);z-index:2147483647;display:none;justify-content:center;padding-top:12vh;">
<div id="ml-v3-container" style="width:700px;background:#111;border:1px solid #333;border-radius:20px;box-shadow:0 30px 100px rgba(0,0,0,0.8);overflow:hidden;color:#fff;font-family:sans-serif;">
<div id="ml-v3-header" style="padding:25px;border-bottom:1px solid #222;position:relative;">
<input type="text" id="ml-v3-input" placeholder="${UI_TEXT.placeholder}" autocomplete="off" style="width:100%;background:transparent;border:none;color:#fff;font-size:22px;outline:none;font-weight:300;" />
<div id="ml-v3-stats" style="position:absolute;right:25px;top:32px;font-size:10px;color:#555;text-transform:uppercase;letter-spacing:1px;">${UI_TEXT.stats}</div>
</div>
<div id="ml-v3-results" style="max-height:450px;overflow-y:auto;padding:10px;"></div>
</div>
</div>`;
document.body.appendChild(root);
root.querySelector('#ml-v3-input').addEventListener('input', (e) => neuralSearch(e.target.value));
};
const neuralSearch = async (query) => {
const resContainer = document.getElementById('ml-v3-results');
if (query.length < 2) {
resContainer.innerHTML = '';
return;
}
const db = await getDB();
const tx = db.transaction(CONFIG.storeName, "readonly");
const data = await new Promise((res) => {
tx.objectStore(CONFIG.storeName).getAll().onsuccess = (e) => res(e.target.result);
});
const fuse = new Fuse(data, {
keys: [
{ name: 'title', weight: 2 },
{ name: 'text', weight: 1 },
{ name: 'domain', weight: 1.5 }
],
threshold: 0.35,
includeScore: true
});
const results = fuse.search(query).slice(0, 10);
renderResults(results.map(r => r.item));
};
const renderResults = (items) => {
const container = document.getElementById('ml-v3-results');
if (items.length === 0) {
container.innerHTML = `<div style="padding:40px;text-align:center;color:#444;font-style:italic;">${UI_TEXT.noResult}</div>`;
return;
}
container.innerHTML = items.map(item => {
const imgSrc = item.image || item.icon;
const displayDesc = item.desc || (item.text ? item.text.slice(0, 150) : UI_TEXT.noDesc);
const dateStr = new Date(item.timestamp).toLocaleDateString();
return `
<div class="ml-v3-card" data-url="${item.url}" style="display:flex;gap:15px;padding:15px;border-radius:12px;cursor:pointer;transition:0.2s;border:1px solid transparent;margin-bottom:5px;">
<img src="${imgSrc}" style="width:50px;height:50px;border-radius:10px;object-fit:cover;background:#222;" onerror="this.src='${item.icon}'">
<div style="flex:1;min-width:0;">
<span style="font-weight:500;font-size:15px;color:#eee;display:block;margin-bottom:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">${item.title}</span>
<p style="font-size:13px;color:#888;margin:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;">${displayDesc}</p>
<div style="margin-top:8px;font-size:11px;color:#444;display:flex;gap:15px;">
<span style="color:#666;font-weight:600;">${item.domain}</span>
<span>${item.readingTime} ${UI_TEXT.readingTime}</span>
<span>${dateStr}</span>
</div>
</div>
</div>`;
}).join('');
container.querySelectorAll('.ml-v3-card').forEach(card => {
card.onclick = function() { window.location.href = this.getAttribute('data-url'); };
card.onmouseover = function() { this.style.background = '#1a1a1a'; this.style.borderColor = '#333'; };
card.onmouseout = function() { this.style.background = 'transparent'; this.style.borderColor = 'transparent'; };
});
};
window.addEventListener('keydown', (e) => {
if (e.altKey && e.key.toLowerCase() === 'k') {
e.preventDefault();
injectUI();
const blur = document.getElementById('ml-v3-blur');
const isOff = blur.style.display === 'none' || blur.style.display === '';
blur.style.display = isOff ? 'flex' : 'none';
if (isOff) document.getElementById('ml-v3-input').focus();
}
if (e.key === 'Escape') {
const blurEl = document.getElementById('ml-v3-blur');
if (blurEl) blurEl.style.display = 'none';
}
});
})();