Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
143 commits
Select commit Hold shift + click to select a range
668c6f2
feat(ci): add GitHub Actions for Docker build and publish to GHCR and…
JohanDevl Mar 18, 2026
f3052bc
feat(docker): add docker-compose.yml with watcher mode and first-run …
JohanDevl Mar 18, 2026
7782e62
feat(validation): add tracker rule validators, dynamic piece sizing, …
JohanDevl Mar 18, 2026
ee7fa88
feat(upload): add EXCLUDED_TAGS to skip uploads by team tag
JohanDevl Mar 18, 2026
4c90d42
Merge pull request #1 from JohanDevl/feat/tracker-rules-validation
JohanDevl Mar 18, 2026
3d0a322
feat(watcher): add persistent state tracking to avoid reprocessing
JohanDevl Mar 18, 2026
9031645
fix(watcher): skip state persistence in dry-run mode (-noup/-noseed)
JohanDevl Mar 18, 2026
d176202
feat(watcher): write dry-run results to separate watcher_dryrun.json
JohanDevl Mar 18, 2026
d4eb555
update(docker): remove done volume and document watcher state files
JohanDevl Mar 18, 2026
a1eb35c
fix(docker): make venv world-executable for arbitrary UIDs
JohanDevl Mar 18, 2026
455bbd2
fix(docker): make home directory traversable for arbitrary UIDs
JohanDevl Mar 18, 2026
33812f1
fix(docker): set HOME env for arbitrary UIDs and remove unused destin…
JohanDevl Mar 18, 2026
cafe4da
fix(cache): use absolute paths for diskcache and prez file output
JohanDevl Mar 18, 2026
95391a2
fix(docker): handle EOFError on input() calls for non-interactive con…
JohanDevl Mar 18, 2026
eddaecc
feat(dry-run): count processed media as uploaded and handle all EOFEr…
JohanDevl Mar 18, 2026
10f5446
feat(dry-run): store normalized release name in watcher state
JohanDevl Mar 18, 2026
125b331
feat(watcher): add multi-folder support with per-folder qBittorrent c…
JohanDevl Mar 18, 2026
adff990
fix(normalizer): transliterate accented characters instead of strippi…
JohanDevl Mar 19, 2026
462bf4d
feat(category): detect animated content via TMDB genre and assign sep…
JohanDevl Mar 19, 2026
deaacc4
fix(normalizer): align release naming with updated tracker rules
JohanDevl Mar 19, 2026
7a22d6f
fix(normalizer): resolve 22 anomalies in release name normalization
JohanDevl Mar 20, 2026
60afe99
fix(normalizer): add NoTag fallback and clean separator/bitrate artif…
JohanDevl Mar 21, 2026
bfa7f2a
feat(validator): reject upscaled releases with ERROR severity
JohanDevl Mar 21, 2026
f1de5d3
feat(validator): reject uploads without a real release group
JohanDevl Mar 22, 2026
4a03f7a
feat(watcher): include validation report details in watcher JSON
JohanDevl Mar 22, 2026
d6a8df7
feat(watcher): add release source type to watcher JSON
JohanDevl Mar 22, 2026
333640a
fix(watcher): treat already_in_archive as uploaded and atomic state s…
JohanDevl Mar 22, 2026
7f3d30c
fix(settings): read version from VERSION file instead of hardcoded value
JohanDevl Mar 22, 2026
b9ec363
fix(qbittorrent): let category handle save path instead of forcing it
JohanDevl Mar 22, 2026
a803176
fix(trackers): correct video TYPE_ID mappings and infer source from r…
JohanDevl Mar 22, 2026
bc944ae
feat(prez): replace screenshot description with BBCode prez style 3
JohanDevl Mar 22, 2026
724964b
fix(settings): use importlib.metadata for version in installed packages
JohanDevl Mar 22, 2026
41c49d4
fix(watcher): preserve validation reports on dry-run re-runs
JohanDevl Mar 22, 2026
8078da3
fix(prez): use width-based resolution classification for quality label
JohanDevl Mar 22, 2026
d473845
fix(trackers): pass title instead of full path to filter_type to prev…
JohanDevl Mar 22, 2026
0c9907f
feat(torrent): add skip hash check option for qBittorrent
JohanDevl Mar 22, 2026
c1a5e7c
fix(settings): use model defaults for new torrent config attributes
JohanDevl Mar 22, 2026
5b6db02
fix(settings): handle empty string for QBIT_SKIP_HASH_CHECK in existi…
JohanDevl Mar 22, 2026
c7721ca
feat(web): add web dashboard for upload approval workflow
JohanDevl Mar 29, 2026
682a153
fix(settings): handle empty string for WEB_PORT in existing configs
JohanDevl Mar 29, 2026
33e29bd
fix(settings): handle empty string for WEB_HOST in existing configs
JohanDevl Mar 29, 2026
a33571c
fix(web): remove makedirs on read-only static dir, include templates …
JohanDevl Mar 29, 2026
89cb92b
fix(web): use new Starlette TemplateResponse API (request as first arg)
JohanDevl Mar 29, 2026
70b720f
fix(video): guard against None db.result before calling get_title()
JohanDevl Mar 29, 2026
26354bf
feat(web): modern dark dashboard with sidebar, interactive tables, re…
JohanDevl Mar 29, 2026
2735fa3
feat(web): add TMDB ID editing and rescan from item detail page
JohanDevl Mar 29, 2026
8bdeac0
feat(web): add save button to persist edits without approving or reje…
JohanDevl Mar 29, 2026
edd42a4
feat(web): add reason labels, status filter dropdown, fix date sorting
JohanDevl Mar 29, 2026
9613f1f
feat(web): add client-side pagination (25/50/100/250/All) on all tables
JohanDevl Mar 29, 2026
f357461
feat(web): add skip reason column with human-readable labels in pendi…
JohanDevl Mar 29, 2026
5885468
feat(web): show current page number in pagination (Page 1 of 3)
JohanDevl Mar 29, 2026
2d7e37c
fix(web): style disabled pagination buttons (opacity + no pointer)
JohanDevl Mar 29, 2026
70bc00b
feat(web): replace prompt() with animated modal for rejection reasons
JohanDevl Mar 29, 2026
8b946a4
fix(watcher): skip non-media files (.nfo, .txt, etc.) in watcher scan
JohanDevl Mar 29, 2026
2cc0ba9
fix(web): show generated NFO (cleaned mediainfo) instead of source NF…
JohanDevl Mar 29, 2026
fcd3a4f
fix(web): remove NFO source display from dashboard, avoid confusion w…
JohanDevl Mar 29, 2026
f2bc095
feat(web): add source type (type_id) correction dropdown in item detail
JohanDevl Mar 29, 2026
94f4f85
fix(web): use exact tracker type_id values with optgroups in source d…
JohanDevl Mar 29, 2026
5a94838
feat(web): add resolution correction dropdown with exact tracker values
JohanDevl Mar 29, 2026
ce55ac8
fix(web): restrict field editing (resolution, source, TMDB) to pendin…
JohanDevl Mar 29, 2026
b15c42d
feat(docker): add TZ environment variable for timezone support
JohanDevl Mar 29, 2026
5aafc81
fix(db): use localtime for discovered_at default to respect TZ env va…
JohanDevl Mar 29, 2026
2fbec21
feat(web): replace confirm alert with approve modal showing upload su…
JohanDevl Mar 29, 2026
c0ac05d
fix(api): make approve endpoint accept empty body to prevent 422 errors
JohanDevl Mar 29, 2026
cd7cba1
fix(web): format all dates as dd/mm/yyyy HH:MM instead of raw ISO tim…
JohanDevl Mar 29, 2026
2cf3746
feat(web): add full rescan button on pending items
JohanDevl Mar 29, 2026
ed97a51
fix(db): use Python datetime.now() for discovered_at instead of SQLit…
JohanDevl Mar 29, 2026
a6909c5
fix(web): use reason_label filter on item detail skip reason
JohanDevl Mar 29, 2026
a32c340
fix(web): robust datetime formatting for all ISO timestamp variants
JohanDevl Mar 29, 2026
220609a
feat(web): fetch TMDB title in French (fr-FR) with English fallback o…
JohanDevl Mar 29, 2026
2330b9d
fix(web): complete mobile responsive overhaul
JohanDevl Mar 29, 2026
332a807
fix(web): replace table scroll with card layout on mobile
JohanDevl Mar 29, 2026
b7135c8
fix(web): remove 480px table min-width causing mobile horizontal scroll
JohanDevl Mar 29, 2026
5b8784e
fix(web): force block display on table/tbody for mobile card layout
JohanDevl Mar 29, 2026
0462512
fix(web): break long release names in mobile card layout
JohanDevl Mar 29, 2026
6432016
fix(web): prevent detail page overflow on mobile with flex shrink and…
JohanDevl Mar 29, 2026
fbcd70f
fix(web): restore left-aligned info-table layout on mobile detail page
JohanDevl Mar 29, 2026
ebe9a06
feat(web): add multi-select column filters and mobile sort dropdown
JohanDevl Mar 30, 2026
b1b84a1
fix(web): preserve pending list pagination across HTMX refreshes
JohanDevl Mar 30, 2026
69a7e3c
fix(web): left-align validation table on mobile detail page
JohanDevl Mar 30, 2026
c54952f
fix(tmdb): use French language for API requests and fix rescan title …
JohanDevl Mar 30, 2026
229cd03
feat(web): add similar torrents link on detail page
JohanDevl Mar 30, 2026
f2f933d
fix(mediainfo): strip full path from Complete name in displayed media…
JohanDevl Mar 30, 2026
73584cd
feat(tmdb): fetch IMDb ID during discover via details/external_ids en…
JohanDevl Mar 30, 2026
60b8ee8
feat(web): add category adjustment on pending item detail page
JohanDevl Mar 30, 2026
ac44404
fix(web): preserve table sort state across HTMX pending refresh
JohanDevl Mar 30, 2026
8a685ec
feat(web): auto-update release name when TMDB ID is rescanned
JohanDevl Mar 30, 2026
6cc7ed0
fix(tmdb): add missing fields to ExternalIds dataclass for TMDB API c…
JohanDevl Mar 31, 2026
5400499
fix(web): redirect to pending page after approve/reject instead of hi…
JohanDevl Mar 31, 2026
0702130
fix(watcher): handle stale torrent archive causing false 'already upl…
JohanDevl Mar 31, 2026
4b06c27
fix(web): use full rescan instead of retry for skipped/rejected items
JohanDevl Mar 31, 2026
3abdd6d
feat(web): add season/episode display and editing for TV series
JohanDevl Mar 31, 2026
6fc1fcd
feat(web): add bulk reject UI for pending items list
JohanDevl Mar 31, 2026
568c771
feat(normalizer): use single-lang tags (VFF/VFQ/VOSTFR) for mono-trac…
JohanDevl Mar 31, 2026
71abe94
fix(media): accept season 0 and episode 0 for TV series uploads
JohanDevl Mar 31, 2026
70f1465
feat(web): add async upload queue with background worker and bulk app…
JohanDevl Apr 4, 2026
1a3259a
feat(web): add queue status page with sidebar badge and live refresh
JohanDevl Apr 4, 2026
0687d1f
feat(web): normalize separators in search bar for flexible name matching
JohanDevl Apr 4, 2026
5bbdfe2
feat(web): add upload-cloud favicon matching sidebar icon
JohanDevl Apr 4, 2026
5b209a2
chore: bump version to 0.12.0
JohanDevl Apr 5, 2026
e50d3bb
Merge pull request #2 from JohanDevl/develop
JohanDevl Apr 5, 2026
ada37d7
feat: add TMDB-based documentary detection mirroring anime pattern
JohanDevl Apr 5, 2026
0d21689
perf(watcher): reduce countdown loop wake-ups from 100/s to 1/s
JohanDevl Apr 5, 2026
114c081
feat(web): display human-readable category labels instead of raw values
JohanDevl Apr 5, 2026
3dda7c6
fix(watcher): break infinite loop on already_in_archive in web mode
JohanDevl Apr 6, 2026
b1f5b00
chore: bump version to 0.13.0
JohanDevl Apr 6, 2026
d2e071b
Merge pull request #3 from JohanDevl/develop
JohanDevl Apr 6, 2026
5a15750
feat(web): add cancel queued and reset uploaded item actions
JohanDevl Apr 6, 2026
790756e
feat(web): add visual analyzing indicator for watcher processing
JohanDevl Apr 6, 2026
9af502d
chore: bump version to 0.14.0
JohanDevl Apr 6, 2026
8afa8d8
Merge pull request #4 from JohanDevl/develop
JohanDevl Apr 8, 2026
ca8a23d
fix(normalizer): normalize SUBFRENCH to VOSTFR in release titles
JohanDevl Apr 9, 2026
0456d6b
chore: bump version to 0.15.0
JohanDevl Apr 9, 2026
fd153af
Merge pull request #5 from JohanDevl/develop
JohanDevl Apr 9, 2026
b81cacf
feat(packaging): make web dependencies optional via pip extras
JohanDevl Apr 9, 2026
18d4c90
feat(web): add track language editor and title-based language fallback
JohanDevl Apr 11, 2026
d5dc25a
feat(web): add season/episode editing to bulk approve modal for TV se…
JohanDevl Apr 11, 2026
3a48237
feat(web): add async bulk rescan queue with web visibility
JohanDevl Apr 11, 2026
8f787b9
update(web): replace native confirm with proper modal for bulk rescan
JohanDevl Apr 11, 2026
898a925
fix(web): batch all rescan transitions before enqueueing in bulk rescan
JohanDevl Apr 11, 2026
bd72633
fix(web): batch all transitions before enqueueing in bulk approve
JohanDevl Apr 11, 2026
967a6da
feat(web): add compliance menu to audit past upload naming against G3…
JohanDevl Apr 17, 2026
6d1abed
fix(web): copy-on-click compliance names + keep H.264/H.265 codec at end
JohanDevl Apr 17, 2026
650d413
fix(compliance): align normalizer & validators with G3MINI docs rules
JohanDevl Apr 17, 2026
23ee647
feat(web): show description & mediainfo in compliance detail modal
JohanDevl Apr 17, 2026
4855637
feat(web): regenerate prez-format description in compliance modal
JohanDevl Apr 17, 2026
90a8c2c
fix(compliance): read UnIT3D media_info/bd_info snake_case API keys
JohanDevl Apr 17, 2026
4a0bb2b
fix(compliance): flatten unwrapped torrent response and modal-ify rec…
JohanDevl Apr 17, 2026
7a265ec
update(web): auto-reload compliance page after single-row recheck
JohanDevl Apr 17, 2026
9e41948
fix(validator): treat x264/x265/AV1 tags as encode, not untouched
JohanDevl Apr 18, 2026
00f7247
fix(prez): normalize language tags with region and english names
JohanDevl Apr 18, 2026
0733e7c
feat(compliance): add regenerate button and per-track language editor
JohanDevl Apr 18, 2026
af5867d
feat(compliance): add ack/ignore buttons in modal with in-place statu…
JohanDevl Apr 21, 2026
41ef372
fix(tmdb): filter unknown kwargs before dataclass init
JohanDevl Apr 22, 2026
ffcf7d4
feat(compliance): add delete & rescan action with bulk selection
JohanDevl Apr 22, 2026
930cd2b
fix(prez): pre-select detected track language and add fr-CA/fr-BE
JohanDevl Apr 23, 2026
ade3a7c
feat(naming): inject TMDB year into series release names
JohanDevl May 1, 2026
5b8b8db
fix(naming): preserve VOF/VOQ/VOB tags in release names
JohanDevl May 1, 2026
ef10a65
fix(naming): prioritize MediaInfo Title VO markers over Language code
JohanDevl May 1, 2026
60a8ca2
feat(web): link duplicate match on tracker and add force-rescan action
JohanDevl May 5, 2026
f820ed0
fix(web): persist tracker_name on duplicate skip and add similar-url …
JohanDevl May 5, 2026
3e20058
chore: bump version to 0.16.0
JohanDevl May 6, 2026
cc9971e
Merge pull request #6 from JohanDevl/develop
JohanDevl May 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.git
.gitignore
__pycache__
*.py[cod]
*.egg-info
dist/
build/
.venv/
tests/
.github/
.claude/
CLAUDE.md
README.md
README.rst
LICENSE
.readthedocs.yaml
.DS_Store
Docker/
71 changes: 71 additions & 0 deletions .github/workflows/auto-tag.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Auto Tag on Version Change

on:
push:
branches:
- main
paths:
- 'VERSION'

permissions:
contents: write

jobs:
check-version:
name: Check for version change and create tag
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Get current version
id: current
run: |
VERSION=$(cat VERSION | tr -d '[:space:]')
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Current version: $VERSION"

- name: Get previous version
id: previous
run: |
git checkout HEAD^1 -- VERSION 2>/dev/null || echo "0.0.0" > VERSION
PREV_VERSION=$(cat VERSION | tr -d '[:space:]')
git checkout HEAD -- VERSION
echo "version=$PREV_VERSION" >> $GITHUB_OUTPUT
echo "Previous version: $PREV_VERSION"

- name: Check if version changed
id: changed
run: |
if [ "${{ steps.current.outputs.version }}" != "${{ steps.previous.outputs.version }}" ]; then
echo "changed=true" >> $GITHUB_OUTPUT
echo "Version changed: ${{ steps.previous.outputs.version }} -> ${{ steps.current.outputs.version }}"
else
echo "changed=false" >> $GITHUB_OUTPUT
echo "Version unchanged"
fi

- name: Check if tag exists
id: tag_exists
if: steps.changed.outputs.changed == 'true'
run: |
TAG="v${{ steps.current.outputs.version }}"
if git rev-parse "$TAG" >/dev/null 2>&1; then
echo "exists=true" >> $GITHUB_OUTPUT
echo "Tag $TAG already exists"
else
echo "exists=false" >> $GITHUB_OUTPUT
fi

- name: Create and push tag
if: steps.changed.outputs.changed == 'true' && steps.tag_exists.outputs.exists == 'false'
run: |
VERSION="${{ steps.current.outputs.version }}"
TAG="v$VERSION"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag -a "$TAG" -m "Release $VERSION"
git push origin "$TAG"
echo "Created tag: $TAG"
178 changes: 178 additions & 0 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
name: Build and Push Docker Image

on:
push:
branches:
- main
- develop
paths:
- "unit3dup/**"
- "common/**"
- "view/**"
- "requirements.txt"
- "pyproject.toml"
- "Docker/dockerfile"
- "VERSION"
- ".github/workflows/docker-publish.yml"
workflow_dispatch:
inputs:
tag:
description: "Image tag (default: latest)"
required: false
default: "latest"

env:
GHCR_IMAGE: ghcr.io/${{ vars.GHCR_USERNAME }}/${{ vars.REPO_NAME }}

jobs:
build:
runs-on: ${{ matrix.runner }}
permissions:
contents: read
packages: write

strategy:
fail-fast: false
matrix:
include:
- platform: linux/amd64
runner: ubuntu-24.04
cache-scope: amd64
# Uncomment to enable ARM64 builds (slower, uses native ARM runner)
# - platform: linux/arm64
# runner: ubuntu-24.04-arm
# cache-scope: arm64

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.GHCR_IMAGE }}

- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
context: .
file: Docker/dockerfile
platforms: ${{ matrix.platform }}
labels: ${{ steps.meta.outputs.labels }}
outputs: type=image,name=${{ env.GHCR_IMAGE }},push-by-digest=true,name-canonical=true,push=true
cache-from: type=gha,scope=${{ matrix.cache-scope }}
cache-to: type=gha,scope=${{ matrix.cache-scope }},mode=max
provenance: false

- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"

- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-${{ matrix.cache-scope }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1

merge:
runs-on: ubuntu-latest
needs: build
permissions:
contents: read
packages: write

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Download digests
uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Read VERSION file
id: version
run: |
VERSION=$(cat VERSION | tr -d '[:space:]')
echo "version=$VERSION" >> $GITHUB_OUTPUT

- name: Extract GHCR metadata
id: meta-ghcr
uses: docker/metadata-action@v5
with:
images: ${{ env.GHCR_IMAGE }}
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=raw,value=${{ steps.version.outputs.version }},enable={{is_default_branch}}
type=ref,event=branch
type=sha,prefix=
type=raw,value=${{ github.event.inputs.tag }},enable=${{ github.event_name == 'workflow_dispatch' }}

- name: Extract Docker Hub metadata
id: meta-dockerhub
uses: docker/metadata-action@v5
with:
images: ${{ secrets.DOCKERHUB_USERNAME }}/${{ vars.REPO_NAME }}
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=raw,value=${{ steps.version.outputs.version }},enable={{is_default_branch}}
type=ref,event=branch
type=sha,prefix=
type=raw,value=${{ github.event.inputs.tag }},enable=${{ github.event_name == 'workflow_dispatch' }}

- name: Create GHCR manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create \
$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< '${{ steps.meta-ghcr.outputs.json }}') \
$(printf '${{ env.GHCR_IMAGE }}@sha256:%s ' *)

# Copy multi-arch manifest from GHCR to Docker Hub without rebuilding
- name: Copy manifest to Docker Hub
run: |
GHCR_SOURCE="${{ env.GHCR_IMAGE }}:$(echo '${{ github.sha }}' | cut -c1-7)"
docker buildx imagetools create \
$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< '${{ steps.meta-dockerhub.outputs.json }}') \
"$GHCR_SOURCE"

- name: Inspect GHCR image
run: |
docker buildx imagetools inspect ${{ env.GHCR_IMAGE }}:${{ steps.meta-ghcr.outputs.version }}

- name: Inspect Docker Hub image
run: |
docker buildx imagetools inspect ${{ secrets.DOCKERHUB_USERNAME }}/${{ vars.REPO_NAME }}:${{ steps.meta-dockerhub.outputs.version }}
29 changes: 12 additions & 17 deletions Docker/dockerfile
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
# 02/05/2025
# Build "docker build -t unit3dup ." inside the Docker folder first
# Remove "docker images", "docker rmi -f unit3dup:latest"
# Build from repo root: docker build -t unit3dup -f Docker/dockerfile .

FROM python:3.11-slim

# Set the username as your Host
ARG USERNAME=pc

# environment
ENV HOME=/home/$USERNAME
ENV VIRTUAL_ENV=/home/$USERNAME/venv
ENV PATH="$VIRTUAL_ENV/bin:$PATH"

Expand All @@ -33,21 +32,17 @@ RUN groupadd -g 1000 $USERNAME && \
USER $USERNAME
WORKDIR /home/$USERNAME

# Upgrade pip
RUN pip install --upgrade pip
# Create virtual env and upgrade pip
RUN python3 -m venv $VIRTUAL_ENV && \
pip install --upgrade pip

# A new virtual env
RUN python3 -m venv $VIRTUAL_ENV

# Activate virtual
RUN . $VIRTUAL_ENV/bin/activate

# Copy .whl in the container
# COPY unit3dup-0.8.6-py3-none-any.whl /app/

# Install .whl
# RUN pip install --no-cache-dir /app/unit3dup-0.8.6-py3-none-any.whl
RUN pip install --no-cache-dir unit3dup
# Copy source and install from source
COPY --chown=$USERNAME:$USERNAME . /home/$USERNAME/app
WORKDIR /home/$USERNAME/app
RUN pip install --no-cache-dir ".[web]" && \
chmod o+rx /home/$USERNAME && \
chmod -R o+rX $VIRTUAL_ENV
WORKDIR /home/$USERNAME

# Set the entry point ( see pyproject.toml)
ENTRYPOINT ["unit3dup"]
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ cd ~/unit3dup
```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
pip install -e . # CLI only
pip install -e ".[web]" # CLI + web dashboard
```

L'option `-e` (editable) permet de recevoir les mises à jour du fork simplement avec un `git pull`, sans réinstaller.
Expand Down Expand Up @@ -146,7 +147,8 @@ Pas besoin de réinstaller grâce au mode `-e`. Si des nouvelles dépendances on

```bash
source .venv/bin/activate
pip install -e .
pip install -e . # CLI only
pip install -e ".[web]" # CLI + web dashboard
```

---
Expand Down
1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.16.0
6 changes: 4 additions & 2 deletions common/bittorrent.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@

@dataclass
class BittorrentData:
tracker_response: str
tracker_response: str | None
torrent_response: Mytorrent | None
content: Media
tracker_message: dict
tracker_message: dict | str
archive_path: str
release_name: str = ""
qbit_category: str | None = None
10 changes: 9 additions & 1 deletion common/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,12 @@ def __init__(self):
parser.add_argument("-personal", "--personal", action="store_true", help="Set to personal release")
parser.add_argument("-confirm", "--confirm", action="store_true",
help="Demande une validation manuelle du release_name avant chaque upload")
parser.add_argument("-skipval", "--skip_validation", action="store_true",
help="Skip tracker rule validation checks")

parser.add_argument("-ftp", "--ftp", action="store_true", help="Connect to FTP")
parser.add_argument("-web", "--web", action="store_true",
help="Start web dashboard (use with -watcher for full mode)")

# optional
parser.add_argument("-dump", "--dump", action="store_true", help="Download all torrent titles")
Expand Down Expand Up @@ -118,7 +122,11 @@ def __init__(self):
if self.args.force.lower() not in [ System.category_list[System.MOVIE],
System.category_list[System.GAME],
System.category_list[System.TV_SHOW],
System.category_list[System.DOCUMENTARY]]:
System.category_list[System.DOCUMENTARY],
System.category_list[System.ANIMATION],
System.category_list[System.TV_ANIMATION],
System.category_list[System.DOCUMENTARY_FILM],
System.category_list[System.TV_DOCUMENTARY]]:
self.args.force = None
print("Invalid -force category")
exit()
6 changes: 5 additions & 1 deletion common/external_services/ftpx/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,11 @@ def change_path(self, selected_folder: str):

def user_input_search(self):
custom_console.print("Search '->' ", end='', style='violet bold')
keyword = input()
try:
keyword = input()
except EOFError:
custom_console.bot_warning_log("No interactive input available, skipping search")
return
for item in self.page.get_items():
if keyword.lower() in item.name.lower():
custom_console.bot_question_log(
Expand Down
Loading