yamcps-arr 0.1.0__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.
@@ -0,0 +1,71 @@
1
+ """Validate the exact ARR-package artifacts before uploading them to PyPI."""
2
+
3
+ import argparse
4
+ import tarfile
5
+ import zipfile
6
+ from email.parser import BytesParser
7
+ from pathlib import Path
8
+
9
+
10
+ def _wheel_metadata(path: Path) -> bytes:
11
+ with zipfile.ZipFile(path) as wheel:
12
+ names = wheel.namelist()
13
+ metadata_paths = [name for name in names if name.endswith(".dist-info/METADATA")]
14
+ if len(metadata_paths) != 1 or any(
15
+ not name.startswith(("yamcps_arr/", "yamcps_arr-")) for name in names
16
+ ):
17
+ raise ValueError("Wheel must contain only the ARR package")
18
+ return wheel.read(metadata_paths[0])
19
+
20
+
21
+ def _source_metadata(path: Path) -> bytes:
22
+ with tarfile.open(path, "r:gz") as archive:
23
+ members = [
24
+ m
25
+ for m in archive.getmembers()
26
+ if m.name.count("/") == 1 and m.name.endswith("/PKG-INFO")
27
+ ]
28
+ if len(members) != 1:
29
+ raise ValueError("Expected one root source metadata file")
30
+ stream = archive.extractfile(members[0])
31
+ if stream is None:
32
+ raise ValueError("Missing source metadata")
33
+ with stream:
34
+ return stream.read()
35
+
36
+
37
+ def verify(directory: Path, tag: str) -> None:
38
+ """Require exactly one yamcps-arr wheel and sdist matching a v-prefixed tag.
39
+
40
+ Args:
41
+ directory: Dedicated output directory for the root package build.
42
+ tag: GitHub release tag, such as v0.1.0.
43
+
44
+ Raises:
45
+ ValueError: Unexpected artifacts, distribution name or version.
46
+ """
47
+ files = sorted(directory.iterdir())
48
+ wheels = [p for p in files if p.name.endswith(".whl")]
49
+ sources = [p for p in files if p.name.endswith(".tar.gz")]
50
+ if len(files) != 2 or len(wheels) != 1 or len(sources) != 1:
51
+ raise ValueError("Expected exactly one ARR wheel and one source archive")
52
+ if not tag.startswith("v") or not tag[1:]:
53
+ raise ValueError("Release tag must have the form v<package-version>")
54
+ metadata = [_wheel_metadata(wheels[0]), _source_metadata(sources[0])]
55
+ for raw in metadata:
56
+ message = BytesParser().parsebytes(raw)
57
+ if message["Name"] != "yamcps-arr" or message["Version"] != tag[1:]:
58
+ raise ValueError("Only yamcps-arr matching the release tag may be published")
59
+
60
+
61
+ def main() -> None:
62
+ """Validate a build directory against its release tag."""
63
+ parser = argparse.ArgumentParser(description=__doc__)
64
+ parser.add_argument("directory", type=Path)
65
+ parser.add_argument("--tag", required=True)
66
+ args = parser.parse_args()
67
+ verify(args.directory, args.tag)
68
+
69
+
70
+ if __name__ == "__main__":
71
+ main()
@@ -0,0 +1,65 @@
1
+ name: Publish yamcps-arr to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ concurrency:
11
+ group: pypi-${{ github.event.release.tag_name }}
12
+ cancel-in-progress: false
13
+
14
+ jobs:
15
+ build:
16
+ name: Build ARR distribution
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+ with:
21
+ ref: ${{ github.event.release.tag_name }}
22
+ fetch-depth: 0
23
+ persist-credentials: false
24
+ - uses: actions/setup-python@v6
25
+ with:
26
+ python-version: '3.12'
27
+ - name: Verify release is based on main
28
+ run: git merge-base --is-ancestor HEAD origin/main
29
+ - name: Install build tools
30
+ run: python -m pip install build twine
31
+ # hatch-vcs reads the release tag from the complete Git history above.
32
+ # Keep the metadata check below: an inferred development version must not be published.
33
+ - name: Build ARR package
34
+ run: python -m build --outdir dist/arr .
35
+ - name: Validate distribution identity and release version
36
+ env:
37
+ RELEASE_TAG: ${{ github.event.release.tag_name }}
38
+ run: python .github/workflows/verify_release.py dist/arr --tag "$RELEASE_TAG"
39
+ - name: Check PyPI metadata
40
+ run: python -m twine check --strict dist/arr/*
41
+ - uses: actions/upload-artifact@v4
42
+ with:
43
+ name: yamcps-arr-distributions
44
+ path: dist/arr/*
45
+ if-no-files-found: error
46
+ retention-days: 7
47
+
48
+ publish:
49
+ name: Publish ARR distribution
50
+ needs: build
51
+ runs-on: ubuntu-latest
52
+ environment:
53
+ name: pypi
54
+ url: https://pypi.org/p/yamcps-arr
55
+ permissions:
56
+ id-token: write
57
+ steps:
58
+ - uses: actions/download-artifact@v4
59
+ with:
60
+ name: yamcps-arr-distributions
61
+ path: dist/arr
62
+ - name: Publish yamcps-arr only
63
+ uses: pypa/gh-action-pypi-publish@release/v1
64
+ with:
65
+ packages-dir: dist/arr/
@@ -0,0 +1,220 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ *.lcov
51
+ .hypothesis/
52
+ .pytest_cache/
53
+ cover/
54
+
55
+ # Translations
56
+ *.mo
57
+ *.pot
58
+
59
+ # Django stuff:
60
+ *.log
61
+ local_settings.py
62
+ db.sqlite3
63
+ db.sqlite3-journal
64
+
65
+ # Flask stuff:
66
+ instance/
67
+ .webassets-cache
68
+
69
+ # Scrapy stuff:
70
+ .scrapy
71
+
72
+ # Sphinx documentation
73
+ docs/_build/
74
+
75
+ # PyBuilder
76
+ .pybuilder/
77
+ target/
78
+
79
+ # Jupyter Notebook
80
+ .ipynb_checkpoints
81
+
82
+ # IPython
83
+ profile_default/
84
+ ipython_config.py
85
+
86
+ # pyenv
87
+ # For a library or package, you might want to ignore these files since the code is
88
+ # intended to run in multiple environments; otherwise, check them in:
89
+ # .python-version
90
+
91
+ # pipenv
92
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
93
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
94
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
95
+ # install all needed dependencies.
96
+ # Pipfile.lock
97
+
98
+ # uv
99
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
100
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
101
+ # commonly ignored for libraries.
102
+ # uv.lock
103
+
104
+ # poetry
105
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
106
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
107
+ # commonly ignored for libraries.
108
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
109
+ # poetry.lock
110
+ # poetry.toml
111
+
112
+ # pdm
113
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
114
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
115
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
116
+ # pdm.lock
117
+ # pdm.toml
118
+ .pdm-python
119
+ .pdm-build/
120
+
121
+ # pixi
122
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
123
+ # pixi.lock
124
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
125
+ # in the .venv directory. It is recommended not to include this directory in version control.
126
+ .pixi/*
127
+ !.pixi/config.toml
128
+
129
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
130
+ __pypackages__/
131
+
132
+ # Celery stuff
133
+ celerybeat-schedule*
134
+ celerybeat.pid
135
+
136
+ # Redis
137
+ *.rdb
138
+ *.aof
139
+ *.pid
140
+
141
+ # RabbitMQ
142
+ mnesia/
143
+ rabbitmq/
144
+ rabbitmq-data/
145
+
146
+ # ActiveMQ
147
+ activemq-data/
148
+
149
+ # SageMath parsed files
150
+ *.sage.py
151
+
152
+ # Environments
153
+ .env
154
+ .envrc
155
+ .venv
156
+ env/
157
+ venv/
158
+ ENV/
159
+ env.bak/
160
+ venv.bak/
161
+
162
+ # Spyder project settings
163
+ .spyderproject
164
+ .spyproject
165
+
166
+ # Rope project settings
167
+ .ropeproject
168
+
169
+ # mkdocs/Zensical documentation
170
+ /site
171
+
172
+ # mypy
173
+ .mypy_cache/
174
+ .dmypy.json
175
+ dmypy.json
176
+
177
+ # Pyre type checker
178
+ .pyre/
179
+
180
+ # pytype static type analyzer
181
+ .pytype/
182
+
183
+ # Cython debug symbols
184
+ cython_debug/
185
+
186
+ # PyCharm
187
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
188
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
189
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
190
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
191
+ # .idea/
192
+
193
+ # Abstra
194
+ # Abstra is an AI-powered process automation framework.
195
+ # Ignore directories containing user credentials, local state, and settings.
196
+ # Learn more at https://abstra.io/docs
197
+ .abstra/
198
+
199
+ # Visual Studio Code
200
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore that
201
+ # can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
202
+ # and can be added to the global gitignore or merged into this file. However, if you prefer, you
203
+ # could uncomment the following to ignore the entire vscode folder
204
+ # .vscode/
205
+ # Temporary file for partial code execution
206
+ tempCodeRunnerFile.py
207
+
208
+ # Ruff stuff:
209
+ .ruff_cache/
210
+
211
+ # PyPI configuration file
212
+ .pypirc
213
+
214
+ # Marimo
215
+ marimo/_static/
216
+ marimo/_lsp/
217
+ __marimo__/
218
+
219
+ # Streamlit
220
+ .streamlit/secrets.toml
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 JoReci
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,123 @@
1
+ Metadata-Version: 2.5
2
+ Name: yamcps-arr
3
+ Version: 0.1.0
4
+ Summary: Unified Sonarr, Radarr and Prowlarr connector for yamcps
5
+ Project-URL: Repository, https://github.com/JoReci2/yamcps-arr
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Requires-Python: >=3.12
9
+ Requires-Dist: httpx<1,>=0.28
10
+ Requires-Dist: yamcps>=0.1
11
+ Provides-Extra: dev
12
+ Requires-Dist: bandit; extra == 'dev'
13
+ Requires-Dist: build; extra == 'dev'
14
+ Requires-Dist: coverage; extra == 'dev'
15
+ Requires-Dist: editables; extra == 'dev'
16
+ Requires-Dist: hatch-vcs<1,>=0.4; extra == 'dev'
17
+ Requires-Dist: hatchling; extra == 'dev'
18
+ Requires-Dist: mypy; extra == 'dev'
19
+ Requires-Dist: pytest-asyncio>=1; extra == 'dev'
20
+ Requires-Dist: pytest>=8; extra == 'dev'
21
+ Requires-Dist: radon; extra == 'dev'
22
+ Requires-Dist: ruff; extra == 'dev'
23
+ Description-Content-Type: text/markdown
24
+
25
+ # yamcps-arr
26
+
27
+ ## Description
28
+
29
+ Plugin unique pour Sonarr, Radarr et Prowlarr : bibliothèques, ajouts et recherches
30
+ pour films et séries, consultation des indexeurs et recherche de releases.
31
+ Les trois services sont configurés ensemble sous l’identifiant `arr`.
32
+ Voir [la contribution](contributing.md) et [la migration](MIGRATION.md).
33
+
34
+ ## Quickstart
35
+
36
+ Python ≥ 3.12, moteur yamcps compatible et instances des trois services requis.
37
+ Depuis la racine du dépôt :
38
+
39
+ ```sh
40
+ python -m pip install -e .
41
+ yamcps connectors list
42
+ yamcps secrets set --connector arr
43
+ yamcps serve --connector arr
44
+ ```
45
+
46
+ L’assistant demande les URL et clés API des trois services dans le terminal et
47
+ les conserve dans le coffre chiffré. Aucun appel réseau n’est fait au démarrage.
48
+ Lire `skill://arr-sonarr-manage/SKILL.md`, `skill://arr-radarr-manage/SKILL.md`
49
+ ou `skill://arr-prowlarr-search/SKILL.md` depuis le client MCP. Par exemple,
50
+ appeler `arr_sonarr_system_status` pour vérifier Sonarr après configuration.
51
+ Pour une installation existante, suivre [MIGRATION.md](MIGRATION.md).
52
+ Les tests utilisent des API simulées. Guides : [Sonarr](docs/sonarr.md),
53
+ [Radarr](docs/radarr.md), [Prowlarr](docs/prowlarr.md).
54
+
55
+ ## Outils
56
+
57
+ | Outil | Description |
58
+ | --- | --- |
59
+ | `arr_sonarr_system_status` | Version et état de l’instance |
60
+ | `arr_sonarr_list_series` | Bibliothèque, filtre facultatif sur le titre |
61
+ | `arr_sonarr_get_series` | Détails d’une série par identifiant Sonarr |
62
+ | `arr_sonarr_list_episodes` | Épisodes d’une série, saison facultative |
63
+ | `arr_sonarr_calendar` | Épisodes diffusés entre deux dates |
64
+ | `arr_sonarr_queue` | File de téléchargements, avec pagination |
65
+ | `arr_sonarr_lookup_series` | Recherche dans le catalogue par titre ou `tvdb:<id>` |
66
+ | `arr_sonarr_quality_profiles` | Profils qualité existants |
67
+ | `arr_sonarr_root_folders` | Dossiers racines existants |
68
+ | `arr_sonarr_add_series` | Ajout à partir d’un identifiant TVDB, d’un profil et d’un dossier racine |
69
+ | `arr_sonarr_search_series` | Recherche active d’épisodes pour une série existante |
70
+ | `arr_sonarr_search_episodes` | Recherche active d’épisodes par identifiants Sonarr |
71
+ | `arr_sonarr_command_status` | Suivi d’une recherche asynchrone par identifiant de commande |
72
+ | `arr_radarr_system_status` | Version et état de l’instance |
73
+ | `arr_radarr_list_movies` | Bibliothèque, filtre facultatif sur le titre |
74
+ | `arr_radarr_get_movie` | Détails d’un film par identifiant Radarr |
75
+ | `arr_radarr_calendar` | Sorties entre deux dates explicites |
76
+ | `arr_radarr_queue` | File de téléchargements avec pagination |
77
+ | `arr_radarr_lookup_movies` | Recherche de catalogue par titre ou `tmdb:<id>` |
78
+ | `arr_radarr_quality_profiles` | Profils qualité existants |
79
+ | `arr_radarr_root_folders` | Dossiers racines existants |
80
+ | `arr_radarr_add_movie` | Ajout par identifiant TMDB, profil qualité et dossier racine |
81
+ | `arr_radarr_search_movies` | Recherche active pour des identifiants Radarr existants |
82
+ | `arr_radarr_command_status` | Suivi d’une recherche asynchrone |
83
+ | `arr_prowlarr_system_status` | Version et informations publiques d’exécution |
84
+ | `arr_prowlarr_list_indexers` | Métadonnées et capacités des indexeurs configurés |
85
+ | `arr_prowlarr_get_indexer` | Métadonnées d’un indexeur par identifiant |
86
+ | `arr_prowlarr_indexer_status` | Derniers échecs et désactivations temporaires |
87
+ | `arr_prowlarr_categories` | Identifiants et hiérarchie des catégories |
88
+ | `arr_prowlarr_search` | Recherche de releases, sans téléchargement |
89
+ | `arr_prowlarr_history` | Historique paginé, filtrable par indexeurs |
90
+ | `arr_prowlarr_health` | Sources et sévérité des contrôles de santé |
91
+ | `arr_prowlarr_statistics` | Compteurs et temps de réponse par indexeur |
92
+ | `arr_prowlarr_applications` | Noms et niveau de synchronisation des applications liées |
93
+
94
+ Sonarr/Radarr : ajout et recherche active peuvent déclencher des téléchargements.
95
+ Prowlarr : recherche sans envoi au téléchargement, avec consommation possible des
96
+ quotas des fournisseurs. Consulter les guides de chaque service.
97
+
98
+ ## Skills
99
+
100
+ | Skill | Description |
101
+ | --- | --- |
102
+ | [arr-sonarr-manage](src/yamcps_arr/sonarr/skills/arr-sonarr-manage/SKILL.md) | Browse Sonarr series, episodes and downloads, find and add series, and launch episode searches. |
103
+ | [arr-radarr-manage](src/yamcps_arr/radarr/skills/arr-radarr-manage/SKILL.md) | Browse Radarr movies and downloads, find and add movies, and launch movie searches. |
104
+ | [arr-prowlarr-search](src/yamcps_arr/prowlarr/skills/arr-prowlarr-search/SKILL.md) | Inspect Prowlarr indexers, categories, history and health, and search releases without downloading. |
105
+
106
+ ## Variable de configuration
107
+
108
+ | Variable | Nom du champ | Description | Obligatoire | Valeur par défaut |
109
+ | --- | --- | --- | --- | --- |
110
+ | Aucune | — | — | — | — |
111
+
112
+ ## Secret
113
+
114
+ | Secret | Nom du champ | Description | Obligatoire |
115
+ | --- | --- | --- | --- |
116
+ | `YAMCPS_ARR_SONARR_URL` | `sonarr-url` | URL de l’instance sans identifiants ni suffixe API | Oui |
117
+ | `YAMCPS_ARR_SONARR_API_KEY` | `sonarr-api-key` | Clé API de l’instance | Oui |
118
+ | `YAMCPS_ARR_RADARR_URL` | `radarr-url` | URL de l’instance sans identifiants ni suffixe API | Oui |
119
+ | `YAMCPS_ARR_RADARR_API_KEY` | `radarr-api-key` | Clé API de l’instance | Oui |
120
+ | `YAMCPS_ARR_PROWLARR_URL` | `prowlarr-url` | URL de l’instance sans identifiants ni suffixe API | Oui |
121
+ | `YAMCPS_ARR_PROWLARR_API_KEY` | `prowlarr-api-key` | Clé API de l’instance | Oui |
122
+
123
+ Les six champs sont requis par `arr` et configurés via le vault.
@@ -0,0 +1,99 @@
1
+ # yamcps-arr
2
+
3
+ ## Description
4
+
5
+ Plugin unique pour Sonarr, Radarr et Prowlarr : bibliothèques, ajouts et recherches
6
+ pour films et séries, consultation des indexeurs et recherche de releases.
7
+ Les trois services sont configurés ensemble sous l’identifiant `arr`.
8
+ Voir [la contribution](contributing.md) et [la migration](MIGRATION.md).
9
+
10
+ ## Quickstart
11
+
12
+ Python ≥ 3.12, moteur yamcps compatible et instances des trois services requis.
13
+ Depuis la racine du dépôt :
14
+
15
+ ```sh
16
+ python -m pip install -e .
17
+ yamcps connectors list
18
+ yamcps secrets set --connector arr
19
+ yamcps serve --connector arr
20
+ ```
21
+
22
+ L’assistant demande les URL et clés API des trois services dans le terminal et
23
+ les conserve dans le coffre chiffré. Aucun appel réseau n’est fait au démarrage.
24
+ Lire `skill://arr-sonarr-manage/SKILL.md`, `skill://arr-radarr-manage/SKILL.md`
25
+ ou `skill://arr-prowlarr-search/SKILL.md` depuis le client MCP. Par exemple,
26
+ appeler `arr_sonarr_system_status` pour vérifier Sonarr après configuration.
27
+ Pour une installation existante, suivre [MIGRATION.md](MIGRATION.md).
28
+ Les tests utilisent des API simulées. Guides : [Sonarr](docs/sonarr.md),
29
+ [Radarr](docs/radarr.md), [Prowlarr](docs/prowlarr.md).
30
+
31
+ ## Outils
32
+
33
+ | Outil | Description |
34
+ | --- | --- |
35
+ | `arr_sonarr_system_status` | Version et état de l’instance |
36
+ | `arr_sonarr_list_series` | Bibliothèque, filtre facultatif sur le titre |
37
+ | `arr_sonarr_get_series` | Détails d’une série par identifiant Sonarr |
38
+ | `arr_sonarr_list_episodes` | Épisodes d’une série, saison facultative |
39
+ | `arr_sonarr_calendar` | Épisodes diffusés entre deux dates |
40
+ | `arr_sonarr_queue` | File de téléchargements, avec pagination |
41
+ | `arr_sonarr_lookup_series` | Recherche dans le catalogue par titre ou `tvdb:<id>` |
42
+ | `arr_sonarr_quality_profiles` | Profils qualité existants |
43
+ | `arr_sonarr_root_folders` | Dossiers racines existants |
44
+ | `arr_sonarr_add_series` | Ajout à partir d’un identifiant TVDB, d’un profil et d’un dossier racine |
45
+ | `arr_sonarr_search_series` | Recherche active d’épisodes pour une série existante |
46
+ | `arr_sonarr_search_episodes` | Recherche active d’épisodes par identifiants Sonarr |
47
+ | `arr_sonarr_command_status` | Suivi d’une recherche asynchrone par identifiant de commande |
48
+ | `arr_radarr_system_status` | Version et état de l’instance |
49
+ | `arr_radarr_list_movies` | Bibliothèque, filtre facultatif sur le titre |
50
+ | `arr_radarr_get_movie` | Détails d’un film par identifiant Radarr |
51
+ | `arr_radarr_calendar` | Sorties entre deux dates explicites |
52
+ | `arr_radarr_queue` | File de téléchargements avec pagination |
53
+ | `arr_radarr_lookup_movies` | Recherche de catalogue par titre ou `tmdb:<id>` |
54
+ | `arr_radarr_quality_profiles` | Profils qualité existants |
55
+ | `arr_radarr_root_folders` | Dossiers racines existants |
56
+ | `arr_radarr_add_movie` | Ajout par identifiant TMDB, profil qualité et dossier racine |
57
+ | `arr_radarr_search_movies` | Recherche active pour des identifiants Radarr existants |
58
+ | `arr_radarr_command_status` | Suivi d’une recherche asynchrone |
59
+ | `arr_prowlarr_system_status` | Version et informations publiques d’exécution |
60
+ | `arr_prowlarr_list_indexers` | Métadonnées et capacités des indexeurs configurés |
61
+ | `arr_prowlarr_get_indexer` | Métadonnées d’un indexeur par identifiant |
62
+ | `arr_prowlarr_indexer_status` | Derniers échecs et désactivations temporaires |
63
+ | `arr_prowlarr_categories` | Identifiants et hiérarchie des catégories |
64
+ | `arr_prowlarr_search` | Recherche de releases, sans téléchargement |
65
+ | `arr_prowlarr_history` | Historique paginé, filtrable par indexeurs |
66
+ | `arr_prowlarr_health` | Sources et sévérité des contrôles de santé |
67
+ | `arr_prowlarr_statistics` | Compteurs et temps de réponse par indexeur |
68
+ | `arr_prowlarr_applications` | Noms et niveau de synchronisation des applications liées |
69
+
70
+ Sonarr/Radarr : ajout et recherche active peuvent déclencher des téléchargements.
71
+ Prowlarr : recherche sans envoi au téléchargement, avec consommation possible des
72
+ quotas des fournisseurs. Consulter les guides de chaque service.
73
+
74
+ ## Skills
75
+
76
+ | Skill | Description |
77
+ | --- | --- |
78
+ | [arr-sonarr-manage](src/yamcps_arr/sonarr/skills/arr-sonarr-manage/SKILL.md) | Browse Sonarr series, episodes and downloads, find and add series, and launch episode searches. |
79
+ | [arr-radarr-manage](src/yamcps_arr/radarr/skills/arr-radarr-manage/SKILL.md) | Browse Radarr movies and downloads, find and add movies, and launch movie searches. |
80
+ | [arr-prowlarr-search](src/yamcps_arr/prowlarr/skills/arr-prowlarr-search/SKILL.md) | Inspect Prowlarr indexers, categories, history and health, and search releases without downloading. |
81
+
82
+ ## Variable de configuration
83
+
84
+ | Variable | Nom du champ | Description | Obligatoire | Valeur par défaut |
85
+ | --- | --- | --- | --- | --- |
86
+ | Aucune | — | — | — | — |
87
+
88
+ ## Secret
89
+
90
+ | Secret | Nom du champ | Description | Obligatoire |
91
+ | --- | --- | --- | --- |
92
+ | `YAMCPS_ARR_SONARR_URL` | `sonarr-url` | URL de l’instance sans identifiants ni suffixe API | Oui |
93
+ | `YAMCPS_ARR_SONARR_API_KEY` | `sonarr-api-key` | Clé API de l’instance | Oui |
94
+ | `YAMCPS_ARR_RADARR_URL` | `radarr-url` | URL de l’instance sans identifiants ni suffixe API | Oui |
95
+ | `YAMCPS_ARR_RADARR_API_KEY` | `radarr-api-key` | Clé API de l’instance | Oui |
96
+ | `YAMCPS_ARR_PROWLARR_URL` | `prowlarr-url` | URL de l’instance sans identifiants ni suffixe API | Oui |
97
+ | `YAMCPS_ARR_PROWLARR_API_KEY` | `prowlarr-api-key` | Clé API de l’instance | Oui |
98
+
99
+ Les six champs sont requis par `arr` et configurés via le vault.
@@ -0,0 +1,63 @@
1
+ # Contribuer à yamcps-arr
2
+
3
+ Python ≥ 3.12. Installer d'abord un moteur yamcps compatible depuis sa distribution,
4
+ son wheel ou, pour travailler sur les deux dépôts, `python -m pip install -e ../yamcps`.
5
+ Depuis la racine de ce dépôt dans un environnement activé :
6
+
7
+ ```sh
8
+ python -m pip install -e '.[dev]'
9
+ ruff format --check src tests
10
+ ruff check src tests
11
+ mypy src
12
+ radon cc src -s -a
13
+ bandit -r src
14
+ coverage run --source=yamcps_arr -m pytest -q
15
+ coverage report --show-missing --fail-under=81
16
+ python -m unittest discover -s tests -p 'test_*.py'
17
+ python -m build
18
+ ```
19
+
20
+ Les sources et les tests de ce dépôt ne nécessitent pas le dépôt source du moteur.
21
+ Le moteur est une dépendance Python installée. Sur poste hors ligne, fournir les
22
+ wheels de toutes les dépendances, dont `hatchling` et `editables` pour le mode
23
+ editable ; utiliser `--no-index --find-links /chemin/wheels` et construire avec
24
+ `python -m build --no-isolation` après installation des outils.
25
+
26
+ Suivre PEP 8 (100 caractères), typer les interfaces publiques, documenter en anglais
27
+ au format Google ; guides en français. Utiliser unittest pour les nouveaux tests,
28
+ conserver les tests existants et simuler les API. Garder stdout pour MCP stdio,
29
+ les secrets hors des logs, et aucun appel réseau à l'import ou à l'enregistrement.
30
+ Tester une installation wheel hors du dépôt, sans PYTHONPATH vers ses sources.
31
+ Conserver une couverture >80 %, examiner Radon/Bandit et signaler les limites.
32
+ Ne pas publier sur PyPI ni déclencher une release sans demande explicite.
33
+
34
+ ## Versions et publication
35
+
36
+ La version est calculée par `hatch-vcs` depuis Git, comme dans yamcps : le tag
37
+ `v0.1.0` produit la version `0.1.0`. Cloner avec l’historique et les tags ; hors
38
+ d’un tag propre, le build peut porter une version de développement. Ne pas
39
+ renseigner de version fixe dans `pyproject.toml`.
40
+
41
+ Le workflow `.github/workflows/workflow.yaml` s’exécute à la publication d’une
42
+ release GitHub. Il extrait son tag avec l’historique complet, vérifie que le commit
43
+ appartient à `main`, construit le wheel et le sdist, puis contrôle que les deux
44
+ métadonnées portent le nom `yamcps-arr` et exactement la version du tag sans `v`.
45
+ Une version inférée de développement ou un artefact supplémentaire bloque l’envoi.
46
+ Les artefacts validés sont transmis au job de publication PyPI par OIDC, dans
47
+ l’environnement GitHub `pypi`.
48
+
49
+ Avant la première publication, configurer le Trusted Publisher PyPI pour le dépôt
50
+ `JoReci2/yamcps-arr`, le workflow `workflow.yaml` et l’environnement `pypi`, ainsi
51
+ que les protections souhaitées de cet environnement. La création de la release
52
+ et la publication restent des actions explicites de maintenance.
53
+
54
+ Vérification locale d’un build issu d’un tag propre (dans un dossier de sortie vide) :
55
+
56
+ ```sh
57
+ python -m build --outdir dist/release .
58
+ python .github/workflows/verify_release.py dist/release --tag v0.1.0
59
+ ```
60
+
61
+ Adapter le tag à la release visée. Ces commandes construisent et vérifient les
62
+ archives sans publier. Inclure `.github/workflows` dans les contrôles Ruff, mypy,
63
+ Radon et Bandit lors d’une modification du workflow ou de sa validation.