Compare commits

...

2 Commits

Author SHA1 Message Date
dcd66fdd11 feat(timer): diskten dosya silme seçeneği ekle
Timer kurallarına torrent silinirken dosyaların diskten de
silinip silinmeyeceğini belirleyen `deleteFiles` alanı eklendi.
Web arayüzüne ilgili ayar checkbox'ı eklendi. Varsayılan değer
dosyaları silmek (`true`) olarak ayarlandı. Torrent listesinde
eklenme tarihi görünümü eklendi.
2026-01-09 12:47:34 +03:00
ce1693cf4e docs: WEB_ALLOWED_HOSTS örneği güncelle 2026-01-09 12:46:24 +03:00
7 changed files with 36 additions and 2 deletions

View File

@@ -51,7 +51,7 @@ Ardından http://localhost:3001
- `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`)
- `WEB_ALLOWED_HOSTS` (ör: `localhost,qbuffer.bee,qbuffer.panda`)
## Klasör Yapısı

View File

@@ -10,6 +10,7 @@ const router = Router();
const ruleSchema = z.object({
tags: z.array(z.string().min(1)).min(1),
seedLimitSeconds: z.number().int().min(60).max(60 * 60 * 24 * 365),
deleteFiles: z.boolean().optional(),
});
router.get("/rules", async (_req, res) => {
@@ -27,6 +28,7 @@ router.post("/rules", async (req, res) => {
id: randomUUID(),
tags: parsed.data.tags,
seedLimitSeconds: parsed.data.seedLimitSeconds,
deleteFiles: parsed.data.deleteFiles ?? true,
createdAt: nowIso(),
};
db.timerRules = [...(db.timerRules ?? []), rule];

View File

@@ -1,4 +1,5 @@
export interface TimerRuleInput {
tags: string[];
seedLimitSeconds: number;
deleteFiles?: boolean;
}

View File

@@ -57,7 +57,7 @@ export const startTimerWorker = (qbit: QbitClient, intervalMs: number) => {
}
try {
await qbit.deleteTorrent(torrent.hash, true);
await qbit.deleteTorrent(torrent.hash, matchingRule.deleteFiles ?? true);
} catch (error) {
continue;
}

View File

@@ -74,6 +74,7 @@ export interface TimerRule {
id: string;
tags: string[];
seedLimitSeconds: number;
deleteFiles: boolean;
createdAt: string;
}

View File

@@ -67,6 +67,11 @@ const formatCountdown = (seconds: number) => {
return `${days}g ${pad(hours)}:${pad(minutes)}:${pad(secs)}`;
};
const formatAddedOn = (addedOn?: number) => {
if (!Number.isFinite(addedOn)) return "Bilinmiyor";
return new Date(addedOn * 1000).toLocaleString();
};
const trackerLabel = (tracker?: string) => {
if (!tracker) return "Bilinmiyor";
try {
@@ -91,6 +96,7 @@ export const TimerPage = () => {
const [seedUnit, setSeedUnit] = useState<(typeof unitOptions)[number]["value"]>(
"weeks"
);
const [deleteFiles, setDeleteFiles] = useState(true);
const [busy, setBusy] = useState(false);
const pushAlert = useUiStore((s) => s.pushAlert);
const [nowTick, setNowTick] = useState(() => Date.now());
@@ -225,9 +231,11 @@ export const TimerPage = () => {
const response = await api.post("/api/timer/rules", {
tags: selectedTags,
seedLimitSeconds,
deleteFiles,
});
setTimerRules([response.data, ...timerRules]);
setSelectedTags([]);
setDeleteFiles(true);
pushAlert({
title: "Kural kaydedildi",
description: "Timer kuralı aktif edildi.",
@@ -322,6 +330,9 @@ export const TimerPage = () => {
.filter(Boolean)
.join(", ") || "-"}
</div>
<div className="truncate">
Added: {formatAddedOn(torrent.added_on)}
</div>
</div>
</div>
))}
@@ -439,6 +450,20 @@ export const TimerPage = () => {
</select>
</div>
</div>
<label className="flex items-start gap-2 text-sm text-slate-700">
<input
type="checkbox"
checked={deleteFiles}
onChange={(event) => setDeleteFiles(event.target.checked)}
className="mt-1 h-4 w-4 rounded border-slate-300 text-slate-900"
/>
<span>
Dosyayı Disk'ten Kaldır
<span className="block text-xs text-slate-500">
İşaretli değilse torrent sadece qBittorrent'tan kaldırılır, dosya disk üzerinde kalır.
</span>
</span>
</label>
<Button onClick={handleSaveRule} disabled={busy}>
{busy ? "Kaydediliyor..." : "Kuralı Kaydet"}
</Button>
@@ -464,6 +489,10 @@ export const TimerPage = () => {
</div>
<div className="text-xs text-slate-500">
Seed limiti: {formatDuration(rule.seedLimitSeconds)}
{" • "}
{rule.deleteFiles ?? true
? "Silme: Disk + qBittorrent"
: "Silme: Sadece qBittorrent"}
</div>
</div>
<AlertDialog>

View File

@@ -54,6 +54,7 @@ export interface TimerRule {
id: string;
tags: string[];
seedLimitSeconds: number;
deleteFiles?: boolean;
createdAt: string;
}