← Back to docs

RSS Watch

Language: SV | EN | SV

RSS Watch

RSS Watch ger feedvisning, kategorigruppering, valfria AI-sammanfattningar och ett fullständigt REST-API för scraper-workers och klientapplikationer.

RSS Watch är både en publik feedläsare och en backend-pipeline för inläsning. De publika sidorna (/feed, kategorivyer och entry-sidor) är för läsare, medan scraper-workers och trigger-jobb hämtar konfigurerade källor och postar normaliserade payloads till Tools för vidare bearbetning.

Crawler-identitet och User-Agent-strängar

RSS Watch-workers identifierar sig som bottrafik och inkluderar en dokumentations-URL i User-Agent.

  • Scrape-runner UA-mönster:
    • Mozilla/5.0 (compatible; RSSWatchBot; +https://tools.tornevall.net/docs/rsswatch; runner=scrape; host=<agent-hostname>)
  • Trigger-runner UA-mönster:
    • Mozilla/5.0 (compatible; RSSWatchBot; +https://tools.tornevall.net/docs/rsswatch; runner=trigger; host=<agent-hostname>)

Driftnotering: schemaläggnings-/agentrapportering nycklas fortfarande på agent_id (hostname) i API-anrop; ändrad User-Agent-text ändrar inte agentattribueringen.

Scrape-workers skriver nu också tidsstämplade körloggar. Scrapern försöker i första hand använda SCRAPE_LOG_FILE, därefter /var/log/tools-scraper/scrape.log, och annars lokala fallback-sökvägar i scraperprojektet när de är skrivbara.

Publik feed-sida

  • URL: /feed
  • Bläddra feeds grupperade per kategori
  • Använd den nya fritextsökningen för inlägg högst upp på /feed för att söka i titlar, beskrivningar, innehåll, sajtnamn och kategorier utan att lämna sidan
  • Sökresultaten laddas via AJAX, grupperas per kategori och ersätter tillfälligt den vanliga feed-/kategori-/sajtöversikten tills Rensa används
  • Standardvärdet för Feeds per page är nu konfigurerbart från /feed-admin (query per_page kan fortfarande överstyra per anrop)
  • Kategorikorten är nu ihopfällda som standard när ingen tidigare state finns sparad
  • Sidan minns nu senast öppnade kategorikort i en cookie och återställer bara det kortet vid nästa besök
  • Feed Admin kan nu sätta en ljus accentfärg per kategorikort så att den publika /feed-sidan blir lättare att skanna utan att textläsbarheten försämras
  • Öppna feed-källa eller kategori-RSS
  • Öppna den nya aggregerade kategorisidan på /feed/c/{categorySlug} (med samma versions-/diffvisning som vanliga feedsidor)
  • Öppna den nya kompakta kategorikortvyn på /feed/cards/{categorySlug} för en mer kortbaserad analysöversikt
  • Kortvyn visar nu AI-analyser överst (exakt en vald variant per period: daily/weekly/monthly/yearly) och därefter den vanliga artikel-listan för kategorin.
  • Kortvyn sorterar nu också analysutgåvorna efter riktig period-bucket i stället för enbart genereringstid, så en ominkörd äldre vecka/månad inte längre hamnar före en nyare bucket bara för att den byggdes om senare.
  • Artiklarna i kortvyn har samma historik-/diffbeteende som klassiska kategorivyn (history=1, history_limit).
  • Kortvyn har nu också ett mer redaktionellt/tidningslikt uttryck med kategori-masthead, analyskort som "utgåvor" och artikelpresentation där huvudartikel lyfts först.
  • Analyslänkar som visas på /feed, /feed/c/{categorySlug} och /feed/cards/{categorySlug} skriver nu om råkade localhost-/loopback-URL:er till den aktiva publika hosten innan de renderas.
  • Publika artikel-/källänkar löser nu också relativa käll-URI:er (till exempel /artiklar/foo) mot feedens real_url/url, så att både /out/{contentId} och de synliga källänkarna blir fullt kvalificerade.
  • Feed-/artikelsidor visar nu upplöst författarnamn när källflödet bara lagrat ett ofärdigt publishby-värde (till exempel ett numeriskt ID) och en operatör lagt in en manuell mappning för just den feeden.
  • Se första och senaste discovery-tid
  • Se cachade AI-sammanfattningar per kategori
  • Feed Admin följer nu också valt anchor-datum när den väljer föredragen kategori-/sitanalys för en period, så granskning av en äldre bucket inte längre tyst faller tillbaka till det som är aktuellt just idag.
  • Feeds som markeras som dolda visas inte i /feed utan får i stället en hash-baserad direkt-URL, till exempel /feed/key/{public-hash} och /api/rss/feed/{public-hash}
  • Analytics-feeds finns nu som dedikerade selectors under /api/rss/feed/{selector}:
    • analytics-daily (alias daily-analytics)
    • analytics-weekly (alias weekly-analytics)
    • analytics-monthly (alias monthly-analytics)
    • analytics-yearly (alias yearly-analytics)
    • analytics-bulk (alias bulk-analytics, kombinerar daily/weekly/monthly/yearly)
  • Analytics-feedposter länkar nu tillbaka till relevant kategori/site där det går (/api/rss/feed/{category-slug} för kategori-analytics och /feed/{site-urlid} för site-analytics)
  • /feed har nu ett mini-kort Ask about all open feeds där besökare kan ställa fria frågor mot den öppna RSS-datan
  • /feed visar nu också en tydlig support-/kontaktsektion intill disclaimers, med både länk till den vanliga kontaktsidan och direktadressen support@tornevall.net för frågor, klagomål, rättelser eller feedrelaterade problem

Feed-frågor och historik

  • Skicka fråga: POST /feed/user-questions
  • Historiksida: GET /feed/user-questions
  • Ask-a-question behåller nu bokstavliga fallback-sökord vid sidan av AI:ns keyword-plan, så korta konkreta termer som faktiskt är SQL/LIKE-sökbara (till exempel sabah) inte lika lätt försvinner ur retrievalen.
  • När träffen bara finns i artikelns beskrivning/brödtext får modellen nu också korta keyword-styrda utdrag från de fälten i stället för bara titelbaserade entry-sammanfattningar.
  • Gäster måste passera Cloudflare Turnstile innan submit och begränsas av konfigurerbara dygns-/veckokvoter
  • Inloggade användare har också kvoter (högre standardvärden), med separat konfigurerbar dygns-/veckogräns
  • Admin-användare är obegränsade och slipper Turnstile för den här funktionen
  • Gästintag har även ett konfigurerbart samtidighetsskydd (distinkta aktiva gäst-IP i kort processfönster)
  • Varje fråga sparar tidpunkt, aktör (user_id eller gäst), IP, user-agent, status, svar/fel och svarsmetadata för audit/historik
  • Frågeformuläret på /feed är nu AJAX-först och visar svar/fel inline; vanlig form post/redirect finns kvar som fallback utan JavaScript
  • AJAX-frågor på /feed och i site-specifika feedpaneler använder nu ett tvåstegsflöde för bättre återkoppling:
    • POST /feed/user-questions med start_only=1 reserverar frågeraden och returnerar en kortlivad klienttoken samt progress-URL:er
    • POST /feed/user-questions/{question}/process kör själva analysen i bakgrundsanropet
    • GET /feed/user-questions/{question}/status låter webbläsaren poll:a aktuell fas/progress tills svaret är klart
  • Dessa progress-anrop kör nu ett i taget i stället för att stapla överlappande /status-förfrågningar. Fastnade poll-anrop avbryts efter en kort timeout, webbläsaren backar av när sidan ligger i bakgrunden, och progressuppdateringen återupptas rent när fliken blir aktiv igen.
  • Om bakgrundsanropet till process redan hinner bli färdigt med slutsvaret tar webbläsaren nu det svaret direkt i stället för att fortsätta skicka extra /status-pollning tills nästa timerhugg.
  • Submit-knappen växlar nu till en tydlig spinner medan webbläsaren väntar på att analysen ska bli färdig.
  • En progressruta visar nu aktiv analysfas, förfluten tid och – när det finns – aktuellt föranalys-pass samt aktuellt kontextblock.
  • För personinriktade frågor (till exempel "artiklar som Andreas Magnusson skrivit") kör Feed Q&A nu ett förstagångspass mot content.publishby innan bredare keyword-fallback.
  • Om en feed lagrar ID-liknande eller äldre publishby-värden i stället för riktiga namn använder Feed Q&A nu också de per-feed manuella publishby-mappningarna från RSS-editorn, så att sådana frågor fortfarande kan hitta rätt skribent.
  • Det förbättrar träffsäkerheten för författarattribuering när byline finns som namn, men behåller fallback-sökning om publishby saknas eller är inkonsekvent.
  • När systemet breddat underlaget med extra relaterade sökord visar /feed nu dessa uttryck i en readonly-hjälpruta under senaste svaret, så läsaren ser vad som också användes för att hitta mer material före svaret.
  • /feed och den site-specifika frågepanelen för en feed visar nu också en separat readonly-ruta med sökord som användes, så läsaren kan se de bokstavliga querybara termer/fråser som backenden faktiskt sökte efter innan eventuella bredare extratermer användes.
  • /feed stöder nu följdfrågor: användaren kan välja ett tidigare färdigt svar som följdfrågekontext, och backenden återanvänder tidigare retrieval-termer samt tidigare svarskontext när frågan ska fördjupas.
  • Följdfrågor återanvänder nu också en kompakt lista över tidigare sparade referensträffar, så djupare frågor kan fortsätta från samma konkreta artikel-/källunderlag och inte bara från den tidigare formuleringen.
  • Feed Q&A-inställningarna har nu även en tydlig webbsökning-toggle (use_web_search) så RSS-svar kan köras med web_search-baserad verifiering när den är påslagen.
  • Rutorna för senaste svar på /feed och i site-specifika feedpaneler visar nu också om webbsökning faktiskt användes för just det svaret och listar, när de finns, de källänkar/citations som returnerades.
  • Samma senaste-svar-rutor visar nu också sparade referensträffar från retrieval-steget, så det blir lättare att se vilka artiklar/källor som låg till grund för svaret innan man ställer en djupare följdfråga.
  • De nyaste ytorna för Feed Q&A-svar renderar nu säker markdown konsekvent, så länkar och styckeformat i senaste/nyliga svar visas formaterat i stället för som rå markdown eller råtext.
  • Dessa extra sökord städas nu också om till bokstavliga/querybara termer före visning och återanvändning, så person-/entitetsfraser blir mer i stil med Tara Sabah / Tara Saleh i stället för konstiga hjälputtryck som tara sabah artiklar eller tara saleh källor.
  • Användare kan nu välja sökordsbredd per fråga (strict, balanced, expansive) både på /feed och i site-specifika frågepaneler.
  • Feed-Q&A har nu admin-konfigurerbart scope: tidsfönster (daily/weekly/monthly/yearly/all_time), tillåtna kategorier, tillåtna sajter, context-cap för antal poster, max antal meningar i svaret, standardsökordsbredd och antal minihistorikrader på /feed
  • /feed visar nu också en liten inline-historik över de senaste färdiga frågorna direkt i frågekortet
  • /feed/user-questions har nu paginering med valbart antal rader per sida för att hantera spammig historik bättre
  • Admin kan nu ta bort frågerader direkt från /feed/user-questions via AJAX (vanlig redirect-fallback fungerar fortsatt utan JavaScript)
  • Admininställningarna på /feed/user-questions och i /feed-admin innehåller nu även val av svarsmodell och tonalitet för OpenAI-svar
  • Adminvyn för historik har nu filter för status, user_id (eller guest), ip och deleted-scope (active/deleted/all)
  • Adminmoderering stöder nu både single-row och bulk-delete med explicit delete-mode:
    • hard delete tar bort raden permanent
    • soft delete sparar raden med raderingsmetadata (deleted_at, deleted_by_user_id, deleted_reason)
  • Soft-deletade rader kan nu återställas via adminåtgärd (POST /feed/user-questions/{question}/restore) för undo-flöde.
  • Feedfrågor stöder nu även en all-time / hela databasen-period så frågor kan söka över hela den lagrade RSS-historiken, inte bara daily, weekly, monthly eller yearly.
  • Feedfrågor kör nu ett keyword-first steg före full kontextbyggnad: OpenAI tar fram kompakta sökord från frågan, backenden smalnar av kandidatrader i content via träffar i title/description/content, och först därefter byggs kontext-/versionsblock från relevanta rader.
  • Dessa SQL-matchade rader följer nu också med som ett eget matched_entries-lager, så konkreta utdrag från title, description, content, publishby, feed_title och artikellänkar fortfarande finns kvar när slutsvaret skrivs.
  • Det förbättrar särskilt frågor som "vem skriver om X just nu?", eftersom slutmodellen då kan titta på de faktiska träffraderna i stället för att bara se aggregerade totalsiffror som antal feeds eller poster.
  • Keyword-extraktorn förväntar sig nu en strikt JSON-lista från OpenAI och sorterar termer från mest specifik fras till bredare stödsökord.
  • Flertokensnamn för personer eller entiteter prioriteras nu som hela fraser (till exempel anders sydborg) före lösare stödsökord, vilket minskar falska träffar från breda förstnamnssökningar.
  • Generiska frågeord och utfyllnadsord som har, du, något, spännande, med, with, about, something och liknande filtreras nu bort även när de råkar finnas kvar i OpenAI-svaret eller i den deterministiska fallbacken.
  • Om OpenAI-baserad keyword-extraktion inte är tillgänglig försöker fallbacken nu först behålla starkare fraskandidater (citerade fraser och tydliga egennamnssekvenser) och breddar bara med mer specifika efterled som efternamn.
  • Admin kan sätta ett standardläge för sökordsbredd, medan den aktuella användaren fortfarande kan överstyra detta per fråga.
  • Keyword-planeringen är nu mer scope-förankrad: extra sökord måste hålla sig nära både användarens fråga och, när det finns, valt kategori-/site-scope. Alltför generiska planner-termer filtreras bort innan SQL-retrieval körs.
  • Kortare perioder (daily, weekly, monthly) tillåter högre träfftak än yearly och all_time, så specifika korttidsfrågor kan få mer underlag utan att promptstorleken skenar.
  • Feedfrågor kan nu köra en begränsad flerpass-loop före slutsvaret: varje pass kan låta OpenAI föreslå vad vi ska leta efter härnäst, köra ytterligare SQL-baserad avsmalning och sedan avgöra om underlaget redan räcker.
  • Standardtaket för föranalysen är 5 pass och är admin-konfigurerbart; om taket nås går systemet ändå vidare till slutanalysen med bästa hittills insamlade underlag.
  • Stora frågor som triggar sekventiell blockanalys visar nu också just den backendfasen i progressrutan, så användaren ser att systemet fortfarande arbetar i stället för att sidan känns låst.
  • Frågemetadata sparar nu rikare analysdetaljer för breda körningar (till exempel när inget fokus valts eller när många sajter ingår): scope-profil, kontextstorlek, blockmetadata och retrievalstrategi.
  • /feed/user-questions visar nu en kompakt ruta How this answer was analyzed för färdiga rader, med metod, scope-/retrievaldetaljer, bokstavliga sökord som användes och eventuella extra sökord före slutsvaret.

Entry-baserade kontroller för brusiga inlägg (/feed/entry/{contentId})

  • Entry/permalink-sidor begränsar nu den inline-visade revisionshistoriken till de 200 senaste lagrade versionerna för samma feed/länk-par, samtidigt som totalt antal revisioner fortfarande visas när en länk har extrem dubblettchurn.
  • Blocket Changes/feed/entry/{contentId} kan nu växla mellan den befintliga highlight-diffen och en side-by-side-jämförelse mellan före/efter via sidans diff-toggle (?diff_view=inline eller ?diff_view=side_by_side).
  • Den råa Versions-listan ligger fortfarande kvar som en revision i taget under diffblocket, så den nya side-by-side-vyn förbättrar jämförelsen mellan versionspar utan att ta bort den kronologiska revisionsloggen.
  • För admin finns nu per-inläggskontroller på entry-sidan för länkar som cyklar/brusar:
    • Markera/avmarkera cautious (auto-purge av brusiga dubbletter vid framtida import)
    • Ignore this post at import (feed-scope eller globalt), så inkommande scraper-rapporter för länken släpps
    • Purge noisy duplicates (behåller senaste representant per distinkt meaningful hash)
    • Purge all except one latest row (hård reset)

Analytics-kort på /feed

  • Vecko-/månads-/årskort visas per kategori endast när cachad analytics faktiskt finns
  • Korten är färgkodade per period
  • Varje kategori-variant har nu en Share-knapp som öppnar /feed/c/{categorySlug} i ny flik
  • Klicka Read more för att expandera längre analyser
  • Huvudöversikten på /feed uppdaterar nu också dessa Read more-knappar när ett ihopfällt kategorikort öppnas, så längre analyser går att expandera där igen och inte bara i kortvyn.
  • Markdown renderas till HTML för bättre läsbarhet
  • /feed visar nu exakt en vald publik utgåva per period (daily, weekly, monthly, yearly) för varje kategori-/sajtblock.
  • Extra cachade utgåvor renderas inte längre inline på /feed; använd /feed/cards/{categorySlug}?show_all=1 när du medvetet vill granska alla sparade utgåvor för en kategori.

Redaktörssida

  • URL: /rss
  • Kräver permission:rss
  • Hantera feed-URL:er och metadata
  • Varje feed-rad har nu en Authors-åtgärd som öppnar /rss/{urlid}/publishby-mappings
  • Där kan operatörer manuellt mappa råa publishby-värden (till exempel 4, 27 eller andra ofärdiga identifierare) till ett riktigt visningsnamn
  • Mappningarna är scoped per urlid, så samma råa publishby-värde kan återanvändas av en annan feed utan krockar
  • Upplösta namn från det här editorflödet återanvänds av publika /feed-sidor, kategorikort, listan över redigerade poster, Feed Q&A och /api/rss/feed/{site}-läsare
  • Se cachad kategori-analytics
  • Site Type stöder nu explicit xpath och json utöver rss och wp
  • När sitetype=xpath krävs elements-regler i JSON och valideras server-side innan sparning
  • elements accepterar båda stödda regel-formaten:
    • objektformat (begin + table) för JSON-traversering
    • äldre pipeline-array-format för HTML/XPath-extraktion
  • I listvyn på /rss visas elements-redigering nu bara för xpath-rader och ligger i en kollapsbar panel med AJAX-sparning på blur
  • Ny visuell hjälpsida: /rss/xpath-lab låter redaktörer klistra in HTML-snippets, inspektera DOM-översikt, testa XPath-uttryck och granska en SimpleXML-liknande XML-preview innan regler sparas
  • URL-mappning i add-form: vid 🤖 Auto skrivs upptäckt feed-endpoint till URL medan den först inmatade sid-URL:en bevaras i Real URL
  • Add-formuläret på /rss gör nu en server-side-dupe-kontroll före insert. Om inskickad URL eller Real URL redan matchar en befintlig feedrad (även korsmatch mellan fälten) blockeras insert och den matchande raden visas i varningen.
  • Add-feed-analysen behandlar nu skyddade WordPress REST-endpoints (401 / 403 från /wp-json/wp/v2/posts) som obrukbara och fortsätter vanlig feedupptäckt, så låsta WordPress-installationer kan falla tillbaka till /feed eller <link rel="alternate">
  • Add-feed-autodetekteringen förstår nu också vBulletin-liknande externa RSS-endpoints som external?type=rss2... och external.php?type=RSS2..., inklusive relativa <link rel="alternate">-feedlänkar som hittas på forumsidor.
  • Kategoriflöde i add-form: välj befintlig kategori i dropdown eller skriv ny i fritextfältet (fritext har företräde)
  • RSS/Atom-importen sparar nu creator/author-byline i content.publishby när feeden skickar med sådan metadata (t.ex. dc:creator).
  • RSS2-importen hanterar nu namespacade vBulletin-fält mer robust (content:encoded, dc:creator, guid, pubDate), prioriterar content:encoded som fulltext när den finns och använder stabil fallback (guid/link/hash) när länk saknas.
  • vBulletin-liknande RSS2-importer behåller nu också item-nivåns kategorimetadata när den finns och använder GUID-medveten duplicate-kontroll innan den äldre länkbundna duplicate-logiken tar vid, vilket hjälper forumfeeds där samma post ibland publiceras om med något ändrad synlig URL.

Feed admin

  • URL: /feed-admin
  • Operatörer med den separata behörigheten rss.posting.handle får nu också ett dedikerat Posting Queue-gränssnitt på både /feed-admin/posting-queue och /rss/posting-queue
  • Den kön är avsedd för enkla Playwright-vänliga publiceringsflöden: varje senaste artikelrad visar AJAX-styrda checkboxar för Handle group, Handle page, Handled group och Handled page, tillsammans med artikelns titel, ett kort ingressutdrag och källänken
  • Köfiltren stöder lägena review, group, page och done, så en bot eller operatör kan fokusera enbart på väntande gruppposter, enbart på väntande sidposter eller det redan hanterade arkivet
  • Rader försvinner automatiskt från den aktiva kön när valda mål är markerade som handled
  • Generera daglig, veckovis, månadsvis eller årsvis kategori-analys
  • Generera daglig, veckovis, månadsvis eller årsvis site-analys per feed/nyhetskälla
  • Använd kalenderfältet Anchor date för att generera historiska perioder (t.ex. förra veckan/månaden/året/dagen om cron missat)
  • Kategori- och site-kort har nu även valfria segmentspecifika Anchor date-fält; prioritet är segment anchor -> global anchor -> dagens datum
  • Nuvarande periodlogik är kalenderstyrd från valt ankardatum (daily = den dagen, weekly = ISO-vecka med måndag som start, monthly = kalendermånad, yearly = kalenderår)
  • Välj modell per körning
  • Fyll i valfri watch_for-text före generering
  • Befintliga cachade varianter har nu åtgärder per variant för Retranslate och Regenerate (replace) (både för kategori och site)
  • När Regenerate (replace) används skrivs vald variant/period över i stället för att skapa en extra dubblettvariant
  • Site-generering har nu ett separat valfritt titelfält per site (skilt från den globala titeln)
  • Feed-admin-korten har nu också två städåtgärder per period:
    • Purge old buckets: rensa bort cachade utgåvor från äldre period-buckets men behåll aktuell bucket
    • Keep only selected edition: radera alla andra cachade utgåvor för vald period och behåll bara den utgåva som just nu är vald
  • Feed-admin innehåller nu även en separat ruta för Feed Q&A scope and brevity settings där admin kan begränsa vilka kategorier/sajter som frågefunktionen på /feed får använda
  • /feed-admin innehåller nu också en panel för Feed script snippets / embeddable widgets där operatören kan spara återanvändbara JavaScript-boxar, autospara dem via AJAX, låta AI generera inline-scriptet och kopiera en mergad bundle-URL för externa sajtinbäddningar.

Scheduler-notering

  • Analytics-schemat är nu admin-konfigurerbart i /feed-admin med separata aktivera/inaktivera- och tidsfält per period för daily, weekly, monthly och yearly.
  • Cron bör köra scheduler-kontrollen varje minut (antingen via Laravel schedule:run eller direkt via php artisan rss:run-scheduled-analytics).
  • Schedulern kör varje period en gång per relevant cykel efter konfigurerad servertid; missade körningar fångas upp så snart som möjligt.
  • Om en period saknar tidigare scheduler-timestamp betraktas den som aldrig körd och körs direkt en gång.
  • Automatiska scheduler-körningar använder en dedikerad auto-varianttitel ([AUTO] Scheduled analytics) och kör alltid med overwrite-current-semantik så att automatiska varianter uppdateras på plats.
  • Feed Admin och Scheduled Jobs visar nu också senaste schemalagda slot, anchor date, tolkade ok/error-räknare, språk och ett kort outpututdrag per period så det är lättare att se vad cronkörningen faktiskt hann klart med.
  • Manuella CLI/API-körningar finns fortfarande kvar vid behov.
  • Manuella CLI-körningar hoppar nu över oförändrade bucket+variant-signaturer som standard för att undvika onödiga upprepade AI-anrop.
  • Använd php artisan rss:generate-analytics --period=yearly --force (eller --overwrite-current) för att uttryckligen köra om och skriva över den aktuella bucketraden även när underliggande snapshot är oförändrat.
  • För större dataset kör kategori- och sajtanalyser nu segmenterad blockbearbetning före slutsyntes (djupare analysmönster i samma stil som blockanalys i Feedfrågor).

RSS Maintenance Admin

  • URL: /rss-maintenance-admin
  • Listar misstänkta länkar med ovanligt många versioner på kort tid
  • Jämför rå hash-churn mot meaningful hash-churn för att hitta brusiga pseudo-uppdateringar
  • Stöd för dry-run och live-purge per länk, där senaste representant per meningsfull förändring behålls

API-referens

Bas-URL

  • Dev: https://tools.tornevall.com/api
  • Prod: https://tools.tornevall.net/api

Autentisering

RSS API-endpoints använder provider-specifika API-nycklar:

  • scraper=1 krävs på /api/rss/urls
  • Ingen autentisering krävs för publika läs-endpoints (/api/rss, /api/rss/feed/{site})
  • Scraper-writeendpoints (/api/rss/data) accepterar anropet utan extra autentisering (rate-limitade)
  • Analytics-triggerEndpoint (/api/rss/analytics/run) kräver Authorization: Bearer <ANALYTICS_CRON_SECRET>
  • Operator-endpointsen för posting queue (/api/rss/posting-queue/items*) kräver inloggad webbsession samt den dedikerade behörigheten rss.posting.handle
  • Återanvändbara frontendbundle-endpoints för feed-widgets finns nu också under /api/managed-scripts/feed och /api/managed-scripts/feed/bundle.js; se docs/frontend-script-boxes för det delade scriptbox-kontraktet.
  • De hanterade feed-scriptendpointsen accepterar nu också additiva filterparametrar som feed_ids, feeds, categories, groups, category_slugs och limit, och skickar tillbaka den normaliserade tolkningen som query_context.filters.

GET /api/rss/posting-queue/items

Returnerar operatörens posting queue som JSON för den aktuellt inloggade användaren.

Queryparametrar:

  • queue=review|group|page|done (standard review)
  • category=<category-slug>
  • feed_id=<urlid>
  • per_page=<10..250>

Svaret innehåller:

  • filters
  • pagination
  • items[] med contentid, urlid, title, description, excerpt, link, feed_title, feed_category, entry_url och queue_status

PATCH /api/rss/posting-queue/items/{contentId}

Uppdaterar checkbox-status för en kö-rad.

Stödda booleanfält:

  • handle_group
  • handle_page
  • handled_group
  • handled_page

Valfritt hjälpfält:

  • queue=review|group|page|done så att svaret också kan tala om för klienten om raden ska tas bort direkt ur den aktuella filtrerade listan.

Success-svar innehåller:

  • contentid
  • queue_status
  • should_remove

GET /api/rss

Returnerar översikt med URL-lista, kategorier och tillgänglig parameterinfo.

Svar (200)

{
  "urls": [
    {
      "urlid": 12,
      "title": "Exempelfeed",
      "url": "https://example.com/rss",
      "real_url": "https://example.com/rss",
      "category": "Nyheter",
      "readinterval": 60,
      "lastscrape": "2026-04-01 08:00:00",
      "publicSelector": "12",
      "hidden": false,
      "feedUrl": "/api/rss/feed/12",
      "categoryFeedUrl": "/api/rss/feed/nyheter"
    }
  ],
  "categories": [
    { "name": "Nyheter", "slug": "nyheter", "feedCount": 3 }
  ],
  "availParams": { "always": [0, 1], "scraper": [0, 1] }
}

GET /api/rss/urls

Returnerar skrapbara feed-URL:er. Kräver scraper=1.

Query-parametrar

Parameter Krav Beskrivning
scraper ja Måste vara 1 annars avvisas anropet med 403
agent_id rekommenderas Stabilt agent/worker-ID. Används för per-agent due-fönster
agent_name fallback Fallback-identifierare när agent_id saknas
always nej 0 (standard) = due-urval för agent; 1 = alla skrapbara rader
limit nej Max antal rader när always=0

always=0-beteende:

  • Returnerar enbart URL:er som är due för anropande agent baserat på readinterval och agentens senaste claim-tidpunkt
  • En agents claims blockerar inte andra agenter
  • När inga URL:er är due just nu innehåller svaret nu också en additiv idle-rapport med väntetrådar (wait_seconds, next_poll_at och next_url) så scraperklienter kan backa av intelligent i stället för att gissa.

always=1-beteende:

  • Returnerar alla rader där deleted=0 och noscrape=0 — ingen intervallfiltrering

Svar (200)

{
  "urls": [
    {
      "urlid": 12,
      "url": "https://example.com/rss",
      "real_url": "https://example.com/rss",
      "readinterval": 60,
      "sitetype": "rss",
      "method": "GET",
      "elements": null
    }
  ],
  "agent": { "agent_id": "scraper-node-1", "resolved_name": "scraper-node-1" },
  "idle": {
    "is_idle": false,
    "reason": "urls_available",
    "schedule_mode": "per_agent_seen",
    "wait_seconds": null,
    "wait_minutes": null,
    "next_poll_at": null,
    "next_url": null,
    "scrapeable_total": 125
  }
}

Exempel på idle-svar (inga URL:er är due just nu):

{
  "urls": [],
  "agent": { "agent_id": "scraper-node-1", "resolved_name": "scraper-node-1" },
  "idle": {
    "is_idle": true,
    "reason": "no_urls_due_for_agent",
    "schedule_mode": "per_agent_seen",
    "wait_seconds": 173,
    "wait_minutes": 3,
    "next_poll_at": "2026-04-05 14:20:00",
    "next_url": {
      "urlid": 12,
      "title": "Exempelfeed",
      "url": "https://example.com/rss"
    },
    "scrapeable_total": 125
  }
}

Den medföljande scrape-runnern använder dessa idle-fält för att logga hur länge den bör vänta innan nästa due-URL förväntas.


POST /api/rss/data

Tar emot rådata från en scraper-worker.

Request body

{
  "agent_id": "scraper-node-1",
  "content": {
    "12": "<rss version=\"2.0\">...</rss>",
    "34": "<html>...</html>"
  }
}
Fält Typ Beskrivning
agent_id string Valfri men rekommenderas; identifierar scrapers
content object Nycklar är numeriska urlid-strängar; värden är rå feed- eller HTML-data

Svar (200)

{
  "received": {
    "12": { "dataLength": 14200, "url": "https://example.com/rss", "title": "Exempelfeed" }
  },
  "exceptions": {},
  "agent": { "agent_id": "scraper-node-1" }
}

Varje received[{urlid}]-objekt innehåller:

  • dataLength – antal byte av accepterad data
  • url – käll-URL från urls.url
  • title – feed-titel från urls.title (användbart för loggar och Google Alerts-spårbarhet)

GET /api/rss/update

Bearbetar köade inbound-poster till normaliserat innehåll och triggar prenumerationsleverans.

Query-parametrar

Parameter Beskrivning
urlid Valfritt heltal. När det anges bearbetas bara inbound-rader för den feeden i det anropet

Köunderhållsbeteende:

  • Hanterade rader (handled=1, processlock=0) rensas vid varje körning
  • Stale lock-frigivning baseras på lås-ålder — lås äldre än konfigurerbart fönster frigörs oavsett radålder

Svar (200)

{
  "converted": 12,
  "skipped": 2,
  "urlid_filter": 27,
  "subscriptionNotifications": {
    "processed": 3,
    "delivered": 2,
    "skipped": 1
  }
}

urlid_filter inkluderas bara när urlid-query-parametern användes.


GET /api/rss/feed/{site}

Returnerar en Atom/RSS-feed för en specifik sajt eller kategori.

Selector-beteende för {site}:

  • Numeriskt urlid — specifik feed
  • Kategori-slug — alla poster i kategorin
  • public_hash — direktåtkomst för dolda feeds (kringgår dolt-filter)
  • Analytics-selectors:
    • analytics-daily / daily-analytics
    • analytics-weekly / weekly-analytics
    • analytics-monthly / monthly-analytics
    • analytics-yearly / yearly-analytics
    • analytics-bulk / bulk-analytics (alla perioder kombinerade)

POST /api/rss/analytics/run

Triggar AI-analytics-generering programmatiskt (för cron eller externa triggers).

Autentisering: Authorization: Bearer <ANALYTICS_CRON_SECRET>

Request body (alla fält valfria)

{
  "period": "weekly",
  "categories": "all",
  "sites": false,
  "model": "gpt-4o-mini",
  "user_id": 1,
  "max_tokens": 1400,
  "dry_run": false
}
Fält Typ Standard Beskrivning
period string weekly daily, weekly, monthly, yearly, all
categories string all Kommaseparerade kategorinamn eller all
sites boolean false Generera även site-analys
model string gpt-4o-mini OpenAI-modellnamn
user_id integer 1 Användar-ID för attribution
max_tokens integer 1400 Max utdata-tokens per analysobjekt
dry_run boolean false Planera körning utan att anropa AI

Feed Q&A API (/feed/user-questions)

Skicka fria frågor mot RSS-datan och hämta svarshistorik.

POST /feed/user-questions

Skicka en fråga. Gäster kräver Cloudflare Turnstile. Inloggade användare slipper Turnstile.

Request (formulär eller JSON)

Fält Typ Beskrivning
question string Frågetexten
question_period string daily, weekly, monthly (standard), yearly, all_time
period string Äldre alias för question_period
keyword_aggressiveness string strict, balanced (standard) eller expansive
focus_categories[] array Begränsa context till specifika kategori-slugs
focus_site_ids[] array Begränsa context till max 10 specifika urlid-värden
cf-turnstile-response string Cloudflare Turnstile-token (gäster)

JSON-svar (när Accept: application/json)

{
  "ok": true,
  "answer": "Baserat på tillgänglig context...",
  "question_id": 42,
  "model": "gpt-5.4",
  "latency_ms": 1830,
  "context_stats": {
    "feed_count": 17,
    "entry_count": 120,
    "period_type": "monthly",
    "period_start": "2026-03-01 00:00:00",
    "period_end": "2026-03-31 23:59:59"
  }
}

Focus selector-beteende:

  • focus_site_ids[] med ≤10 ID aktiverar JSON context-läge: AI tar emot ett version_history.articles-block med all lagrad redigeringshistorik oavsett tidsperiod
  • focus_categories[] filtrerar context till matchande feeds
  • Site-ID:n har prioritet: om båda anges används bara focus_site_ids[]

Versionshistorik i context

Varje version-sample i version_history.articles innehåller:

  • v — sekvensnummer (1 = äldst, N = nyast)
  • hash — 6-teckens prefix av content_hash för spårbarhet
  • published — tidpunkt för den lagrade versionen
  • title — rubrik vid den versionen
  • description — upp till 220 tecken av description (när ej tom)
  • content — upp till 320 tecken av content (när ej tom)

När version_count ≤ VERSION_SAMPLE_LIMIT visas alla versioner. För artiklar med fler versioner väljs representativa urval spridda över hela historikspannet.


XPath Lab (/rss/xpath-lab)

XPath Lab är tillgängligt via /rss/xpath-lab och kräver permission:rss.

Funktioner

  • Klistra in rå HTML i snippet-fältet
  • Inspektera visuell DOM-översikt med djup, XPath, attribut och textförhandsvisning
  • Klicka på föreslagna XPath-hints (auto-detekterade från vanliga mönster)
  • Testa ett enskilt XPath-uttryck mot HTML
  • Testa fullständiga elements-pipeline-regler (samma 5-elements JSON som urls.elements)
  • Jämför en snabb labbpreview med en legacy scraper compatibility preview som använder samma parser-väg som liveimporten
  • Se kompatibilitetsvarningar när icke-value-extraktorer som href eller src kommer att hoppas över av legacy-renderaren
  • Granska SimpleXML-liknande XML-representation
  • Be OpenAI generera XPath-pipeline-regler från det inklistrade HTML

elements / Pipeline JSON-format

XPath-feeds (sitetype=xpath) lagrar extraheringsregler i urls.elements som en 5-elements JSON-array:

[
  element 0: Radselectors (array med absoluta XPaths)
  element 1: Fält-XPaths (objekt: fältnamn → array med relativa XPaths)
  element 2: Värdetyper som används (försök helst hålla dig till bara "value")
  element 3: Källkarta (objekt: fältnamn → "mainNode")
  element 4: Output-mappning (objekt: RSS-fält → [fältnamn, värdetyp])
]

Obligatoriska output-fält i element 4: title, description, link. Valfritt: pubdate.

Rekommenderat exempel — attributnoder mappade via value:

[
  [
    "//*[@role='main']//ol[contains(concat(' ',normalize-space(@class),' '),' sap-search__result ')]/li[contains(concat(' ',normalize-space(@class),' '),' sap-search__result-item ')]",
    "//*[@role='main']//li[contains(concat(' ',normalize-space(@class),' '),' sap-search__result-item ')]",
    "//li[contains(concat(' ',normalize-space(@class),' '),' sap-search__result-item ')]"
  ],
  {
    "titleNode": [
      "/div[contains(concat(' ',normalize-space(@class),' '),' sap-search__text ')]/div[contains(concat(' ',normalize-space(@class),' '),' sv-notopmargin ')]/a",
      "/div[contains(concat(' ',normalize-space(@class),' '),' sap-search__text ')]/div[@tabindex='0']/a"
    ],
    "titleHrefNode": [
      "/div[contains(concat(' ',normalize-space(@class),' '),' sap-search__text ')]/div[contains(concat(' ',normalize-space(@class),' '),' sv-notopmargin ')]/a/@href",
      "/div[contains(concat(' ',normalize-space(@class),' '),' sap-search__text ')]/div[@tabindex='0']/a/@href"
    ],
    "summary": [
      "/div[contains(concat(' ',normalize-space(@class),' '),' sap-search__text ')]/p[contains(concat(' ',normalize-space(@class),' '),' normal ')]",
      "/div[contains(concat(' ',normalize-space(@class),' '),' sap-search__text ')]/p"
    ],
    "date": [
      "/div[contains(concat(' ',normalize-space(@class),' '),' sap-search__text ')]/div[contains(concat(' ',normalize-space(@class),' '),' sap-search__meta ')]/span[2]",
      "/div[contains(concat(' ',normalize-space(@class),' '),' sap-search__text ')]/div[contains(concat(' ',normalize-space(@class),' '),' sap-search__meta ')]/*[2]"
    ]
  },
  ["value"],
  {
    "titleNode": "mainNode",
    "titleHrefNode": "mainNode",
    "summary": "mainNode",
    "date": "mainNode"
  },
  {
    "title": ["titleNode", "value"],
    "description": ["summary", "value"],
    "link": ["titleHrefNode", "value"],
    "pubdate": ["date", "value"]
  }
]

XPath-konventioner:

  • Element 0 (radselectors): absoluta XPaths som börjar med //
  • Element 1 (fält-XPaths): relativa sökvägar som börjar med / (enkelt snedstreck = barnaxel relativt matchad radnod). Scrapern lägger till . vid runtime för att göra dem kontextuella
  • För attributbaserat output som länkar, bild-URL:er eller maskinläsbara datum är det oftast säkrast att extrahera själva attributnoden direkt (/@href, /@src, /@datetime) och sedan mappa den med "value"
  • Alla contains(@class, ...)-mönster bör använda concat(' ',normalize-space(@class),' ') för exakt matchning av klassnamn

Viktig legacy-parser-notering:

  • Äldre live-rendering av XPath kan hoppa över icke-value-extraktorer om inte pipeline[3] också deklarerar just den extractor-nyckeln (till exempel "href": "mainNode").
  • XPath Lab visar nu en separat legacy scraper compatibility preview så att du kan upptäcka den här mismatchen innan regler sparas.
  • Om labbpreviewn ser rätt ut men legacy-previewn tappar link, src eller datetime, skriv om fältet till en dedikerad attributnod-XPath och mappa det via "value".

Använda XPath Lab för att debugga en pipeline:

  1. Klistra in AJAX-HTML-svar eller sidkällan i snippet-fältet
  2. Klistra in hela elements-JSON i fältet Pipeline rules
  3. Klicka Analyze snippet — labbet visar vilken radselector som matchade och extraherar upp till 25 rader i labbpreviewn
  4. Kontrollera sedan Production / legacy scraper compatibility preview under den. Det är den panelen som visar vad liveimporten faktiskt kommer att få.
  5. Om varningarna nämner saknad href / src-kompatibilitet, skriv om dessa värden till dedikerade attributnodfält (/@href, /@src, /@datetime) mappade via "value"
  6. Om 0 rader matchar triggar labbet automatiskt AI-förslag (eller kryssa i Ask AI explicit)
  7. Kopiera den AI-genererade JSON till elements-fältet i RSS-editorn

Prenumerationer

Inloggade användare kan prenumerera per:

  • Feed
  • Kategori

Tillgängliga kanaler beror på kontoinställningar.

/feed/subscriptions är kanalinställningarna nu AJAX-first med autosave:

  • Av/på på kanal-checkboxar sparas direkt via AJAX
  • Text-/webhookfält sparas på blur (när fältet lämnas)
  • Pause/Resume och Remove uppdateras också inline via AJAX
  • Det är nu tillåtet att avchecka alla kanaler explicit (alla leveranskanaler avstängda)

Om JavaScript saknas finns fortfarande fallback till vanlig server-post/redirect.

Discord-setup på /feed/subscriptions:

  • Du kan antingen klistra in Discord-webhook manuellt eller använda Connect Discord app (get webhook).
  • OAuth-flödet använder webhook.incoming och går tillbaka via callback (/oauth/discord/callback).
  • Callback-URL visas på sidan så admin vet vilken URL som ska registreras i Discord Developer Portal.
  • Efter callback sparas senaste Discord-webhook-payload i session och kan återanvändas per prenumeration med ett klick.

Leveransbeteende:

  • Nya RSS-importer försöker nu göra en omedelbar prenumerationsnotifiering direkt efter att /api/rss/update har konverterat inbound-rader
  • Prenumerationsutskick innehåller nu direktlänk till Tools-entry först (/feed/entry/{contentId}), med originallänken som sekundär fallback
  • Det schemalagda kommandot rss:notify-subscribers körs fortfarande var femtonde minut som fallback/återförsök om en omedelbar leverans missas eller en kanal tillfälligt fallerar