No description
Find a file
Csaba Okrona 3442357f19
Some checks failed
CI / Build and Test (push) Successful in 13s
CI / Code Format Check (push) Successful in 12s
Docker / Build and Push Docker Image (push) Failing after 6s
Release / Build and Release (push) Successful in 30s
feat: improved error handling and comprehensive test coverage
- Improved ArrClientFactory exception handling and logging
  * BrokenCircuitException logged at Debug level (expected behavior)
  * Connection failures logged concisely without stack traces
  * Reduces log noise when Arr services are temporarily unavailable

- Added comprehensive unit tests (improvement #17)
  * 4 new ArrClientFactory exception handling tests
  * 4 new DownloadManager target generation tests
  * 4 new DownloadManager seen tracking tests (thread-safety verified)
  * Test count: 198 → 210 tests

All tests passing 
2025-12-13 16:50:24 +01:00
.forgejo/workflows Use Docker-in-Docker (dind) image with privileged mode 2025-12-13 06:49:09 +01:00
.github ci: bump actions/cache from 4 to 5 2025-12-12 13:29:47 +00:00
src/Csharparr feat: improved error handling and comprehensive test coverage 2025-12-13 16:50:24 +01:00
tests/Csharparr.Tests feat: improved error handling and comprehensive test coverage 2025-12-13 16:50:24 +01:00
.gitignore init 2025-12-11 13:26:55 +01:00
CHANGELOG.md feat: improved error handling and comprehensive test coverage 2025-12-13 16:50:24 +01:00
Csharparr.sln init 2025-12-11 13:26:55 +01:00
docker-compose.yaml init 2025-12-11 13:26:55 +01:00
Dockerfile fix: use stable .NET 10 images instead of preview 2025-12-11 13:50:44 +01:00
IMPROVEMENT_IDEAS.md feat: improved error handling and comprehensive test coverage 2025-12-13 16:50:24 +01:00
LICENSE init 2025-12-11 13:26:55 +01:00
README.md init 2025-12-11 13:26:55 +01:00

csharparr

.NET C# License

Proxy that allows put.io to be used as a download client for sonarr/radarr/whisparr. The proxy uses the Transmission protocol.

This is a C# / .NET 10 port of the original Rust implementation.

Installation

From Source

Make sure you have .NET 10 SDK or later installed.

# Clone the repository
git clone https://github.com/ochronus/csharparr.git
cd csharparr

# Build
dotnet build -c Release

# Run
dotnet run --project src/Csharparr -- run

# Or publish a self-contained executable
dotnet publish -c Release -o publish

Docker

docker run -d \
  --name=csharparr \
  -e PUID=1000 \
  -e PGID=1000 \
  -e TZ=Etc/UTC \
  -p 9091:9091 \
  -v /path/to/csharparr/config:/config \
  -v /path/to/your/downloads:/downloads \
  --restart unless-stopped \
  ghcr.io/ochronus/csharparr:latest

Docker Compose

version: "3.8"
services:
  csharparr:
    image: ghcr.io/ochronus/csharparr:latest
    container_name: csharparr
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Etc/UTC
    volumes:
      - /path/to/csharparr/config:/config
      - /path/to/your/downloads:/downloads
    ports:
      - 9091:9091
    restart: unless-stopped

Usage

Commands

# Run the proxy
csharparr run

# Run with custom config path
csharparr run -c /path/to/config.toml

# Generate a put.io API token
csharparr get-token

# Generate a config file (will prompt for put.io authentication)
csharparr generate-config

# Generate config at a specific path
csharparr generate-config -c /path/to/config.toml

# Show version
csharparr version

First-Time Setup

  1. Run csharparr generate-config to create a configuration file
  2. Follow the prompts to authenticate with put.io
  3. Edit the generated config file to set:
    • username and password for the proxy
    • download_directory for where files should be downloaded
    • Sonarr/Radarr/Whisparr connection details
  4. Run csharparr run to start the proxy
  5. Configure the Transmission download client in sonarr/radarr/whisparr:
    • Host: Your csharparr host
    • Port: 9091 (default)
    • Url Base: /transmission
    • Username:
    • Password:

Configuration

A configuration file can be specified using -c, but the default configuration file location is:

  • Linux/macOS: ~/.config/putioarr/config.toml

TOML is used as the configuration format:

# Required. Username and password that sonarr/radarr/whisparr use to connect to the proxy
username = "myusername"
password = "mypassword"

# Required. Directory where the proxy will download files to. This directory has to be readable by
# sonarr/radarr/whisparr in order to import downloads
download_directory = "/path/to/downloads"

# Optional bind address, default "0.0.0.0"
bind_address = "0.0.0.0"

# Optional TCP port, default 9091
port = 9091

# Optional log level, default "info"
loglevel = "info"

# Optional UID, default 1000. Change the owner of the downloaded files to this UID. Requires root.
uid = 1000

# Optional polling interval in secs, default 10.
polling_interval = 10

# Optional skip directories when downloading, default ["sample", "extras"]
skip_directories = ["sample", "extras"]

# Optional number of orchestration workers, default 10. Unless there are many changes coming from
# put.io, you shouldn't have to touch this number. 10 is already overkill.
orchestration_workers = 10

# Optional number of download workers, default 4. This controls how many downloads we run in parallel.
download_workers = 4

[putio]
# Required. Putio API key. You can generate one using 'csharparr get-token'
api_key = "MYPUTIOKEY"

# Both [sonarr] and [radarr] are optional, but you'll need at least one of them
[sonarr]
url = "http://mysonarrhost:8989/sonarr"
# Can be found in Settings -> General
api_key = "MYSONARRAPIKEY"

[radarr]
url = "http://myradarrhost:7878/radarr"
# Can be found in Settings -> General
api_key = "MYRADARRAPIKEY"

[whisparr]
url = "http://mywhisparrhost:6969/whisparr"
# Can be found in Settings -> General
api_key = "MYWHISPARRAPIKEY"

Behavior

The proxy will:

  1. Upload torrents or magnet links to put.io
  2. Monitor transfers for completion
  3. Download completed files to the specified download directory
  4. Wait for sonarr/radarr/whisparr to import the files
  5. Remove files after import and when put.io is done seeding
  6. Skip directories named "Sample" or "Extras" by default

Project Structure

.
├── src/
│   └── Csharparr/
│       ├── Commands/           # CLI command handlers
│       ├── Configuration/      # Configuration types and loading
│       ├── Download/           # Download orchestration
│       ├── Http/               # HTTP/Transmission RPC handlers
│       ├── Services/           # API clients (Put.io, Arr)
│       └── Program.cs          # Application entry point
├── tests/
│   └── Csharparr.Tests/        # Unit tests
├── Dockerfile
├── docker-compose.yaml
└── Csharparr.sln

Dependencies

Development

Building

dotnet build

Running Tests

dotnet test

Running Locally

dotnet run --project src/Csharparr -- run -c path/to/config.toml

Contributing

Contributions are welcome! When contributing:

  1. Add tests for new features
  2. Ensure dotnet test passes
  3. Run dotnet format to format code
  4. Update documentation as needed

License

MIT

Thanks