<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ashu_Bharti</title>
    <description>The latest articles on DEV Community by Ashu_Bharti (@ashusosuke).</description>
    <link>https://dev.to/ashusosuke</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4082705%2Fd3ef2ddc-621a-434a-823c-5759e421ce88.jpg</url>
      <title>DEV Community: Ashu_Bharti</title>
      <link>https://dev.to/ashusosuke</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ashusosuke"/>
    <language>en</language>
    <item>
      <title>I Built an Agent That Reads the News For Me, So I Stopped Opening Five Apps Every Morning</title>
      <dc:creator>Ashu_Bharti</dc:creator>
      <pubDate>Fri, 21 Aug 2026 05:42:12 +0000</pubDate>
      <link>https://dev.to/ashusosuke/i-built-an-agent-that-reads-the-news-for-me-so-i-stopped-opening-five-apps-every-morning-4bh4</link>
      <guid>https://dev.to/ashusosuke/i-built-an-agent-that-reads-the-news-for-me-so-i-stopped-opening-five-apps-every-morning-4bh4</guid>
      <description>&lt;p&gt;The itch&lt;/p&gt;

&lt;p&gt;My home server already runs my own Netflix and Spotify — self-hosted, Docker, reachable from anywhere over Tailscale. The next annoyance wasn't about subscriptions, it was about habit: checking Hacker News, a couple of tech blogs, and a few AI-news sites every morning, out of FOMO more than intention.&lt;/p&gt;

&lt;p&gt;So I built Hermes — not a chatbot, a background agent. It reads a config file of topics and RSS feeds, checks every 15 minutes whether anything's due, and when it's time, fetches the latest articles, sends them to an LLM to actually curate and summarize, and delivers a clean digest straight to Telegram. No dashboard. Nothing to open. It either shows up, or it doesn't need to.&lt;/p&gt;

&lt;p&gt;Building it in provable pieces&lt;/p&gt;

&lt;p&gt;I didn't write the orchestrator first and hope for the best. Every stage was proven standalone before anything touched anything else:&lt;/p&gt;

&lt;p&gt;Telegram delivery, tested first — before a single line of Python existed, I created a bot via BotFather and fired a raw curl request at the Telegram API just to confirm the token and chat ID actually worked. If the simplest possible test fails, nothing built on top of it matters.&lt;br&gt;
Feed fetching, tested alone — a script that pulled entries from one RSS feed and printed them. No AI, no Telegram — just "does this return real, current data."&lt;br&gt;
Summarization, read critically — fed real fetched entries into an LLM with a prompt built to curate (skip filler, keep substance) rather than just paraphrase headlines. I read the actual output for quality before trusting it, and had to swap models mid-build after my first choice returned a 404 for being deprecated for new API keys — a good reminder that "the docs I remember" and "what the API currently supports" aren't always the same thing.&lt;br&gt;
Full pipeline, run by hand — only once all three worked alone did I chain them and trigger the whole thing manually, watching it land on my phone for real.&lt;br&gt;
Scheduling, last — a systemd timer plus a oneshot service, ticking every 15 minutes, checking a small SQLite table for what's actually due.&lt;br&gt;
The bug that looked like success&lt;/p&gt;

&lt;p&gt;The first morning, nothing arrived. That was confusing, because everything looked fine: the timer had fired exactly on schedule, every 15 minutes, all night. The logs showed clean, successful runs. No errors, no crashes.&lt;/p&gt;

&lt;p&gt;The actual problem was in the logic itself, not the infrastructure around it. I'd written the "is this topic due" check as a rolling cooldown: has it been 24 hours since the last send? That's the correct question if you want something to run "every 12 hours" or "every 6 hours." It's the wrong question if what you actually want is "every day at a specific clock time." A topic last sent at 11:58 PM the night before wouldn't cross the 24-hour mark again until nearly midnight the next day — completely sailing past the 7 AM window I'd configured, day after day, without a single error to flag it.&lt;/p&gt;

&lt;p&gt;The fix was to stop treating a fixed daily time as a duration problem at all. For any topic with a set send time, the real question is: has today's target time already passed, and have I not sent anything today yet? That's a date comparison, not an hours-elapsed comparison — two ideas that look almost identical in code but produce completely different schedules.&lt;/p&gt;

&lt;p&gt;There was a second, smaller version of the same lesson: I'd also assumed the server ran in UTC when scheduling times, when in reality the fix needed to account for the actual system timezone matching the times I cared about — otherwise "7 AM" silently means 7 AM somewhere else.&lt;/p&gt;

&lt;p&gt;What actually proved it worked&lt;/p&gt;

&lt;p&gt;Not the timer showing active (waiting). Not the service exiting with status=0/SUCCESS. The only real proof was checking journalctl logs for the actual scheduled window and confirming a topic was fetched, summarized, and marked sent — and then checking my phone. A green checkmark from systemd means the process didn't crash. It says nothing about whether the logic inside it did what I actually wanted.&lt;/p&gt;

&lt;p&gt;Where it stands now&lt;/p&gt;

&lt;p&gt;Hermes runs unattended today, delivering a curated digest every morning without me touching anything. The build was small compared to some of my other server projects, but it reinforced the same principle: nothing "just works," and the gap between "ran without errors" and "did the right thing" is exactly where the real bugs hide.&lt;/p&gt;

&lt;p&gt;Next up: a fallback chain across multiple AI providers, so a rate limit on one doesn't mean a missed morning — and reusing this same dispatch-and-deliver skeleton for other background agents instead of rebuilding the plumbing from scratch each time.&lt;/p&gt;

&lt;h1&gt;
  
  
  selfhosted #python #buildinpublic #AI
&lt;/h1&gt;

</description>
      <category>agents</category>
      <category>automation</category>
      <category>llm</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Tired of Subscriptions, So I Built My Own Server</title>
      <dc:creator>Ashu_Bharti</dc:creator>
      <pubDate>Tue, 18 Aug 2026 07:09:56 +0000</pubDate>
      <link>https://dev.to/ashusosuke/tired-of-subscriptions-so-i-built-my-own-server-14m</link>
      <guid>https://dev.to/ashusosuke/tired-of-subscriptions-so-i-built-my-own-server-14m</guid>
      <description>&lt;p&gt;Another month, another stack of bills for a music app, a movie app, cloud storage — all for things I could technically host myself. So I did.&lt;/p&gt;

&lt;p&gt;That question turned into a home server on a repurposed laptop, a full Docker stack, and a Python pipeline that's had four separate fights with YouTube's anti-bot systems in a single week. And once I had a server I actually controlled, the ideas didn't stop — a personal webpage, automations, my own music/movie player, an AI agent to manage it all. Here's how it came together.&lt;/p&gt;

&lt;p&gt;The setup&lt;/p&gt;

&lt;p&gt;A 16GB/i5 laptop I wasn't using became a Debian 13 VM (headless, VirtualBox), reachable from anywhere via Tailscale. One Docker stack runs on top:&lt;/p&gt;

&lt;p&gt;Jellyfin — my own Netflix&lt;br&gt;
Navidrome — my own Spotify&lt;br&gt;
Samba — a network drive from any device&lt;br&gt;
Portainer / Homepage — management + dashboard&lt;br&gt;
PostgreSQL — shared DB engine&lt;br&gt;
Pi-hole — network-wide ad block (in progress)&lt;/p&gt;

&lt;p&gt;No more monthly bills for things a spare laptop can do for free.&lt;/p&gt;

&lt;p&gt;The hard part: filling it with music&lt;/p&gt;

&lt;p&gt;Hosting a Spotify clone is easy. Filling it with your actual library isn't. Spotify's Feb 2026 API change blocked the clean OAuth route, so I improvised: export playlists as CSVs (via Exportify), then built MusicVault — a pipeline that parses them, finds each track on YouTube, downloads it, and auto-generates playlists Navidrome can serve.&lt;/p&gt;

&lt;p&gt;5,748 tracks. 97 playlists. Starting from zero.&lt;/p&gt;

&lt;p&gt;Four fights with YouTube&lt;br&gt;
Storage — FLAC files were about to blow past my 200GB disk. Switched everything to MP3.&lt;br&gt;
Silent failures — my own script was hiding the real error. Fixed the logging first, which revealed YouTube's bot-check. Fixed with browser cookies.&lt;br&gt;
"Format not available" — YouTube now requires solving a JS challenge for some streams. Installed a JS runtime + solver, and caught a sneaky bug where ~ silently failed inside a command flag.&lt;br&gt;
Mass 403 errors — a live, actively-evolving yt-dlp issue other users were hitting that same week. Fixed by forcing a different YouTube client. Even the fix had a gotcha: a tabs-vs-spaces mismatch silently blocked my first patch attempt.&lt;/p&gt;

&lt;p&gt;Four unrelated failure modes, back to back — each one real debugging, not copy-paste.&lt;/p&gt;

&lt;p&gt;What's next&lt;br&gt;
A personal webpage, hosted off the server&lt;br&gt;
Automations — disk monitoring, auto-cleanup, alerts when things break&lt;br&gt;
A custom-built music/movie player instead of default UIs&lt;br&gt;
An AI agent layer to manage the server in plain language&lt;br&gt;
Eventually: Nextcloud, Gitea, self-hosted photo backup&lt;/p&gt;

&lt;p&gt;What started as "stop paying for four apps" turned into a home-lab I'm still adding to every week — and that's the part I like most.&lt;/p&gt;

</description>
      <category>selfhosted</category>
      <category>docker</category>
      <category>homelab</category>
      <category>python</category>
    </item>
  </channel>
</rss>
