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. Optionally ignores subscriptions whose URL contains any of the keywords supplied via --ignore (see Usage).
  5. Checks each feed URL by sending an HTTP HEAD request (falling back to GET if HEAD is not supported or returns an error).
  6. Detects stale feeds — fetches the latest item date via the Inoreader API and flags subscriptions that have not received a new item in over 3 years as problematic, offering them for deletion alongside dead URLs.
  7. Prompts you to delete any subscription whose URL returns 404 Not Found or 503 Service Unavailable, or whose feed is stale.
  8. 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

To ignore subscriptions whose URL contains specific keywords, pass them as a comma-separated list via --ignore (optional):

dotnet run -- --ignore "feedburner,blogspot"

Multiple keywords are matched case-insensitively as substrings against each subscription's full URL.

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

1 star

Watchers

1 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages