(self, request)
| 1231 | }, |
| 1232 | ) |
| 1233 | def post(self, request): |
| 1234 | repo_id = request.data.get("repo_id") |
| 1235 | slug = request.data.get("slug") |
| 1236 | version = request.data.get("version") |
| 1237 | download_url = request.data.get("download_url") |
| 1238 | |
| 1239 | if not all([repo_id, slug, version, download_url]): |
| 1240 | return Response( |
| 1241 | {"error": "repo_id, slug, version, and download_url are required"}, |
| 1242 | status=status.HTTP_400_BAD_REQUEST, |
| 1243 | ) |
| 1244 | |
| 1245 | try: |
| 1246 | repo = PluginRepo.objects.get(pk=repo_id) |
| 1247 | except PluginRepo.DoesNotExist: |
| 1248 | return Response( |
| 1249 | {"error": "Repo not found"}, status=status.HTTP_404_NOT_FOUND |
| 1250 | ) |
| 1251 | |
| 1252 | # Resolve the plugin key and look up any existing install |
| 1253 | plugin_key = _sanitize_plugin_key(slug) |
| 1254 | if len(plugin_key) > 128: |
| 1255 | plugin_key = plugin_key[:128] |
| 1256 | |
| 1257 | existing_cfg = PluginConfig.objects.filter(key=plugin_key).first() |
| 1258 | # Backward compat: if no match, also try with dashes (legacy entries saved before |
| 1259 | # normalization was enforced) so overwrite is still allowed on update. |
| 1260 | if not existing_cfg: |
| 1261 | dash_key = plugin_key.replace("_", "-") |
| 1262 | if dash_key != plugin_key: |
| 1263 | existing_cfg = PluginConfig.objects.filter(key=dash_key).first() |
| 1264 | |
| 1265 | # Version compatibility check against the running Dispatcharr version |
| 1266 | min_version = request.data.get("min_dispatcharr_version") |
| 1267 | max_version = request.data.get("max_dispatcharr_version") |
| 1268 | if min_version or max_version: |
| 1269 | from version import __version__ as app_version |
| 1270 | try: |
| 1271 | if min_version and _compare_versions(app_version, min_version) < 0: |
| 1272 | return Response( |
| 1273 | {"error": f"This plugin version requires Dispatcharr {min_version} or newer (you have {app_version})"}, |
| 1274 | status=status.HTTP_400_BAD_REQUEST, |
| 1275 | ) |
| 1276 | if max_version and _compare_versions(app_version, max_version) > 0: |
| 1277 | return Response( |
| 1278 | {"error": f"This plugin version requires Dispatcharr {max_version} or older (you have {app_version})"}, |
| 1279 | status=status.HTTP_400_BAD_REQUEST, |
| 1280 | ) |
| 1281 | except (ValueError, TypeError): |
| 1282 | logger.warning("Failed to parse version constraints: min=%s, max=%s", min_version, max_version) |
| 1283 | |
| 1284 | # Download the zip |
| 1285 | try: |
| 1286 | _validate_fetch_url(download_url) |
| 1287 | except ValueError as e: |
| 1288 | return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST) |
| 1289 | try: |
| 1290 | resp = http_requests.get(download_url, timeout=60, stream=True) |
nothing calls this directly
no test coverage detected