# q-buffer

q-buffer, qBittorrent üzerinde torrentleri kontrollü şekilde döngüye almayı ve peer kısıtlamasını otomatikleştirmeyi amaçlayan bir uygulamadır. Buffer ekranında torrent seçip loop akışını başlatabilir, Timer ekranında etiket bazlı otomatik silme kuralları tanımlayabilirsiniz.

## Neler yapar?

- qBittorrent WebUI API ile bağlanır, aktif torrent listesini gösterir.
- Seçilen torrent için loop (indir → sil → yeniden ekle) işlemini yönetir.
- Allow IP kuralıyla agresif peer kısıtlaması uygular (destek varsa ban). 
- Timer kurallarıyla etiket bazlı seed süresi dolan torrentleri otomatik siler.
- Gerçek zamanlı durum, log ve metrikleri UI üzerinden gösterir.

## Hızlı Başlangıç

1) `.env.example` dosyasını `.env` olarak kopyalayın ve değerleri doldurun.
2) İlk kurulumda `wscraper-service` tarafını okuyun: `Watcher` özelliği için host makinede Python 3.10+ gerekir.
3) Geliştirme ortamını başlatın:

```bash
./scripts/bootstrap.sh --dev-mode
```

4) Açın:

- Web: http://localhost:5173
- API/Socket: http://localhost:3001

## Watcher Notu

`Watcher` akışı `wscraper -> scrapling -> Playwright` zincirini kullanır. Playwright DNS ve browser bağımlılıklarını Docker içine taşımak yerine `wscraper-service` host makinede çalışır; `web` ve `server` ise Docker içinde kalır. `server`, host servisle `http://host.docker.internal:8787` üzerinden konuşur.

`bootstrap.sh` şu işleri tek komutta yapar:

- eksikse `wscraper` repo'yu `bin/wscraper` altına otomatik clone eder
- Docker servislerini `up --build` ile kaldırır
- host `wscraper-service` için Python venv hazırlar
- eksik Python paketlerini ve Playwright bağımlılıklarını kurar
- `wscraper-service`i başlatır

`wscraper-service` kurulumu her çalıştırmada sıfırdan yapılmaz. Kurulum daha önce tamamlandıysa script sadece kontrol eder ve eksik yoksa yeniden kurmaz. `wscraper` repo da aynı şekilde idempotent yönetilir: repo eksikse clone edilir, varsa tekrar clone edilmez.

### İlk Kurulumda wscraper Yapılandırması

Bu bölüm ilk kez `q-buffer` kuranlar içindir. Sık karışan nokta şu:

- `bin/wscraper/` dizini scraper paketinin kendisidir
- `bin/wscraper-service/server.py`, `q-buffer` backend'in çağırdığı host servisidir
- yani `wscraper` dizininde yalnızca `server.py` yok; asıl tracker adapter kodları `bin/wscraper/src/wscraper/...` altındadır

Geçerli kurulum modeli:

- önce `q-buffer` repo clone edilir
- `bootstrap.sh`, `bin/wscraper` eksikse `wscraper` repo'yu otomatik clone eder
- repo zaten varsa olduğu gibi bırakır
- sadece açıkça `--update-wscraper` verirseniz mevcut checkout `git pull --ff-only` ile güncellenir

İlk kurulum adımları:

1. `q-buffer` repo'yu clone edin.
2. `.env.example` dosyasını `.env` olarak kopyalayın.
3. qBittorrent ve uygulama auth ayarlarını doldurun.
4. watcher servis ayarlarını kontrol edin:
   - `WSCRAPER_SERVICE_BASE_URL=http://host.docker.internal:8787`
   - `WSCRAPER_SERVICE_TOKEN=` boş bırakılabilir
   - `WSCRAPER_SERVICE_HOST=0.0.0.0`
   - `WSCRAPER_SERVICE_PORT=8787`
   - `WSCRAPER_SERVICE_PYTHON_BIN=python3.12`
   - `WSCRAPER_GIT_URL=https://github.com/wisecolt/Bookmark-Tracker.git`
   - `WSCRAPER_GIT_REF=main`
5. Host makinede uygun Python sürümü olduğundan emin olun:
   - `python3.12 --version`
   - yoksa `python3.11` veya `python3.10`
6. Repo root'ta şu komutu çalıştırın:

```bash
./scripts/bootstrap.sh --dev-mode
```

7. İlk bootstrap tamamlandıktan sonra `q-buffer/bin/wscraper` altında şu dosyaların geldiğini doğrulayın:
   - `pyproject.toml`
   - `setup.py`
   - `src/wscraper/cli.py`
   - `src/wscraper/sites/happyfappy.py`
   - `src/wscraper/sites/privatehd.py`

Bu komut şunları yapar:

- `bin/wscraper` yoksa `WSCRAPER_GIT_URL` ve `WSCRAPER_GIT_REF` ile repo'yu clone eder
- Docker `web` ve `server` servislerini `up --build` ile başlatır
- host'ta `.runtime/wscraper-service/.venv` oluşturur
- `scrapling[fetchers]` kurar
- `scrapling install` çalıştırır
- `bin/wscraper-service/server.py` sürecini başlatır

Kurulumdan sonra kontrol edilecekler:

```bash
curl http://127.0.0.1:8787/health
docker compose -f docker-compose.dev.yml ps
```

İlk komutta `{"ok":true,...}` benzeri cevap, ikinci komutta `server` ve `web` container'ları görülmelidir.

Host makinede Python 3.10+ gerekir. Script sırasıyla `python3.12`, `python3.11`, `python3.10`, `python3` ikililerini dener ve uygun ilk sürümü seçer. Gerekirse `.env` içine `WSCRAPER_SERVICE_PYTHON_BIN=python3.12` benzeri açık bir değer verebilirsiniz.

Kullanılabilir bayraklar:

```bash
./scripts/bootstrap.sh --dev-mode
./scripts/bootstrap.sh --prod-mode
./scripts/bootstrap.sh --dev-mode --skip-wscraper-fetch
./scripts/bootstrap.sh --dev-mode --update-wscraper
./scripts/bootstrap.sh --dev-mode --skip-wscraper-install
./scripts/bootstrap.sh --dev-mode --restart-wscraper
```

### bootstrap.sh Bayrakları

`bootstrap.sh` şu anda tek giriş komutudur. Aynı script hem Docker servislerini kaldırır hem de host tarafındaki `wscraper-service` sürecini yönetir. Bu yüzden bayrakların neyi etkilediğini net bilmek önemlidir.

#### `--dev-mode`

Geliştirme ortamını başlatır.

Ne yapar:
- `docker compose -f docker-compose.dev.yml up --build` çalıştırır
- development compose dosyasındaki `web` ve `server` servislerini ayağa kaldırır
- host makinede `wscraper-service` sürecini hazırlar ve başlatır

Ne zaman kullanılır:
- günlük geliştirme akışında
- watcher veya UI/backend değişikliği yaparken
- ilk lokal kurulumda

Örnek:

```bash
./scripts/bootstrap.sh --dev-mode
```

#### `--prod-mode`

Production benzeri çalışma modunu başlatır.

Ne yapar:
- `docker compose -f docker-compose.yml up --build -d` çalıştırır
- servisleri detached modda ayağa kaldırır
- host makinede `wscraper-service` sürecini hazırlar ve başlatır

Ne zaman kullanılır:
- kalıcı çalışan kurulumda
- UI terminale bağlı kalmasın istendiğinde
- production veya staging benzeri testlerde

Örnek:

```bash
./scripts/bootstrap.sh --prod-mode
```

#### `--skip-wscraper-fetch`

`bin/wscraper` repo yönetimini tamamen atlar.

Ne yapar:
- `bin/wscraper` yoksa clone etmeye çalışmaz
- varsa update etmeye çalışmaz
- `WSCRAPER_GIT_URL` ve `WSCRAPER_GIT_REF` değerlerini kullanmaz

Ne yapmaz:
- `wscraper-service` Python kurulumunu atlamaz
- `wscraper-service` başlatmayı atlamaz
- Docker servislerini atlamaz

Ne zaman kullanılır:
- `bin/wscraper` repo’sunu manuel yönetiyorsanız
- farklı bir branch üzerinde çalışıyorsanız
- bootstrap’in `git clone/pull` davranışına dokunmasını istemiyorsanız

Örnek:

```bash
./scripts/bootstrap.sh --dev-mode --skip-wscraper-fetch
```

#### `--update-wscraper`

Mevcut `bin/wscraper` checkout’unu günceller.

Ne yapar:
- `bin/wscraper` yoksa önce clone eder
- repo varsa `git pull --ff-only` dener
- yalnızca fast-forward güncellemeye izin verir

Güvenlik davranışı:
- `bin/wscraper` içinde local değişiklik varsa script durur
- merge/rebase yapmaz
- mevcut branch’i zorla değiştirmez

Ne zaman kullanılır:
- `wscraper` repo’daki son değişiklikleri almak istediğinizde
- watcher tracker güncellemeleri geldiyse
- `q-buffer` ile birlikte `wscraper`ı da senkron tutmak istediğinizde

Örnek:

```bash
./scripts/bootstrap.sh --dev-mode --update-wscraper
```

#### `--skip-wscraper-install`

Host makinedeki `wscraper-service` Python kurulum kontrolünü atlar.

Ne yapar:
- `.runtime/wscraper-service/.venv` doğrulamasını atlar
- `pip install` ve `scrapling install` çalıştırmaz

Ne yapmaz:
- `wscraper-service` başlatmayı engellemez
- `bin/wscraper` repo kontrolünü engellemez
- Docker servislerini engellemez

Ne zaman kullanılır:
- Python ortamının zaten doğru kurulu olduğundan eminseniz
- kurulum adımını kısaltmak istiyorsanız
- ağ erişimi geçici olarak sorunluysa ve mevcut venv’i kullanmak istiyorsanız

Risk:
- mevcut venv eksik veya bozuksa servis daha sonra start aşamasında hata verebilir

Örnek:

```bash
./scripts/bootstrap.sh --dev-mode --skip-wscraper-install
```

#### `--restart-wscraper`

Çalışan `wscraper-service` sürecini zorla yeniden başlatır.

Ne yapar:
- mevcut PID dosyasını okuyup çalışan host service’i durdurur
- sonra yeni bir `wscraper-service` süreci başlatır

Ne zaman kullanılır:
- `bin/wscraper-service/server.py` değiştiyse
- tracker adapter kodu değiştiyse
- eski host process cache/state taşıyor gibi görünüyorsa

Örnek:

```bash
./scripts/bootstrap.sh --dev-mode --restart-wscraper
```

### Bayrak Kombinasyonları

En sık kullanılan kombinasyonlar:

- Normal geliştirme:

```bash
./scripts/bootstrap.sh --dev-mode
```

- `wscraper` repo’yu da güncelleyerek geliştirme:

```bash
./scripts/bootstrap.sh --dev-mode --update-wscraper
```

- Mevcut `wscraper` checkout’una hiç dokunmadan geliştirme:

```bash
./scripts/bootstrap.sh --dev-mode --skip-wscraper-fetch
```

- Host service’i yeniden başlatarak geliştirme:

```bash
./scripts/bootstrap.sh --dev-mode --restart-wscraper
```

- Ağsız veya hızlı tekrar başlatma denemesi:

```bash
./scripts/bootstrap.sh --dev-mode --skip-wscraper-fetch --skip-wscraper-install --restart-wscraper
```

### Önemli Notlar

- `--update-wscraper` ile `--skip-wscraper-fetch` aynı anda kullanılmamalıdır. Mantıksal olarak biri güncelleme isterken diğeri git işlemlerini kapatır.
- `--skip-wscraper-install`, yalnızca host Python ortamının zaten doğru kurulu olduğundan eminseniz kullanılmalıdır.
- `--restart-wscraper`, yalnızca host service sürecini etkiler; Docker container’ları yeniden oluşturmaz.

Docker tarafında normal ağ erişimi hâlâ gereklidir. DNS problemi yaşarsanız Docker Desktop içinde sabit resolver (`8.8.8.8`, `1.1.1.1`) tanımlayın. Docker DNS doğru ayarlanmamışsa:

- `pnpm install`
- image pull işlemleri
- container içi paket kurulumları

kurulum sırasında kırılabilir.

Önerilen Docker Engine ayarı:

```json
{
  "builder": {
    "gc": {
      "defaultKeepStorage": "20GB",
      "enabled": true
    }
  },
  "experimental": false,
  "dns": ["8.8.8.8", "1.1.1.1"]
}
```

Docker Desktop yeniden başladıktan sonra şu testler başarılı olmalıdır:

```bash
docker run --rm alpine nslookup registry-1.docker.io
docker run --rm alpine nslookup files.pythonhosted.org
docker run --rm alpine nslookup cdn.playwright.dev
```

Host servis için kullanılacak ortam değişkenleri:

- `WSCRAPER_SERVICE_BASE_URL` varsayılan: `http://host.docker.internal:8787`
- `WSCRAPER_SERVICE_TOKEN` varsayılan: boş
- `WSCRAPER_SERVICE_HOST` varsayılan: `0.0.0.0`
- `WSCRAPER_SERVICE_PORT` varsayılan: `8787`
- `WSCRAPER_SERVICE_PYTHON_BIN` örnek: `python3.12`
- `WSCRAPER_GIT_URL` varsayılan: `https://github.com/wisecolt/Bookmark-Tracker.git`
- `WSCRAPER_GIT_REF` varsayılan: `main`

Daha detaylı `wscraper` dökümü için:

- [bin/wscraper/README.md](/Users/wisecolt-macmini/Project/q-buffer/bin/wscraper/README.md)

## Kullanım (Buffer)

1) qBittorrent’te torrentleri ekleyin (UI listeye düşer).
2) Loop yapmak istediğiniz torrent için listede **upload ikonu**na tıklayın ve `.torrent` dosyasını seçin.
   - Bu işlem torrent dosyasını arşivler.
   - **Arşiv yüklenmeden Loop Setup başlamaz.**
3) Allow IP, Loop sayısı ve Delay değerlerini girip **Start**’a basın.

## Kullanım (Timer)

1) Etiketleri qBittorrent’te oluşturun (radarr, tv-sonarr gibi).
2) Timer ekranında etiket seçip seed süresi kuralı ekleyin.
3) Süresi dolan torrentler qBittorrent ve diskten silinir.

## Production

```bash
./scripts/bootstrap.sh --prod-mode
```

Ardından http://localhost:3001

## Ortam Değişkenleri

- `QBIT_BASE_URL`, `QBIT_USERNAME`, `QBIT_PASSWORD`
- `APP_USERNAME`, `APP_PASSWORD`, `JWT_SECRET`
- `POLL_INTERVAL_MS`, `ENFORCE_INTERVAL_MS`, `DEFAULT_DELAY_MS`, `MAX_LOOP_LIMIT`
- `WEB_ALLOWED_HOSTS` (ör: `localhost,qbuffer.bee,qbuffer.panda`)
- `WSCRAPER_SERVICE_BASE_URL`, `WSCRAPER_SERVICE_TOKEN`

## Klasör Yapısı

- `apps/server`: Express API + socket.io
- `apps/web`: Vite React UI
- `data`: JSON DB, loglar, arşivlenen torrent dosyaları
