Skip to content

dpsrc/InoreaderDefunctSubscriptionAutoCleaner

Repository files navigation

Inoreader Defunct Subscription Auto Cleaner

A console application that scans your Inoreader RSS subscriptions, detects defunct (dead) or otherwise problematic feed URLs, and lets you interactively unsubscribe from them.

What It Does

  1. Fetches all subscriptions from your Inoreader account via the Inoreader API.
  2. Filters out unsupported entries — email subscriptions and keyword-monitoring (non-RSS YouTube) subscriptions are skipped automatically.
  3. Normalizes feed URLs — handles webfeed:// custom scheme URLs by unwrapping and decoding the embedded URL.
  4. Checks each feed URL by sending an HTTP HEAD request (falling back to GET if HEAD is not supported or returns an error).
  5. Prompts you to delete any subscription whose URL returns 404 Not Found or 503 Service Unavailable.
  6. Unsubscribes via the Inoreader API when you confirm deletion.

Prerequisites

  • .NET 8 SDK
  • An Inoreader account with API access (App ID and App Key)

Configuration

Create or edit appsettings.json in the project root:

{
  "InoreaderAPI": {
    "AppId": "YOUR_APP_ID",
    "AppKey": "YOUR_APP_KEY",
    "BaseUrl": "https://www.inoreader.com/reader/api/0"
  }
}

⚠️ Do not commit real credentials. Add appsettings.json to .gitignore or use user secrets.

Authentication

The app uses the OAuth2 Authorization Code flow to obtain and manage access tokens automatically.

First run

  1. The app opens your browser to the Inoreader authorization page.
  2. You authorize the app and get redirected to https://localhost/?code=....
  3. You paste the code value from the redirect URL into the console.
  4. The app exchanges the code for an access token and a refresh token, and saves both to .tokens.json.

Subsequent runs

  • If the cached access token is still valid (within its 24-hour lifetime), it is reused — no network call needed.
  • If the access token has expired, the app automatically refreshes it using the saved refresh token — no browser interaction needed.
  • If the refresh token is revoked or invalid, the app falls back to the browser authorization flow.

The token_type from the OAuth response (e.g., Bearer) is stored and used for API calls — it is never hardcoded.

Build & Run

dotnet build
dotnet run

Usage

When you run the app, it will:

  1. Authenticate (automatically if tokens are cached, or prompt for browser authorization on first run).
  2. Fetch and scan all subscriptions.
  3. Display each defunct subscription it finds.
  4. Ask you to confirm deletion (y/n) for each one.
 Using cached access token.
🚀 Obtaining the subscriptions...
🚀 Processing the subscriptions...

❌ Checked status 404 NotFound: [Some Dead Blog]
   URL: https://example.com/feed.xml
   Delete this subscription? (y/n): y
   ✅ Deletion status True of https://example.com/feed.xml

Project Structure

├── Api/
│   ├── InoreaderSubscriptionClient.cs  # Inoreader API client (subscriptions, URL checks, unsubscribe)
│   └── InoreaderHttpClientFactory.cs   # Creates HttpClients for API and external URL checks
├── Auth/
│   ├── AuthPrompt.cs                   # Console UI for the browser authorization prompt
│   ├── InoreaderOAuthClient.cs         # OAuth2 flows (authorize, exchange code, refresh tokens)
│   ├── OAuthTokenResponse.cs           # Deserialization model for /oauth2/token responses
│   └── TokenStore.cs                   # Persists tokens to .tokens.json with expiry tracking
├── Config/
│   ├── InoreaderAPIConfig.cs           # Strongly-typed config with URI validation
│   └── InoreaderConfigFactory.cs       # Loads and validates config from appsettings.json
├── Extensions/
│   └── ExceptionExtensions.cs          # Exception message chain helper (supports AggregateException)
├── Manager/
│   └── InoreaderSubscriptionManager.cs # Orchestrates the scan-and-clean workflow
├── Models/
│   └── Subscription.cs                 # Subscription model with URL normalization and validation
├── Utilities/
│   └── BrowserLauncher.cs              # Cross-platform browser launcher
├── Program.cs                          # Entry point (orchestration only)
├── appsettings.json                    # Configuration (excluded from source control)
├── .tokens.json                        # OAuth tokens (auto-generated, excluded from source control) - MUST be in .gitignore
└── .editorconfig                       # Code style and naming conventions

License

This project is provided as-is for personal use.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages