From de4bf0554f85a6d726a9b0af1e62ddcdbe30877c Mon Sep 17 00:00:00 2001 From: Nilsonlinux Date: Thu, 30 Jul 2026 22:43:05 -0300 Subject: [PATCH] Add nilsonlinux/rss-notifier plugin v1.0.0 (#137) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add nilsonlinux/rss-notifier plugin v1.0.0 * fix: correct all validation errors for rss-notifier * Update tags in plugin.toml for rss-notifier * Revise README for RSS Notifier plugin Updated README to reflect plugin name and improved clarity. * Update README.md by removing unnecessary content Removed placeholder text and installation instructions from README. * Update README with plugin details and usage instructions Expanded README to include plugin details, usage instructions, and settings configuration. * Traduz README.md para português e atualiza conteúdo Atualiza o README.md com informações em português sobre o plugin RSS/Atom Notifier, incluindo uso, configurações e notas sobre o funcionamento. * Update tags in plugin.toml Removed 'rss' tag from the plugin configuration. * Revise README for RSS Notifier plugin Updated the README to reflect changes in the plugin description, installation instructions, usage details, settings, and dependencies. * Enhance README with plugin details and usage Updated README.md to include detailed plugin features, settings, and usage instructions. * Update README for RSS Utils plugin * Add files via upload * Add xdg-open as a dependency in plugin.toml * Revise README for RSS/Atom Notifier plugin Updated configuration options and usage instructions in README. * Add Brazilian Portuguese translation file * Revise README for clarity and updated instructions Updated README to improve clarity and consistency, including installation and usage instructions. * Add xdg-open as a dependency in README Updated dependencies section to include xdg-open. * Fix formatting of requirements section in README * Add files via upload * feat: add individual item delete option and scrollbar - Implemented the ability to delete individual feed items using an 'X' button. - Added a fixed height scrollbar to the panel list. - Fixed badge synchronization and command communication for the V5 Beta 6 environment. * fix tags e correções de funcionamento * Add dependencies section to plugin.toml * Add files via upload * Enhance README with plugin details Updated README with plugin ID and entries table. --- rss-notifier/README.md | 53 +++ rss-notifier/panel.luau | 128 +++++++ rss-notifier/plugin.toml | 60 +++ rss-notifier/service.luau | 525 +++++++++++++++++++++++++++ rss-notifier/thumbnail.webp | Bin 0 -> 72444 bytes rss-notifier/translations/en.json | 20 + rss-notifier/translations/pt-BR.json | 20 + rss-notifier/widget.luau | 62 ++++ 8 files changed, 868 insertions(+) create mode 100644 rss-notifier/README.md create mode 100644 rss-notifier/panel.luau create mode 100644 rss-notifier/plugin.toml create mode 100644 rss-notifier/service.luau create mode 100644 rss-notifier/thumbnail.webp create mode 100644 rss-notifier/translations/en.json create mode 100644 rss-notifier/translations/pt-BR.json create mode 100644 rss-notifier/widget.luau diff --git a/rss-notifier/README.md b/rss-notifier/README.md new file mode 100644 index 0000000..f635e85 --- /dev/null +++ b/rss-notifier/README.md @@ -0,0 +1,53 @@ +# RSS/Atom Notifier + +Monitor RSS/Atom feeds and get notifications for new items. + +## Plugin + +| Field | Value | +| --- | --- | +| ID | `nilsonlinux/rss-notifier` | +| Entries | Bar widget: `indicator`; panel: `panel`| + +**Entries:** +- **Service:** `fetcher` - Background service that fetches and parses feeds +- **Widget:** `badge` - Shows unread count on the bar +- **Panel:** `list` - Displays feed items in a list + +**IPC Command:** + +noctalia msg panel-toggle nilsonlinux/rss-notifier:list +text + + +## Settings + +| Setting | Type | Default | Description | +|---------|------|---------|-------------| +| `feed_urls` | string_list | `[]` | List of RSS/Atom feed URLs to monitor (one per line) | +| `refresh_minutes` | int | `30` | How often to check for new items (1-1440 minutes) | +| `notify_new` | bool | `true` | Display notifications when new items arrive | +| `max_notifications_per_cycle` | int | `5` | Maximum notifications shown per check (1-50) | + +## Installation + +Install via Noctalia Plugin Store. + +## Requirements + +- `xdg-open` - Required to open feed URLs in your default web browser. Usually pre-installed on most Linux distributions. + +## Usage + +1. Add feed URLs in the plugin settings +2. The widget will show a badge with unread count +3. Click the widget to open the panel +4. Click an item to open it in your default browser + +## Dependencies + +**xdg-open** + +## License + +MIT diff --git a/rss-notifier/panel.luau b/rss-notifier/panel.luau new file mode 100644 index 0000000..e4aaa7b --- /dev/null +++ b/rss-notifier/panel.luau @@ -0,0 +1,128 @@ +-- panel.luau +-- Janela pop-up mostrada ao clicar no widget da barra: lista os itens mais +-- recentes, ou um estado vazio com icone quando nao ha nada novo. + +local items = {} + +-- declaradas antes para permitir referencia cruzada entre elas +local render +local dismissItem +local itemRow +local emptyState + +local function openLink(link) + if not link or link == "" then + return + end + -- escapa aspas simples pra evitar quebrar o comando do shell + local safe = link:gsub("'", "'\\''") + noctalia.runAsync("xdg-open '" .. safe .. "'") +end + +dismissItem = function(item) + -- remove localmente (resposta imediata) e avisa o service pra nao + -- reaparecer nas proximas atualizacoes + for i, it in ipairs(items) do + if it == item then + table.remove(items, i) + break + end + end + render() + + local id = item.id or item.link or item.title + if id then + local safe = tostring(id):gsub("'", "'\\''") + noctalia.runAsync("noctalia msg plugin nilsonlinux/rss-notifier:fetcher all dismiss '" .. safe .. "'") + end +end + +itemRow = function(item) + return ui.row({ + key = item.id or item.link or item.title, + gap = 6, + padding = 10, + radius = 8, + fill = "surface_variant/0.4", + align = "center", + }, { + ui.column({ + gap = 2, + flexGrow = 1, + onClick = function() openLink(item.link) end, + }, { + ui.label({ text = item.title or "(sem titulo)", fontWeight = "bold", maxLines = 2 }), + ui.label({ text = item.feedTitle or "", fontSize = 12, color = "outline" }), + }), + ui.button({ + glyph = "close", + variant = "ghost", + controlSize = "sm", + tooltip = "Dispensar", + onClick = function() dismissItem(item) end, + }), + }) +end + +emptyState = function() + return ui.column({ gap = 10, align = "center", padding = 32, flexGrow = 1, justify = "center" }, { + ui.glyph({ name = "rss", size = 32, color = "outline" }), + ui.label({ text = "Nenhuma atualização", color = "outline" }), + }) +end + +render = function() + local body + + if #items == 0 then + body = emptyState() + else + local rows = {} + for _, item in ipairs(items) do + table.insert(rows, itemRow(item)) + end + body = ui.scroll({ gap = 6, flexGrow = 1 }, rows) + end + + local headerButtons = {} + if #items > 0 then + table.insert(headerButtons, ui.button({ glyph = "trash", variant = "ghost", controlSize = "sm", tooltip = "Limpar tudo", onClick = "onClearAllClicked" })) + end + table.insert(headerButtons, ui.button({ glyph = "refresh", variant = "ghost", controlSize = "sm", tooltip = "Atualizar agora", onClick = "onRefreshClicked" })) + table.insert(headerButtons, ui.button({ glyph = "close", variant = "ghost", controlSize = "sm", onClick = "onCloseClicked" })) + + panel.render(ui.column({ gap = 10, padding = 12, fill = true }, { + ui.row({ align = "center", justify = "space_between" }, { + ui.label({ text = "RSS/Atom Notifier", fontSize = 15, fontWeight = "bold" }), + ui.row({ gap = 4 }, headerButtons), + }), + ui.separator({}), + body, + })) +end + +noctalia.state.watch("items", function(raw) + local ok, decoded = pcall(noctalia.json.decode, raw or "[]") + items = (ok and decoded) or {} + render() +end) + +function onOpen(_context) + render() + -- abrir o painel conta como "li as novidades": zera o badge no service + noctalia.runAsync("noctalia msg plugin nilsonlinux/rss-notifier:fetcher all mark-read") +end + +function onRefreshClicked() + noctalia.runAsync("noctalia msg plugin nilsonlinux/rss-notifier:fetcher all refresh") +end + +function onClearAllClicked() + items = {} + render() + noctalia.runAsync("noctalia msg plugin nilsonlinux/rss-notifier:fetcher all clear-all") +end + +function onCloseClicked() + panel.close() +end diff --git a/rss-notifier/plugin.toml b/rss-notifier/plugin.toml new file mode 100644 index 0000000..79a0e94 --- /dev/null +++ b/rss-notifier/plugin.toml @@ -0,0 +1,60 @@ +id = "nilsonlinux/rss-notifier" +name = "RSS/Atom Notifier" +version = "1.0.0" +plugin_api = 14 +author = "Nilsonlinux" +license = "MIT" +icon = "rss" +description = "Acompanha feeds RSS/Atom e notifica quando surgem novos itens." +tags = ["utility", "indicator"] +dependencies = ["xdg-open"] + +[[setting]] +key = "feed_urls" +type = "string_list" +label_key = "settings.feed_urls.label" +description_key = "settings.feed_urls.description" +default = [] + +[[setting]] +key = "refresh_minutes" +type = "int" +label_key = "settings.refresh_minutes.label" +description_key = "settings.refresh_minutes.description" +default = 30 +min = 1 +max = 1440 + +[[setting]] +key = "notify_new" +type = "bool" +label_key = "settings.notify_new.label" +description_key = "settings.notify_new.description" +default = true + +[[setting]] +key = "max_notifications_per_cycle" +type = "int" +label_key = "settings.max_notifications_per_cycle.label" +description_key = "settings.max_notifications_per_cycle.description" +default = 5 +min = 1 +max = 50 +advanced = true + +[[service]] +id = "fetcher" +entry = "service.luau" + +[[widget]] +id = "badge" +entry = "widget.luau" + +[[panel]] +id = "list" +entry = "panel.luau" +width = 360 +height = 440 +placement = "attached" +position = "auto" +open_near_click = true diff --git a/rss-notifier/service.luau b/rss-notifier/service.luau new file mode 100644 index 0000000..cd3369f --- /dev/null +++ b/rss-notifier/service.luau @@ -0,0 +1,525 @@ +-- service.luau +-- Servico headless: busca cada feed configurado, extrai itens (RSS ou +-- Atom ), compara com o que ja foi visto, notifica o que for novo e +-- publica a contagem de nao-lidos em noctalia.state para o widget consumir. + +local seen = {} -- { [feedUrl] = { ids = { [itemId]=true, ... }, order = { id1, id2, ... } } } +local unread = 0 +local recentItems = {} -- lista dos itens mais recentes, mais novo primeiro +local dataPath = nil + +local MAX_RECENT_ITEMS = 50 +local MAX_SEEN_PER_FEED = 300 -- limite de ids "ja vistos" guardados por feed (evita crescer sem fim) + +-- Limites para manter o parsing rapido o suficiente para o orcamento de CPU +-- (muito apertado) do callback assincrono. +local MAX_BODY_BYTES = 8000 -- so olhamos os primeiros ~8KB do corpo do feed +local MAX_ITEM_BYTES = 400 -- corta cada bloco / antes de extrair tags +local MAX_ITEMS = 8 -- para de processar itens depois desse tanto + +local function isUtf8Continuation(b) + return b ~= nil and b >= 0x80 and b < 0xC0 +end + +-- Corta a string em ate n bytes, mas nunca no meio de um caractere UTF-8 +-- multibyte (acentos, aspas curvas, emoji, etc.) - cortar assim gera bytes +-- invalidos que o renderizador de texto (Pango) rejeita, deixando labels +-- (e por tabela o painel inteiro) sem aparecer. +local function truncate(s, n) + if not s or #s <= n then + return s + end + local cut = n + -- recua enquanto o byte da posicao for byte de continuacao (0x80-0xBF) + while cut > 0 and isUtf8Continuation(s:byte(cut)) do + cut = cut - 1 + end + -- se o byte que sobrou for o inicio de uma sequencia multibyte, so mantem + -- se ela couber inteira dentro do limite n; senao descarta ele tambem + local b = cut > 0 and s:byte(cut) or nil + if b and b >= 0xC0 then + local seqLen = (b >= 0xF0 and 4) or (b >= 0xE0 and 3) or 2 + if cut + seqLen - 1 > n then + cut = cut - 1 + end + end + return s:sub(1, cut) +end + +-- Mesma logica de "nao corte no meio de UTF-8", mas trabalhando so com +-- indices/bytes individuais (sem materializar substrings gigantes) - usado +-- para limitar o tamanho de um bloco sem copiar o conteudo inteiro +-- antes de cortar. +local function safeCutEnd(xml, endPos, minPos) + local pos = endPos + while pos > minPos do + local b = xml:byte(pos) + if not b then + break + end + if b < 0x80 then + break -- ascii, seguro + elseif b >= 0xC0 then + local seqLen = (b >= 0xF0 and 4) or (b >= 0xE0 and 3) or 2 + if pos + seqLen - 1 <= endPos then + break -- sequencia cabe inteira ate endPos, seguro + end + pos = pos - 1 -- nao cabe inteira, descarta o lead byte tambem + else + pos = pos - 1 -- byte de continuacao, ainda no meio da sequencia + end + end + return pos +end + +-- Testa se um item ja foi visto e, se nao, marca como visto - com limite de +-- tamanho por feed (descarta o mais antigo quando passa do limite), para +-- nunca deixar a estrutura "seen" crescer sem fim (e estourar o encode/save). +local function markSeen(url, id) + local bucket = seen[url] + if not bucket or not bucket.ids then + bucket = { ids = {}, order = {} } + seen[url] = bucket + end + if bucket.ids[id] then + return false -- ja visto + end + bucket.ids[id] = true + table.insert(bucket.order, id) + while #bucket.order > MAX_SEEN_PER_FEED do + local oldest = table.remove(bucket.order, 1) + bucket.ids[oldest] = nil + end + return true -- era novo +end + +local function isFirstRunForFeed(url) + local bucket = seen[url] + return not bucket or not bucket.order or #bucket.order == 0 +end + +-- Remove/descarta qualquer sequencia de bytes que NAO seja UTF-8 valido. +-- Necessario porque alguns feeds vem com o charset errado no servidor (bytes +-- Latin-1/CP-1252 marcados como UTF-8, por exemplo) - nesse caso nem um corte +-- perfeito resolve, o defeito ja vem no texto original. +local function sanitizeUtf8(s) + if not s then + return s + end + local out = {} + local i = 1 + local len = #s + while i <= len do + local b = s:byte(i) + if b < 0x80 then + out[#out + 1] = string.char(b) + i = i + 1 + else + local seqLen + if b >= 0xF0 and b <= 0xF4 then + seqLen = 4 + elseif b >= 0xE0 then + seqLen = 3 + elseif b >= 0xC2 then + seqLen = 2 + else + seqLen = 0 -- lead byte invalido (0x80-0xC1) + end + + local valid = seqLen > 0 and (i + seqLen - 1) <= len + if valid then + for k = 1, seqLen - 1 do + local cb = s:byte(i + k) + if not cb or cb < 0x80 or cb >= 0xC0 then + valid = false + break + end + end + end + + if valid then + out[#out + 1] = s:sub(i, i + seqLen - 1) + i = i + seqLen + else + i = i + 1 -- byte invalido: descarta so ele e continua + end + end + end + return table.concat(out) +end + +-- --------------------------------------------------------------------------- +-- Persistencia (sobrevive a restarts do plugin/shell) +-- --------------------------------------------------------------------------- + +local function loadState() + local dir = noctalia.pluginDataDir() + if not dir then + return + end + dataPath = dir .. "/state.json" + + local raw = noctalia.readFile(dataPath) + if raw then + local ok, decoded = pcall(noctalia.json.decode, raw) + if ok and type(decoded) == "table" then + seen = decoded.seen or {} + recentItems = decoded.recentItems or {} + unread = decoded.unread or 0 + + -- migra formato antigo ({ [id]=true, ... } direto) para o novo + -- ({ ids=..., order=... }), se necessario + for url, bucket in pairs(seen) do + if type(bucket) == "table" and not bucket.ids then + local migrated = { ids = {}, order = {} } + for id, v in pairs(bucket) do + if v == true then + migrated.ids[id] = true + table.insert(migrated.order, id) + end + end + seen[url] = migrated + end + end + + -- sanitiza itens ja persistidos (podem ter sido salvos com UTF-8 + -- quebrado por versoes anteriores deste plugin, antes deste fix) + for _, item in ipairs(recentItems) do + if item.title then + item.title = sanitizeUtf8(item.title) + end + if item.feedTitle then + item.feedTitle = sanitizeUtf8(item.feedTitle) + end + end + end + end +end + +-- Nunca deixa uma falha de encode/escrita derrubar o entry (isso ja causou o +-- service ser desativado apos varios erros seguidos no update()). +local function saveState() + if not dataPath then + return + end + local ok, encoded = pcall(noctalia.json.encode, { + seen = seen, + recentItems = recentItems, + unread = unread, + }) + if ok and type(encoded) == "string" then + pcall(noctalia.writeFile, dataPath, encoded) + end +end + +-- Idem para publicar em noctalia.state: nunca propaga erro pra cima. +local function publishItems() + local ok, encoded = pcall(noctalia.json.encode, recentItems) + if ok and type(encoded) == "string" then + noctalia.state.set("items", encoded) + end +end + +-- --------------------------------------------------------------------------- +-- Parsing minimo de RSS 2.0 / Atom 1.0 usando SO busca literal (string.find +-- com plain=true) - evita o motor de padroes do Lua (".-", "[^>]", etc.), +-- que parece caro demais para o orcamento de CPU deste ambiente. +-- --------------------------------------------------------------------------- + +local function decodeEntities(s) + if not s then + return s + end + s = s:gsub("<", "<") + s = s:gsub(">", ">") + s = s:gsub(""", '"') + s = s:gsub("'", "'") + s = s:gsub("&", "&") + return sanitizeUtf8(noctalia.string.trim(s)) +end + +local function stripCdata(s) + if s:sub(1, 9) == "", 10, true) + if endPos then + return s:sub(10, endPos - 1) + end + end + return s +end + +-- Extrai o conteudo de ... usando so find() literal. +local function findTagContent(s, tag) + local openStart = s:find("<" .. tag, 1, true) + if not openStart then + return nil + end + local openEnd = s:find(">", openStart, true) + if not openEnd then + return nil + end + local closeStart = s:find("", openEnd, true) + if not closeStart then + return nil + end + return decodeEntities(stripCdata(s:sub(openEnd + 1, closeStart - 1))) +end + +-- Extrai um valor de atributo de dentro da PRIMEIRA ocorrencia de . +local function findAttr(s, tag, attr) + local openStart = s:find("<" .. tag, 1, true) + if not openStart then + return nil + end + local openEnd = s:find(">", openStart, true) + if not openEnd then + return nil + end + local tagSrc = s:sub(openStart, openEnd) + local attrStart = tagSrc:find(attr .. '="', 1, true) + if not attrStart then + return nil + end + local valueStart = attrStart + #attr + 2 + local valueEnd = tagSrc:find('"', valueStart, true) + if not valueEnd then + return nil + end + return tagSrc:sub(valueStart, valueEnd - 1) +end + +local function extractLink(block) + local rssLink = findTagContent(block, "link") -- RSS: URL + if rssLink and rssLink ~= "" then + return rssLink + end + return findAttr(block, "link", "href") -- Atom: +end + +local function extractId(block) + return findTagContent(block, "guid") or findTagContent(block, "id") or extractLink(block) +end + +-- Encontra o PROXIMO bloco ... a partir de fromPos, usando so +-- find() literal. Retorna o conteudo do bloco (ja cortado) e a posicao onde +-- parar na proxima chamada - permite processar um item por vez, em ticks +-- separados, em vez de tudo de uma vez dentro do callback http. +local function findNextBlock(xml, tag, fromPos, maxItemBytes) + local openStart = xml:find("<" .. tag, fromPos, true) + if not openStart then + return nil, fromPos + end + local openEnd = xml:find(">", openStart, true) + if not openEnd then + return nil, fromPos + end + local closeTag = "" + local closeStart = xml:find(closeTag, openEnd, true) + if not closeStart then + return nil, fromPos + end + local contentEnd = math.min(closeStart - 1, openEnd + maxItemBytes) + if contentEnd < closeStart - 1 then + -- so precisa corrigir a fronteira UTF-8 quando o corte foi mesmo pelo + -- limite de bytes (nao pela tag de fechamento, que ja e uma fronteira segura) + contentEnd = safeCutEnd(xml, contentEnd, openEnd) + end + local block = xml:sub(openEnd + 1, contentEnd) + return block, closeStart + #closeTag +end + +-- --------------------------------------------------------------------------- +-- Fila de processamento incremental: o callback http so guarda o corpo (ja +-- cortado) na fila; o parsing de verdade acontece aos poucos, um item por +-- tick de update(), porque o orcamento de CPU do callback assincrono e +-- pequeno demais para processar um feed inteiro de uma vez. +-- --------------------------------------------------------------------------- + +local queue = {} -- lista de { url=, body=, pos=, tag=, feedTitle=, items=, notifyBudget= } + +local function enqueueFeed(url, body, notifyBudget) + table.insert(queue, { + url = url, + body = truncate(body, MAX_BODY_BYTES), + pos = 1, + tag = "item", + triedEntry = false, + feedTitle = nil, + items = {}, + notifyBudget = notifyBudget, + }) +end + +-- Finaliza um feed da fila: compara com o que ja foi visto, notifica o que +-- for novo e publica o estado. E um passo isolado (nao mistura com a +-- extracao de itens) para manter cada callback pequeno. +local function finalizeFeed(f) + local url = f.url + local firstRun = isFirstRunForFeed(url) + local notifyEnabled = noctalia.getConfig("notify_new") + local newCount = 0 + + for _, item in ipairs(f.items) do + local id = item.id or item.link or item.title + if id and markSeen(url, id) then + newCount = newCount + 1 + + if not firstRun then + table.insert(recentItems, 1, { + id = id, + title = item.title, + link = item.link, + feedTitle = f.feedTitle, + }) + if notifyEnabled and f.notifyBudget.count < f.notifyBudget.max then + f.notifyBudget.count = f.notifyBudget.count + 1 + noctalia.notify(item.title, f.feedTitle) + end + end + end + end + + while #recentItems > MAX_RECENT_ITEMS do + table.remove(recentItems) + end + + if not firstRun and newCount > 0 then + unread = unread + newCount + noctalia.state.set("unread", unread) + publishItems() + end + + saveState() +end + +-- Processa UM pequeno passo da fila: extrai no maximo um item do feed que +-- esta na frente da fila. Chamado uma vez por tick de update(). +local function processQueueStep() + local f = queue[1] + if not f then + return + end + + if not f.feedTitle then + f.feedTitle = findTagContent(truncate(f.body, 300), "title") or f.url + return -- um passo por tick: so o titulo desta vez + end + + if #f.items >= MAX_ITEMS then + table.remove(queue, 1) + finalizeFeed(f) + return + end + + local block, nextPos = findNextBlock(f.body, f.tag, f.pos, MAX_ITEM_BYTES) + + if not block then + if f.tag == "item" and not f.triedEntry then + -- RSS nao encontrado: tenta Atom () a partir do comeco + f.tag = "entry" + f.pos = 1 + f.triedEntry = true + return + end + -- acabaram os itens (ou nao achou nenhum) - finaliza + table.remove(queue, 1) + finalizeFeed(f) + return + end + + f.pos = nextPos + table.insert(f.items, { + title = findTagContent(block, "title") or "(sem titulo)", + link = extractLink(block), + id = extractId(block), + }) +end + +-- --------------------------------------------------------------------------- +-- Ciclo de busca +-- --------------------------------------------------------------------------- + +local function checkFeed(url, notifyBudget) + -- o callback http faz o MINIMO possivel: so guarda o corpo na fila. + -- Todo o parsing de verdade acontece depois, aos poucos, em processQueueStep(). + noctalia.http({ url = url, headers = { "Accept: application/rss+xml, application/atom+xml, application/xml, text/xml" } }, function(res) + if not res.ok or not res.body or res.body == "" then + return + end + enqueueFeed(url, res.body, notifyBudget) + end) +end + +local function fetchAll() + local urls = noctalia.getConfig("feed_urls") or {} + local notifyBudget = { count = 0, max = noctalia.getConfig("max_notifications_per_cycle") or 5 } + + for _, url in ipairs(urls) do + if url and noctalia.string.trim(url) ~= "" then + checkFeed(url, notifyBudget) + end + end +end + +local REFRESH_TICK_MS = 1000 -- update() roda a cada segundo: drena a fila aos poucos +local ticksUntilFetch = 1 + +local function applyInterval() + local minutes = noctalia.getConfig("refresh_minutes") or 30 + if minutes < 1 then + minutes = 1 + end + noctalia.setUpdateInterval(REFRESH_TICK_MS) + ticksUntilFetch = math.floor((minutes * 60000) / REFRESH_TICK_MS) +end + +-- --------------------------------------------------------------------------- +-- Ciclo de vida +-- --------------------------------------------------------------------------- + +loadState() +applyInterval() +noctalia.state.set("unread", unread) +publishItems() +fetchAll() -- primeira leitura: so marca como "vistos", sem notificar (firstRun) + +function update() + processQueueStep() -- sempre drena um pedacinho da fila, se houver algo + + ticksUntilFetch = ticksUntilFetch - 1 + if ticksUntilFetch <= 0 then + fetchAll() + local minutes = noctalia.getConfig("refresh_minutes") or 30 + if minutes < 1 then + minutes = 1 + end + ticksUntilFetch = math.floor((minutes * 60000) / REFRESH_TICK_MS) + end +end + +function onConfigChanged() + applyInterval() + fetchAll() +end + +function onIpc(_event, payload) + if _event == "refresh" then + fetchAll() + elseif _event == "mark-read" then + unread = 0 + noctalia.state.set("unread", 0) + elseif _event == "dismiss" and payload then + for i, item in ipairs(recentItems) do + if item.id == payload then + table.remove(recentItems, i) + break + end + end + publishItems() + saveState() + elseif _event == "clear-all" then + recentItems = {} + publishItems() + saveState() + end +end diff --git a/rss-notifier/thumbnail.webp b/rss-notifier/thumbnail.webp new file mode 100644 index 0000000000000000000000000000000000000000..df307665ce7a81a9c20caead6652262bdd35e3ca GIT binary patch literal 72444 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 z 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 literal 0 HcmV?d00001 diff --git a/rss-notifier/translations/en.json b/rss-notifier/translations/en.json new file mode 100644 index 0000000..26038c1 --- /dev/null +++ b/rss-notifier/translations/en.json @@ -0,0 +1,20 @@ +{ + "settings": { + "feed_urls": { + "label": "Feed URLs", + "description": "List of RSS/Atom feed URLs to monitor (one per line)" + }, + "refresh_minutes": { + "label": "Refresh Interval (minutes)", + "description": "How often to check for new items" + }, + "notify_new": { + "label": "Show Notifications", + "description": "Display notifications when new items arrive" + }, + "max_notifications_per_cycle": { + "label": "Max Notifications per Cycle", + "description": "Maximum notifications to show in one check" + } + } +} diff --git a/rss-notifier/translations/pt-BR.json b/rss-notifier/translations/pt-BR.json new file mode 100644 index 0000000..ec18891 --- /dev/null +++ b/rss-notifier/translations/pt-BR.json @@ -0,0 +1,20 @@ +{ + "settings": { + "feed_urls": { + "label": "URLs dos Feeds", + "description": "Lista de URLs de feeds RSS/Atom para monitorar (por linha)." + }, + "refresh_minutes": { + "label": "Intervalo de atualização", + "description": "Com que frequência verificar novos itens (em minutos)." + }, + "notify_new": { + "label": "Notificar novos itens", + "description": "Mostrar notificação para cada novo item encontrado." + }, + "max_notifications_per_cycle": { + "label": "Máximo de notificações", + "description": "Limitar o número de notificações enviadas em um único ciclo." + } + } +} diff --git a/rss-notifier/widget.luau b/rss-notifier/widget.luau new file mode 100644 index 0000000..ab8af22 --- /dev/null +++ b/rss-notifier/widget.luau @@ -0,0 +1,62 @@ +-- widget.luau +-- Widget de barra: icone RSS com uma pilula colorida (badge) de itens nao +-- lidos encostada no lado esquerdo, publicada pelo service via noctalia.state. + +local unread = 0 + +local function render() + local children = {} + + if unread > 0 then + -- pilula: um container com fundo colorido e cantos arredondados, com o + -- numero dentro - o mais perto que a API declarativa chega de um "badge" + table.insert(children, ui.row({ + fill = "primary", + radius = 8, + paddingH = 5, + paddingV = 1, + align = "center", + justify = "center", + }, { + ui.label({ text = tostring(unread), fontSize = 10, fontWeight = "bold", color = "on_primary" }), + })) + end + + table.insert(children, ui.glyph({ name = "rss", size = 14 })) + + local container = barWidget.isVertical() and ui.column or ui.row + barWidget.render(container({ gap = 4, align = "center" }, children)) + + barWidget.setTooltip(unread > 0 and (tostring(unread) .. " novo(s) item(ns) nos feeds") or "Nenhum item novo") +end + +noctalia.state.watch("unread", function(value) + unread = value or 0 + render() +end) + +render() + +function update() + noctalia.setUpdateInterval(5000) -- so mantem o widget "vivo"; os dados reais vem do state +end + +function onClick() + -- abre/fecha a janelinha com a lista de itens; o proprio painel marca + -- como lido (zera o badge) quando e aberto, via IPC pro service + noctalia.togglePanel("nilsonlinux/rss-notifier:list") +end + +function onRightClick() + -- clique direito: forca uma nova checagem imediata dos feeds, + -- enviando um evento IPC para a entry [[service]] (que e um singleton, alvo "all") + noctalia.runAsync("noctalia msg plugin nilsonlinux/rss-notifier:fetcher all refresh") + noctalia.notify("RSS/Atom Notifier", "Atualizando feeds...") +end + +function onIpc(event, payload) + if event == "set" then + unread = tonumber(payload) or 0 + render() + end +end