feat(import): import content from Yodeck via an extensible import-provider framework - #3144
Merged
Conversation
…ramework
- add a transport-agnostic ImportProvider framework (registry + Yodeck provider)
- import Yodeck image/video/webpage media as Anthias assets; skip audio/document
- reuse the v2 create pipeline via api.helpers.persist_new_asset (idempotent re-runs)
- expose POST /api/v2/integrations/import/<provider>/{validate,item}
- add a Settings "Import content" wizard and an import_content management command
- cover the provider + endpoints with unit tests
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
There was a problem hiding this comment.
Pull request overview
Adds an inbound “import content” capability to Anthias via an extensible import-provider framework, introducing Yodeck as the first provider and wiring it through UI, API, and CLI while reusing the existing asset creation pipeline.
Changes:
- Introduces
ImportProvider/RemoteMediaItem/ImportOutcomeabstractions plus a provider registry, with a new Yodeck provider implementation. - Adds v2 API endpoints + a new Settings wizard page to validate tokens, enumerate remote media, and import items with progress reporting.
- Refactors v2 asset creation persistence/dispatch into
api.helpers.persist_new_assetand adds amanage.py import_contentcommand.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/anthias_server/lib/integrations/yodeck.py | Implements Yodeck REST import provider (token validation, listing, per-item import + download). |
| src/anthias_server/lib/integrations/registry.py | Registers import providers and exposes provider metadata for UI/API/CLI discovery. |
| src/anthias_server/lib/integrations/base.py | Defines provider-neutral contracts and dataclasses for import. |
| src/anthias_server/lib/integrations/init.py | Documents the integrations import subsystem. |
| src/anthias_server/app/views.py | Adds settings import wizard view and injects provider list into Settings page context. |
| src/anthias_server/app/urls.py | Routes the provider-specific import wizard page. |
| src/anthias_server/app/templates/settings.html | Renders “Import content” cards for registered providers. |
| src/anthias_server/app/templates/import_content.html | Implements the Alpine-driven import wizard UI (token → select → progress). |
| src/anthias_server/app/management/commands/import_content.py | Adds CLI for validating/listing/importing content from a provider. |
| src/anthias_server/api/views/v2.py | Adds import validate/item endpoints; refactors asset create path to call persist_new_asset. |
| src/anthias_server/api/urls/v2.py | Registers new v2 import endpoints. |
| src/anthias_server/api/tests/test_yodeck_import.py | Adds unit coverage for provider logic and new endpoints/pages. |
| src/anthias_server/api/tests/test_assets.py | Updates dispatch patching to match persist_new_asset refactor. |
| src/anthias_server/api/serializers/v2.py | Adds request serializers for import validate and import item endpoints. |
| src/anthias_server/api/helpers.py | Introduces persist_new_asset shared persistence/dispatch helper. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- guard _default_duration against non-numeric input (mypy arg-type) - narrow the import_item Asset|None branch (mypy assignment) - drop http:// test literal to clear the SonarCloud new-code security gate - reuse one provider instance in tests (S5778) and simplify the CLI (S3776) - add management-command tests Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
- scope the Yodeck API token to the Yodeck host on download, never forwarding it to a pre-signed CDN original (credential leak) - correct the pagination stop-condition comment - return a uniform import-item response shape on error (asset_id/skipped/ reason present alongside error), matching the success path + schema - test the download auth-scoping both ways Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
- skip Yodeck "webpage" media that resolves to Yodeck-hosted apps/widgets (internal URLs that would import as broken assets) - add a website docs page describing content import, what's supported, and what's skipped (audio/documents, apps/internal content, non-downloadable originals) Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
5 tasks
- restrict URL selection to http(s) (validate_url also accepts rtsp/rtmp) - sanitise the download file extension to safe .<alnum> so a hostile file_extension can't escape the asset directory (path traversal) - return the uniform error shape from the unknown-provider branch Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
5 tasks
…nload - token is entered as "<label>:<token>" (matches the Yodeck auth header "Authorization: Token <label>:<token_value>"), reflected in token_help - document that arguments.download_from_url is the original-file download link for uploaded (source: local) media too — resolves via the existing _file_url path (token attached for the Yodeck host, dropped on the S3 redirect); no code change needed Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Issues Fixed
Not associated with a tracked issue. Adds a new capability: migrating content into Anthias from another digital signage platform (the inbound mirror of the existing Migrate-to-Screenly export wizard).
Description
Adds an extensible import-provider framework with Yodeck as the first provider. Built as a framework because more providers are planned as stacked PRs (ScreenCloud, OptiSign, NoviSign, PiSignage) — each is a new module plus one registry entry, with no change to the endpoints, wizard, or CLI.
lib/integrations/): a transport-agnosticImportProviderABC + neutralRemoteMediaItem/ImportOutcomedataclasses + a registry. Providers may be REST or GraphQL backed./api/v2/media/, and importsimage/video/webpagemedia (audio/documentare skipped with a reported reason). Image/video originals are downloaded into the asset dir and flow through the existingCreateAssetSerializerV2pipeline (rename → normalise → duration probe); webpages store the URL. Re-imports are idempotent viametadata.import_source.POST /api/v2/integrations/import/<provider>/{validate,item}(validate + enumerate in one call; per-item import with live progress), matching the Screenly endpoints' error hygiene.manage.py import_content --provider yodeck --token … [--workspace] [--dry-run].api.helpers.persist_new_assetso imported and uploaded assets share one code path.Follow-ups before this is fully field-ready: the resolver (
_resolve_sourceinyodeck.py) is isolated and defensive but two Yodeck detail-object field names still need confirming against a live token — the key holding a webpage's destination URL, and whether a directly-uploaded image/video exposes an original-file URL (beyondthumbnail_url); if not, those are skipped-with-reason rather than guessed.Checklist
🤖 Generated with Claude Code