@gentbajko/slopify 3.25.9 → 4.1.0
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.
- package/dist/adapters/account-limits.js +30 -0
- package/dist/adapters/alignment/audio.js +1 -1
- package/dist/adapters/alignment/cache.js +4 -6
- package/dist/adapters/alignment/ctc.js +1 -2
- package/dist/adapters/alignment/lock.js +4 -3
- package/dist/adapters/alignment/multilingual.js +2 -4
- package/dist/adapters/alignment/prefetch.js +2 -1
- package/dist/adapters/alignment/runner.js +1 -1
- package/dist/adapters/alignment/worker.js +3 -2
- package/dist/adapters/explain.js +10 -12
- package/dist/adapters/ffmpeg.js +19 -1
- package/dist/adapters/host-cli/index.js +21 -4
- package/dist/adapters/host-cli/transport.js +2 -1
- package/dist/adapters/http-failure.js +53 -0
- package/dist/adapters/image/bytes.js +2 -1
- package/dist/adapters/image/codex.js +42 -9
- package/dist/adapters/image/fal.js +21 -53
- package/dist/adapters/image/google.js +33 -56
- package/dist/adapters/image/models.js +2 -2
- package/dist/adapters/image/openai.js +22 -48
- package/dist/adapters/image/reference.js +36 -0
- package/dist/adapters/image/replicate.js +21 -49
- package/dist/adapters/image/video.js +2 -1
- package/dist/adapters/interest/search-interest.js +113 -0
- package/dist/adapters/key-probes.js +54 -3
- package/dist/adapters/llm/antigravity-models.js +1 -1
- package/dist/adapters/llm/antigravity.js +11 -6
- package/dist/adapters/llm/assistant-cli.js +388 -0
- package/dist/adapters/llm/child-session.js +83 -0
- package/dist/adapters/llm/claude-code-models.js +52 -99
- package/dist/adapters/llm/claude-code.js +16 -4
- package/dist/adapters/llm/codex-limits.js +27 -68
- package/dist/adapters/llm/codex-models.js +1 -1
- package/dist/adapters/llm/codex-server-models.js +61 -109
- package/dist/adapters/llm/codex.js +12 -1
- package/dist/adapters/llm/document-workspace.js +3 -2
- package/dist/adapters/llm/image-workspace.js +3 -2
- package/dist/adapters/llm/openrouter.js +12 -48
- package/dist/adapters/llm/run-cli.js +9 -24
- package/dist/adapters/llm/sse-lines.js +5 -1
- package/dist/adapters/model-access.js +37 -0
- package/dist/adapters/tts/cartesia.js +15 -46
- package/dist/adapters/tts/elevenlabs.js +20 -52
- package/dist/adapters/tts/gemini.js +21 -41
- package/dist/adapters/tts/inworld-async.js +6 -2
- package/dist/adapters/tts/inworld.js +6 -2
- package/dist/adapters/tts/openai.js +20 -50
- package/dist/adapters/tts/system.js +2 -1
- package/dist/assets/models-lifecycle.yaml +6 -0
- package/dist/assistant-wiring.js +60 -0
- package/dist/autopilot-timers.js +59 -0
- package/dist/catalog/lifecycle.js +52 -0
- package/dist/catalog/propose.js +204 -0
- package/dist/catalog/registry.js +23 -14
- package/dist/catalog/schema.js +4 -1
- package/dist/catalog/store.js +39 -0
- package/dist/catalog/validate.js +5 -2
- package/dist/edge/autostart/native.js +3 -5
- package/dist/edge/autostart/prompt.js +2 -1
- package/dist/edge/autostart/service.js +3 -4
- package/dist/edge/cli-args.js +3 -4
- package/dist/edge/cli.js +2 -1
- package/dist/edge/docker-install/apply.js +11 -11
- package/dist/edge/docker-install/run.js +2 -1
- package/dist/edge/docker-install/state.js +4 -3
- package/dist/edge/docker-install/tree.js +2 -4
- package/dist/edge/docker-install/volume.js +3 -2
- package/dist/edge/docker.js +5 -4
- package/dist/edge/events/hub.js +5 -5
- package/dist/edge/http/actions.js +11 -32
- package/dist/edge/http/actor.js +5 -3
- package/dist/edge/http/app.js +86 -11
- package/dist/edge/http/assistant.js +129 -0
- package/dist/edge/http/audio-preview.js +4 -11
- package/dist/edge/http/auditions.js +1 -1
- package/dist/edge/http/autostart.js +5 -5
- package/dist/edge/http/backups.js +2 -4
- package/dist/edge/http/channel-memory.js +9 -22
- package/dist/edge/http/channels.js +14 -27
- package/dist/edge/http/checkpoints.js +39 -21
- package/dist/edge/http/design-templates.js +167 -0
- package/dist/edge/http/designs.js +178 -0
- package/dist/edge/http/diagnostics.js +5 -1
- package/dist/edge/http/document-themes.js +5 -14
- package/dist/edge/http/draft-files.js +1 -3
- package/dist/edge/http/draft-problem.js +5 -10
- package/dist/edge/http/drafts.js +3 -3
- package/dist/edge/http/entries.js +6 -9
- package/dist/edge/http/extension-auth.js +27 -0
- package/dist/edge/http/external-reviews.js +12 -11
- package/dist/edge/http/files.js +5 -11
- package/dist/edge/http/folder-location.js +1 -4
- package/dist/edge/http/fonts.js +0 -7
- package/dist/edge/http/home.js +47 -14
- package/dist/edge/http/host-cli.js +18 -8
- package/dist/edge/http/ids.js +8 -0
- package/dist/edge/http/keywords.js +35 -0
- package/dist/edge/http/model-checks.js +132 -0
- package/dist/edge/http/narration-peaks.js +5 -13
- package/dist/edge/http/onboarding.js +30 -26
- package/dist/edge/http/open-folder.js +5 -10
- package/dist/edge/http/outputs.js +7 -14
- package/dist/edge/http/patch-notes.js +6 -12
- package/dist/edge/http/planning.js +3 -7
- package/dist/edge/http/problem.js +2 -4
- package/dist/edge/http/project-create.js +2 -1
- package/dist/edge/http/project-templates.js +31 -19
- package/dist/edge/http/projects.js +24 -16
- package/dist/edge/http/prompts.js +9 -16
- package/dist/edge/http/pronunciations.js +1 -2
- package/dist/edge/http/providers.js +48 -34
- package/dist/edge/http/refusal.js +29 -0
- package/dist/edge/http/remote-access.js +40 -0
- package/dist/edge/http/remote-guard.js +71 -0
- package/dist/edge/http/request-guard.js +91 -0
- package/dist/edge/http/reviews.js +12 -25
- package/dist/edge/http/revision-files.js +6 -11
- package/dist/edge/http/revisions.js +14 -19
- package/dist/edge/http/run-cost.js +1 -2
- package/dist/edge/http/same-page.js +80 -0
- package/dist/edge/http/schedules.js +69 -40
- package/dist/edge/http/settings.js +27 -14
- package/dist/edge/http/social.js +283 -0
- package/dist/edge/http/staging.js +3 -5
- package/dist/edge/http/storage-files.js +5 -7
- package/dist/edge/http/storage.js +33 -25
- package/dist/edge/http/studio.js +94 -69
- package/dist/edge/http/style-preview.js +3 -6
- package/dist/edge/http/subtitles.js +3 -17
- package/dist/edge/http/template-studio.js +436 -0
- package/dist/edge/http/trash.js +11 -12
- package/dist/edge/http/tutorial.js +1 -2
- package/dist/edge/http/tutorials.js +5 -11
- package/dist/edge/http/update.js +7 -13
- package/dist/edge/http/waveform.js +3 -6
- package/dist/edge/http/youtube-edits.js +3 -4
- package/dist/edge/mcp/assistant.js +279 -0
- package/dist/edge/mcp/attribution.js +8 -2
- package/dist/edge/mcp/call-route.js +11 -2
- package/dist/edge/mcp/excluded-routes.js +29 -3
- package/dist/edge/mcp/http.js +11 -2
- package/dist/edge/mcp/instructions.js +6 -4
- package/dist/edge/mcp/library-tools.js +9 -5
- package/dist/edge/mcp/remake-tools.js +7 -4
- package/dist/edge/mcp/route-tool.js +35 -15
- package/dist/edge/mcp/server.js +13 -8
- package/dist/edge/mcp/tools-channels.js +11 -9
- package/dist/edge/mcp/tools-designs.js +165 -0
- package/dist/edge/mcp/tools-library.js +19 -7
- package/dist/edge/mcp/tools-planning.js +40 -21
- package/dist/edge/mcp/tools-projects.js +38 -11
- package/dist/edge/mcp/tools-publishing.js +9 -9
- package/dist/edge/mcp/tools-runs.js +23 -10
- package/dist/edge/mcp/tools-schedules.js +32 -8
- package/dist/edge/mcp/tools-setup.js +75 -11
- package/dist/edge/mcp/tools-social.js +47 -0
- package/dist/edge/mcp/tools-storage.js +11 -3
- package/dist/edge/mcp/tools-template-studio.js +166 -0
- package/dist/edge/mcp/tools.js +6 -0
- package/dist/edge/remote-access/cli.js +71 -0
- package/dist/edge/remote-access/model.js +32 -0
- package/dist/edge/remote-access/rules.js +207 -0
- package/dist/edge/remote-access/service.js +203 -0
- package/dist/edge/remote-access/store.js +44 -0
- package/dist/edge/remote-access/views.js +43 -0
- package/dist/extension/slopify-studio-chrome.zip +0 -0
- package/dist/extension/slopify-studio-firefox.zip +0 -0
- package/dist/host-cli/install.js +2 -2
- package/dist/host-cli/open-folder.js +2 -2
- package/dist/host-cli/paths.js +2 -4
- package/dist/host-cli/server.js +4 -4
- package/dist/host-cli/service.js +3 -3
- package/dist/host-cli/status.js +7 -7
- package/dist/kernel/db/migrations/0063-model-checks.sql +20 -0
- package/dist/kernel/db/migrations/0064-template-studio.sql +46 -0
- package/dist/kernel/db/migrations/0065-promise-and-assistant-reviews.sql +58 -0
- package/dist/kernel/db/migrations/0066-assistant.sql +44 -0
- package/dist/kernel/db/migrations/0067-autopilot.sql +6 -0
- package/dist/kernel/db/migrations/0068-topic-scores.sql +17 -0
- package/dist/kernel/db/migrations/0070-designs.sql +53 -0
- package/dist/kernel/db/migrations/0071-design-usage.sql +33 -0
- package/dist/kernel/db/migrations/0072-design-templates.sql +33 -0
- package/dist/kernel/db/migrations/0073-schedule-design-kind.sql +5 -0
- package/dist/kernel/db/migrations/0074-template-bakeoffs.sql +44 -0
- package/dist/kernel/db/migrations/0075-social-posts.sql +25 -0
- package/dist/kernel/db/migrations/0076-channel-social.sql +5 -0
- package/dist/kernel/db/migrations/0077-post-prompts.sql +17 -0
- package/dist/kernel/db/migrations/0078-uploaded-from-links.sql +7 -0
- package/dist/kernel/db/tx.js +2 -4
- package/dist/kernel/errors.js +27 -1
- package/dist/kernel/json-answer.js +15 -0
- package/dist/kernel/lock.js +4 -9
- package/dist/kernel/paths.js +8 -0
- package/dist/kernel/pipeline.js +12 -0
- package/dist/kernel/ports/assistant-cli.js +4 -0
- package/dist/kernel/ports/host-cli.js +3 -0
- package/dist/kernel/ports/interest.js +4 -0
- package/dist/kernel/ports/languages.js +0 -3
- package/dist/kernel/ports/model.js +2 -0
- package/dist/kernel/ports/settings-places.js +31 -0
- package/dist/kernel/ports/system-speech.js +31 -3
- package/dist/kernel/runner/attempt.js +14 -4
- package/dist/kernel/runner/audition.js +3 -1
- package/dist/kernel/runner/checkpoint-authority.js +2 -1
- package/dist/kernel/runner/index.js +8 -10
- package/dist/kernel/runner/model-access.js +40 -0
- package/dist/kernel/runner/model-check.js +153 -0
- package/dist/kernel/runner/providers.js +18 -12
- package/dist/kernel/runner/standalone.js +11 -7
- package/dist/main.js +338 -21
- package/dist/model-catalog.js +20 -0
- package/dist/model-checks.js +166 -0
- package/dist/patch-notes/4.0.0.md +51 -0
- package/dist/patch-notes/4.1.0.md +42 -0
- package/dist/patch-notes/index.json +12 -0
- package/dist/slices/admission/heads.js +2 -1
- package/dist/slices/admission/listing-facts.js +95 -0
- package/dist/slices/admission/repo.js +11 -7
- package/dist/slices/admission/rules.js +50 -15
- package/dist/slices/admission/schema.js +8 -0
- package/dist/slices/admission/stage-writes.js +0 -3
- package/dist/slices/admission/start.js +48 -31
- package/dist/slices/admission/state-words.js +34 -5
- package/dist/slices/admission/substitute.js +7 -4
- package/dist/slices/agents/attention-posts.js +31 -0
- package/dist/slices/agents/attention-templates.js +33 -0
- package/dist/slices/agents/attention.js +10 -1
- package/dist/slices/agents/connection.js +2 -6
- package/dist/slices/agents/model.js +6 -3
- package/dist/slices/agents/repo.js +15 -7
- package/dist/slices/article/continuation.js +0 -63
- package/dist/slices/article/plain.js +3 -2
- package/dist/slices/article/segments.js +2 -62
- package/dist/slices/assistant/access.js +1 -0
- package/dist/slices/assistant/asks.js +80 -0
- package/dist/slices/assistant/cost.js +54 -0
- package/dist/slices/assistant/gate.js +222 -0
- package/dist/slices/assistant/model.js +86 -0
- package/dist/slices/assistant/names.js +23 -0
- package/dist/slices/assistant/prompt.js +74 -0
- package/dist/slices/assistant/repo.js +74 -0
- package/dist/slices/assistant/tokens.js +18 -0
- package/dist/slices/assistant/turn.js +344 -0
- package/dist/slices/autopilot/buffer.js +76 -0
- package/dist/slices/autopilot/model.js +14 -0
- package/dist/slices/autopilot/notify.js +27 -0
- package/dist/slices/autopilot/repo.js +34 -0
- package/dist/slices/autopilot/signals.js +194 -0
- package/dist/slices/autopilot/warnings.js +85 -0
- package/dist/slices/autopilot/weekly.js +100 -0
- package/dist/slices/backups/files.js +2 -6
- package/dist/slices/backups/repo.js +3 -15
- package/dist/slices/backups/service.js +8 -7
- package/dist/slices/channels/cast-images.js +3 -2
- package/dist/slices/channels/model.js +0 -1
- package/dist/slices/channels/rebrand.js +0 -3
- package/dist/slices/channels/repo.js +4 -0
- package/dist/slices/channels/schema.js +7 -1
- package/dist/slices/channels/service.js +10 -0
- package/dist/slices/channels/videos.js +3 -15
- package/dist/slices/checkpoints/index.js +0 -1
- package/dist/slices/control/providers.js +2 -28
- package/dist/slices/designs/artwork.js +66 -0
- package/dist/slices/designs/budget.js +23 -0
- package/dist/slices/designs/calls.js +124 -0
- package/dist/slices/designs/check-context.js +38 -0
- package/dist/slices/designs/check-text.js +43 -0
- package/dist/slices/designs/fields.js +88 -0
- package/dist/slices/designs/frames.js +34 -0
- package/dist/slices/designs/gate.js +130 -0
- package/dist/slices/designs/layout.js +293 -0
- package/dist/slices/designs/model.js +35 -0
- package/dist/slices/designs/pdf-job.js +23 -0
- package/dist/slices/designs/pdf-pages.js +30 -0
- package/dist/slices/designs/pdf-runner.js +68 -0
- package/dist/slices/designs/pdf-worker.js +24 -0
- package/dist/slices/designs/picture-size.js +79 -0
- package/dist/slices/designs/pictures.js +55 -0
- package/dist/slices/designs/quote.js +24 -0
- package/dist/slices/designs/render-args.js +36 -0
- package/dist/slices/designs/render-input.js +59 -0
- package/dist/slices/designs/render.js +215 -0
- package/dist/slices/designs/repo.js +101 -0
- package/dist/slices/designs/requests.js +80 -0
- package/dist/slices/designs/runner.js +239 -0
- package/dist/slices/designs/sample-repo.js +91 -0
- package/dist/slices/designs/sample.js +223 -0
- package/dist/slices/designs/schema.js +87 -0
- package/dist/slices/designs/sections.js +44 -0
- package/dist/slices/designs/service.js +233 -0
- package/dist/slices/designs/steps-repo.js +102 -0
- package/dist/slices/designs/studio-kind.js +39 -0
- package/dist/slices/designs/template-checks.js +44 -0
- package/dist/slices/designs/template-make.js +118 -0
- package/dist/slices/designs/templates.js +218 -0
- package/dist/slices/document/fonts.js +2 -1
- package/dist/slices/document/model.js +7 -4
- package/dist/slices/document/render.js +2 -1
- package/dist/slices/document/theme-schema.js +1 -1
- package/dist/slices/document/theme.js +49 -3
- package/dist/slices/episodes/summarize.js +6 -2
- package/dist/slices/estimate/index.js +72 -28
- package/dist/slices/estimate/requests.js +4 -4
- package/dist/slices/fixes/rules.js +3 -1
- package/dist/slices/fonts/catalog.js +5 -3
- package/dist/slices/fonts/coverage.js +2 -1
- package/dist/slices/fonts/discovery.js +3 -2
- package/dist/slices/fonts/files.js +2 -6
- package/dist/slices/fonts/index.js +0 -1
- package/dist/slices/fonts/sfnt.js +45 -10
- package/dist/slices/images/appearance.js +8 -16
- package/dist/slices/images/scenes.js +102 -28
- package/dist/slices/keywords/digest.js +85 -0
- package/dist/slices/keywords/facts.js +92 -0
- package/dist/slices/keywords/fill.js +80 -0
- package/dist/slices/keywords/model.js +75 -0
- package/dist/slices/keywords/rules.js +187 -0
- package/dist/slices/keywords/schema.js +28 -0
- package/dist/slices/keywords/specs.js +260 -0
- package/dist/slices/keywords/values.js +74 -0
- package/dist/slices/library/lint.js +29 -12
- package/dist/slices/library/model.js +2 -0
- package/dist/slices/library/photorealistic.js +4 -12
- package/dist/slices/library/rename.js +9 -7
- package/dist/slices/library/save.js +14 -10
- package/dist/slices/library/slots.js +37 -11
- package/dist/slices/library/transfer.js +5 -4
- package/dist/slices/library/used-by.js +25 -10
- package/dist/slices/loudness/loudnorm.js +53 -12
- package/dist/slices/loudness/model.js +3 -2
- package/dist/slices/loudness/sentence-level.js +2 -1
- package/dist/slices/model-checks/cost.js +61 -0
- package/dist/slices/model-checks/listing.js +124 -0
- package/dist/slices/model-checks/model.js +20 -0
- package/dist/slices/model-checks/record.js +32 -0
- package/dist/slices/model-checks/repo.js +120 -0
- package/dist/slices/model-checks/rules.js +125 -0
- package/dist/slices/model-checks/run.js +143 -0
- package/dist/slices/model-checks/service.js +198 -0
- package/dist/slices/model-upkeep/model.js +1 -1
- package/dist/slices/model-upkeep/switch.js +72 -27
- package/dist/slices/model-upkeep/usage.js +39 -13
- package/dist/slices/narration/breaths.js +3 -1
- package/dist/slices/narration/clean-pieces.js +3 -1
- package/dist/slices/narration/concat.js +2 -1
- package/dist/slices/narration/pauses-model.js +3 -2
- package/dist/slices/narration/peaks.js +3 -4
- package/dist/slices/narration/pronunciation-chunks.js +4 -3
- package/dist/slices/narration/pronunciation.js +6 -4
- package/dist/slices/narration/steering.js +4 -3
- package/dist/slices/notifications/notifier.js +4 -3
- package/dist/slices/notifications/rules.js +5 -2
- package/dist/slices/notifications/settings.js +4 -12
- package/dist/slices/notifications/subject.js +4 -3
- package/dist/slices/onboarding/copy.js +21 -3
- package/dist/slices/onboarding/first-run.js +16 -40
- package/dist/slices/onboarding/full-video.js +3 -2
- package/dist/slices/onboarding/install.js +6 -4
- package/dist/slices/onboarding/model.js +26 -37
- package/dist/slices/onboarding/packs.js +22 -22
- package/dist/slices/onboarding/preferred-model.js +14 -0
- package/dist/slices/onboarding/quick-short.js +105 -65
- package/dist/slices/onboarding/sample.js +4 -2
- package/dist/slices/onboarding/state.js +9 -11
- package/dist/slices/onboarding/template.js +8 -6
- package/dist/slices/outputs/add.js +3 -2
- package/dist/slices/outputs/service.js +2 -2
- package/dist/slices/patch-notes/library.js +4 -3
- package/dist/slices/play-drafts/convert.js +4 -0
- package/dist/slices/play-drafts/readiness.js +3 -3
- package/dist/slices/play-drafts/review-inputs.js +9 -3
- package/dist/slices/play-drafts/review.js +5 -4
- package/dist/slices/play-drafts/schema.js +4 -0
- package/dist/slices/play-drafts/service.js +17 -7
- package/dist/slices/project-templates/from-project.js +9 -2
- package/dist/slices/project-templates/next-chapter.js +2 -1
- package/dist/slices/project-templates/provider-defaults.js +22 -0
- package/dist/slices/project-templates/repo.js +6 -1
- package/dist/slices/project-templates/setup-sections.js +26 -0
- package/dist/slices/project-templates/setup.js +14 -1
- package/dist/slices/project-templates/stand-ins.js +22 -0
- package/dist/slices/rebuild/activity.js +2 -0
- package/dist/slices/rebuild/admission-repo.js +3 -2
- package/dist/slices/rebuild/narration-history.js +4 -5
- package/dist/slices/rebuild/narration-retry.js +2 -1
- package/dist/slices/rebuild/preview-details.js +32 -14
- package/dist/slices/rebuild/preview-plan.js +3 -8
- package/dist/slices/rebuild/recipe-build.js +8 -3
- package/dist/slices/rebuild/recipe-describe.js +3 -3
- package/dist/slices/rebuild/recipe-digest.js +58 -0
- package/dist/slices/rebuild/recipe-input-schema.js +10 -0
- package/dist/slices/rebuild/recipe-keywords.js +71 -0
- package/dist/slices/rebuild/recipe-legacy.js +5 -1
- package/dist/slices/rebuild/recipe-model.js +4 -0
- package/dist/slices/rebuild/recipe-narration-text.js +2 -1
- package/dist/slices/rebuild/recipe-preparation.js +4 -4
- package/dist/slices/rebuild/recipe-reference.js +8 -4
- package/dist/slices/rebuild/recipe-reviews.js +27 -7
- package/dist/slices/rebuild/recipe-save.js +8 -5
- package/dist/slices/rebuild/recipe-scenes.js +40 -11
- package/dist/slices/rebuild/recipe-shorts.js +8 -8
- package/dist/slices/rebuild/recipe-social.js +46 -0
- package/dist/slices/rebuild/recipe-text.js +64 -20
- package/dist/slices/rebuild/recipe-validation.js +102 -31
- package/dist/slices/rebuild/recipe-visual.js +55 -16
- package/dist/slices/rebuild/recipe-voices.js +3 -2
- package/dist/slices/rebuild/recipe-work.js +19 -7
- package/dist/slices/rebuild/recipe-youtube.js +4 -3
- package/dist/slices/rebuild/recovery-selection.js +3 -1
- package/dist/slices/rebuild/recovery.js +9 -8
- package/dist/slices/rebuild/remake-outdated.js +5 -5
- package/dist/slices/rebuild/repo.js +4 -3
- package/dist/slices/rebuild/review-promise.js +25 -0
- package/dist/slices/rebuild/review-redo.js +3 -2
- package/dist/slices/rebuild/runtime-admission.js +4 -3
- package/dist/slices/rebuild/runtime-agent-review.js +11 -5
- package/dist/slices/rebuild/runtime-animate.js +10 -9
- package/dist/slices/rebuild/runtime-article.js +7 -5
- package/dist/slices/rebuild/runtime-checkpoints.js +5 -4
- package/dist/slices/rebuild/runtime-document.js +11 -13
- package/dist/slices/rebuild/runtime-export-bed.js +8 -12
- package/dist/slices/rebuild/runtime-export-edit.js +8 -16
- package/dist/slices/rebuild/runtime-export-inputs.js +12 -11
- package/dist/slices/rebuild/runtime-export-short.js +9 -5
- package/dist/slices/rebuild/runtime-export.js +38 -15
- package/dist/slices/rebuild/runtime-figure-card.js +2 -1
- package/dist/slices/rebuild/runtime-image.js +8 -12
- package/dist/slices/rebuild/runtime-instructions.js +2 -0
- package/dist/slices/rebuild/runtime-keywords.js +59 -0
- package/dist/slices/rebuild/runtime-lines.js +2 -11
- package/dist/slices/rebuild/runtime-local.js +17 -22
- package/dist/slices/rebuild/runtime-narration-publication.js +2 -5
- package/dist/slices/rebuild/runtime-narration-reuse.js +9 -13
- package/dist/slices/rebuild/runtime-narration-text.js +13 -17
- package/dist/slices/rebuild/runtime-pictures.js +2 -4
- package/dist/slices/rebuild/runtime-piece-label.js +10 -6
- package/dist/slices/rebuild/runtime-plan.js +31 -5
- package/dist/slices/rebuild/runtime-provider.js +67 -25
- package/dist/slices/rebuild/runtime-publication.js +10 -9
- package/dist/slices/rebuild/runtime-review.js +39 -33
- package/dist/slices/rebuild/runtime-run.js +4 -1
- package/dist/slices/rebuild/runtime-shorts.js +31 -50
- package/dist/slices/rebuild/runtime-store.js +20 -10
- package/dist/slices/rebuild/runtime-subtitles.js +28 -25
- package/dist/slices/rebuild/runtime-voices.js +10 -16
- package/dist/slices/rebuild/runtime-youtube.js +14 -31
- package/dist/slices/rebuild/service-readiness.js +11 -3
- package/dist/slices/rebuild/transition-repo.js +6 -5
- package/dist/slices/rebuild/work-records.js +6 -0
- package/dist/slices/reruns/cascade.js +1 -2
- package/dist/slices/reruns/index.js +6 -9
- package/dist/slices/research/synthesis.js +3 -2
- package/dist/slices/reviews/external-model.js +4 -1
- package/dist/slices/reviews/external-repo.js +2 -1
- package/dist/slices/reviews/external-rows.js +2 -3
- package/dist/slices/reviews/holds.js +5 -4
- package/dist/slices/reviews/model.js +32 -11
- package/dist/slices/reviews/repo.js +2 -1
- package/dist/slices/reviews/rules.js +4 -3
- package/dist/slices/reviews/verdict.js +2 -1
- package/dist/slices/reviews/view.js +5 -2
- package/dist/slices/revisions/downloads.js +4 -5
- package/dist/slices/revisions/image-plan.js +1 -1
- package/dist/slices/revisions/mutation-assets.js +9 -5
- package/dist/slices/revisions/mutation-cues.js +2 -5
- package/dist/slices/revisions/mutations.js +3 -3
- package/dist/slices/revisions/repo.js +3 -1
- package/dist/slices/revisions/schema.js +1 -0
- package/dist/slices/revisions/view.js +20 -0
- package/dist/slices/run-cost/limits.js +5 -2
- package/dist/slices/run-cost/meter.js +12 -5
- package/dist/slices/run-cost/panel.js +8 -74
- package/dist/slices/run-cost/plan-readings.js +127 -0
- package/dist/slices/run-cost/plan-use.js +169 -0
- package/dist/slices/run-cost/pricing.js +3 -3
- package/dist/slices/run-cost/week.js +32 -4
- package/dist/slices/schedules/agenda.js +18 -7
- package/dist/slices/schedules/by-date.js +42 -0
- package/dist/slices/schedules/calendar.js +5 -0
- package/dist/slices/schedules/design-agenda.js +36 -0
- package/dist/slices/schedules/design-check.js +41 -0
- package/dist/slices/schedules/design-run.js +126 -0
- package/dist/slices/schedules/next-run.js +62 -0
- package/dist/slices/schedules/prepare.js +18 -2
- package/dist/slices/schedules/repo.js +30 -21
- package/dist/slices/schedules/rescore.js +35 -0
- package/dist/slices/schedules/scheduler.js +13 -3
- package/dist/slices/schedules/schema.js +57 -3
- package/dist/slices/schedules/score.js +107 -0
- package/dist/slices/schedules/service.js +57 -24
- package/dist/slices/schedules/topic-list.js +15 -0
- package/dist/slices/schedules/topic-scores.js +104 -0
- package/dist/slices/schedules/topics.js +53 -41
- package/dist/slices/settings/cli-paths.js +4 -6
- package/dist/slices/settings/first-run.js +8 -43
- package/dist/slices/settings/health.js +30 -15
- package/dist/slices/settings/key-test.js +1 -1
- package/dist/slices/settings/model-reach.js +3 -17
- package/dist/slices/settings/model.js +14 -2
- package/dist/slices/settings/playback.js +34 -23
- package/dist/slices/settings/probe-read.js +16 -0
- package/dist/slices/settings/repo.js +33 -0
- package/dist/slices/settings/tutorial.js +2 -2
- package/dist/slices/settings/voices.js +4 -12
- package/dist/slices/shorts/keep.js +2 -1
- package/dist/slices/shorts/pick.js +6 -18
- package/dist/slices/shorts/prompts.js +4 -14
- package/dist/slices/shorts/render.js +6 -2
- package/dist/slices/social/channel.js +44 -0
- package/dist/slices/social/defaults.js +17 -0
- package/dist/slices/social/due.js +36 -0
- package/dist/slices/social/extension.js +18 -0
- package/dist/slices/social/fit.js +115 -0
- package/dist/slices/social/limits.js +186 -0
- package/dist/slices/social/links.js +21 -0
- package/dist/slices/social/media.js +132 -0
- package/dist/slices/social/model.js +75 -0
- package/dist/slices/social/notice.js +19 -0
- package/dist/slices/social/pack.js +176 -0
- package/dist/slices/social/post-prompt.js +56 -0
- package/dist/slices/social/queue.js +31 -0
- package/dist/slices/social/repo.js +133 -0
- package/dist/slices/social/reshape.js +97 -0
- package/dist/slices/social/rules.js +5 -0
- package/dist/slices/social/schema.js +70 -0
- package/dist/slices/social/serve.js +51 -0
- package/dist/slices/social/service.js +129 -0
- package/dist/slices/social/settings.js +21 -0
- package/dist/slices/social/sources.js +114 -0
- package/dist/slices/social/state.js +110 -0
- package/dist/slices/social/text.js +149 -0
- package/dist/slices/storage/arrange.js +3 -1
- package/dist/slices/storage/assets.js +8 -10
- package/dist/slices/storage/backup-designs.js +74 -0
- package/dist/slices/storage/backup-export.js +8 -3
- package/dist/slices/storage/backup-format.js +10 -0
- package/dist/slices/storage/backup-import.js +22 -4
- package/dist/slices/storage/delete-project.js +6 -5
- package/dist/slices/storage/files-location.js +6 -8
- package/dist/slices/storage/layout.js +13 -2
- package/dist/slices/storage/model.js +3 -0
- package/dist/slices/storage/portable.js +17 -12
- package/dist/slices/storage/schema.js +2 -0
- package/dist/slices/storage/staging-refs.js +2 -1
- package/dist/slices/storage/staging.js +6 -9
- package/dist/slices/storage/trim.js +26 -9
- package/dist/slices/studio/calendar.js +7 -2
- package/dist/slices/studio/disclosure.js +4 -4
- package/dist/slices/studio/model.js +1 -1
- package/dist/slices/studio/pack.js +9 -8
- package/dist/slices/studio/pick.js +2 -11
- package/dist/slices/studio/plan.js +7 -16
- package/dist/slices/studio/queue.js +3 -14
- package/dist/slices/studio/releases.js +26 -0
- package/dist/slices/studio/settings.js +20 -57
- package/dist/slices/studio/videos.js +35 -4
- package/dist/slices/style-preview/render.js +37 -16
- package/dist/slices/style-preview/schema.js +14 -1
- package/dist/slices/style-preview/service.js +2 -1
- package/dist/slices/style-preview/settings.js +33 -5
- package/dist/slices/subtitles/captions.js +1 -1
- package/dist/slices/telemetry/collector-client.js +2 -4
- package/dist/slices/telemetry/flush.js +2 -4
- package/dist/slices/telemetry/model.js +0 -7
- package/dist/slices/telemetry/record.js +10 -3
- package/dist/slices/template-studio/anatomy-view.js +161 -0
- package/dist/slices/template-studio/anatomy.js +73 -0
- package/dist/slices/template-studio/bakeoff-make.js +225 -0
- package/dist/slices/template-studio/bakeoff-repo.js +83 -0
- package/dist/slices/template-studio/bakeoff.js +333 -0
- package/dist/slices/template-studio/budget.js +106 -0
- package/dist/slices/template-studio/cards.js +78 -0
- package/dist/slices/template-studio/checks.js +322 -0
- package/dist/slices/template-studio/document-sample.js +56 -0
- package/dist/slices/template-studio/edit.js +15 -0
- package/dist/slices/template-studio/for-all.js +161 -0
- package/dist/slices/template-studio/free-video.js +31 -0
- package/dist/slices/template-studio/free.js +176 -0
- package/dist/slices/template-studio/gate.js +40 -0
- package/dist/slices/template-studio/hidden.js +20 -0
- package/dist/slices/template-studio/jobs.js +79 -0
- package/dist/slices/template-studio/loudness.js +111 -0
- package/dist/slices/template-studio/make.js +40 -0
- package/dist/slices/template-studio/model.js +58 -0
- package/dist/slices/template-studio/pack-import.js +253 -0
- package/dist/slices/template-studio/pack-samples.js +60 -0
- package/dist/slices/template-studio/pack.js +207 -0
- package/dist/slices/template-studio/paid-view.js +66 -0
- package/dist/slices/template-studio/paid.js +355 -0
- package/dist/slices/template-studio/quote.js +155 -0
- package/dist/slices/template-studio/ready.js +104 -0
- package/dist/slices/template-studio/repo.js +134 -0
- package/dist/slices/template-studio/reviews-path.js +58 -0
- package/dist/slices/template-studio/runner.js +84 -0
- package/dist/slices/template-studio/save.js +236 -0
- package/dist/slices/template-studio/say-it-as.js +248 -0
- package/dist/slices/template-studio/schedule-gate.js +34 -0
- package/dist/slices/template-studio/schedule-price.js +32 -0
- package/dist/slices/template-studio/schedule-sample.js +91 -0
- package/dist/slices/template-studio/schema.js +243 -0
- package/dist/slices/template-studio/scope.js +124 -0
- package/dist/slices/template-studio/sections.js +176 -0
- package/dist/slices/template-studio/service.js +175 -0
- package/dist/slices/template-studio/status.js +191 -0
- package/dist/slices/template-studio/topic.js +223 -0
- package/dist/slices/thumbnail/by-llm.js +1 -1
- package/dist/slices/trash/designs.js +76 -0
- package/dist/slices/trash/model.js +13 -4
- package/dist/slices/trash/service.js +52 -2
- package/dist/slices/tutorials/library.js +3 -2
- package/dist/slices/uploads/repo.js +37 -1
- package/dist/slices/uploads/rules.js +3 -2
- package/dist/slices/video/ass-text.js +17 -0
- package/dist/slices/video/audio-export.js +2 -64
- package/dist/slices/video/edit-list.js +2 -2
- package/dist/slices/video/edit-settings.js +1 -1
- package/dist/slices/video/encoding.js +169 -0
- package/dist/slices/video/ffmpeg.js +23 -21
- package/dist/slices/video/figure-card.js +1 -15
- package/dist/slices/video/plan.js +2 -1
- package/dist/slices/video/slideshow.js +43 -18
- package/dist/slices/voices/attribution.js +3 -2
- package/dist/slices/voices/model.js +9 -8
- package/dist/slices/voices/palette.js +0 -3
- package/dist/slices/voices/script.js +2 -1
- package/dist/slices/youtube/answer.js +4 -16
- package/dist/slices/youtube/edits-repo.js +3 -12
- package/dist/tutorials/AI-CLIs.md +25 -25
- package/dist/tutorials/Agents-MCP.md +34 -33
- package/dist/tutorials/Assistant.md +42 -0
- package/dist/tutorials/Backups.md +7 -7
- package/dist/tutorials/Calendar.md +17 -25
- package/dist/tutorials/Cast-Library.md +19 -19
- package/dist/tutorials/Channels.md +42 -35
- package/dist/tutorials/Costs-and-Run-Cost.md +38 -40
- package/dist/tutorials/Create-Article.md +114 -0
- package/dist/tutorials/Create-Extras.md +112 -0
- package/dist/tutorials/Create-Images.md +165 -0
- package/dist/tutorials/Create-Narration.md +178 -0
- package/dist/tutorials/Create-Overview.md +244 -0
- package/dist/tutorials/Create-Video-and-Style.md +144 -0
- package/dist/tutorials/Docker.md +3 -3
- package/dist/tutorials/Document-Themes.md +32 -32
- package/dist/tutorials/Editing-a-Project.md +94 -94
- package/dist/tutorials/FAQ.md +18 -18
- package/dist/tutorials/First-Launch-and-Welcome.md +50 -64
- package/dist/tutorials/Home-and-Projects.md +115 -71
- package/dist/tutorials/Home.md +33 -33
- package/dist/tutorials/Install.md +14 -13
- package/dist/tutorials/Intros-and-Outros.md +33 -34
- package/dist/tutorials/Keyboard-Shortcuts-and-Command-Palette.md +62 -58
- package/dist/tutorials/Keywords-Slopify-Fills.md +87 -0
- package/dist/tutorials/Models.md +53 -21
- package/dist/tutorials/Multiple-Voices.md +41 -40
- package/dist/tutorials/Narration-Aliases-and-Glossary.md +14 -14
- package/dist/tutorials/Notifications.md +27 -17
- package/dist/tutorials/Other-Languages.md +15 -15
- package/dist/tutorials/PDF-Documents.md +38 -29
- package/dist/tutorials/Posting-to-Social-Sites.md +121 -0
- package/dist/tutorials/Project-Page.md +118 -120
- package/dist/tutorials/Prompts-and-Templates.md +84 -0
- package/dist/tutorials/Prompts.md +48 -44
- package/dist/tutorials/Providers-and-Keys.md +105 -98
- package/dist/tutorials/Publishing-to-YouTube.md +31 -31
- package/dist/tutorials/Recovery-and-Retries.md +31 -31
- package/dist/tutorials/Remote-Access.md +63 -0
- package/dist/tutorials/Reviews-and-Checkpoints.md +98 -90
- package/dist/tutorials/Schedules.md +46 -27
- package/dist/tutorials/Settings-Reference.md +194 -174
- package/dist/tutorials/Shorts.md +34 -33
- package/dist/tutorials/Start-at-Login.md +3 -3
- package/dist/tutorials/Studio-Extension.md +22 -24
- package/dist/tutorials/Template-Studio.md +128 -0
- package/dist/tutorials/Templates.md +51 -77
- package/dist/tutorials/Trash.md +4 -4
- package/dist/tutorials/Troubleshooting.md +44 -44
- package/dist/tutorials/Uninstalling-and-Moving.md +5 -5
- package/dist/tutorials/Updating-and-Patch-Notes.md +18 -18
- package/dist/tutorials/Video-Editing.md +34 -34
- package/dist/tutorials/Where-Your-Files-Live.md +10 -10
- package/dist/tutorials/YouTube-Description.md +26 -26
- package/dist/tutorials/Your-First-Short.md +35 -35
- package/dist/tutorials/_Sidebar.md +19 -14
- package/dist/updater/work-in-progress.js +42 -12
- package/dist/web/assets/index-BNftKQrA.css +1 -0
- package/dist/web/assets/index-Cpa58woP.js +459 -0
- package/dist/web/assets/pdf-BKh8f7R6.js +56 -0
- package/dist/web/assets/pdf.worker.min-BmVo14Nb.mjs +28 -0
- package/dist/web/assets/pdf.worker.min-D7i8o3wR.js +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +6 -2
- package/dist/slices/article/provided-entries.js +0 -66
- package/dist/slices/article/run.js +0 -145
- package/dist/slices/images/run.js +0 -234
- package/dist/slices/narration/legacy-plan.js +0 -58
- package/dist/slices/narration/run.js +0 -270
- package/dist/slices/rebuild/runtime-actions.js +0 -90
- package/dist/slices/research/run.js +0 -224
- package/dist/slices/subtitles/prepare.js +0 -194
- package/dist/slices/subtitles/transcript.js +0 -34
- package/dist/slices/thumbnail/run.js +0 -219
- package/dist/slices/video/audio-inputs.js +0 -33
- package/dist/slices/video/reuse-audio.js +0 -62
- package/dist/slices/video/run.js +0 -78
- package/dist/slices/video/write-export.js +0 -158
- package/dist/slices/video/write-subtitles.js +0 -59
- package/dist/tutorials/Library-Overview.md +0 -76
- package/dist/tutorials/Play-Images.md +0 -161
- package/dist/tutorials/Play-Narration.md +0 -167
- package/dist/tutorials/Play-Outputs.md +0 -109
- package/dist/tutorials/Play-Overview.md +0 -227
- package/dist/tutorials/Play-Title-and-Article.md +0 -136
- package/dist/tutorials/Play-Video-and-Style.md +0 -143
- package/dist/web/assets/index-BadsoORk.css +0 -1
- package/dist/web/assets/index-D8LqNsCl.js +0 -326
- package/dist/web/assets/pdf-T7MCwjIv.js +0 -54
- package/dist/web/assets/pdf.worker.min-Dswkl-cV.mjs +0 -29
- package/dist/web/assets/pdf.worker.min-zC6nfbxG.js +0 -1
package/dist/edge/http/studio.js
CHANGED
|
@@ -8,6 +8,7 @@ import { transact } from "../../kernel/db/tx.js";
|
|
|
8
8
|
import { derive } from "../../kernel/runner/graph.js";
|
|
9
9
|
import { listProjects, projectById, stagesOf } from "../../slices/admission/repo.js";
|
|
10
10
|
import { channelById, projectChannels } from "../../slices/channels/repo.js";
|
|
11
|
+
import { isSampleProject } from "../../slices/onboarding/sample.js";
|
|
11
12
|
import { scheduleById, scheduleRunOfProject } from "../../slices/schedules/repo.js";
|
|
12
13
|
import { readSetting, writeSetting } from "../../slices/settings/repo.js";
|
|
13
14
|
import { findDownload } from "../../slices/storage/downloads.js";
|
|
@@ -19,17 +20,16 @@ import { writeUploadPick } from "../../slices/studio/pick.js";
|
|
|
19
20
|
import { postingPlanSchema, readPlan, readStoredPlan, weekdayIn, writePlan, } from "../../slices/studio/plan.js";
|
|
20
21
|
import { leadHoursMax, seriesOf } from "../../slices/studio/plan-model.js";
|
|
21
22
|
import { enqueueFill, fillOnly, readFillQueue, removeFill, } from "../../slices/studio/queue.js";
|
|
22
|
-
import { allReleases, freeSlots, planReleases, readLeadHours, releasesOf, setRelease, swapReleases, writeLeadHours, } from "../../slices/studio/releases.js";
|
|
23
|
-
import { autoCommentKey, bearerToken,
|
|
23
|
+
import { allReleases, freeSlots, lineZone, planReleases, readLeadHours, releasesOf, setRelease, swapReleases, writeLeadHours, } from "../../slices/studio/releases.js";
|
|
24
|
+
import { autoCommentKey, bearerToken, pairStudioExtension, readChannelPlaylists, readStudioPlaylists, resetStudioPairing, saveProjectPlaylists, saveRealFootage, saveStudioPlaylists, studioPairing, studioPlaylistsMax, studioPlaylistsProblem, } from "../../slices/studio/settings.js";
|
|
24
25
|
import { abResults, abVariantSchema, saveAbResult } from "../../slices/studio/stats.js";
|
|
25
|
-
import { confirmUpload, doneVideos, forgetVideo, projectVideos, recordedVideos, recordVideo, setChecks, setTaskState, videoIdOf, videoIdPattern, videoOf, waitingTasks, } from "../../slices/studio/videos.js";
|
|
26
|
+
import { confirmUpload, doneVideos, forgetVideo, projectVideos, recordedVideos, recordVideo, setAbState, setChecks, setTaskState, videoIdOf, videoIdPattern, videoOf, waitingTasks, } from "../../slices/studio/videos.js";
|
|
26
27
|
import { setAsideProjects, uploadedProjects } from "../../slices/uploads/repo.js";
|
|
27
|
-
import {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
.regex(/^[0-9A-Za-z_-]+$/);
|
|
28
|
+
import { extensionAuth } from "./extension-auth.js";
|
|
29
|
+
import { idString } from "./ids.js";
|
|
30
|
+
import { onInvalid, problem } from "./problem.js";
|
|
31
|
+
import { fromSlopifyPage } from "./same-page.js";
|
|
32
|
+
const id = idString;
|
|
33
33
|
const projectParam = z.object({ projectId: id });
|
|
34
34
|
const fileParam = z.object({
|
|
35
35
|
projectId: id,
|
|
@@ -80,8 +80,9 @@ const videoLinkBody = z.object({ short: shortField, link: z.string().max(500) })
|
|
|
80
80
|
const slotBody = z.object({
|
|
81
81
|
slot: z.object({ row: z.string().min(1).max(20), longAt: z.string().max(40) }).nullable(),
|
|
82
82
|
});
|
|
83
|
+
// "ab": the extension set up (or couldn't set up) A/B Testing on the video's Details page.
|
|
83
84
|
const taskResultBody = z.object({
|
|
84
|
-
task: z.enum(["finish", "comment"]),
|
|
85
|
+
task: z.enum(["finish", "comment", "ab"]),
|
|
85
86
|
projectId: id,
|
|
86
87
|
short: shortField,
|
|
87
88
|
ok: z.boolean(),
|
|
@@ -122,34 +123,24 @@ export function studioRoutes(deps) {
|
|
|
122
123
|
return project === undefined ? [] : [{ ...entry, projectTitle: project.title }];
|
|
123
124
|
});
|
|
124
125
|
const samePage = (c) => {
|
|
125
|
-
|
|
126
|
-
if (origin === undefined || origin === new URL(c.req.url).origin)
|
|
126
|
+
if (fromSlopifyPage(c, deps.remoteAccess?.remoteHost))
|
|
127
127
|
return undefined;
|
|
128
128
|
return problem(c, {
|
|
129
129
|
status: 403,
|
|
130
|
-
title: titleOf(403),
|
|
131
130
|
detail: "For your safety, YouTube Studio settings can only be changed from the Slopify page itself. Open Slopify and try again there.",
|
|
132
131
|
});
|
|
133
132
|
};
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
c.header("Access-Control-Max-Age", "600");
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
|
-
const refused = (c) => problem(c, {
|
|
149
|
-
status: 401,
|
|
150
|
-
title: "Unauthorized",
|
|
151
|
-
detail: "The Slopify Studio extension isn't paired with this Slopify. Copy the pairing token from Slopify's Settings → YouTube Studio into the extension's options and press Pair.",
|
|
152
|
-
});
|
|
133
|
+
const { allowOrigin, refused, allowed: extAllowed } = extensionAuth(deps.db);
|
|
134
|
+
// The bundled samples are read-only and never go to YouTube, so nothing here writes a
|
|
135
|
+
// release, a link, a pick or a fill for one, as the project routes refuse its writes
|
|
136
|
+
// (`app.ts`). Reading them stays open: the sample's page shows what a finished video offers.
|
|
137
|
+
const sampleRefused = (c, ...projectIds) => projectIds.some((one) => isSampleProject(deps.db, one))
|
|
138
|
+
? problem(c, {
|
|
139
|
+
status: 409,
|
|
140
|
+
detail: "This is a sample project, which is read-only: it isn't on YouTube and can't be. Press Make my own copy at the top of its page to post your own.",
|
|
141
|
+
extensions: { reason: "sample-read-only" },
|
|
142
|
+
})
|
|
143
|
+
: undefined;
|
|
153
144
|
// A project's place in the plan: its series, and the schedule and run day that made it.
|
|
154
145
|
const whoOf = (projectId, series) => {
|
|
155
146
|
const run = scheduleRunOfProject(deps.db, projectId);
|
|
@@ -165,7 +156,10 @@ export function studioRoutes(deps) {
|
|
|
165
156
|
// A project ready to upload gets its release times from the posting plan when its upload is
|
|
166
157
|
// prepared (`releases.ts`).
|
|
167
158
|
// A long video already on YouTube keeps when it went up; its shorts still get times.
|
|
159
|
+
// A sample never gets a time: it isn't going to YouTube.
|
|
168
160
|
const planned = (projectId) => {
|
|
161
|
+
if (isSampleProject(deps.db, projectId))
|
|
162
|
+
return;
|
|
169
163
|
const long = videoOf(deps.db, projectId, null);
|
|
170
164
|
const out = long?.uploadState === "done" ? long.recordedAt : undefined;
|
|
171
165
|
const result = uploadPack(deps, projectId);
|
|
@@ -187,18 +181,18 @@ export function studioRoutes(deps) {
|
|
|
187
181
|
.toSorted(),
|
|
188
182
|
});
|
|
189
183
|
const slotChoices = (projectId, series) => freeSlots(deps.db, readPlan(deps.db), whoOf(projectId, series), deps.clock.now(), 9);
|
|
190
|
-
// Finished projects not marked uploaded: the popup's list and the calendar's candidates.
|
|
184
|
+
// Finished projects not marked uploaded: the popup's list and the calendar's candidates. The
|
|
185
|
+
// samples are never among them.
|
|
191
186
|
const finishedProjects = () => {
|
|
192
187
|
const uploads = uploadedProjects(deps.db);
|
|
193
188
|
const aside = setAsideProjects(deps.db);
|
|
194
189
|
return listProjects(deps.db).filter((project) => {
|
|
195
|
-
if (uploads.has(project.id))
|
|
190
|
+
if (uploads.has(project.id) || isSampleProject(deps.db, project.id))
|
|
196
191
|
return false;
|
|
197
192
|
const state = derive(stagesOf(deps.db, project.id), project.paused === true);
|
|
198
193
|
return (state === "done" || state === "partial" || (state === "pending" && aside.has(project.id)));
|
|
199
194
|
});
|
|
200
195
|
};
|
|
201
|
-
const extAllowed = (c) => studioRequestAllowed(deps.db, bearerToken(c.req.header("authorization")), c.req.header("origin"));
|
|
202
196
|
return (new Hono()
|
|
203
197
|
.get("/settings", (c) => {
|
|
204
198
|
// The token is read only by the Slopify page, never by another origin's.
|
|
@@ -267,8 +261,13 @@ export function studioRoutes(deps) {
|
|
|
267
261
|
return unknownProject(c);
|
|
268
262
|
const leadMs = readLeadHours(deps.db) * 3_600_000;
|
|
269
263
|
const releases = releasesOf(deps.db, projectId);
|
|
264
|
+
// The long video is on YouTube once its link is known or the project is marked
|
|
265
|
+
// uploaded (one fact, `videos.ts`); a short only by its own link.
|
|
266
|
+
const uploaded = uploadedProjects(deps.db).has(projectId);
|
|
270
267
|
return c.json({
|
|
271
268
|
leadHours: readLeadHours(deps.db),
|
|
269
|
+
// The zone its times are read in: its line's schedule's, else the plan's.
|
|
270
|
+
timeZone: lineZone(readPlan(deps.db), releases.find((release) => release.short === 0)?.line ?? null),
|
|
272
271
|
items: pack.pack.items
|
|
273
272
|
.filter((item) => item.video !== null || item.kind === "video")
|
|
274
273
|
.map((item) => {
|
|
@@ -279,7 +278,8 @@ export function studioRoutes(deps) {
|
|
|
279
278
|
title: item.title,
|
|
280
279
|
at: at === "" ? null : at,
|
|
281
280
|
uploadBy: at === "" ? null : new Date(Date.parse(at) - leadMs).toISOString(),
|
|
282
|
-
onYoutube: videoOf(deps.db, projectId, item.short ?? null)?.uploadState === "done"
|
|
281
|
+
onYoutube: videoOf(deps.db, projectId, item.short ?? null)?.uploadState === "done" ||
|
|
282
|
+
(item.kind === "video" && uploaded),
|
|
283
283
|
};
|
|
284
284
|
}),
|
|
285
285
|
free: slotChoices(projectId, pack.pack.series),
|
|
@@ -292,11 +292,13 @@ export function studioRoutes(deps) {
|
|
|
292
292
|
return denied;
|
|
293
293
|
const { projectId } = c.req.valid("param");
|
|
294
294
|
const other = c.req.valid("json").with;
|
|
295
|
+
const sample = sampleRefused(c, projectId, other);
|
|
296
|
+
if (sample !== undefined)
|
|
297
|
+
return sample;
|
|
295
298
|
const swapped = transact(deps.db, () => swapReleases(deps.db, projectId, other, deps.clock.now()));
|
|
296
299
|
if (!swapped)
|
|
297
300
|
return problem(c, {
|
|
298
301
|
status: 409,
|
|
299
|
-
title: titleOf(409),
|
|
300
302
|
detail: "Both videos need a release time to swap. Give this one a time first, or reload the page and pick another video.",
|
|
301
303
|
});
|
|
302
304
|
planned(projectId);
|
|
@@ -316,6 +318,9 @@ export function studioRoutes(deps) {
|
|
|
316
318
|
if (denied !== undefined)
|
|
317
319
|
return denied;
|
|
318
320
|
const { projectId } = c.req.valid("param");
|
|
321
|
+
const sample = sampleRefused(c, projectId);
|
|
322
|
+
if (sample !== undefined)
|
|
323
|
+
return sample;
|
|
319
324
|
if (uploadPack(deps, projectId).ok === false)
|
|
320
325
|
return unknownProject(c);
|
|
321
326
|
const { short, at, line } = c.req.valid("json");
|
|
@@ -331,14 +336,12 @@ export function studioRoutes(deps) {
|
|
|
331
336
|
if (channelId !== undefined && channelById(deps.db, channelId) === undefined)
|
|
332
337
|
return problem(c, {
|
|
333
338
|
status: 404,
|
|
334
|
-
|
|
335
|
-
detail: "The playlists weren't saved: that channel no longer exists. Reload Settings → YouTube Studio and pick the channel again.",
|
|
339
|
+
detail: "The playlists weren't saved: that channel no longer exists. Reload Settings → YouTube Studio and posting and pick the channel again.",
|
|
336
340
|
});
|
|
337
341
|
const invalid = studioPlaylistsProblem(raw);
|
|
338
342
|
if (invalid !== undefined)
|
|
339
343
|
return problem(c, {
|
|
340
344
|
status: 400,
|
|
341
|
-
title: titleOf(400),
|
|
342
345
|
detail: invalid,
|
|
343
346
|
extensions: { fields: [{ field: "playlists", message: invalid }] },
|
|
344
347
|
});
|
|
@@ -361,12 +364,15 @@ export function studioRoutes(deps) {
|
|
|
361
364
|
return unknownProject(c);
|
|
362
365
|
return c.json({ ...result.pack, slotChoices: slotChoices(projectId, result.pack.series) });
|
|
363
366
|
})
|
|
364
|
-
//
|
|
367
|
+
// Copy for YouTube Studio's Release picker: another free time of the plan, or none.
|
|
365
368
|
.put("/packs/:projectId/slot", zValidator("param", projectParam, onInvalid), zValidator("json", slotBody, onInvalid), (c) => {
|
|
366
369
|
const denied = samePage(c);
|
|
367
370
|
if (denied !== undefined)
|
|
368
371
|
return denied;
|
|
369
372
|
const { projectId } = c.req.valid("param");
|
|
373
|
+
const sample = sampleRefused(c, projectId);
|
|
374
|
+
if (sample !== undefined)
|
|
375
|
+
return sample;
|
|
370
376
|
const wanted = c.req.valid("json").slot;
|
|
371
377
|
const before = uploadPack(deps, projectId);
|
|
372
378
|
if (!before.ok)
|
|
@@ -378,8 +384,7 @@ export function studioRoutes(deps) {
|
|
|
378
384
|
if (!free)
|
|
379
385
|
return problem(c, {
|
|
380
386
|
status: 409,
|
|
381
|
-
|
|
382
|
-
detail: "That slot is taken or past. Reload Prepare upload and choose one of the slots it lists.",
|
|
387
|
+
detail: "That time is taken or past. Close Copy for YouTube Studio, open it again and choose one of the times it lists.",
|
|
383
388
|
});
|
|
384
389
|
setRelease(deps.db, projectId, 0, wanted.longAt, wanted.row, deps.clock.now());
|
|
385
390
|
}
|
|
@@ -389,37 +394,47 @@ export function studioRoutes(deps) {
|
|
|
389
394
|
? c.json({ ...result.pack, slotChoices: slotChoices(projectId, result.pack.series) })
|
|
390
395
|
: unknownProject(c);
|
|
391
396
|
})
|
|
392
|
-
//
|
|
397
|
+
// Copy for YouTube Studio's AI use tick: the project's uploaded clips are real footage.
|
|
393
398
|
.put("/packs/:projectId/real-footage", zValidator("param", projectParam, onInvalid), zValidator("json", realFootageBody, onInvalid), (c) => {
|
|
394
399
|
const denied = samePage(c);
|
|
395
400
|
if (denied !== undefined)
|
|
396
401
|
return denied;
|
|
397
402
|
const { projectId } = c.req.valid("param");
|
|
403
|
+
const sample = sampleRefused(c, projectId);
|
|
404
|
+
if (sample !== undefined)
|
|
405
|
+
return sample;
|
|
398
406
|
if (!uploadPack(deps, projectId).ok)
|
|
399
407
|
return unknownProject(c);
|
|
400
408
|
saveRealFootage(deps.db, projectId, c.req.valid("json").realFootage);
|
|
401
409
|
const result = uploadPack(deps, projectId);
|
|
402
410
|
return result.ok ? c.json(result.pack) : unknownProject(c);
|
|
403
411
|
})
|
|
404
|
-
//
|
|
412
|
+
// Copy for YouTube Studio's pick: which title and thumbnail the upload carries; the A/B test tries
|
|
405
413
|
// the others once the video is public.
|
|
406
414
|
.put("/packs/:projectId/pick", zValidator("param", projectParam, onInvalid), zValidator("json", pickBody, onInvalid), (c) => {
|
|
407
415
|
const denied = samePage(c);
|
|
408
416
|
if (denied !== undefined)
|
|
409
417
|
return denied;
|
|
410
418
|
const { projectId } = c.req.valid("param");
|
|
419
|
+
const sample = sampleRefused(c, projectId);
|
|
420
|
+
if (sample !== undefined)
|
|
421
|
+
return sample;
|
|
411
422
|
if (!uploadPack(deps, projectId).ok)
|
|
412
423
|
return unknownProject(c);
|
|
413
424
|
writeUploadPick(deps.db, projectId, c.req.valid("json"));
|
|
414
425
|
const result = uploadPack(deps, projectId);
|
|
415
426
|
return result.ok ? c.json(result.pack) : unknownProject(c);
|
|
416
427
|
})
|
|
417
|
-
//
|
|
428
|
+
// Copy for YouTube Studio's playlist ticks: which of the channel's playlists this project
|
|
429
|
+
// goes into.
|
|
418
430
|
.put("/packs/:projectId/playlists", zValidator("param", projectParam, onInvalid), zValidator("json", projectPlaylistsBody, onInvalid), (c) => {
|
|
419
431
|
const denied = samePage(c);
|
|
420
432
|
if (denied !== undefined)
|
|
421
433
|
return denied;
|
|
422
434
|
const { projectId } = c.req.valid("param");
|
|
435
|
+
const sample = sampleRefused(c, projectId);
|
|
436
|
+
if (sample !== undefined)
|
|
437
|
+
return sample;
|
|
423
438
|
if (!uploadPack(deps, projectId).ok)
|
|
424
439
|
return unknownProject(c);
|
|
425
440
|
saveProjectPlaylists(deps.db, projectId, c.req.valid("json").playlists);
|
|
@@ -431,6 +446,9 @@ export function studioRoutes(deps) {
|
|
|
431
446
|
if (denied !== undefined)
|
|
432
447
|
return denied;
|
|
433
448
|
const { projectId } = c.req.valid("param");
|
|
449
|
+
const sample = sampleRefused(c, projectId);
|
|
450
|
+
if (sample !== undefined)
|
|
451
|
+
return sample;
|
|
434
452
|
const { short } = c.req.valid("json");
|
|
435
453
|
const result = uploadPack(deps, projectId);
|
|
436
454
|
if (!result.ok)
|
|
@@ -438,8 +456,7 @@ export function studioRoutes(deps) {
|
|
|
438
456
|
if (packItem(result.pack, short) === undefined)
|
|
439
457
|
return problem(c, {
|
|
440
458
|
status: 404,
|
|
441
|
-
|
|
442
|
-
detail: `This project has no short ${String(short)}. Reload the project page and press Prepare upload again.`,
|
|
459
|
+
detail: `This project has no short ${String(short)}. Reload the project page and press Copy for YouTube Studio again.`,
|
|
443
460
|
});
|
|
444
461
|
const queue = enqueueFill(deps.db, projectId, short ?? null, deps.clock.now());
|
|
445
462
|
return c.json({ chosen: { projectId, short: short ?? null }, queue: queueView(queue) });
|
|
@@ -450,22 +467,25 @@ export function studioRoutes(deps) {
|
|
|
450
467
|
// The YouTube videos a project's uploads became, and their A/B tests.
|
|
451
468
|
.get("/videos/:projectId", zValidator("param", projectParam, onInvalid), (c) => c.json({ videos: projectVideos(deps.db, c.req.valid("param").projectId) }))
|
|
452
469
|
// A video's link pasted in Slopify, for an upload made without the extension; an empty
|
|
453
|
-
// link forgets it.
|
|
470
|
+
// link forgets it. The long video's link marks the project uploaded, and forgetting it
|
|
471
|
+
// takes the mark off (`videos.ts`).
|
|
454
472
|
.put("/videos/:projectId", zValidator("param", projectParam, onInvalid), zValidator("json", videoLinkBody, onInvalid), (c) => {
|
|
455
473
|
const wrong = samePage(c);
|
|
456
474
|
if (wrong !== undefined)
|
|
457
475
|
return wrong;
|
|
458
476
|
const { projectId } = c.req.valid("param");
|
|
477
|
+
const sample = sampleRefused(c, projectId);
|
|
478
|
+
if (sample !== undefined)
|
|
479
|
+
return sample;
|
|
459
480
|
const { short, link } = c.req.valid("json");
|
|
460
481
|
if (link.trim() === "") {
|
|
461
|
-
forgetVideo(deps.db, projectId, short ?? null);
|
|
482
|
+
forgetVideo(deps.db, projectId, short ?? null, deps.clock.now().toISOString());
|
|
462
483
|
return c.json({ videos: projectVideos(deps.db, projectId) });
|
|
463
484
|
}
|
|
464
485
|
const videoId = videoIdOf(link);
|
|
465
486
|
if (videoId === undefined)
|
|
466
487
|
return problem(c, {
|
|
467
488
|
status: 400,
|
|
468
|
-
title: titleOf(400),
|
|
469
489
|
detail: "That isn't a YouTube video link. Copy the video's link from YouTube Studio (Details → Video link, like https://youtu.be/…) and paste it again.",
|
|
470
490
|
});
|
|
471
491
|
recordVideo(deps.db, projectId, short ?? null, videoId, deps.clock.now().toISOString());
|
|
@@ -486,7 +506,7 @@ export function studioRoutes(deps) {
|
|
|
486
506
|
queue: queueView(removeFill(deps.db, projectId, short ?? null, deps.clock.now())),
|
|
487
507
|
});
|
|
488
508
|
})
|
|
489
|
-
// The extension's own zips, for Settings' and
|
|
509
|
+
// The extension's own zips, for Settings' and Copy for YouTube Studio's Download.
|
|
490
510
|
.get("/extension/:file", zValidator("param", extensionParam, onInvalid), (c) => {
|
|
491
511
|
const { file } = c.req.valid("param");
|
|
492
512
|
const name = extensionFiles[file] ?? "";
|
|
@@ -495,7 +515,6 @@ export function studioRoutes(deps) {
|
|
|
495
515
|
if (path === undefined || stat === undefined || !stat.isFile())
|
|
496
516
|
return problem(c, {
|
|
497
517
|
status: 404,
|
|
498
|
-
title: titleOf(404),
|
|
499
518
|
detail: "The Slopify Studio extension isn't included in this copy of Slopify, so there is nothing to download. Update or reinstall Slopify; when running from the repository, run `npm run build` at its root, which builds the extension too.",
|
|
500
519
|
});
|
|
501
520
|
return c.body(Readable.toWeb(createReadStream(path)), 200, {
|
|
@@ -522,8 +541,7 @@ export function studioRoutes(deps) {
|
|
|
522
541
|
? refused(c)
|
|
523
542
|
: problem(c, {
|
|
524
543
|
status: 403,
|
|
525
|
-
|
|
526
|
-
detail: "Only the Slopify Studio browser extension can pair with Slopify. Install it (see Settings → YouTube Studio) and pair from its options page.",
|
|
544
|
+
detail: "Only the Slopify Studio browser extension can pair with Slopify. Install it (see Settings → YouTube Studio and posting) and pair from its options page.",
|
|
527
545
|
});
|
|
528
546
|
// The origin is paired now; the response carries its headers.
|
|
529
547
|
allowOrigin(c, false);
|
|
@@ -531,7 +549,7 @@ export function studioRoutes(deps) {
|
|
|
531
549
|
})
|
|
532
550
|
.get("/ext/pack", (c) => {
|
|
533
551
|
allowOrigin(c, false);
|
|
534
|
-
if (!
|
|
552
|
+
if (!extAllowed(c))
|
|
535
553
|
return refused(c);
|
|
536
554
|
// The first waiting item that can still be filled; one whose project or short is gone
|
|
537
555
|
// leaves the queue.
|
|
@@ -549,17 +567,16 @@ export function studioRoutes(deps) {
|
|
|
549
567
|
}
|
|
550
568
|
return problem(c, {
|
|
551
569
|
status: 404,
|
|
552
|
-
title: titleOf(404),
|
|
553
570
|
detail: gone > 0
|
|
554
|
-
? "The project chosen to fill in is gone. In Slopify, open the project again, press
|
|
555
|
-
: "Nothing is waiting to be filled in. In Slopify, open the project, press
|
|
571
|
+
? "The project chosen to fill in is gone. In Slopify, open the project again, press Copy for YouTube Studio, then Fill in YouTube Studio."
|
|
572
|
+
: "Nothing is waiting to be filled in. In Slopify, open the project, press Copy for YouTube Studio, then Fill in YouTube Studio.",
|
|
556
573
|
});
|
|
557
574
|
})
|
|
558
575
|
// The extension filled an item: it leaves the queue, so the next upload dialog takes the
|
|
559
576
|
// next one.
|
|
560
577
|
.post("/ext/filled", zValidator("json", queueItemBody, onInvalid), (c) => {
|
|
561
578
|
allowOrigin(c, false);
|
|
562
|
-
if (!
|
|
579
|
+
if (!extAllowed(c))
|
|
563
580
|
return refused(c);
|
|
564
581
|
const { projectId, short } = c.req.valid("json");
|
|
565
582
|
const left = removeFill(deps.db, projectId, short ?? null, deps.clock.now());
|
|
@@ -623,11 +640,13 @@ export function studioRoutes(deps) {
|
|
|
623
640
|
if (!extAllowed(c))
|
|
624
641
|
return refused(c);
|
|
625
642
|
const { projectId, short } = c.req.valid("json");
|
|
643
|
+
const sample = sampleRefused(c, projectId);
|
|
644
|
+
if (sample !== undefined)
|
|
645
|
+
return sample;
|
|
626
646
|
const result = uploadPack(deps, projectId);
|
|
627
647
|
if (!result.ok || packItem(result.pack, short ?? undefined) === undefined)
|
|
628
648
|
return problem(c, {
|
|
629
649
|
status: 404,
|
|
630
|
-
title: titleOf(404),
|
|
631
650
|
detail: "That upload isn't in the project any more. Open the popup again.",
|
|
632
651
|
});
|
|
633
652
|
planned(projectId);
|
|
@@ -641,6 +660,9 @@ export function studioRoutes(deps) {
|
|
|
641
660
|
if (!extAllowed(c))
|
|
642
661
|
return refused(c);
|
|
643
662
|
const { projectId } = c.req.valid("json");
|
|
663
|
+
const sample = sampleRefused(c, projectId);
|
|
664
|
+
if (sample !== undefined)
|
|
665
|
+
return sample;
|
|
644
666
|
planned(projectId);
|
|
645
667
|
const result = uploadPack(deps, projectId);
|
|
646
668
|
if (!result.ok)
|
|
@@ -692,10 +714,14 @@ export function studioRoutes(deps) {
|
|
|
692
714
|
if (!extAllowed(c))
|
|
693
715
|
return refused(c);
|
|
694
716
|
const { task, projectId, short, ok, message } = c.req.valid("json");
|
|
695
|
-
|
|
717
|
+
if (task === "ab")
|
|
718
|
+
setAbState(deps.db, projectId, short ?? null, ok ? "started" : "failed", message, deps.clock.now().toISOString());
|
|
719
|
+
else
|
|
720
|
+
setTaskState(deps.db, task, projectId, short ?? null, ok ? "done" : "failed", message);
|
|
696
721
|
return c.json({ ok: true });
|
|
697
722
|
})
|
|
698
|
-
// The long videos whose A/B test is running
|
|
723
|
+
// The long videos whose A/B test is running (the extension reported setting it up), for
|
|
724
|
+
// the extension to read each result.
|
|
699
725
|
.get("/ext/known-videos", (c) => {
|
|
700
726
|
allowOrigin(c, false);
|
|
701
727
|
if (!extAllowed(c))
|
|
@@ -740,7 +766,7 @@ export function studioRoutes(deps) {
|
|
|
740
766
|
for (const { projectId, short, videoId } of body.videos) {
|
|
741
767
|
if (videoOf(deps.db, projectId, short ?? null)?.videoId !== videoId)
|
|
742
768
|
continue;
|
|
743
|
-
forgetVideo(deps.db, projectId, short ?? null);
|
|
769
|
+
forgetVideo(deps.db, projectId, short ?? null, deps.clock.now().toISOString());
|
|
744
770
|
deps.hub.emit(projectId, { type: "project.updated", projectId });
|
|
745
771
|
forgotten++;
|
|
746
772
|
}
|
|
@@ -795,7 +821,7 @@ export function studioRoutes(deps) {
|
|
|
795
821
|
})
|
|
796
822
|
.get("/ext/files/:projectId/:asset", zValidator("param", fileParam, onInvalid), (c) => {
|
|
797
823
|
allowOrigin(c, false);
|
|
798
|
-
if (!
|
|
824
|
+
if (!extAllowed(c))
|
|
799
825
|
return refused(c);
|
|
800
826
|
const { projectId, asset } = c.req.valid("param");
|
|
801
827
|
// Only a pack's own files, its videos, thumbnails and captions: the extension puts the
|
|
@@ -810,7 +836,6 @@ export function studioRoutes(deps) {
|
|
|
810
836
|
if (found === undefined || !found.ok)
|
|
811
837
|
return problem(c, {
|
|
812
838
|
status: 404,
|
|
813
|
-
title: titleOf(404),
|
|
814
839
|
detail: "That file isn't in the project's upload pack any more. Reload the project in Slopify and press Fill in YouTube Studio again.",
|
|
815
840
|
});
|
|
816
841
|
return c.body(Readable.toWeb(createReadStream(found.download.path)), 200, {
|
|
@@ -824,8 +849,9 @@ export function studioRoutes(deps) {
|
|
|
824
849
|
// (a short's related video, the long video's end screen and captions, unless they went in
|
|
825
850
|
// during the upload) wait for the extension, the pinned comment for the video to be public.
|
|
826
851
|
function confirmVideoUpload(deps, projectId, short, videoId, captionsAdded = false) {
|
|
827
|
-
|
|
828
|
-
|
|
852
|
+
const at = deps.clock.now().toISOString();
|
|
853
|
+
if (!confirmUpload(deps.db, projectId, short, videoId, at))
|
|
854
|
+
recordVideo(deps.db, projectId, short, videoId, at);
|
|
829
855
|
const confirmedPack = uploadPack(deps, projectId);
|
|
830
856
|
const confirmedItem = confirmedPack.ok
|
|
831
857
|
? packItem(confirmedPack.pack, short ?? undefined)
|
|
@@ -843,7 +869,6 @@ function confirmVideoUpload(deps, projectId, short, videoId, captionsAdded = fal
|
|
|
843
869
|
function unknownProject(c) {
|
|
844
870
|
return problem(c, {
|
|
845
871
|
status: 404,
|
|
846
|
-
title: titleOf(404),
|
|
847
872
|
detail: "This project no longer exists. Go back to Projects and open it again.",
|
|
848
873
|
});
|
|
849
874
|
}
|
|
@@ -4,7 +4,7 @@ import { z } from "zod";
|
|
|
4
4
|
import { StylePreviewError } from "../../slices/style-preview/render.js";
|
|
5
5
|
import { stylePreviewRequestSchema } from "../../slices/style-preview/schema.js";
|
|
6
6
|
import { fileResponse } from "./byte-range.js";
|
|
7
|
-
import { onInvalid, problem
|
|
7
|
+
import { onInvalid, problem } from "./problem.js";
|
|
8
8
|
export { byteRange } from "./byte-range.js";
|
|
9
9
|
// POST renders (or finds) the preview for a set of caption and Look settings and answers where
|
|
10
10
|
// to play it; GET streams the mp4, with byte ranges so the browser's player can seek.
|
|
@@ -31,7 +31,6 @@ export function stylePreviewRoutes(deps) {
|
|
|
31
31
|
const status = error.reason === "font-missing" ? 409 : error.reason === "ffmpeg-missing" ? 503 : 500;
|
|
32
32
|
return problem(c, {
|
|
33
33
|
status,
|
|
34
|
-
title: titleOf(status),
|
|
35
34
|
detail: error.message,
|
|
36
35
|
extensions: { reason: error.reason },
|
|
37
36
|
});
|
|
@@ -42,8 +41,7 @@ export function stylePreviewRoutes(deps) {
|
|
|
42
41
|
if (saved === undefined)
|
|
43
42
|
return problem(c, {
|
|
44
43
|
status: 404,
|
|
45
|
-
|
|
46
|
-
detail: "This style preview is no longer saved; Slopify keeps only the most recent ones. Press Render again to make it.",
|
|
44
|
+
detail: "This style preview is no longer saved; Slopify keeps only the most recent ones. Press Make the preview again to make it.",
|
|
47
45
|
});
|
|
48
46
|
return fileResponse(c, saved.path, saved.bytes, {
|
|
49
47
|
"content-type": "video/mp4",
|
|
@@ -55,7 +53,6 @@ export function stylePreviewRoutes(deps) {
|
|
|
55
53
|
function unavailable(c) {
|
|
56
54
|
return problem(c, {
|
|
57
55
|
status: 503,
|
|
58
|
-
|
|
59
|
-
detail: "The style preview isn't available because this Slopify started without its video renderer. Restart Slopify, then press Render again.",
|
|
56
|
+
detail: "The style preview isn't available because this Slopify started without its video renderer. Restart Slopify, then press Make the preview again.",
|
|
60
57
|
});
|
|
61
58
|
}
|
|
@@ -1,22 +1,8 @@
|
|
|
1
1
|
import { zValidator } from "@hono/zod-validator";
|
|
2
2
|
import { Hono } from "hono";
|
|
3
|
-
import {
|
|
4
|
-
import { onInvalid
|
|
5
|
-
|
|
6
|
-
id: z
|
|
7
|
-
.string()
|
|
8
|
-
.min(1)
|
|
9
|
-
.max(64)
|
|
10
|
-
.regex(/^[0-9A-Za-z_-]+$/),
|
|
11
|
-
});
|
|
3
|
+
import { idParam } from "./ids.js";
|
|
4
|
+
import { onInvalid } from "./problem.js";
|
|
5
|
+
import { revisionRequired } from "./refusal.js";
|
|
12
6
|
export function subtitleRoutes(_deps) {
|
|
13
7
|
return new Hono().patch("/:id/subtitles", zValidator("param", idParam, onInvalid), revisionRequired);
|
|
14
8
|
}
|
|
15
|
-
function revisionRequired(c) {
|
|
16
|
-
return problem(c, {
|
|
17
|
-
status: 409,
|
|
18
|
-
title: titleOf(409),
|
|
19
|
-
detail: "This change is now made from the Edit tab. Choose Edit project, save your change, then use Choose what to remake (in the project's More menu).",
|
|
20
|
-
extensions: { reason: "revision-required" },
|
|
21
|
-
});
|
|
22
|
-
}
|