<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Sqlite on Christian Martínez De La Rosa</title><link>https://christt105.github.io/es/tags/sqlite/</link><description>Recent content in Sqlite on Christian Martínez De La Rosa</description><generator>Hugo -- gohugo.io</generator><language>es</language><lastBuildDate>Wed, 28 Oct 2026 00:00:00 +0100</lastBuildDate><atom:link href="https://christt105.github.io/es/tags/sqlite/index.xml" rel="self" type="application/rss+xml"/><item><title>InformadoRSS</title><link>https://christt105.github.io/es/projects/informadorss/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://christt105.github.io/es/projects/informadorss/</guid><enclosure url="https://christt105.github.io/projects/informadorss/cover.webp" length="34178" type="image/webp"/><description>&lt;p&gt;&lt;code&gt;InformadoRSS&lt;/code&gt; es un servicio ligero y self-hosted que vigila feeds RSS y Atom, filtra sus elementos por ruta y los entrega a canales de Discord o a &lt;a class="link" href="https://ntfy.sh/" target="_blank" rel="noopener"&#10; &gt;ntfy&lt;/a&gt;. Funciona en un único contenedor: un binario en C# con .NET 10 compilado con NativeAOT que sirve una interfaz web en Vue 3 y guarda todo en SQLite. Solo habla con Discord a través de la API REST del bot (sin gateway ni comandos). Es de código abierto con licencia MIT.&lt;/p&gt;&#10;&lt;p&gt;Características principales:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Feeds y rutas&lt;/strong&gt;: Un feed es una URL; cada feed tiene rutas con un filtro, uno o varios destinos (Discord o ntfy) y una plantilla de mensaje.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Constructor de filtros y editor de plantillas&lt;/strong&gt;: Crea los filtros y edita los mensajes desde la interfaz web en lugar de escribirlos a mano.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Selector de servidor y canal de Discord&lt;/strong&gt;: Elige los destinos por nombre y comprueba en qué canales no puede publicar el bot.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Alertas&lt;/strong&gt;: Un aviso cuando un feed o un destino se rompe y otro cuando se recupera, por Discord o ntfy.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Copias de seguridad diarias&lt;/strong&gt;: Copias programadas de la base de datos en una carpeta, conservando las más recientes.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Importador de MonitoRSS&lt;/strong&gt;: Importa feeds y rutas desde una exportación de MonitoRSS, con simulación y un canal de pruebas para comparar los mensajes antes de cambiar.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Patrón de identidad para feeds que reescriben entradas&lt;/strong&gt;: Una expresión regular sobre la descripción que se añade al id del elemento, así un cambio de estado en una lista de MyAnimeList cuenta como elemento nuevo.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Cuento cómo y por qué lo hice en &lt;a class="link" href="https://christt105.github.io/es/blog/informadorss/" &gt;el post del blog&lt;/a&gt;. La imagen se publica en &lt;code&gt;ghcr.io/christt105/informadorss&lt;/code&gt;.&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="El editor de rutas: filtro, plantilla del mensaje y canal de destino" class="gallery-image" data-flex-basis="252px" data-flex-grow="105" height="1994" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/projects/informadorss/web-route.webp" srcset="https://christt105.github.io/projects/informadorss/web-route_hu_a1005d249803043c.webp 800w, https://christt105.github.io/projects/informadorss/web-route_hu_458b51e51904d625.webp 1600w, https://christt105.github.io/projects/informadorss/web-route.webp 2100w" width="2100"&gt;&lt;/p&gt;&#10;</description></item><item><title>InformadoRSS: sustituyendo MonitoRSS</title><link>https://christt105.github.io/es/blog/informadorss/</link><pubDate>Wed, 28 Oct 2026 00:00:00 +0100</pubDate><guid>https://christt105.github.io/es/blog/informadorss/</guid><enclosure url="https://christt105.github.io/blog/informadorss/cover.png" length="429533" type="image/png"/><description>&lt;p&gt;¡Hola otra vez!&lt;/p&gt;&#10;&lt;p&gt;Tengo un par de servidores de Discord donde un bot avisa de las entradas nuevas de blogs, vídeos de YouTube, newsletters y de las listas de anime y manga de mis amigos. Durante años eso lo hizo MonitoRSS. Funciona, pero son nueve contenedores (varios servicios en Node, Mongo, Postgres, RabbitMQ&amp;hellip;) y unos 670 MB de RAM para mirar cada diez minutos si hay algo nuevo en unos feeds. En un servidor casero que ya tiene Jellyfin y media docena de cosas más, me parecía una barbaridad, y como sabéis, el mundo no está para regalar RAM. Así que me hice el mío.&lt;/p&gt;&#10;&lt;h2 id="qué-es"&gt;Qué es&#10;&lt;/h2&gt;&lt;p&gt;InformadoRSS es un servicio autoalojado que mira feeds RSS y Atom, filtra los elementos y los manda a canales de Discord. Un contenedor, un archivo SQLite y una web que sirve el mismo binario. Es de código abierto (MIT):&lt;/p&gt;&#10;&lt;a class="github-repo-card" href="https://github.com/christt105/InformadoRSS" target="_blank" rel="noopener"&gt;&#10; &lt;img src="https://avatars.githubusercontent.com/u/36189169?v=4" alt="christt105 avatar" class="repo-avatar"&gt;&#10; &lt;h3&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-github" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"&gt;&#10; &lt;path stroke="none" d="M0 0h24v24H0z" fill="none"/&gt;&#10; &lt;path d="M9 19c-4.3 1.4 -4.3 -2.5 -6 -3m12 5v-3.5c0 -1 .1 -1.4 -.5 -2c2.8 -.3 5.5 -1.4 5.5 -6a4.6 4.6 0 0 0 -1.3 -3.2a4.2 4.2 0 0 0 -.1 -3.2s-1.1 -.3 -3.5 1.3a12.3 12.3 0 0 0 -6.2 0c-2.4 -1.6 -3.5 -1.3 -3.5 -1.3a4.2 4.2 0 0 0 -.1 3.2a4.6 4.6 0 0 0 -1.3 3.2c0 4.6 2.7 5.7 5.5 6c-.6 .6 -.6 1.2 -.5 2v3.5" /&gt;&#10;&lt;/svg&gt;&#10;&#10;&#10; christt105/InformadoRSS&lt;/h3&gt;&#10; &lt;p&gt;Lightweight single-container RSS/Atom to Discord forwarder&lt;/p&gt;&#10; &lt;div class="repo-stats"&gt;&#10; &lt;span&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" class="icon icon-tabler icons-tabler-filled icon-tabler-star"&gt;&lt;path stroke="none" d="M0 0h24v24H0z" fill="none"/&gt;&lt;path d="M8.243 7.34l-6.38 .925l-.113 .023a1 1 0 0 0 -.44 1.684l4.622 4.499l-1.09 6.355l-.013 .11a1 1 0 0 0 1.464 .944l5.706 -3l5.693 3l.1 .046a1 1 0 0 0 1.352 -1.1l-1.091 -6.355l4.624 -4.5l.078 -.085a1 1 0 0 0 -.633 -1.62l-6.38 -.926l-2.852 -5.78a1 1 0 0 0 -1.794 0l-2.853 5.78z" /&gt;&lt;/svg&gt; 0&lt;/span&gt;&#10; &lt;span&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-git-fork"&gt;&lt;path stroke="none" d="M0 0h24v24H0z" fill="none"/&gt;&lt;path d="M10 18a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" /&gt;&lt;path d="M5 6a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" /&gt;&lt;path d="M15 6a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" /&gt;&lt;path d="M7 8v2a2 2 0 0 0 2 2h6a2 2 0 0 0 2 -2v-2" /&gt;&lt;path d="M12 12l0 4" /&gt;&lt;/svg&gt; 0&lt;/span&gt;&#10; &lt;span&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-calendar-event"&gt;&lt;path stroke="none" d="M0 0h24v24H0z" fill="none"/&gt;&lt;path d="M4 7a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2l0 -12" /&gt;&lt;path d="M16 3l0 4" /&gt;&lt;path d="M8 3l0 4" /&gt;&lt;path d="M4 11l16 0" /&gt;&lt;path d="M8 15h2v2h-2l0 -2" /&gt;&lt;/svg&gt; 2026-10-24&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;p&gt;&lt;img alt="El Pregonero, el bot, avisando de una entrada nueva del blog de Godot" class="gallery-image" data-flex-basis="225px" data-flex-grow="94" height="1360" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/blog/informadorss/discord-godot.webp" srcset="https://christt105.github.io/blog/informadorss/discord-godot_hu_be3e79b240a22aeb.webp 800w, https://christt105.github.io/blog/informadorss/discord-godot.webp 1280w" width="1280"&gt;&lt;/p&gt;&#10;&lt;p&gt;La idea es sencilla:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Un &lt;strong&gt;feed&lt;/strong&gt; es una URL.&lt;/li&gt;&#10;&lt;li&gt;Una &lt;strong&gt;ruta&lt;/strong&gt; dice qué hacer con un feed: un filtro, uno o varios destinos (un canal de Discord o ntfy) y una plantilla de mensaje.&lt;/li&gt;&#10;&lt;li&gt;La web tiene un constructor de filtros, un editor de plantillas y un selector de servidores y canales, para no tener que copiar ids a mano.&lt;/li&gt;&#10;&lt;li&gt;El bot habla con Discord solo por la API REST. Nada de gateway, ni comandos, ni webhooks. Así de simple.&lt;/li&gt;&#10;&lt;li&gt;Cuando un feed o un destino se rompe me manda un único mensaje privado por Discord, y otro cuando se recupera.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;img alt="La lista de feeds, con la última entrada de cada uno y su estado" class="gallery-image" data-flex-basis="204px" data-flex-grow="85" height="1690" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/blog/informadorss/web-feeds.webp" srcset="https://christt105.github.io/blog/informadorss/web-feeds_hu_5ee8d49264e2f793.webp 800w, https://christt105.github.io/blog/informadorss/web-feeds.webp 1440w" width="1440"&gt;&lt;/p&gt;&#10;&lt;p&gt;Por ejemplo, el feed de Media Tracker, donde sale lo que termino de ver o jugar, tiene cuatro rutas: en cada servidor las películas y series van a un canal y los videojuegos a otro. Cuando termino Tetris, la entrada pasa por las cuatro y solo llega a los canales que la aceptan:&lt;/p&gt;&#10;&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart LR&#10; I["Nueva entrada&lt;br/&gt;en Media Tracker&lt;br/&gt;&lt;b&gt;Tetris&lt;/b&gt; · película"]&#10; I --&gt; R1["Ruta 3&lt;br/&gt;sin videojuegos"]&#10; I --&gt; R2["Ruta 4&lt;br/&gt;solo videojuegos"]&#10; I --&gt; R3["Ruta 1&lt;br/&gt;sin videojuegos"]&#10; I --&gt; R4["Ruta 2&lt;br/&gt;solo videojuegos"]&#10; R1 --&gt;|"✔ pasa"| C1&#10; R2 -.-x|"✘ no pasa"| G1&#10; R3 --&gt;|"✔ pasa"| C2&#10; R4 -.-x|"✘ no pasa"| G2&#10; subgraph Z["Discord · Los Zanahorios"]&#10; C1["#cine"]&#10; G1["#games"]&#10; end&#10; subgraph P["Discord · Los Panas"]&#10; C2["#animu-pelis-series"]&#10; G2["#gaming"]&#10; end&lt;/pre&gt;&lt;p&gt;&lt;img alt="El editor de una ruta: filtro, plantilla del mensaje y canal de destino" class="gallery-image" data-flex-basis="252px" data-flex-grow="105" height="1994" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/blog/informadorss/web-route.webp" srcset="https://christt105.github.io/blog/informadorss/web-route_hu_a1005d249803043c.webp 800w, https://christt105.github.io/blog/informadorss/web-route_hu_458b51e51904d625.webp 1600w, https://christt105.github.io/blog/informadorss/web-route.webp 2100w" width="2100"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="Así llega Tetris a Discord" class="gallery-image" data-flex-basis="157px" data-flex-grow="65" height="1955" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/blog/informadorss/discord-mediatracker.webp" srcset="https://christt105.github.io/blog/informadorss/discord-mediatracker_hu_fb324b3eb85bfa5f.webp 800w, https://christt105.github.io/blog/informadorss/discord-mediatracker.webp 1280w" width="1280"&gt;&lt;/p&gt;&#10;&lt;h2 id="el-stack"&gt;El stack&#10;&lt;/h2&gt;&lt;p&gt;C# con .NET 10 compilado con NativeAOT, y un frontend en Vue 3 que acaba como archivos estáticos dentro del mismo binario. Elegí C# porque es lo que uso a diario, y por eso descarté Go y C++. Me daba curiosidad probar a hacer algo de este estilo con uno de esos lenguajes, pero al final C# es con el que me siento más cómodo leyendo. El almacenamiento es SQLite, con una copia de seguridad diaria a otro disco, aunque no sería mucha pérdida.&lt;/p&gt;&#10;&lt;p&gt;Así se ve por dentro:&lt;/p&gt;&#10;&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TD&#10; F["Feeds RSS / Atom"] --&gt; SRC&#10; YO["Navegador en la LAN"] --&gt; WEB&#10; subgraph BIN["Un solo binario de C# · .NET 10 con NativeAOT"]&#10; WEB["Web en Vue 3"] &lt;--&gt; API["API"]&#10; API &lt;--&gt; DB[("SQLite")]&#10; SCH["Planificador"] &lt;--&gt; DB&#10; SCH --&gt; SRC["Fuente&lt;br/&gt;descarga y parsea"]&#10; SRC --&gt; PIPE["Rutas&lt;br/&gt;filtro y plantilla"]&#10; subgraph SK["Sinks"]&#10; DSC["Discord"]&#10; NT["ntfy"]&#10; NEXT["¿Telegram?"]&#10; end&#10; PIPE --&gt; DSC&#10; PIPE --&gt; NT&#10; PIPE -.-&gt; NEXT&#10; end&#10; classDef futuro stroke-dasharray: 5 5&#10; class NEXT futuro&lt;/pre&gt;&lt;p&gt;La idea es que todo sea modular. Cada destino es un sink, una clase que implementa una interfaz muy pequeña: un nombre y un método que entrega el mensaje. Ahora mismo hay dos, Discord y ntfy, y añadir otro, como Telegram, es escribir esa clase y registrarla, sin tocar el planificador ni los filtros; la web lo detecta sola y ya lo ofrece como destino. Con las fuentes pasa lo mismo: hoy solo hay RSS y Atom, pero están detrás de su propia interfaz.&lt;/p&gt;&#10;&lt;h2 id="los-números"&gt;Los números&#10;&lt;/h2&gt;&lt;p&gt;Vamos a poner los números sobre la mesa y a comparar los dos servicios en momentos parecidos: en reposo, con los mismos feeds y mirando cada diez minutos. MonitoRSS ya lo he apagado por razones obvias, así que sus cifras son de antes del cambio.&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;InformadoRSS&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;MonitoRSS&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Contenedores&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;9&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;RAM&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;75 MiB&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;unos 670 MB&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Imagen&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;37 MB&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;unos 3,9 GB sumadas&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Datos en disco&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;4,5 MB&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;656 MB&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;Aunque los números son muy buenos, aún hay margen de mejora. En el primer experimento, sin feeds ni web, el binario AOT gastaba unos 10 MiB, y en producción son 75 MiB: el recolector de basura de .NET no tiene ninguna prisa por devolver memoria en una máquina con 15 GB libres. Si algún día me importa, puedo limitarle el heap. También escribe unos 50 MB al día en disco, casi todo logs demasiado detallados del cliente HTTP, que se arreglan bajando el nivel de log.&lt;/p&gt;&#10;&lt;h2 id="hecho-con-claude"&gt;Hecho con Claude&#10;&lt;/h2&gt;&lt;p&gt;Primero escribí el diseño en una nota de Obsidian (qué hace MonitoRSS, qué uso yo de verdad y qué puedo tirar) y luego lo partí en tareas. Claude ejecutó varias en paralelo en worktrees de git distintos, cada una con su pull request, y yo las revisaba y mergeaba por oleadas: almacenamiento, filtros y parser de feeds, luego el planificador y el envío a Discord, y por último el importador, las alertas, las copias de seguridad y la web. Creo que he encontrado un flujo de trabajo muy cómodo con la IA, puede que pronto escriba un post de cómo trabajo.&lt;/p&gt;&#10;&lt;h2 id="el-cambio"&gt;El cambio&#10;&lt;/h2&gt;&lt;p&gt;Lo que daba miedo no era el código, era el cambio de uno a otro. Hice un importador que lee un &lt;code&gt;mongoexport&lt;/code&gt; de MonitoRSS y crea los feeds y las rutas. La primera pasada mandaba todos los destinos a un canal de pruebas y enviaba el último elemento de cada feed, para comparar los mensajes uno al lado del otro. Cuando cuadró, paré los contenedores de MonitoRSS, apunté las 22 rutas a los canales de verdad y las marqué como vistas en silencio para que nadie se comiera una avalancha de entradas viejas. Si algo salía mal, un &lt;code&gt;docker start&lt;/code&gt; y vuelve el stack antiguo. La verdad es que salió casi perfecto a la primera.&lt;/p&gt;&#10;&lt;h2 id="cosas-que-me-dieron-guerra"&gt;Cosas que me dieron guerra&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Los feeds de YouTube devuelven 404 unas horas cada mañana.&lt;/strong&gt; Es una caída global, no mi IP. Por eso un feed solo se considera roto tras seis horas seguidas fallando. No entiendo muy bien por qué le pasa esto a YouTube. &lt;a class="link" href="https://www.reddit.com/r/youtube/comments/1r61jpo/all_youtube_channel_rss_feeds_are_down_return_404/" target="_blank" rel="noopener"&#10; &gt;Parece un error de hace algo de tiempo&lt;/a&gt;.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;MyAnimeList reescribe las entradas en el sitio.&lt;/strong&gt; El guid de cada entrada es la URL del anime y el estado vive en la descripción, así que pasar de &lt;code&gt;Watching&lt;/code&gt; a &lt;code&gt;Completed&lt;/code&gt; nunca se enviaba. En MonitoRSS pasaba igual. Ahora un feed puede tener un patrón de identidad, una expresión regular sobre la descripción que se añade al id del elemento, y cada estado cuenta como elemento nuevo. Igualmente es una mierda cómo MAL organiza el RSS (Ori no te lo digo más, mete RSS en tu app de tracking).&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Elementos viejos tras una caída.&lt;/strong&gt; Los elementos más antiguos que un máximo se marcan como vistos sin enviarse, y desde la web se puede enviar o resetear cualquiera a mano. Esto me suele pasar porque tardo varios días en escribir un post: me olvido de actualizar la fecha, aparece como publicado hace varios días y se pierde el envío.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;img alt="Un cambio de estado en MyAnimeList que ahora sí llega a Discord" class="gallery-image" data-flex-basis="375px" data-flex-grow="156" height="818" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/blog/informadorss/discord-mal.webp" srcset="https://christt105.github.io/blog/informadorss/discord-mal_hu_a1a7bf577e79ccc3.webp 800w, https://christt105.github.io/blog/informadorss/discord-mal.webp 1280w" width="1280"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="La vista de un feed, con sus rutas y el campo del patrón de identidad" class="gallery-image" data-flex-basis="309px" data-flex-grow="128" height="1629" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/blog/informadorss/web-feed.webp" srcset="https://christt105.github.io/blog/informadorss/web-feed_hu_384fba0bd150d037.webp 800w, https://christt105.github.io/blog/informadorss/web-feed_hu_a98081b772e13ef9.webp 1600w, https://christt105.github.io/blog/informadorss/web-feed.webp 2100w" width="2100"&gt;&lt;/p&gt;&#10;&lt;h2 id="lo-que-falta"&gt;Lo que falta&#10;&lt;/h2&gt;&lt;p&gt;Es un servicio muy básico, tiene justo lo que necesito. MonitoRSS tiene mucha más personalización y puedes hacer más cosas, pero no lo necesito, y menos a cambio de gastar nueve veces más RAM.&lt;/p&gt;&#10;&lt;p&gt;Faltan cosas como los mensajes de Discord con Components V2, una vista previa del mensaje estilo Discord y un filtro de Shorts para YouTube. No tiene login: está pensado para una LAN de confianza.&lt;/p&gt;&#10;&lt;p&gt;Lo tengo montado bastante modular, así que puedo añadir otras fuentes u otros sinks, y si necesito alguna funcionalidad la puedo añadir fácilmente: no es un servicio muy complejo. De momento lo dejaré así, abierto para quien quiera usarlo o mejorarlo.&lt;/p&gt;&#10;&lt;p&gt;Si usas MonitoRSS y quieres algo más ligero, pruébalo y échale un vistazo.&lt;/p&gt;&#10;&lt;p&gt;¡Nos vemos en el siguiente!&lt;/p&gt;&#10;</description></item></channel></rss>