diff --git a/omni/store.py b/omni/store.py index 1e865bf..83ada87 100644 --- a/omni/store.py +++ b/omni/store.py @@ -216,9 +216,22 @@ def browse2(q="", names=None, limit=60, offset=0, sort="score", priced=False, ty if typ and typ != "all": where += "AND (',' || COALESCE(types,'') || ',') LIKE ? " args += [f"%,{typ},%"] + if sort == "quality": + # Чистая лента: выкидываем шум до сортировки — длинные склейки-«лапши», + # короткие хайповые куски, сервисный мусор (wiki/docs/changelog/chapterlist), + # и записи без даты и без текста. + where += """AND length(COALESCE(title,'')) BETWEEN 8 AND 220 + AND title NOT GLOB '*[[]Chapter List*' AND title NOT LIKE '%||%||%' + AND lower(COALESCE(title,'')) NOT LIKE '%changelog%' + AND lower(COALESCE(title,'')) NOT LIKE '%release notes%' + AND lower(COALESCE(title,'')) NOT LIKE '%documentation%' + AND (COALESCE(text,'') = '' OR length(text) <= 4000 OR length(title) >= 25) + AND (published IS NOT NULL AND published != '' OR length(COALESCE(text,'')) >= 60) + """ order = {"fresh": "ORDER BY published DESC, id DESC", "price": "ORDER BY CAST(price AS REAL) DESC, score DESC", - "old": "ORDER BY published ASC, id ASC"}.get(sort, "ORDER BY score DESC, id DESC") + "old": "ORDER BY published ASC, id ASC", + "quality": "ORDER BY score DESC, id DESC"}.get(sort, "ORDER BY score DESC, id DESC") with db() as c: total = c.execute("SELECT COUNT(*) FROM items " + where, args).fetchone()[0] rows = c.execute("SELECT id,provider,kind,source,title,text,author,published,score,price,currency,url,types " diff --git a/web/index.html b/web/index.html index abd57c9..5f0ef9e 100644 --- a/web/index.html +++ b/web/index.html @@ -352,7 +352,7 @@ pre { padding: var(--omni-space-4); } @@ -449,7 +449,7 @@ function requestScope(key,ctx=activeContext){const serial=(serials[key]||0)+1;se function route(){ const [raw,query=""]=location.hash.replace(/^#\/?/,"").split("?"),p=new URLSearchParams(query),before=S.view; S.view=NAV.some(n=>n.id===raw)?raw:"feed";S.q=p.get("q")||"";S.cat=p.get("cat")||"";S.type=p.get("type")||"all"; - S.sort=["fresh","old","score","price"].includes(p.get("sort"))?p.get("sort"):"fresh";S.days=int(p.get("days"),0,3650);S.priced=p.get("priced")==="1";S.src=p.get("src")||"";S.page=int(p.get("page")||1,1,25001);S.tag=p.get("tag")||"";S.tab=p.get("tab")==="panels"?"panels":"signals"; + S.sort=["fresh","old","score","price","quality"].includes(p.get("sort"))?p.get("sort"):"fresh";S.days=int(p.get("days"),0,3650);S.priced=p.get("priced")==="1";S.src=p.get("src")||"";S.page=int(p.get("page")||1,1,25001);S.tag=p.get("tag")||"";S.tab=p.get("tab")==="panels"?"panels":"signals"; closeDrawer();if($("#modal").classList.contains("show"))tabler.Modal.getOrCreateInstance($("#modal")).hide(); if(before!==S.view)$("#global-feedback").innerHTML="";render(before!==S.view); } @@ -489,7 +489,7 @@ function itemRow(it,compact=false){const labels=typeLabels(),types=typesOf(it).s const exQS=()=>new URLSearchParams({q:S.q,category:S.cat,type:S.type,sort:S.sort,...(S.days?{days:String(S.days)}:{}),...(S.priced?{priced:"1"}:{}),...(S.src?{src:S.src}:{}),limit:"1000"}).toString(); function readFeedFilters(){return {q:$("#q")?.value.trim()||"",cat:$("#cat")?.value||"",sort:$("#f-sort")?.value||"fresh",days:+($("#f-days")?.value||0),type:$("#f-type")?.value||"all",src:$("#f-src")?.value.trim()||"",priced:!!$("#f-priced")?.checked,page:1}} V.feed=async ctx=>{ - ctx.mount(`