feat: konu bazlı bildirim + gerçek site tarama
1) Bildirim artık KONU odaklı (il değil)
- Kullanıcı hangi konularda ihale alabildiğini seçer; varsayılan tüm Türkiye
- İl/alım türü/favori kurum 'daha da daralt' altında isteğe bağlı
- notify-store: konular kolonu + otomatik şema geçişi
- notifier: konu başlıkları ihale başlığı/sektör/branş/kalemlerde aranır
2) Gerçek firma sitesi tarama (webScraperService mock'unun yerine)
- server/site-scan.mjs: siteyi GERÇEKTEN çeker, ana sayfa + ürün/hizmet/
hakkımızda iç sayfalarını tarar, HTML'i metne çevirir, AI ile firmanın
tedarik edebildiği ihale konularını çıkarır ('uydurma' yasaklı prompt)
- /api/company/scan (auth'lu)
- ai.mjs: systemOverride desteği (farklı görevler için ayrı sistem promptu)
- Arayüz: 'Sitenizi tarayıp konuları otomatik önerelim' → tıklayarak ekleme
Not: eski webScraperService.js sabit anahtar-kelime sözlüğüydü; domain adında
'tanriverdi' geçince tıbbi ürün listesi uyduruyordu.
This commit is contained in:
+10
-3
@@ -29,6 +29,7 @@ CREATE TABLE IF NOT EXISTS abonelikler (
|
||||
alim_turu TEXT,
|
||||
anahtar TEXT,
|
||||
kurumlar TEXT, -- JSON: favori kurum listesi
|
||||
konular TEXT, -- JSON: konu başlıkları (kullanıcı seçer)
|
||||
aktif INTEGER NOT NULL DEFAULT 1,
|
||||
sonGonderim TEXT,
|
||||
sonGorulenler TEXT, -- JSON: son gönderimde bildirilen ihale id'leri
|
||||
@@ -50,6 +51,10 @@ function open({ create = true } = {}) {
|
||||
}
|
||||
const db = new DatabaseSync(DB_PATH);
|
||||
db.exec(SCHEMA);
|
||||
try {
|
||||
const k = db.prepare('PRAGMA table_info(abonelikler)').all().map((c) => c.name);
|
||||
if (!k.includes('konular')) db.exec('ALTER TABLE abonelikler ADD COLUMN konular TEXT');
|
||||
} catch (e) { console.warn('[notify-store] şema geçişi:', e.message); }
|
||||
return db;
|
||||
}
|
||||
|
||||
@@ -60,10 +65,10 @@ export function subscribe(email, kriter = {}, ad = null) {
|
||||
if (!db) throw new Error('Bildirim deposu kullanılamıyor');
|
||||
try {
|
||||
db.prepare(`
|
||||
INSERT INTO abonelikler (email, ad, sehir, sektor, alim_turu, anahtar, kurumlar, aktif, olusturma)
|
||||
VALUES (?,?,?,?,?,?,?,1,?)
|
||||
INSERT INTO abonelikler (email, ad, sehir, sektor, alim_turu, anahtar, kurumlar, konular, aktif, olusturma)
|
||||
VALUES (?,?,?,?,?,?,?,?,1,?)
|
||||
ON CONFLICT(email, sehir, sektor, alim_turu, anahtar) DO UPDATE SET
|
||||
aktif=1, kurumlar=excluded.kurumlar, ad=excluded.ad
|
||||
aktif=1, kurumlar=excluded.kurumlar, konular=excluded.konular, ad=excluded.ad
|
||||
`).run(
|
||||
email,
|
||||
ad,
|
||||
@@ -72,6 +77,7 @@ export function subscribe(email, kriter = {}, ad = null) {
|
||||
bosaNull(kriter.alimTuru),
|
||||
bosaNull(kriter.anahtar),
|
||||
JSON.stringify(kriter.kurumlar || []),
|
||||
JSON.stringify(kriter.konular || []),
|
||||
new Date().toISOString()
|
||||
);
|
||||
return list(email);
|
||||
@@ -96,6 +102,7 @@ export function list(email) {
|
||||
alimTuru: r.alim_turu || null,
|
||||
anahtar: r.anahtar || null,
|
||||
kurumlar: (() => { try { return JSON.parse(r.kurumlar || '[]'); } catch { return []; } })(),
|
||||
konular: (() => { try { return JSON.parse(r.konular || '[]'); } catch { return []; } })(),
|
||||
aktif: Boolean(r.aktif),
|
||||
sonGonderim: r.sonGonderim,
|
||||
sonGorulenler: (() => { try { return JSON.parse(r.sonGorulenler || '[]'); } catch { return []; } })(),
|
||||
|
||||
Reference in New Issue
Block a user