quasarr 2.4.8__tar.gz → 2.4.10__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of quasarr might be problematic. Click here for more details.
- {quasarr-2.4.8 → quasarr-2.4.10}/.github/workflows/HostnameRedaction.yml +1 -1
- quasarr-2.4.10/.github/workflows/PullRequests.yml +334 -0
- {quasarr-2.4.8 → quasarr-2.4.10}/.github/workflows/Release.yml +68 -12
- {quasarr-2.4.8 → quasarr-2.4.10}/.gitignore +1 -2
- quasarr-2.4.10/CONTRIBUTING.md +42 -0
- {quasarr-2.4.8 → quasarr-2.4.10}/PKG-INFO +4 -3
- {quasarr-2.4.8 → quasarr-2.4.10}/Quasarr.py +1 -1
- {quasarr-2.4.8 → quasarr-2.4.10}/README.md +2 -1
- {quasarr-2.4.8 → quasarr-2.4.10}/docker/Dockerfile +5 -4
- quasarr-2.4.10/maintenance.py +284 -0
- {quasarr-2.4.8 → quasarr-2.4.10}/pyproject.toml +13 -3
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/__init__.py +134 -70
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/api/__init__.py +40 -31
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/api/arr/__init__.py +116 -108
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/api/captcha/__init__.py +262 -137
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/api/config/__init__.py +76 -46
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/api/packages/__init__.py +138 -102
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/api/sponsors_helper/__init__.py +29 -16
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/api/statistics/__init__.py +19 -19
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/__init__.py +165 -72
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/linkcrypters/al.py +35 -18
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/linkcrypters/filecrypt.py +107 -52
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/linkcrypters/hide.py +5 -6
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/packages/__init__.py +342 -177
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/sources/al.py +191 -100
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/sources/by.py +31 -13
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/sources/dd.py +27 -14
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/sources/dj.py +1 -3
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/sources/dl.py +126 -71
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/sources/dt.py +11 -5
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/sources/dw.py +28 -14
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/sources/he.py +32 -24
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/sources/mb.py +19 -9
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/sources/nk.py +14 -10
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/sources/nx.py +8 -18
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/sources/sf.py +45 -20
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/sources/sj.py +1 -3
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/sources/sl.py +9 -5
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/sources/wd.py +32 -12
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/sources/wx.py +35 -21
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/providers/auth.py +42 -37
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/providers/cloudflare.py +28 -30
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/providers/hostname_issues.py +2 -1
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/providers/html_images.py +2 -2
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/providers/html_templates.py +22 -14
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/providers/imdb_metadata.py +149 -80
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/providers/jd_cache.py +131 -39
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/providers/log.py +1 -1
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/providers/myjd_api.py +260 -196
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/providers/notifications.py +53 -41
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/providers/obfuscated.py +9 -4
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/providers/sessions/al.py +71 -55
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/providers/sessions/dd.py +21 -14
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/providers/sessions/dl.py +30 -19
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/providers/sessions/nx.py +23 -14
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/providers/shared_state.py +292 -141
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/providers/statistics.py +75 -43
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/providers/utils.py +33 -27
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/providers/version.py +45 -14
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/providers/web_server.py +10 -5
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/search/__init__.py +30 -18
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/search/sources/al.py +124 -73
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/search/sources/by.py +110 -59
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/search/sources/dd.py +57 -35
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/search/sources/dj.py +69 -48
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/search/sources/dl.py +159 -100
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/search/sources/dt.py +110 -74
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/search/sources/dw.py +121 -61
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/search/sources/fx.py +108 -62
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/search/sources/he.py +78 -49
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/search/sources/mb.py +96 -48
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/search/sources/nk.py +80 -50
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/search/sources/nx.py +91 -62
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/search/sources/sf.py +171 -106
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/search/sources/sj.py +69 -48
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/search/sources/sl.py +115 -71
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/search/sources/wd.py +67 -44
- quasarr-2.4.10/quasarr/search/sources/wx.py +417 -0
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/storage/config.py +65 -52
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/storage/setup.py +238 -140
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/storage/sqlite_database.py +10 -4
- quasarr-2.4.10/uv.lock +431 -0
- quasarr-2.4.8/.github/workflows/Beta.yml +0 -240
- quasarr-2.4.8/.github/workflows/PrVersionBumpCheck.yml +0 -138
- quasarr-2.4.8/docker/dev-setup.md +0 -21
- quasarr-2.4.8/quasarr/search/sources/wx.py +0 -352
- {quasarr-2.4.8 → quasarr-2.4.10}/.github/FUNDING.yml +0 -0
- {quasarr-2.4.8 → quasarr-2.4.10}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {quasarr-2.4.8 → quasarr-2.4.10}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {quasarr-2.4.8 → quasarr-2.4.10}/LICENSE +0 -0
- {quasarr-2.4.8 → quasarr-2.4.10}/Quasarr.png +0 -0
- {quasarr-2.4.8 → quasarr-2.4.10}/docker/dev-services-compose.yml +0 -0
- {quasarr-2.4.8 → quasarr-2.4.10}/docker/docker-compose.yml +0 -0
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/linkcrypters/__init__.py +0 -0
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/downloads/sources/__init__.py +0 -0
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/providers/__init__.py +0 -0
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/providers/sessions/__init__.py +0 -0
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/search/sources/__init__.py +0 -0
- {quasarr-2.4.8 → quasarr-2.4.10}/quasarr/storage/__init__.py +0 -0
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
name: CI/CD & Beta Build
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
concurrency:
|
|
8
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
9
|
+
cancel-in-progress: true
|
|
10
|
+
|
|
11
|
+
env:
|
|
12
|
+
GHCR_ENDPOINT: "ghcr.io/rix1337/quasarr"
|
|
13
|
+
DESCRIPTION: "Quasarr connects JDownloader with Radarr, Sonarr and LazyLibrarian."
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
quality-check:
|
|
17
|
+
name: Check & Auto-Fix
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
permissions:
|
|
20
|
+
contents: write
|
|
21
|
+
pull-requests: write
|
|
22
|
+
actions: write
|
|
23
|
+
outputs:
|
|
24
|
+
changes_pushed: ${{ steps.manager.outputs.changes_pushed }}
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v6
|
|
27
|
+
with:
|
|
28
|
+
repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
|
|
29
|
+
ref: ${{ github.head_ref || github.ref_name }}
|
|
30
|
+
fetch-depth: 0
|
|
31
|
+
|
|
32
|
+
- name: Install uv
|
|
33
|
+
uses: astral-sh/setup-uv@v5
|
|
34
|
+
with:
|
|
35
|
+
enable-cache: true
|
|
36
|
+
|
|
37
|
+
# We just install python here so uv run has something to target
|
|
38
|
+
- run: uv python install 3.12
|
|
39
|
+
|
|
40
|
+
- name: Run Maintenance
|
|
41
|
+
id: manager
|
|
42
|
+
env:
|
|
43
|
+
GH_TOKEN: ${{ github.token }}
|
|
44
|
+
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
45
|
+
TARGET_REF: ${{ github.head_ref || github.ref_name }}
|
|
46
|
+
GITHUB_REPO: ${{ github.repository }}
|
|
47
|
+
WORKFLOW_NAME: ${{ github.workflow }}
|
|
48
|
+
run: |
|
|
49
|
+
uv run maintenance.py --ci
|
|
50
|
+
|
|
51
|
+
version:
|
|
52
|
+
needs: [ quality-check ]
|
|
53
|
+
if: needs.quality-check.outputs.changes_pushed != 'true' && (github.head_ref || github.ref_name) == 'dev'
|
|
54
|
+
runs-on: ubuntu-latest
|
|
55
|
+
outputs:
|
|
56
|
+
version: ${{ steps.version.outputs.version }}
|
|
57
|
+
steps:
|
|
58
|
+
- uses: actions/checkout@v6
|
|
59
|
+
- uses: actions/setup-python@v5
|
|
60
|
+
with:
|
|
61
|
+
python-version: '3.12'
|
|
62
|
+
- uses: astral-sh/setup-uv@v5
|
|
63
|
+
with:
|
|
64
|
+
enable-cache: true
|
|
65
|
+
- id: version
|
|
66
|
+
run: echo "version=$(uv run python quasarr/providers/version.py)" >> $GITHUB_OUTPUT
|
|
67
|
+
|
|
68
|
+
build-wheel:
|
|
69
|
+
needs: [ quality-check, version ]
|
|
70
|
+
if: needs.quality-check.outputs.changes_pushed != 'true' && (github.head_ref || github.ref_name) == 'dev'
|
|
71
|
+
runs-on: ubuntu-latest
|
|
72
|
+
outputs:
|
|
73
|
+
attestation-id: ${{ steps.attest.outputs.attestation-id }}
|
|
74
|
+
permissions:
|
|
75
|
+
contents: read
|
|
76
|
+
id-token: write
|
|
77
|
+
attestations: write
|
|
78
|
+
steps:
|
|
79
|
+
- uses: actions/checkout@v6
|
|
80
|
+
- uses: actions/setup-python@v5
|
|
81
|
+
with:
|
|
82
|
+
python-version: '3.12'
|
|
83
|
+
- uses: astral-sh/setup-uv@v5
|
|
84
|
+
with:
|
|
85
|
+
enable-cache: true
|
|
86
|
+
- run: uv build
|
|
87
|
+
- id: attest
|
|
88
|
+
uses: actions/attest-build-provenance@v2
|
|
89
|
+
with:
|
|
90
|
+
subject-path: "dist/*.whl"
|
|
91
|
+
- uses: actions/upload-artifact@v4
|
|
92
|
+
with:
|
|
93
|
+
name: wheel
|
|
94
|
+
path: ./dist/*
|
|
95
|
+
|
|
96
|
+
build-exe:
|
|
97
|
+
needs: [ quality-check, version ]
|
|
98
|
+
if: needs.quality-check.outputs.changes_pushed != 'true' && (github.head_ref || github.ref_name) == 'dev'
|
|
99
|
+
runs-on: windows-latest
|
|
100
|
+
env:
|
|
101
|
+
TMP: "D:\\a\\temp"
|
|
102
|
+
TEMP: "D:\\a\\temp"
|
|
103
|
+
steps:
|
|
104
|
+
- run: mkdir D:\a\temp -Force
|
|
105
|
+
- uses: actions/checkout@v6
|
|
106
|
+
- uses: actions/setup-python@v5
|
|
107
|
+
with:
|
|
108
|
+
python-version: '3.12'
|
|
109
|
+
|
|
110
|
+
- uses: astral-sh/setup-uv@v5
|
|
111
|
+
with:
|
|
112
|
+
enable-cache: true
|
|
113
|
+
cache-suffix: "win-build" # Isolate this cache from Linux builds if you share keys
|
|
114
|
+
|
|
115
|
+
# --- CACHE ---
|
|
116
|
+
- name: Cache PyInstaller Analysis
|
|
117
|
+
uses: actions/cache@v4
|
|
118
|
+
with:
|
|
119
|
+
path: |
|
|
120
|
+
build
|
|
121
|
+
~\AppData\Local\pyinstaller
|
|
122
|
+
# Invalidates cache only if dependencies (uv.lock) change
|
|
123
|
+
key: pyinstaller-analysis-${{ runner.os }}-${{ hashFiles('uv.lock') }}
|
|
124
|
+
restore-keys: |
|
|
125
|
+
pyinstaller-analysis-${{ runner.os }}-
|
|
126
|
+
|
|
127
|
+
- shell: powershell
|
|
128
|
+
run: Set-MpPreference -DisableRealtimeMonitoring $true
|
|
129
|
+
|
|
130
|
+
- run: uv sync --group build
|
|
131
|
+
|
|
132
|
+
# --- BUILD COMMAND ---
|
|
133
|
+
- run: |
|
|
134
|
+
uv run python -c "from PIL import Image; Image.open('Quasarr.png').save('Quasarr.ico')"
|
|
135
|
+
uv run python quasarr/providers/version.py --create-version-file
|
|
136
|
+
# 1. Removed '--clean'
|
|
137
|
+
# 2. Added '--workpath "build"' (Matches the cached path above)
|
|
138
|
+
# 3. Added '--distpath "dist"' (Explicit output folder)
|
|
139
|
+
uv run pyinstaller --onefile -y --version-file "file_version_info.txt" --workpath "build" --distpath "dist" --icon "Quasarr.ico" "Quasarr.py" -n "quasarr-${{ needs.version.outputs.version }}-standalone-win64"
|
|
140
|
+
|
|
141
|
+
- uses: actions/upload-artifact@v4
|
|
142
|
+
with:
|
|
143
|
+
name: exe-amd64
|
|
144
|
+
path: ./dist/*.exe
|
|
145
|
+
|
|
146
|
+
beta-release:
|
|
147
|
+
needs: [ version, build-wheel, build-exe ]
|
|
148
|
+
runs-on: ubuntu-latest
|
|
149
|
+
permissions: { contents: write }
|
|
150
|
+
steps:
|
|
151
|
+
- uses: actions/checkout@v6
|
|
152
|
+
with:
|
|
153
|
+
fetch-depth: 0
|
|
154
|
+
- uses: actions/download-artifact@v4
|
|
155
|
+
with:
|
|
156
|
+
name: wheel
|
|
157
|
+
path: ./wheel
|
|
158
|
+
- uses: actions/download-artifact@v4
|
|
159
|
+
with:
|
|
160
|
+
name: exe-amd64
|
|
161
|
+
path: ./exe-amd64
|
|
162
|
+
- id: changelog
|
|
163
|
+
uses: metcalfc/changelog-generator@v4.6.2
|
|
164
|
+
with:
|
|
165
|
+
myToken: ${{ secrets.GITHUB_TOKEN }}
|
|
166
|
+
- name: Create Release Body
|
|
167
|
+
run: |
|
|
168
|
+
echo "### Docker:" > release_body.md
|
|
169
|
+
echo "\`docker pull ${{ env.GHCR_ENDPOINT }}:beta\`" >> release_body.md
|
|
170
|
+
echo "### Python:" >> release_body.md
|
|
171
|
+
echo "\`uv tool upgrade quasarr\`" >> release_body.md
|
|
172
|
+
echo "### Changelog:" >> release_body.md
|
|
173
|
+
echo "${{ steps.changelog.outputs.changelog }}" >> release_body.md
|
|
174
|
+
echo "[Attestation](https://github.com/${{ github.repository }}/attestations/${{ needs.build-wheel.outputs.attestation-id }})" >> release_body.md
|
|
175
|
+
- uses: ncipollo/release-action@v1
|
|
176
|
+
with:
|
|
177
|
+
artifacts: "./wheel/*.whl,./exe-amd64/*.exe"
|
|
178
|
+
allowUpdates: true
|
|
179
|
+
removeArtifacts: true
|
|
180
|
+
replacesArtifacts: true
|
|
181
|
+
tag: beta
|
|
182
|
+
name: Beta Build
|
|
183
|
+
bodyFile: "release_body.md"
|
|
184
|
+
prerelease: true
|
|
185
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
186
|
+
|
|
187
|
+
build-docker-amd64:
|
|
188
|
+
needs: [ quality-check, version, build-wheel ]
|
|
189
|
+
if: needs.quality-check.outputs.changes_pushed != 'true' && (github.head_ref || github.ref_name) == 'dev'
|
|
190
|
+
runs-on: ubuntu-latest
|
|
191
|
+
steps:
|
|
192
|
+
- uses: actions/checkout@v6
|
|
193
|
+
- uses: actions/download-artifact@v4
|
|
194
|
+
with:
|
|
195
|
+
name: wheel
|
|
196
|
+
path: ./docker/dist
|
|
197
|
+
- uses: docker/setup-buildx-action@v3
|
|
198
|
+
- uses: docker/login-action@v3
|
|
199
|
+
with:
|
|
200
|
+
registry: ghcr.io
|
|
201
|
+
username: ${{ github.actor }}
|
|
202
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
203
|
+
- uses: docker/build-push-action@v6
|
|
204
|
+
with:
|
|
205
|
+
context: ./docker
|
|
206
|
+
platforms: linux/amd64
|
|
207
|
+
push: true
|
|
208
|
+
provenance: false
|
|
209
|
+
sbom: false
|
|
210
|
+
annotations: org.opencontainers.image.description=${{ env.DESCRIPTION }}
|
|
211
|
+
tags: |
|
|
212
|
+
${{ env.GHCR_ENDPOINT }}:beta-amd64
|
|
213
|
+
${{ env.GHCR_ENDPOINT }}:${{ needs.version.outputs.version }}-beta-amd64
|
|
214
|
+
build-args: VS=${{ needs.version.outputs.version }}
|
|
215
|
+
cache-from: type=gha,scope=beta-amd64
|
|
216
|
+
cache-to: type=gha,mode=max,scope=beta-amd64
|
|
217
|
+
|
|
218
|
+
build-docker-arm64:
|
|
219
|
+
needs: [ quality-check, version, build-wheel ]
|
|
220
|
+
if: needs.quality-check.outputs.changes_pushed != 'true' && (github.head_ref || github.ref_name) == 'dev'
|
|
221
|
+
runs-on: ubuntu-24.04-arm
|
|
222
|
+
steps:
|
|
223
|
+
- uses: actions/checkout@v6
|
|
224
|
+
- uses: actions/download-artifact@v4
|
|
225
|
+
with:
|
|
226
|
+
name: wheel
|
|
227
|
+
path: ./docker/dist
|
|
228
|
+
- uses: docker/setup-buildx-action@v3
|
|
229
|
+
- uses: docker/login-action@v3
|
|
230
|
+
with:
|
|
231
|
+
registry: ghcr.io
|
|
232
|
+
username: ${{ github.actor }}
|
|
233
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
234
|
+
- uses: docker/build-push-action@v6
|
|
235
|
+
with:
|
|
236
|
+
context: ./docker
|
|
237
|
+
platforms: linux/arm64
|
|
238
|
+
push: true
|
|
239
|
+
provenance: false
|
|
240
|
+
sbom: false
|
|
241
|
+
annotations: org.opencontainers.image.description=${{ env.DESCRIPTION }}
|
|
242
|
+
tags: |
|
|
243
|
+
${{ env.GHCR_ENDPOINT }}:beta-arm64
|
|
244
|
+
${{ env.GHCR_ENDPOINT }}:${{ needs.version.outputs.version }}-beta-arm64
|
|
245
|
+
build-args: VS=${{ needs.version.outputs.version }}
|
|
246
|
+
cache-from: type=gha,scope=beta-arm64
|
|
247
|
+
cache-to: type=gha,mode=max,scope=beta-arm64
|
|
248
|
+
|
|
249
|
+
merge-docker-manifest:
|
|
250
|
+
needs: [ version, build-docker-amd64, build-docker-arm64 ]
|
|
251
|
+
runs-on: ubuntu-latest
|
|
252
|
+
steps:
|
|
253
|
+
- uses: docker/setup-buildx-action@v3
|
|
254
|
+
- uses: docker/login-action@v3
|
|
255
|
+
with:
|
|
256
|
+
registry: ghcr.io
|
|
257
|
+
username: ${{ github.actor }}
|
|
258
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
259
|
+
- run: |
|
|
260
|
+
TAG_AMD64="${{ needs.version.outputs.version }}-beta-amd64"
|
|
261
|
+
TAG_ARM64="${{ needs.version.outputs.version }}-beta-arm64"
|
|
262
|
+
ANNOTATION="index:org.opencontainers.image.description=$DESCRIPTION"
|
|
263
|
+
|
|
264
|
+
docker buildx imagetools create -t ${{ env.GHCR_ENDPOINT }}:beta \
|
|
265
|
+
--annotation "$ANNOTATION" \
|
|
266
|
+
${{ env.GHCR_ENDPOINT }}:beta-amd64 \
|
|
267
|
+
${{ env.GHCR_ENDPOINT }}:beta-arm64
|
|
268
|
+
|
|
269
|
+
docker buildx imagetools create -t ${{ env.GHCR_ENDPOINT }}:${{ needs.version.outputs.version }}-beta \
|
|
270
|
+
--annotation "$ANNOTATION" \
|
|
271
|
+
${{ env.GHCR_ENDPOINT }}:${TAG_AMD64} \
|
|
272
|
+
${{ env.GHCR_ENDPOINT }}:${TAG_ARM64}
|
|
273
|
+
|
|
274
|
+
notify:
|
|
275
|
+
name: Notify Discord & PR
|
|
276
|
+
needs: [ quality-check, version, beta-release, merge-docker-manifest ]
|
|
277
|
+
# Only run if the build wasn't skipped by the auto-fixer and the release succeeded
|
|
278
|
+
if: needs.quality-check.outputs.changes_pushed != 'true' && needs.beta-release.result == 'success'
|
|
279
|
+
runs-on: ubuntu-latest
|
|
280
|
+
permissions:
|
|
281
|
+
pull-requests: write # Required to comment on the PR
|
|
282
|
+
contents: read
|
|
283
|
+
steps:
|
|
284
|
+
- uses: actions/checkout@v6
|
|
285
|
+
|
|
286
|
+
- name: Send Notifications
|
|
287
|
+
env:
|
|
288
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
289
|
+
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
|
290
|
+
VERSION: ${{ needs.version.outputs.version }}
|
|
291
|
+
REPO: ${{ github.repository }}
|
|
292
|
+
run: |
|
|
293
|
+
echo "Fetching release details..."
|
|
294
|
+
# Get the body of the release we just created (beta tag)
|
|
295
|
+
RELEASE_BODY=$(gh release view beta --json body --jq .body)
|
|
296
|
+
|
|
297
|
+
# --- 1. DISCORD NOTIFICATION ---
|
|
298
|
+
if [ -n "$DISCORD_WEBHOOK" ]; then
|
|
299
|
+
echo "Sending Discord Webhook..."
|
|
300
|
+
|
|
301
|
+
# Construct a JSON payload safely using jq (handles escaping quotes/newlines)
|
|
302
|
+
# We create a simple embed with the version and the release body
|
|
303
|
+
jq -n \
|
|
304
|
+
--arg title "🚀 New Beta Build: $VERSION" \
|
|
305
|
+
--arg desc "$RELEASE_BODY" \
|
|
306
|
+
--arg url "https://github.com/$REPO/releases/tag/beta" \
|
|
307
|
+
'{content: null, embeds: [{title: $title, description: $desc, url: $url, color: 5814783}]}' \
|
|
308
|
+
> discord_payload.json
|
|
309
|
+
|
|
310
|
+
curl -H "Content-Type: application/json" \
|
|
311
|
+
-d @discord_payload.json \
|
|
312
|
+
"$DISCORD_WEBHOOK"
|
|
313
|
+
else
|
|
314
|
+
echo "::warning::Skipping Discord notification (DISCORD_WEBHOOK secret not set)"
|
|
315
|
+
fi
|
|
316
|
+
|
|
317
|
+
# --- 2. PR COMMENT FALLBACK ---
|
|
318
|
+
# Find the PR associated with the commit that triggered this push
|
|
319
|
+
echo "Looking for associated PR..."
|
|
320
|
+
PR_NUMBER=$(gh pr list --search "${{ github.sha }}" --state merged --json number --jq '.[0].number')
|
|
321
|
+
|
|
322
|
+
if [ -n "$PR_NUMBER" ]; then
|
|
323
|
+
echo "Found PR #$PR_NUMBER. Posting comment..."
|
|
324
|
+
|
|
325
|
+
echo "## 🚀 Beta Release $VERSION is Live!" > pr_comment.md
|
|
326
|
+
echo "" >> pr_comment.md
|
|
327
|
+
echo "$RELEASE_BODY" >> pr_comment.md
|
|
328
|
+
echo "" >> pr_comment.md
|
|
329
|
+
echo "[View Release on GitHub](https://github.com/$REPO/releases/tag/beta)" >> pr_comment.md
|
|
330
|
+
|
|
331
|
+
gh pr comment "$PR_NUMBER" --body-file pr_comment.md
|
|
332
|
+
else
|
|
333
|
+
echo "No merged PR found for commit ${{ github.sha }}. Skipping PR comment."
|
|
334
|
+
fi
|
|
@@ -34,7 +34,6 @@ jobs:
|
|
|
34
34
|
uses: astral-sh/setup-uv@v5
|
|
35
35
|
with:
|
|
36
36
|
enable-cache: true
|
|
37
|
-
cache-dependency-glob: "pyproject.toml"
|
|
38
37
|
- name: Get Version
|
|
39
38
|
id: version
|
|
40
39
|
run: |
|
|
@@ -58,7 +57,6 @@ jobs:
|
|
|
58
57
|
uses: astral-sh/setup-uv@v5
|
|
59
58
|
with:
|
|
60
59
|
enable-cache: true
|
|
61
|
-
cache-dependency-glob: "pyproject.toml"
|
|
62
60
|
- name: Build wheel
|
|
63
61
|
run: uv build
|
|
64
62
|
- name: Generate artifact attestation
|
|
@@ -76,21 +74,33 @@ jobs:
|
|
|
76
74
|
runs-on: windows-latest
|
|
77
75
|
needs: version
|
|
78
76
|
env:
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
# We define a consistent build path to make caching reliable
|
|
78
|
+
BUILD_PATH: "build"
|
|
81
79
|
steps:
|
|
82
|
-
- name: Create Temp Dir
|
|
83
|
-
run: mkdir D:\a\temp -Force
|
|
84
80
|
- uses: actions/checkout@v6
|
|
85
81
|
- uses: actions/setup-python@v5
|
|
86
82
|
with:
|
|
87
83
|
python-version: '3.12'
|
|
88
84
|
|
|
85
|
+
# 1. Install uv with its own persistent cache
|
|
89
86
|
- name: Install uv
|
|
90
87
|
uses: astral-sh/setup-uv@v5
|
|
91
88
|
with:
|
|
92
89
|
enable-cache: true
|
|
93
|
-
cache-
|
|
90
|
+
cache-suffix: "win-build"
|
|
91
|
+
|
|
92
|
+
# 2. PyInstaller Caching
|
|
93
|
+
# We cache the local 'build' folder AND the global PyInstaller cache.
|
|
94
|
+
# The key invalidates if 'uv.lock' changes, forcing a re-analysis only when deps update.
|
|
95
|
+
- name: Cache PyInstaller Analysis
|
|
96
|
+
uses: actions/cache@v4
|
|
97
|
+
with:
|
|
98
|
+
path: |
|
|
99
|
+
build
|
|
100
|
+
~\AppData\Local\pyinstaller
|
|
101
|
+
key: pyinstaller-analysis-${{ runner.os }}-${{ hashFiles('uv.lock') }}
|
|
102
|
+
restore-keys: |
|
|
103
|
+
pyinstaller-analysis-${{ runner.os }}-
|
|
94
104
|
|
|
95
105
|
- name: Disable Windows Defender
|
|
96
106
|
shell: powershell
|
|
@@ -101,10 +111,14 @@ jobs:
|
|
|
101
111
|
uv sync --group build
|
|
102
112
|
|
|
103
113
|
- name: Build exe
|
|
114
|
+
# CHANGES:
|
|
115
|
+
# 1. Removed '--clean' (Critical for speed)
|
|
116
|
+
# 2. Added '--workpath' to point to our cached folder
|
|
117
|
+
# 3. Added '--distpath' explicitly
|
|
104
118
|
run: |
|
|
105
119
|
uv run python -c "from PIL import Image; Image.open('Quasarr.png').save('Quasarr.ico')"
|
|
106
120
|
uv run python quasarr/providers/version.py --create-version-file
|
|
107
|
-
uv run pyinstaller --
|
|
121
|
+
uv run pyinstaller --onefile -y --version-file "file_version_info.txt" --workpath "build" --distpath "dist" --icon "Quasarr.ico" "Quasarr.py" -n "quasarr-${{ needs.version.outputs.version }}-standalone-win64"
|
|
108
122
|
|
|
109
123
|
- uses: actions/upload-artifact@v4
|
|
110
124
|
with:
|
|
@@ -252,7 +266,6 @@ jobs:
|
|
|
252
266
|
uses: astral-sh/setup-uv@v5
|
|
253
267
|
with:
|
|
254
268
|
enable-cache: true
|
|
255
|
-
cache-dependency-glob: "pyproject.toml"
|
|
256
269
|
|
|
257
270
|
- name: Publish to PyPI
|
|
258
271
|
if: ${{ !inputs.skip_pypi }}
|
|
@@ -273,7 +286,11 @@ jobs:
|
|
|
273
286
|
fi
|
|
274
287
|
- name: Create Release Body
|
|
275
288
|
run: |
|
|
276
|
-
echo "###
|
|
289
|
+
echo "### Docker:" > release_body.md
|
|
290
|
+
echo "" >> release_body.md
|
|
291
|
+
echo "\`docker pull ${{ env.GHCR_ENDPOINT }}:latest\`" >> release_body.md
|
|
292
|
+
echo "" >> release_body.md
|
|
293
|
+
echo "### Python:" >> release_body.md
|
|
277
294
|
echo "" >> release_body.md
|
|
278
295
|
echo "\`uv tool upgrade quasarr\`" >> release_body.md
|
|
279
296
|
echo "" >> release_body.md
|
|
@@ -282,8 +299,6 @@ jobs:
|
|
|
282
299
|
echo "${{ steps.changelog.outputs.changelog }}" >> release_body.md
|
|
283
300
|
echo "" >> release_body.md
|
|
284
301
|
echo "[Attestation](https://github.com/${{ github.repository }}/attestations/${{ needs.build-wheel.outputs.attestation-id }})" >> release_body.md
|
|
285
|
-
echo "" >> release_body.md
|
|
286
|
-
echo "\`docker pull ${{ env.GHCR_ENDPOINT }}:latest\`" >> release_body.md
|
|
287
302
|
|
|
288
303
|
- name: Create Release
|
|
289
304
|
uses: ncipollo/release-action@v1
|
|
@@ -292,3 +307,44 @@ jobs:
|
|
|
292
307
|
artifactErrorsFailBuild: true
|
|
293
308
|
bodyFile: "release_body.md"
|
|
294
309
|
tag: v.${{ needs.version.outputs.version }}
|
|
310
|
+
|
|
311
|
+
notify:
|
|
312
|
+
name: Notify Discord
|
|
313
|
+
needs: [ version, release, merge-docker-manifest ]
|
|
314
|
+
if: always() && needs.release.result == 'success'
|
|
315
|
+
runs-on: ubuntu-latest
|
|
316
|
+
steps:
|
|
317
|
+
- uses: actions/checkout@v6
|
|
318
|
+
|
|
319
|
+
- name: Send Discord Webhook
|
|
320
|
+
env:
|
|
321
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
322
|
+
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
|
323
|
+
VERSION: ${{ needs.version.outputs.version }}
|
|
324
|
+
REPO: ${{ github.repository }}
|
|
325
|
+
run: |
|
|
326
|
+
# Use the exact tag format defined in the release job (v.X.X.X)
|
|
327
|
+
TAG="v.$VERSION"
|
|
328
|
+
echo "Fetching release details for $TAG..."
|
|
329
|
+
|
|
330
|
+
# Fetch the body from the release we just created
|
|
331
|
+
RELEASE_BODY=$(gh release view "$TAG" --json body --jq .body)
|
|
332
|
+
|
|
333
|
+
if [ -n "$DISCORD_WEBHOOK" ]; then
|
|
334
|
+
echo "Sending notification..."
|
|
335
|
+
|
|
336
|
+
# Construct JSON payload using jq
|
|
337
|
+
# Color 5763719 is 'Green'
|
|
338
|
+
jq -n \
|
|
339
|
+
--arg title "🚀 New Release: $TAG" \
|
|
340
|
+
--arg desc "$RELEASE_BODY" \
|
|
341
|
+
--arg url "https://github.com/$REPO/releases/tag/$TAG" \
|
|
342
|
+
'{content: null, embeds: [{title: $title, description: $desc, url: $url, color: 5763719}]}' \
|
|
343
|
+
> discord_payload.json
|
|
344
|
+
|
|
345
|
+
curl -H "Content-Type: application/json" \
|
|
346
|
+
-d @discord_payload.json \
|
|
347
|
+
"$DISCORD_WEBHOOK"
|
|
348
|
+
else
|
|
349
|
+
echo "::warning::Skipping Discord notification (DISCORD_WEBHOOK secret not set)"
|
|
350
|
+
fi
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Development Setup for Pull Requests
|
|
2
|
+
|
|
3
|
+
To test your changes before submitting a pull request:
|
|
4
|
+
|
|
5
|
+
**1. Prepare your Environment with `uv`**
|
|
6
|
+
|
|
7
|
+
Ensure you have the development tools (like `ruff`) installed and your environment synced:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
uv sync --group dev
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
**2. Run Quasarr with the `--internal_address` parameter**
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
uv run Quasarr.py --internal_address=http://<host-ip>:<port>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Replace `<host-ip>` and `<port>` with the scheme, IP, and port of your host machine.
|
|
20
|
+
The `--internal_address` parameter is **mandatory**.
|
|
21
|
+
|
|
22
|
+
**3. Start the required services using the `dev-services-compose.yml` file**
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
CONFIG_VOLUMES=/path/to/config docker-compose -f docker/dev-services-compose.yml up
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Replace `/path/to/config` with your desired configuration location.
|
|
29
|
+
The `CONFIG_VOLUMES` environment variable is **mandatory**.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
### Code Quality & Maintenance
|
|
34
|
+
|
|
35
|
+
The CI pipeline enforces strict code styling and import optimization. Please run this commands before pushing your
|
|
36
|
+
changes:
|
|
37
|
+
|
|
38
|
+
**Format code AND upgrade dependencies:**
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
uv run maintenance.py --upgrade
|
|
42
|
+
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: quasarr
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.10
|
|
4
4
|
Summary: Quasarr connects JDownloader with Radarr, Sonarr and LazyLibrarian. It also decrypts links protected by CAPTCHAs.
|
|
5
5
|
Author-email: rix1337 <rix1337@users.noreply.github.com>
|
|
6
6
|
License-File: LICENSE
|
|
@@ -11,7 +11,7 @@ Requires-Python: >=3.12
|
|
|
11
11
|
Requires-Dist: beautifulsoup4>=4.14.3
|
|
12
12
|
Requires-Dist: bottle>=0.13.4
|
|
13
13
|
Requires-Dist: dukpy>=0.5.0
|
|
14
|
-
Requires-Dist: pillow>=12.
|
|
14
|
+
Requires-Dist: pillow>=12.1.0
|
|
15
15
|
Requires-Dist: pycryptodomex>=3.23.0
|
|
16
16
|
Requires-Dist: requests>=2.32.5
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
@@ -243,11 +243,12 @@ Most feature requests can be satisfied by:
|
|
|
243
243
|
[here](https://github.com/rix1337/Quasarr/pulls).
|
|
244
244
|
- **Pull requests are welcome!** Especially for popular hostnames.
|
|
245
245
|
- A short guide to set up required dev services is found
|
|
246
|
-
|
|
246
|
+
[here](https://github.com/rix1337/Quasarr/blob/main/CONTRIBUTING.md).
|
|
247
247
|
- Always reach out on Discord before starting work on a new feature to prevent waste of time.
|
|
248
248
|
- Please follow the existing code style and project structure.
|
|
249
249
|
- Anti-bot measures must be circumvented fully by Quasarr. Thus, you will need to provide a working solution for new
|
|
250
250
|
CAPTCHA types by integrating it in the Quasarr Web UI.
|
|
251
|
+
The simplest CAPTCHA bypass involves creating a Tampermonkey user script.
|
|
251
252
|
- Please provide proof of functionality (screenshots/examples) when submitting your pull request.
|
|
252
253
|
|
|
253
254
|
# SponsorsHelper
|
|
@@ -225,11 +225,12 @@ Most feature requests can be satisfied by:
|
|
|
225
225
|
[here](https://github.com/rix1337/Quasarr/pulls).
|
|
226
226
|
- **Pull requests are welcome!** Especially for popular hostnames.
|
|
227
227
|
- A short guide to set up required dev services is found
|
|
228
|
-
|
|
228
|
+
[here](https://github.com/rix1337/Quasarr/blob/main/CONTRIBUTING.md).
|
|
229
229
|
- Always reach out on Discord before starting work on a new feature to prevent waste of time.
|
|
230
230
|
- Please follow the existing code style and project structure.
|
|
231
231
|
- Anti-bot measures must be circumvented fully by Quasarr. Thus, you will need to provide a working solution for new
|
|
232
232
|
CAPTCHA types by integrating it in the Quasarr Web UI.
|
|
233
|
+
The simplest CAPTCHA bypass involves creating a Tampermonkey user script.
|
|
233
234
|
- Please provide proof of functionality (screenshots/examples) when submitting your pull request.
|
|
234
235
|
|
|
235
236
|
# SponsorsHelper
|
|
@@ -13,13 +13,14 @@ COPY --from=uv /uv /usr/local/bin/uv
|
|
|
13
13
|
# install local package
|
|
14
14
|
COPY dist/*.whl /tmp/
|
|
15
15
|
|
|
16
|
-
#
|
|
16
|
+
# Configure uv to install tools in globally accessible paths
|
|
17
|
+
ENV UV_TOOL_DIR=/opt/uv-tools
|
|
18
|
+
ENV UV_TOOL_BIN_DIR=/usr/local/bin
|
|
19
|
+
|
|
20
|
+
# The binary will now automatically appear in /usr/local/bin
|
|
17
21
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
|
18
22
|
uv tool install /tmp/*.whl --force && rm /tmp/*.whl
|
|
19
23
|
|
|
20
|
-
# Ensure the binary is in the PATH
|
|
21
|
-
ENV PATH="/root/.local/bin:$PATH"
|
|
22
|
-
|
|
23
24
|
# volumes and ports
|
|
24
25
|
VOLUME /config
|
|
25
26
|
EXPOSE 8080
|