vidspotai-shared 1.0.82 → 1.0.83
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/lib/globals/aiModels/enums.d.ts +11 -1
- package/lib/globals/aiModels/enums.d.ts.map +1 -1
- package/lib/globals/aiModels/enums.js +24 -1
- package/lib/globals/aiModels/index.d.ts.map +1 -1
- package/lib/globals/aiModels/index.js +2 -0
- package/lib/globals/aiModels/providers/anthropic.d.ts +12 -0
- package/lib/globals/aiModels/providers/anthropic.d.ts.map +1 -0
- package/lib/globals/aiModels/providers/anthropic.js +88 -0
- package/lib/globals/aiModels/providers/google.d.ts.map +1 -1
- package/lib/globals/aiModels/providers/google.js +82 -0
- package/lib/globals/aiModels/providers/openai.d.ts.map +1 -1
- package/lib/globals/aiModels/providers/openai.js +63 -4
- package/lib/globals/aiModels/tierHelpers.d.ts +12 -0
- package/lib/globals/aiModels/tierHelpers.d.ts.map +1 -1
- package/lib/globals/aiModels/tierHelpers.js +83 -0
- package/lib/globals/aiModels/types.d.ts +19 -0
- package/lib/globals/aiModels/types.d.ts.map +1 -1
- package/lib/globals/types.d.ts +120 -1
- package/lib/globals/types.d.ts.map +1 -1
- package/lib/globals/types.js +135 -1
- package/lib/models/agent.model.d.ts +41 -1
- package/lib/models/agent.model.d.ts.map +1 -1
- package/lib/models/index.d.ts +1 -0
- package/lib/models/index.d.ts.map +1 -1
- package/lib/models/index.js +1 -0
- package/lib/models/social.model.d.ts +180 -0
- package/lib/models/social.model.d.ts.map +1 -0
- package/lib/models/social.model.js +2 -0
- package/lib/models/user.model.d.ts +10 -0
- package/lib/models/user.model.d.ts.map +1 -1
- package/lib/models/video.model.d.ts +6 -0
- package/lib/models/video.model.d.ts.map +1 -1
- package/lib/schemas/brief.schema.d.ts +46 -0
- package/lib/schemas/brief.schema.d.ts.map +1 -1
- package/lib/schemas/brief.schema.js +72 -1
- package/lib/schemas/index.d.ts +1 -0
- package/lib/schemas/index.d.ts.map +1 -1
- package/lib/schemas/index.js +1 -0
- package/lib/schemas/project.schema.d.ts +67 -0
- package/lib/schemas/project.schema.d.ts.map +1 -1
- package/lib/schemas/project.schema.js +12 -0
- package/lib/schemas/social.schema.d.ts +91 -0
- package/lib/schemas/social.schema.d.ts.map +1 -0
- package/lib/schemas/social.schema.js +114 -0
- package/lib/schemas/videoPlan.schema.d.ts +114 -0
- package/lib/schemas/videoPlan.schema.d.ts.map +1 -1
- package/lib/schemas/videoPlan.schema.js +141 -1
- package/lib/services/agent/chatAgent.d.ts +25 -1
- package/lib/services/agent/chatAgent.d.ts.map +1 -1
- package/lib/services/agent/chatAgent.js +145 -9
- package/lib/services/agent/costPreflight.d.ts +11 -1
- package/lib/services/agent/costPreflight.d.ts.map +1 -1
- package/lib/services/agent/costPreflight.js +18 -1
- package/lib/services/agent/covers/coverPlanner.d.ts +41 -0
- package/lib/services/agent/covers/coverPlanner.d.ts.map +1 -0
- package/lib/services/agent/covers/coverPlanner.js +278 -0
- package/lib/services/agent/covers/covers.schema.d.ts +158 -0
- package/lib/services/agent/covers/covers.schema.d.ts.map +1 -0
- package/lib/services/agent/covers/covers.schema.js +166 -0
- package/lib/services/agent/covers/index.d.ts +3 -0
- package/lib/services/agent/covers/index.d.ts.map +1 -0
- package/lib/services/agent/covers/index.js +18 -0
- package/lib/services/agent/critic.d.ts +10 -0
- package/lib/services/agent/critic.d.ts.map +1 -1
- package/lib/services/agent/critic.js +37 -1
- package/lib/services/agent/editClassifier.d.ts +2 -2
- package/lib/services/agent/editClassifier.js +2 -2
- package/lib/services/agent/editExisting/editAssembler.d.ts +78 -0
- package/lib/services/agent/editExisting/editAssembler.d.ts.map +1 -0
- package/lib/services/agent/editExisting/editAssembler.js +172 -0
- package/lib/services/agent/editExisting/editExisting.schema.d.ts +119 -0
- package/lib/services/agent/editExisting/editExisting.schema.d.ts.map +1 -0
- package/lib/services/agent/editExisting/editExisting.schema.js +157 -0
- package/lib/services/agent/editExisting/highlightPicker.d.ts +48 -0
- package/lib/services/agent/editExisting/highlightPicker.d.ts.map +1 -0
- package/lib/services/agent/editExisting/highlightPicker.js +199 -0
- package/lib/services/agent/editExisting/index.d.ts +4 -0
- package/lib/services/agent/editExisting/index.d.ts.map +1 -0
- package/lib/services/agent/editExisting/index.js +19 -0
- package/lib/services/agent/eval/seedBriefs.d.ts +4 -3
- package/lib/services/agent/eval/seedBriefs.d.ts.map +1 -1
- package/lib/services/agent/eval/seedBriefs.js +283 -3
- package/lib/services/agent/eval/types.d.ts +10 -0
- package/lib/services/agent/eval/types.d.ts.map +1 -1
- package/lib/services/agent/executor/core.d.ts +70 -0
- package/lib/services/agent/executor/core.d.ts.map +1 -0
- package/lib/services/agent/executor/core.js +250 -0
- package/lib/services/agent/executor/duration.d.ts +20 -0
- package/lib/services/agent/executor/duration.d.ts.map +1 -0
- package/lib/services/agent/executor/duration.js +46 -0
- package/lib/services/agent/executor/index.d.ts +15 -0
- package/lib/services/agent/executor/index.d.ts.map +1 -0
- package/lib/services/agent/executor/index.js +32 -0
- package/lib/services/agent/executor/types.d.ts +183 -0
- package/lib/services/agent/executor/types.d.ts.map +1 -0
- package/lib/services/agent/executor/types.js +29 -0
- package/lib/services/agent/executor/visual.d.ts +32 -0
- package/lib/services/agent/executor/visual.d.ts.map +1 -0
- package/lib/services/agent/executor/visual.js +400 -0
- package/lib/services/agent/executor/voice.d.ts +17 -0
- package/lib/services/agent/executor/voice.d.ts.map +1 -0
- package/lib/services/agent/executor/voice.js +119 -0
- package/lib/services/agent/extendChain.d.ts +101 -0
- package/lib/services/agent/extendChain.d.ts.map +1 -0
- package/lib/services/agent/extendChain.js +177 -0
- package/lib/services/agent/index.d.ts +11 -1
- package/lib/services/agent/index.d.ts.map +1 -1
- package/lib/services/agent/index.js +11 -1
- package/lib/services/agent/llmCaller.d.ts +7 -8
- package/lib/services/agent/llmCaller.d.ts.map +1 -1
- package/lib/services/agent/llmCallerAnthropic.d.ts +44 -31
- package/lib/services/agent/llmCallerAnthropic.d.ts.map +1 -1
- package/lib/services/agent/llmCallerAnthropic.js +135 -60
- package/lib/services/agent/llmCallerFactory.d.ts +34 -0
- package/lib/services/agent/llmCallerFactory.d.ts.map +1 -0
- package/lib/services/agent/llmCallerFactory.js +31 -0
- package/lib/services/agent/llmCallerGemini.d.ts +62 -0
- package/lib/services/agent/llmCallerGemini.d.ts.map +1 -0
- package/lib/services/agent/llmCallerGemini.js +235 -0
- package/lib/services/agent/llmCallerOpenai.d.ts +56 -0
- package/lib/services/agent/llmCallerOpenai.d.ts.map +1 -0
- package/lib/services/agent/llmCallerOpenai.js +230 -0
- package/lib/services/agent/llmCallerRegistry.d.ts.map +1 -1
- package/lib/services/agent/llmCallerRegistry.js +7 -7
- package/lib/services/agent/llmCallerRouting.d.ts +63 -0
- package/lib/services/agent/llmCallerRouting.d.ts.map +1 -0
- package/lib/services/agent/llmCallerRouting.js +124 -0
- package/lib/services/agent/llmModelRegistry.d.ts +59 -0
- package/lib/services/agent/llmModelRegistry.d.ts.map +1 -0
- package/lib/services/agent/llmModelRegistry.js +168 -0
- package/lib/services/agent/llmRetry.d.ts +57 -0
- package/lib/services/agent/llmRetry.d.ts.map +1 -0
- package/lib/services/agent/llmRetry.js +102 -0
- package/lib/services/agent/modelRouter.d.ts +3 -3
- package/lib/services/agent/modelRouter.d.ts.map +1 -1
- package/lib/services/agent/modelRouter.js +27 -13
- package/lib/services/agent/planMutations.d.ts +54 -1
- package/lib/services/agent/planMutations.d.ts.map +1 -1
- package/lib/services/agent/planMutations.js +78 -0
- package/lib/services/agent/planner/Planner.d.ts +0 -17
- package/lib/services/agent/planner/Planner.d.ts.map +1 -1
- package/lib/services/agent/planner/Planner.js +67 -303
- package/lib/services/agent/planner/overlayRegen.d.ts +38 -0
- package/lib/services/agent/planner/overlayRegen.d.ts.map +1 -0
- package/lib/services/agent/planner/overlayRegen.js +145 -0
- package/lib/services/agent/planner/plannerMessages.d.ts +34 -0
- package/lib/services/agent/planner/plannerMessages.d.ts.map +1 -0
- package/lib/services/agent/planner/plannerMessages.js +185 -0
- package/lib/services/agent/planner/promptSections.d.ts +12 -0
- package/lib/services/agent/planner/promptSections.d.ts.map +1 -1
- package/lib/services/agent/planner/promptSections.js +57 -0
- package/lib/services/agent/planner/scriptFirstPlanner.d.ts +35 -0
- package/lib/services/agent/planner/scriptFirstPlanner.d.ts.map +1 -0
- package/lib/services/agent/planner/scriptFirstPlanner.js +140 -0
- package/lib/services/agent/planner/structuralRules.d.ts +10 -0
- package/lib/services/agent/planner/structuralRules.d.ts.map +1 -1
- package/lib/services/agent/planner/structuralRules.js +92 -9
- package/lib/services/agent/planner/validators.d.ts +18 -0
- package/lib/services/agent/planner/validators.d.ts.map +1 -1
- package/lib/services/agent/planner/validators.js +97 -0
- package/lib/services/agent/planner.d.ts +2 -1
- package/lib/services/agent/planner.d.ts.map +1 -1
- package/lib/services/agent/planner.js +5 -1
- package/lib/services/agent/priorProject.d.ts +26 -0
- package/lib/services/agent/priorProject.d.ts.map +1 -0
- package/lib/services/agent/priorProject.js +51 -0
- package/lib/services/agent/providerFallback/chains.d.ts.map +1 -1
- package/lib/services/agent/providerFallback/chains.js +27 -15
- package/lib/services/agent/repurpose/index.d.ts +3 -0
- package/lib/services/agent/repurpose/index.d.ts.map +1 -0
- package/lib/services/agent/repurpose/index.js +18 -0
- package/lib/services/agent/repurpose/repurpose.schema.d.ts +132 -0
- package/lib/services/agent/repurpose/repurpose.schema.d.ts.map +1 -0
- package/lib/services/agent/repurpose/repurpose.schema.js +144 -0
- package/lib/services/agent/repurpose/shortsPicker.d.ts +25 -0
- package/lib/services/agent/repurpose/shortsPicker.d.ts.map +1 -0
- package/lib/services/agent/repurpose/shortsPicker.js +218 -0
- package/lib/services/agent/runHelpers.d.ts +21 -2
- package/lib/services/agent/runHelpers.d.ts.map +1 -1
- package/lib/services/agent/runHelpers.js +71 -2
- package/lib/services/agent/tools/animateImage.tool.d.ts +1 -0
- package/lib/services/agent/tools/animateImage.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/animateImage.tool.js +12 -0
- package/lib/services/agent/tools/chapterOutline.tool.d.ts +42 -0
- package/lib/services/agent/tools/chapterOutline.tool.d.ts.map +1 -0
- package/lib/services/agent/tools/chapterOutline.tool.js +115 -0
- package/lib/services/agent/tools/composeScene.tool.d.ts +63 -0
- package/lib/services/agent/tools/composeScene.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/estimateCost.tool.d.ts +27 -0
- package/lib/services/agent/tools/estimateCost.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/estimateCost.tool.js +55 -7
- package/lib/services/agent/tools/extendVideo.tool.d.ts +26 -0
- package/lib/services/agent/tools/extendVideo.tool.d.ts.map +1 -0
- package/lib/services/agent/tools/extendVideo.tool.js +149 -0
- package/lib/services/agent/tools/generateScript.tool.d.ts +184 -0
- package/lib/services/agent/tools/generateScript.tool.d.ts.map +1 -0
- package/lib/services/agent/tools/generateScript.tool.js +123 -0
- package/lib/services/agent/tools/generateVideo.tool.d.ts +1 -0
- package/lib/services/agent/tools/generateVideo.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/generateVideo.tool.js +20 -1
- package/lib/services/agent/tools/index.d.ts +4 -0
- package/lib/services/agent/tools/index.d.ts.map +1 -1
- package/lib/services/agent/tools/index.js +4 -0
- package/lib/services/agent/tools/matchBrollToScript.tool.d.ts +50 -0
- package/lib/services/agent/tools/matchBrollToScript.tool.d.ts.map +1 -0
- package/lib/services/agent/tools/matchBrollToScript.tool.js +139 -0
- package/lib/services/agent/tools/planVideo.tool.d.ts +56 -0
- package/lib/services/agent/tools/planVideo.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/planVideo.tool.js +3 -3
- package/lib/services/agent/tools/render.tool.d.ts +21 -0
- package/lib/services/agent/tools/render.tool.d.ts.map +1 -1
- package/lib/services/aiGen/aiGenFactory.service.d.ts.map +1 -1
- package/lib/services/aiGen/aiGenFactory.service.js +18 -3
- package/lib/services/aiGen/providers/anthropic/anthropic.service.d.ts +26 -0
- package/lib/services/aiGen/providers/anthropic/anthropic.service.d.ts.map +1 -0
- package/lib/services/aiGen/providers/anthropic/anthropic.service.js +95 -0
- package/lib/services/aiGen/providers/google/google.service.d.ts +24 -1
- package/lib/services/aiGen/providers/google/google.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/google/google.service.js +87 -243
- package/lib/services/aiGen/providers/google/googleErrors.d.ts +13 -0
- package/lib/services/aiGen/providers/google/googleErrors.d.ts.map +1 -0
- package/lib/services/aiGen/providers/google/googleErrors.js +102 -0
- package/lib/services/aiGen/providers/google/googleFetch.d.ts +8 -0
- package/lib/services/aiGen/providers/google/googleFetch.d.ts.map +1 -0
- package/lib/services/aiGen/providers/google/googleFetch.js +96 -0
- package/lib/services/aiGen/providers/google/googleMusic.d.ts +15 -0
- package/lib/services/aiGen/providers/google/googleMusic.d.ts.map +1 -0
- package/lib/services/aiGen/providers/google/googleMusic.js +77 -0
- package/lib/services/aiGen/providers/kling/kling.service.d.ts +7 -3
- package/lib/services/aiGen/providers/kling/kling.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/kling/kling.service.js +23 -367
- package/lib/services/aiGen/providers/kling/klingCredits.d.ts +9 -0
- package/lib/services/aiGen/providers/kling/klingCredits.d.ts.map +1 -0
- package/lib/services/aiGen/providers/kling/klingCredits.js +63 -0
- package/lib/services/aiGen/providers/kling/klingRequests.d.ts +32 -0
- package/lib/services/aiGen/providers/kling/klingRequests.d.ts.map +1 -0
- package/lib/services/aiGen/providers/kling/klingRequests.js +194 -0
- package/lib/services/aiGen/providers/kling/klingStatus.d.ts +16 -0
- package/lib/services/aiGen/providers/kling/klingStatus.d.ts.map +1 -0
- package/lib/services/aiGen/providers/kling/klingStatus.js +173 -0
- package/lib/services/bullmq.service.d.ts +61 -0
- package/lib/services/bullmq.service.d.ts.map +1 -1
- package/lib/services/bullmq.service.js +101 -1
- package/lib/services/crypto/index.d.ts +2 -0
- package/lib/services/crypto/index.d.ts.map +1 -0
- package/lib/services/crypto/index.js +17 -0
- package/lib/services/crypto/tokenVault.d.ts +47 -0
- package/lib/services/crypto/tokenVault.d.ts.map +1 -0
- package/lib/services/crypto/tokenVault.js +179 -0
- package/lib/services/editor/captionStyleHint.d.ts +3 -0
- package/lib/services/editor/captionStyleHint.d.ts.map +1 -0
- package/lib/services/editor/captionStyleHint.js +112 -0
- package/lib/services/editor/planToProject.d.ts +7 -66
- package/lib/services/editor/planToProject.d.ts.map +1 -1
- package/lib/services/editor/planToProject.helpers.d.ts +40 -0
- package/lib/services/editor/planToProject.helpers.d.ts.map +1 -0
- package/lib/services/editor/planToProject.helpers.js +177 -0
- package/lib/services/editor/planToProject.js +197 -180
- package/lib/services/editor/planToProject.types.d.ts +94 -0
- package/lib/services/editor/planToProject.types.d.ts.map +1 -0
- package/lib/services/editor/planToProject.types.js +2 -0
- package/lib/services/firestore.service.d.ts +5 -0
- package/lib/services/firestore.service.d.ts.map +1 -1
- package/lib/services/firestore.service.js +13 -0
- package/lib/services/index.d.ts +12 -0
- package/lib/services/index.d.ts.map +1 -1
- package/lib/services/index.js +12 -0
- package/lib/services/promptEnhancer/index.d.ts +18 -0
- package/lib/services/promptEnhancer/index.d.ts.map +1 -0
- package/lib/services/promptEnhancer/index.js +33 -0
- package/lib/services/promptEnhancer/models.d.ts +54 -0
- package/lib/services/promptEnhancer/models.d.ts.map +1 -0
- package/lib/services/promptEnhancer/models.js +37 -0
- package/lib/services/promptEnhancer/profiles/agent.profile.d.ts +14 -0
- package/lib/services/promptEnhancer/profiles/agent.profile.d.ts.map +1 -0
- package/lib/services/promptEnhancer/profiles/agent.profile.js +40 -0
- package/lib/services/promptEnhancer/profiles/avatar.profile.d.ts +13 -0
- package/lib/services/promptEnhancer/profiles/avatar.profile.d.ts.map +1 -0
- package/lib/services/promptEnhancer/profiles/avatar.profile.js +40 -0
- package/lib/services/promptEnhancer/profiles/base.d.ts +28 -0
- package/lib/services/promptEnhancer/profiles/base.d.ts.map +1 -0
- package/lib/services/promptEnhancer/profiles/base.js +35 -0
- package/lib/services/promptEnhancer/profiles/image.profile.d.ts +11 -0
- package/lib/services/promptEnhancer/profiles/image.profile.d.ts.map +1 -0
- package/lib/services/promptEnhancer/profiles/image.profile.js +42 -0
- package/lib/services/promptEnhancer/profiles/index.d.ts +12 -0
- package/lib/services/promptEnhancer/profiles/index.d.ts.map +1 -0
- package/lib/services/promptEnhancer/profiles/index.js +33 -0
- package/lib/services/promptEnhancer/profiles/video.profile.d.ts +15 -0
- package/lib/services/promptEnhancer/profiles/video.profile.d.ts.map +1 -0
- package/lib/services/promptEnhancer/profiles/video.profile.js +81 -0
- package/lib/services/promptEnhancer/promptEnhancer.service.d.ts +45 -0
- package/lib/services/promptEnhancer/promptEnhancer.service.d.ts.map +1 -0
- package/lib/services/promptEnhancer/promptEnhancer.service.js +157 -0
- package/lib/services/promptEnhancer/schema.d.ts +19 -0
- package/lib/services/promptEnhancer/schema.d.ts.map +1 -0
- package/lib/services/promptEnhancer/schema.js +43 -0
- package/lib/services/promptEnhancer/types.d.ts +112 -0
- package/lib/services/promptEnhancer/types.d.ts.map +1 -0
- package/lib/services/promptEnhancer/types.js +2 -0
- package/lib/services/socialAI/captionGen.d.ts +81 -0
- package/lib/services/socialAI/captionGen.d.ts.map +1 -0
- package/lib/services/socialAI/captionGen.js +206 -0
- package/lib/services/socialAI/hookScore.d.ts +85 -0
- package/lib/services/socialAI/hookScore.d.ts.map +1 -0
- package/lib/services/socialAI/hookScore.js +170 -0
- package/lib/services/socialAI/index.d.ts +3 -0
- package/lib/services/socialAI/index.d.ts.map +1 -0
- package/lib/services/socialAI/index.js +18 -0
- package/lib/services/socialAccounts/index.d.ts +2 -0
- package/lib/services/socialAccounts/index.d.ts.map +1 -0
- package/lib/services/socialAccounts/index.js +17 -0
- package/lib/services/socialAccounts/socialAccountService.d.ts +25 -0
- package/lib/services/socialAccounts/socialAccountService.d.ts.map +1 -0
- package/lib/services/socialAccounts/socialAccountService.js +105 -0
- package/lib/services/socialEngage/factory.d.ts +7 -0
- package/lib/services/socialEngage/factory.d.ts.map +1 -0
- package/lib/services/socialEngage/factory.js +25 -0
- package/lib/services/socialEngage/index.d.ts +6 -0
- package/lib/services/socialEngage/index.d.ts.map +1 -0
- package/lib/services/socialEngage/index.js +21 -0
- package/lib/services/socialEngage/meta.engage.d.ts +17 -0
- package/lib/services/socialEngage/meta.engage.d.ts.map +1 -0
- package/lib/services/socialEngage/meta.engage.js +128 -0
- package/lib/services/socialEngage/metaWebhook.d.ts +50 -0
- package/lib/services/socialEngage/metaWebhook.d.ts.map +1 -0
- package/lib/services/socialEngage/metaWebhook.js +93 -0
- package/lib/services/socialEngage/types.d.ts +72 -0
- package/lib/services/socialEngage/types.d.ts.map +1 -0
- package/lib/services/socialEngage/types.js +10 -0
- package/lib/services/socialEngage/youtube.engage.d.ts +9 -0
- package/lib/services/socialEngage/youtube.engage.d.ts.map +1 -0
- package/lib/services/socialEngage/youtube.engage.js +87 -0
- package/lib/services/socialFormat/aspectGeometry.d.ts +74 -0
- package/lib/services/socialFormat/aspectGeometry.d.ts.map +1 -0
- package/lib/services/socialFormat/aspectGeometry.js +135 -0
- package/lib/services/socialFormat/index.d.ts +2 -0
- package/lib/services/socialFormat/index.d.ts.map +1 -0
- package/lib/services/socialFormat/index.js +19 -0
- package/lib/services/socialInsights/index.d.ts +3 -0
- package/lib/services/socialInsights/index.d.ts.map +1 -0
- package/lib/services/socialInsights/index.js +18 -0
- package/lib/services/socialInsights/recommendations.d.ts +131 -0
- package/lib/services/socialInsights/recommendations.d.ts.map +1 -0
- package/lib/services/socialInsights/recommendations.js +277 -0
- package/lib/services/socialInsights/timeBuckets.d.ts +35 -0
- package/lib/services/socialInsights/timeBuckets.d.ts.map +1 -0
- package/lib/services/socialInsights/timeBuckets.js +78 -0
- package/lib/services/socialMetrics/factory.d.ts +5 -0
- package/lib/services/socialMetrics/factory.d.ts.map +1 -0
- package/lib/services/socialMetrics/factory.js +24 -0
- package/lib/services/socialMetrics/index.d.ts +6 -0
- package/lib/services/socialMetrics/index.d.ts.map +1 -0
- package/lib/services/socialMetrics/index.js +21 -0
- package/lib/services/socialMetrics/meta.metrics.d.ts +22 -0
- package/lib/services/socialMetrics/meta.metrics.d.ts.map +1 -0
- package/lib/services/socialMetrics/meta.metrics.js +137 -0
- package/lib/services/socialMetrics/tiktok.metrics.d.ts +8 -0
- package/lib/services/socialMetrics/tiktok.metrics.d.ts.map +1 -0
- package/lib/services/socialMetrics/tiktok.metrics.js +43 -0
- package/lib/services/socialMetrics/types.d.ts +54 -0
- package/lib/services/socialMetrics/types.d.ts.map +1 -0
- package/lib/services/socialMetrics/types.js +2 -0
- package/lib/services/socialMetrics/youtube.metrics.d.ts +8 -0
- package/lib/services/socialMetrics/youtube.metrics.d.ts.map +1 -0
- package/lib/services/socialMetrics/youtube.metrics.js +43 -0
- package/lib/services/socialOAuth/factory.d.ts +7 -0
- package/lib/services/socialOAuth/factory.d.ts.map +1 -0
- package/lib/services/socialOAuth/factory.js +42 -0
- package/lib/services/socialOAuth/index.d.ts +11 -0
- package/lib/services/socialOAuth/index.d.ts.map +1 -0
- package/lib/services/socialOAuth/index.js +26 -0
- package/lib/services/socialOAuth/linkedin.oauth.d.ts +14 -0
- package/lib/services/socialOAuth/linkedin.oauth.d.ts.map +1 -0
- package/lib/services/socialOAuth/linkedin.oauth.js +127 -0
- package/lib/services/socialOAuth/meta.oauth.d.ts +31 -0
- package/lib/services/socialOAuth/meta.oauth.d.ts.map +1 -0
- package/lib/services/socialOAuth/meta.oauth.js +214 -0
- package/lib/services/socialOAuth/oauthState.d.ts +14 -0
- package/lib/services/socialOAuth/oauthState.d.ts.map +1 -0
- package/lib/services/socialOAuth/oauthState.js +66 -0
- package/lib/services/socialOAuth/pinterest.oauth.d.ts +15 -0
- package/lib/services/socialOAuth/pinterest.oauth.d.ts.map +1 -0
- package/lib/services/socialOAuth/pinterest.oauth.js +126 -0
- package/lib/services/socialOAuth/threads.oauth.d.ts +14 -0
- package/lib/services/socialOAuth/threads.oauth.d.ts.map +1 -0
- package/lib/services/socialOAuth/threads.oauth.js +129 -0
- package/lib/services/socialOAuth/tiktok.oauth.d.ts +15 -0
- package/lib/services/socialOAuth/tiktok.oauth.d.ts.map +1 -0
- package/lib/services/socialOAuth/tiktok.oauth.js +151 -0
- package/lib/services/socialOAuth/types.d.ts +67 -0
- package/lib/services/socialOAuth/types.d.ts.map +1 -0
- package/lib/services/socialOAuth/types.js +2 -0
- package/lib/services/socialOAuth/x.oauth.d.ts +17 -0
- package/lib/services/socialOAuth/x.oauth.d.ts.map +1 -0
- package/lib/services/socialOAuth/x.oauth.js +134 -0
- package/lib/services/socialOAuth/youtube.oauth.d.ts +15 -0
- package/lib/services/socialOAuth/youtube.oauth.d.ts.map +1 -0
- package/lib/services/socialOAuth/youtube.oauth.js +156 -0
- package/lib/services/socialPublish/factory.d.ts +5 -0
- package/lib/services/socialPublish/factory.d.ts.map +1 -0
- package/lib/services/socialPublish/factory.js +32 -0
- package/lib/services/socialPublish/index.d.ts +10 -0
- package/lib/services/socialPublish/index.d.ts.map +1 -0
- package/lib/services/socialPublish/index.js +25 -0
- package/lib/services/socialPublish/linkedin.publish.d.ts +9 -0
- package/lib/services/socialPublish/linkedin.publish.d.ts.map +1 -0
- package/lib/services/socialPublish/linkedin.publish.js +143 -0
- package/lib/services/socialPublish/meta.publish.d.ts +28 -0
- package/lib/services/socialPublish/meta.publish.d.ts.map +1 -0
- package/lib/services/socialPublish/meta.publish.js +149 -0
- package/lib/services/socialPublish/pinterest.publish.d.ts +13 -0
- package/lib/services/socialPublish/pinterest.publish.d.ts.map +1 -0
- package/lib/services/socialPublish/pinterest.publish.js +130 -0
- package/lib/services/socialPublish/threads.publish.d.ts +12 -0
- package/lib/services/socialPublish/threads.publish.d.ts.map +1 -0
- package/lib/services/socialPublish/threads.publish.js +96 -0
- package/lib/services/socialPublish/tiktok.publish.d.ts +13 -0
- package/lib/services/socialPublish/tiktok.publish.d.ts.map +1 -0
- package/lib/services/socialPublish/tiktok.publish.js +118 -0
- package/lib/services/socialPublish/types.d.ts +47 -0
- package/lib/services/socialPublish/types.d.ts.map +1 -0
- package/lib/services/socialPublish/types.js +2 -0
- package/lib/services/socialPublish/x.publish.d.ts +12 -0
- package/lib/services/socialPublish/x.publish.d.ts.map +1 -0
- package/lib/services/socialPublish/x.publish.js +147 -0
- package/lib/services/socialPublish/youtube.publish.d.ts +9 -0
- package/lib/services/socialPublish/youtube.publish.d.ts.map +1 -0
- package/lib/services/socialPublish/youtube.publish.js +107 -0
- package/lib/services/stock/index.d.ts +2 -0
- package/lib/services/stock/index.d.ts.map +1 -0
- package/lib/services/stock/index.js +17 -0
- package/lib/services/stock/realPersonSafety.d.ts +99 -0
- package/lib/services/stock/realPersonSafety.d.ts.map +1 -0
- package/lib/services/stock/realPersonSafety.js +248 -0
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.d.ts.map +1 -1
- package/lib/utils/index.js +1 -0
- package/lib/utils/renderTier.d.ts +26 -0
- package/lib/utils/renderTier.d.ts.map +1 -0
- package/lib/utils/renderTier.js +34 -0
- package/package.json +1 -1
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.YouTubeOAuthProvider = void 0;
|
|
4
|
+
const types_1 = require("../../globals/types");
|
|
5
|
+
const logger_1 = require("../../utils/logger");
|
|
6
|
+
/**
|
|
7
|
+
* YouTube (Google) OAuth 2.0 provider. Phase 1 of the Social Suite — the first
|
|
8
|
+
* end-to-end platform (cleanest API + native scheduling). See SOCIAL_SUITE_PLAN.md.
|
|
9
|
+
*
|
|
10
|
+
* Config (env):
|
|
11
|
+
* GOOGLE_OAUTH_CLIENT_ID — OAuth client id (Web application)
|
|
12
|
+
* GOOGLE_OAUTH_CLIENT_SECRET — OAuth client secret
|
|
13
|
+
*
|
|
14
|
+
* Notes:
|
|
15
|
+
* - `access_type=offline` + `prompt=consent` are required to reliably receive a
|
|
16
|
+
* refresh token (Google only returns it on first consent unless prompted).
|
|
17
|
+
* - While the OAuth app is in "Testing", refresh tokens expire after 7 days —
|
|
18
|
+
* publish the consent screen before production. (Plan §3.)
|
|
19
|
+
*/
|
|
20
|
+
const AUTH_ENDPOINT = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
21
|
+
const TOKEN_ENDPOINT = "https://oauth2.googleapis.com/token";
|
|
22
|
+
const REVOKE_ENDPOINT = "https://oauth2.googleapis.com/revoke";
|
|
23
|
+
const CHANNELS_ENDPOINT = "https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true";
|
|
24
|
+
/** Scopes needed to upload + read analytics + manage comments. */
|
|
25
|
+
const BASE_SCOPES = [
|
|
26
|
+
"https://www.googleapis.com/auth/youtube.upload",
|
|
27
|
+
"https://www.googleapis.com/auth/youtube.readonly",
|
|
28
|
+
"https://www.googleapis.com/auth/yt-analytics.readonly",
|
|
29
|
+
];
|
|
30
|
+
/** force-ssl is required for comment list/insert/moderate (premium engage). */
|
|
31
|
+
const COMMENT_SCOPES = ["https://www.googleapis.com/auth/youtube.force-ssl"];
|
|
32
|
+
class YouTubeOAuthProvider {
|
|
33
|
+
constructor() {
|
|
34
|
+
this.provider = types_1.ESocialProvider.YOUTUBE;
|
|
35
|
+
}
|
|
36
|
+
clientId() {
|
|
37
|
+
const id = process.env.GOOGLE_OAUTH_CLIENT_ID;
|
|
38
|
+
if (!id)
|
|
39
|
+
throw new Error("YouTubeOAuth: GOOGLE_OAUTH_CLIENT_ID not set");
|
|
40
|
+
return id;
|
|
41
|
+
}
|
|
42
|
+
clientSecret() {
|
|
43
|
+
const secret = process.env.GOOGLE_OAUTH_CLIENT_SECRET;
|
|
44
|
+
if (!secret)
|
|
45
|
+
throw new Error("YouTubeOAuth: GOOGLE_OAUTH_CLIENT_SECRET not set");
|
|
46
|
+
return secret;
|
|
47
|
+
}
|
|
48
|
+
getAuthUrl({ state, redirectUri, requestBusinessScopes, }) {
|
|
49
|
+
const scopes = requestBusinessScopes
|
|
50
|
+
? [...BASE_SCOPES, ...COMMENT_SCOPES]
|
|
51
|
+
: BASE_SCOPES;
|
|
52
|
+
const params = new URLSearchParams({
|
|
53
|
+
client_id: this.clientId(),
|
|
54
|
+
redirect_uri: redirectUri,
|
|
55
|
+
response_type: "code",
|
|
56
|
+
scope: scopes.join(" "),
|
|
57
|
+
access_type: "offline",
|
|
58
|
+
include_granted_scopes: "true",
|
|
59
|
+
prompt: "consent",
|
|
60
|
+
state,
|
|
61
|
+
});
|
|
62
|
+
return `${AUTH_ENDPOINT}?${params.toString()}`;
|
|
63
|
+
}
|
|
64
|
+
async exchangeCode({ code, redirectUri, }) {
|
|
65
|
+
const body = new URLSearchParams({
|
|
66
|
+
code,
|
|
67
|
+
client_id: this.clientId(),
|
|
68
|
+
client_secret: this.clientSecret(),
|
|
69
|
+
redirect_uri: redirectUri,
|
|
70
|
+
grant_type: "authorization_code",
|
|
71
|
+
});
|
|
72
|
+
const token = await this.postToken(body);
|
|
73
|
+
if (!token.access_token) {
|
|
74
|
+
throw new Error("YouTubeOAuth: token exchange returned no access_token");
|
|
75
|
+
}
|
|
76
|
+
const tokens = this.toTokens(token);
|
|
77
|
+
const account = await this.resolveAccount(token.access_token);
|
|
78
|
+
return { account, tokens };
|
|
79
|
+
}
|
|
80
|
+
async refresh(refreshToken) {
|
|
81
|
+
const body = new URLSearchParams({
|
|
82
|
+
client_id: this.clientId(),
|
|
83
|
+
client_secret: this.clientSecret(),
|
|
84
|
+
refresh_token: refreshToken,
|
|
85
|
+
grant_type: "refresh_token",
|
|
86
|
+
});
|
|
87
|
+
const token = await this.postToken(body);
|
|
88
|
+
if (!token.access_token) {
|
|
89
|
+
throw new Error("YouTubeOAuth: refresh returned no access_token");
|
|
90
|
+
}
|
|
91
|
+
// Google does not re-issue a refresh token on refresh; preserve the old one.
|
|
92
|
+
const tokens = this.toTokens(token);
|
|
93
|
+
if (!tokens.refreshToken)
|
|
94
|
+
tokens.refreshToken = refreshToken;
|
|
95
|
+
return tokens;
|
|
96
|
+
}
|
|
97
|
+
async revoke(token) {
|
|
98
|
+
try {
|
|
99
|
+
await fetch(REVOKE_ENDPOINT, {
|
|
100
|
+
method: "POST",
|
|
101
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
102
|
+
body: new URLSearchParams({ token }).toString(),
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
logger_1.logger.warn("YouTubeOAuth.revoke: failed (non-fatal)", {
|
|
107
|
+
error: err instanceof Error ? err.message : String(err),
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
async postToken(body) {
|
|
112
|
+
const resp = await fetch(TOKEN_ENDPOINT, {
|
|
113
|
+
method: "POST",
|
|
114
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
115
|
+
body: body.toString(),
|
|
116
|
+
});
|
|
117
|
+
const json = (await resp.json());
|
|
118
|
+
if (!resp.ok || json.error) {
|
|
119
|
+
throw new Error(`YouTubeOAuth: token endpoint ${resp.status} ${json.error ?? ""} ${json.error_description ?? ""}`.trim());
|
|
120
|
+
}
|
|
121
|
+
return json;
|
|
122
|
+
}
|
|
123
|
+
toTokens(token) {
|
|
124
|
+
const expiresInMs = (token.expires_in ?? 3600) * 1000;
|
|
125
|
+
return {
|
|
126
|
+
accessToken: token.access_token,
|
|
127
|
+
refreshToken: token.refresh_token,
|
|
128
|
+
expiresAt: Date.now() + expiresInMs,
|
|
129
|
+
scopes: token.scope ? token.scope.split(" ").filter(Boolean) : [],
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
async resolveAccount(accessToken) {
|
|
133
|
+
const resp = await fetch(CHANNELS_ENDPOINT, {
|
|
134
|
+
headers: { Authorization: `Bearer ${accessToken}` },
|
|
135
|
+
});
|
|
136
|
+
if (!resp.ok) {
|
|
137
|
+
throw new Error(`YouTubeOAuth: channels lookup ${resp.status}`);
|
|
138
|
+
}
|
|
139
|
+
const json = (await resp.json());
|
|
140
|
+
const channel = json.items?.[0];
|
|
141
|
+
if (!channel?.id) {
|
|
142
|
+
throw new Error("YouTubeOAuth: no channel on this Google account");
|
|
143
|
+
}
|
|
144
|
+
const thumb = channel.snippet?.thumbnails?.high?.url ??
|
|
145
|
+
channel.snippet?.thumbnails?.default?.url;
|
|
146
|
+
return {
|
|
147
|
+
providerAccountId: channel.id,
|
|
148
|
+
displayName: channel.snippet?.title ?? "YouTube channel",
|
|
149
|
+
handle: channel.snippet?.customUrl,
|
|
150
|
+
avatarUrl: thumb,
|
|
151
|
+
// YouTube has no API "business" flag; channels are creator-grade by default.
|
|
152
|
+
kind: types_1.ESocialAccountKind.CREATOR,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
exports.YouTubeOAuthProvider = YouTubeOAuthProvider;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ESocialProvider } from "../../globals/types";
|
|
2
|
+
import { ISocialPublisher } from "./types";
|
|
3
|
+
export declare function getSocialPublisher(provider: ESocialProvider): ISocialPublisher;
|
|
4
|
+
export declare function isSocialPublishSupported(provider: ESocialProvider): boolean;
|
|
5
|
+
//# sourceMappingURL=factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/services/socialPublish/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAMtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAe3C,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,eAAe,GACxB,gBAAgB,CAMlB;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAE3E"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getSocialPublisher = getSocialPublisher;
|
|
4
|
+
exports.isSocialPublishSupported = isSocialPublishSupported;
|
|
5
|
+
const types_1 = require("../../globals/types");
|
|
6
|
+
const linkedin_publish_1 = require("./linkedin.publish");
|
|
7
|
+
const meta_publish_1 = require("./meta.publish");
|
|
8
|
+
const pinterest_publish_1 = require("./pinterest.publish");
|
|
9
|
+
const threads_publish_1 = require("./threads.publish");
|
|
10
|
+
const tiktok_publish_1 = require("./tiktok.publish");
|
|
11
|
+
const x_publish_1 = require("./x.publish");
|
|
12
|
+
const youtube_publish_1 = require("./youtube.publish");
|
|
13
|
+
const registry = {
|
|
14
|
+
[types_1.ESocialProvider.YOUTUBE]: () => new youtube_publish_1.YouTubePublisher(),
|
|
15
|
+
[types_1.ESocialProvider.INSTAGRAM]: () => new meta_publish_1.InstagramPublisher(),
|
|
16
|
+
[types_1.ESocialProvider.FACEBOOK]: () => new meta_publish_1.FacebookPublisher(),
|
|
17
|
+
[types_1.ESocialProvider.TIKTOK]: () => new tiktok_publish_1.TikTokPublisher(),
|
|
18
|
+
[types_1.ESocialProvider.THREADS]: () => new threads_publish_1.ThreadsPublisher(),
|
|
19
|
+
[types_1.ESocialProvider.LINKEDIN]: () => new linkedin_publish_1.LinkedInPublisher(),
|
|
20
|
+
[types_1.ESocialProvider.X]: () => new x_publish_1.XPublisher(),
|
|
21
|
+
[types_1.ESocialProvider.PINTEREST]: () => new pinterest_publish_1.PinterestPublisher(),
|
|
22
|
+
};
|
|
23
|
+
function getSocialPublisher(provider) {
|
|
24
|
+
const make = registry[provider];
|
|
25
|
+
if (!make) {
|
|
26
|
+
throw new Error(`Social publishing not implemented for '${provider}'`);
|
|
27
|
+
}
|
|
28
|
+
return make();
|
|
29
|
+
}
|
|
30
|
+
function isSocialPublishSupported(provider) {
|
|
31
|
+
return Boolean(registry[provider]);
|
|
32
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from "./types";
|
|
2
|
+
export * from "./youtube.publish";
|
|
3
|
+
export * from "./meta.publish";
|
|
4
|
+
export * from "./tiktok.publish";
|
|
5
|
+
export * from "./threads.publish";
|
|
6
|
+
export * from "./linkedin.publish";
|
|
7
|
+
export * from "./x.publish";
|
|
8
|
+
export * from "./pinterest.publish";
|
|
9
|
+
export * from "./factory";
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/socialPublish/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,WAAW,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./types"), exports);
|
|
18
|
+
__exportStar(require("./youtube.publish"), exports);
|
|
19
|
+
__exportStar(require("./meta.publish"), exports);
|
|
20
|
+
__exportStar(require("./tiktok.publish"), exports);
|
|
21
|
+
__exportStar(require("./threads.publish"), exports);
|
|
22
|
+
__exportStar(require("./linkedin.publish"), exports);
|
|
23
|
+
__exportStar(require("./x.publish"), exports);
|
|
24
|
+
__exportStar(require("./pinterest.publish"), exports);
|
|
25
|
+
__exportStar(require("./factory"), exports);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ESocialProvider } from "../../globals/types";
|
|
2
|
+
import { ISocialPublisher, PublishInput, PublishResult } from "./types";
|
|
3
|
+
export declare class LinkedInPublisher implements ISocialPublisher {
|
|
4
|
+
readonly provider = ESocialProvider.LINKEDIN;
|
|
5
|
+
publish(input: PublishInput): Promise<PublishResult>;
|
|
6
|
+
private resolveVisibility;
|
|
7
|
+
private buildCommentary;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=linkedin.publish.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linkedin.publish.d.ts","sourceRoot":"","sources":["../../../src/services/socialPublish/linkedin.publish.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AA0CxE,qBAAa,iBAAkB,YAAW,gBAAgB;IACxD,QAAQ,CAAC,QAAQ,4BAA4B;IAEvC,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;IAwG1D,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,eAAe;CAQxB"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LinkedInPublisher = void 0;
|
|
4
|
+
const types_1 = require("../../globals/types");
|
|
5
|
+
const logger_1 = require("../../utils/logger");
|
|
6
|
+
/**
|
|
7
|
+
* LinkedIn publisher — Phase 6. Member-feed video via the versioned Videos +
|
|
8
|
+
* Posts REST API:
|
|
9
|
+
* 1. POST /rest/videos?action=initializeUpload → video URN + upload URL(s)
|
|
10
|
+
* 2. PUT the bytes to each upload URL → collect ETags
|
|
11
|
+
* 3. POST /rest/videos?action=finalizeUpload (uploadedPartIds = ETags)
|
|
12
|
+
* 4. POST /rest/posts (author, commentary, content.media = video URN)
|
|
13
|
+
*
|
|
14
|
+
* Author = urn:li:person:{providerAccountId}. Company-page posting (author =
|
|
15
|
+
* urn:li:organization:{id}) is a business-tier follow-on. No native scheduling.
|
|
16
|
+
*
|
|
17
|
+
* Config (env): LINKEDIN_API_VERSION (optional, default "202401").
|
|
18
|
+
*/
|
|
19
|
+
const REST_BASE = "https://api.linkedin.com/rest";
|
|
20
|
+
function apiVersion() {
|
|
21
|
+
return process.env.LINKEDIN_API_VERSION || "202401";
|
|
22
|
+
}
|
|
23
|
+
function headers(token) {
|
|
24
|
+
return {
|
|
25
|
+
Authorization: `Bearer ${token}`,
|
|
26
|
+
"Content-Type": "application/json",
|
|
27
|
+
"LinkedIn-Version": apiVersion(),
|
|
28
|
+
"X-Restli-Protocol-Version": "2.0.0",
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
class LinkedInPublisher {
|
|
32
|
+
constructor() {
|
|
33
|
+
this.provider = types_1.ESocialProvider.LINKEDIN;
|
|
34
|
+
}
|
|
35
|
+
async publish(input) {
|
|
36
|
+
const memberId = input.providerAccountId;
|
|
37
|
+
if (!memberId) {
|
|
38
|
+
throw new Error("LinkedInPublisher: missing providerAccountId (member id)");
|
|
39
|
+
}
|
|
40
|
+
const author = `urn:li:person:${memberId}`;
|
|
41
|
+
const token = input.accessToken;
|
|
42
|
+
// 0. Fetch the media bytes (worker passes a public/rendered URL).
|
|
43
|
+
const mediaResp = await fetch(input.mediaUrl);
|
|
44
|
+
if (!mediaResp.ok) {
|
|
45
|
+
throw new Error(`LinkedInPublisher: media fetch ${mediaResp.status}`);
|
|
46
|
+
}
|
|
47
|
+
const bytes = Buffer.from(await mediaResp.arrayBuffer());
|
|
48
|
+
// 1. Initialize the upload.
|
|
49
|
+
const initResp = await fetch(`${REST_BASE}/videos?action=initializeUpload`, {
|
|
50
|
+
method: "POST",
|
|
51
|
+
headers: headers(token),
|
|
52
|
+
body: JSON.stringify({
|
|
53
|
+
initializeUploadRequest: {
|
|
54
|
+
owner: author,
|
|
55
|
+
fileSizeBytes: bytes.length,
|
|
56
|
+
uploadCaptions: false,
|
|
57
|
+
uploadThumbnail: false,
|
|
58
|
+
},
|
|
59
|
+
}),
|
|
60
|
+
});
|
|
61
|
+
const init = (await initResp.json());
|
|
62
|
+
const videoUrn = init.value?.video;
|
|
63
|
+
const instructions = init.value?.uploadInstructions ?? [];
|
|
64
|
+
if (!initResp.ok || !videoUrn || instructions.length === 0) {
|
|
65
|
+
throw new Error(`LinkedInPublisher: initializeUpload ${initResp.status} ${init.error?.message ?? ""}`.trim());
|
|
66
|
+
}
|
|
67
|
+
// 2. Upload each byte range; collect ETags in order.
|
|
68
|
+
const uploadedPartIds = [];
|
|
69
|
+
for (const instr of instructions) {
|
|
70
|
+
if (!instr.uploadUrl)
|
|
71
|
+
continue;
|
|
72
|
+
const first = instr.firstByte ?? 0;
|
|
73
|
+
const last = instr.lastByte ?? bytes.length - 1;
|
|
74
|
+
const chunk = bytes.subarray(first, last + 1);
|
|
75
|
+
const putResp = await fetch(instr.uploadUrl, {
|
|
76
|
+
method: "PUT",
|
|
77
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
78
|
+
body: chunk,
|
|
79
|
+
});
|
|
80
|
+
if (!putResp.ok) {
|
|
81
|
+
throw new Error(`LinkedInPublisher: chunk upload ${putResp.status}`);
|
|
82
|
+
}
|
|
83
|
+
const etag = putResp.headers.get("etag");
|
|
84
|
+
if (etag)
|
|
85
|
+
uploadedPartIds.push(etag.replace(/"/g, ""));
|
|
86
|
+
}
|
|
87
|
+
// 3. Finalize the upload.
|
|
88
|
+
const finalizeResp = await fetch(`${REST_BASE}/videos?action=finalizeUpload`, {
|
|
89
|
+
method: "POST",
|
|
90
|
+
headers: headers(token),
|
|
91
|
+
body: JSON.stringify({
|
|
92
|
+
finalizeUploadRequest: { video: videoUrn, uploadToken: "", uploadedPartIds },
|
|
93
|
+
}),
|
|
94
|
+
});
|
|
95
|
+
if (!finalizeResp.ok) {
|
|
96
|
+
const text = await finalizeResp.text();
|
|
97
|
+
throw new Error(`LinkedInPublisher: finalizeUpload ${finalizeResp.status} ${text}`);
|
|
98
|
+
}
|
|
99
|
+
// 4. Create the post referencing the video URN.
|
|
100
|
+
const postResp = await fetch(`${REST_BASE}/posts`, {
|
|
101
|
+
method: "POST",
|
|
102
|
+
headers: headers(token),
|
|
103
|
+
body: JSON.stringify({
|
|
104
|
+
author,
|
|
105
|
+
commentary: this.buildCommentary(input),
|
|
106
|
+
visibility: this.resolveVisibility(input),
|
|
107
|
+
distribution: {
|
|
108
|
+
feedDistribution: "MAIN_FEED",
|
|
109
|
+
targetEntities: [],
|
|
110
|
+
thirdPartyDistributionChannels: [],
|
|
111
|
+
},
|
|
112
|
+
content: { media: { id: videoUrn, title: (input.title ?? "").slice(0, 200) } },
|
|
113
|
+
lifecycleState: "PUBLISHED",
|
|
114
|
+
isReshareDisabledByAuthor: false,
|
|
115
|
+
}),
|
|
116
|
+
});
|
|
117
|
+
if (!postResp.ok) {
|
|
118
|
+
const text = await postResp.text();
|
|
119
|
+
throw new Error(`LinkedInPublisher: create post ${postResp.status} ${text}`);
|
|
120
|
+
}
|
|
121
|
+
// The new post URN is returned in the x-restli-id (or x-linkedin-id) header.
|
|
122
|
+
const postUrn = postResp.headers.get("x-restli-id") ??
|
|
123
|
+
postResp.headers.get("x-linkedin-id") ??
|
|
124
|
+
videoUrn;
|
|
125
|
+
logger_1.logger.info("LinkedInPublisher: published", { postUrn });
|
|
126
|
+
return {
|
|
127
|
+
providerPostId: postUrn,
|
|
128
|
+
publishedUrl: `https://www.linkedin.com/feed/update/${postUrn}`,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
resolveVisibility(input) {
|
|
132
|
+
const p = (input.privacy ?? "public").toUpperCase();
|
|
133
|
+
return p === "CONNECTIONS" ? "CONNECTIONS" : "PUBLIC";
|
|
134
|
+
}
|
|
135
|
+
buildCommentary(input) {
|
|
136
|
+
const tags = input.hashtags && input.hashtags.length
|
|
137
|
+
? "\n\n" +
|
|
138
|
+
input.hashtags.map((h) => (h.startsWith("#") ? h : `#${h}`)).join(" ")
|
|
139
|
+
: "";
|
|
140
|
+
return `${input.caption ?? ""}${tags}`.trim().slice(0, 3000);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
exports.LinkedInPublisher = LinkedInPublisher;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ESocialProvider } from "../../globals/types";
|
|
2
|
+
import { ISocialPublisher, PublishInput, PublishResult } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Instagram publisher — Reels via the two-step container flow:
|
|
5
|
+
* 1. POST /{ig-user-id}/media (media_type=REELS, video_url, caption) → container
|
|
6
|
+
* 2. Poll /{container-id}?fields=status_code until FINISHED
|
|
7
|
+
* 3. POST /{ig-user-id}/media_publish (creation_id) → media id
|
|
8
|
+
* IG has no native API scheduling — the worker schedules via BullMQ delay, so we
|
|
9
|
+
* always publish immediately here.
|
|
10
|
+
*/
|
|
11
|
+
export declare class InstagramPublisher implements ISocialPublisher {
|
|
12
|
+
readonly provider = ESocialProvider.INSTAGRAM;
|
|
13
|
+
private readonly maxPolls;
|
|
14
|
+
private readonly pollDelayMs;
|
|
15
|
+
publish(input: PublishInput): Promise<PublishResult>;
|
|
16
|
+
private waitForContainer;
|
|
17
|
+
private resolvePermalink;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Facebook Page publisher — posts a video to the Page via /{page-id}/videos with
|
|
21
|
+
* a hosted `file_url` (Graph downloads it). Supports native scheduling through
|
|
22
|
+
* `published=false` + `scheduled_publish_time` (unix seconds, 10m–6mo out).
|
|
23
|
+
*/
|
|
24
|
+
export declare class FacebookPublisher implements ISocialPublisher {
|
|
25
|
+
readonly provider = ESocialProvider.FACEBOOK;
|
|
26
|
+
publish(input: PublishInput): Promise<PublishResult>;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=meta.publish.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meta.publish.d.ts","sourceRoot":"","sources":["../../../src/services/socialPublish/meta.publish.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AA+DxE;;;;;;;GAOG;AACH,qBAAa,kBAAmB,YAAW,gBAAgB;IACzD,QAAQ,CAAC,QAAQ,6BAA6B;IAE9C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAM;IAC/B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IAE9B,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;YAsC5C,gBAAgB;YAyBhB,gBAAgB;CAgB/B;AAED;;;;GAIG;AACH,qBAAa,iBAAkB,YAAW,gBAAgB;IACxD,QAAQ,CAAC,QAAQ,4BAA4B;IAEvC,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;CAmC3D"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FacebookPublisher = exports.InstagramPublisher = void 0;
|
|
4
|
+
const types_1 = require("../../globals/types");
|
|
5
|
+
const logger_1 = require("../../utils/logger");
|
|
6
|
+
/**
|
|
7
|
+
* Meta publishers — Phase 3. Instagram and Facebook both run on the Graph API
|
|
8
|
+
* but with different publish flows, so they are separate ISocialPublisher impls
|
|
9
|
+
* (registered under INSTAGRAM / FACEBOOK).
|
|
10
|
+
*
|
|
11
|
+
* Both take the managing Page access token (provided by MetaOAuthProvider) and
|
|
12
|
+
* the account's providerAccountId (IG user id / FB Page id) via PublishInput.
|
|
13
|
+
*
|
|
14
|
+
* Config (env): META_GRAPH_VERSION (optional, default v21.0).
|
|
15
|
+
*/
|
|
16
|
+
const DEFAULT_GRAPH_VERSION = "v21.0";
|
|
17
|
+
function graphVersion() {
|
|
18
|
+
return process.env.META_GRAPH_VERSION || DEFAULT_GRAPH_VERSION;
|
|
19
|
+
}
|
|
20
|
+
function graph(path) {
|
|
21
|
+
return `https://graph.facebook.com/${graphVersion()}${path}`;
|
|
22
|
+
}
|
|
23
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
24
|
+
function buildCaption(input) {
|
|
25
|
+
const tags = input.hashtags && input.hashtags.length
|
|
26
|
+
? "\n\n" +
|
|
27
|
+
input.hashtags.map((h) => (h.startsWith("#") ? h : `#${h}`)).join(" ")
|
|
28
|
+
: "";
|
|
29
|
+
return `${input.caption ?? ""}${tags}`.trim();
|
|
30
|
+
}
|
|
31
|
+
async function postForm(url, form) {
|
|
32
|
+
const resp = await fetch(url, {
|
|
33
|
+
method: "POST",
|
|
34
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
35
|
+
body: form.toString(),
|
|
36
|
+
});
|
|
37
|
+
const json = (await resp.json());
|
|
38
|
+
if (!resp.ok || json.error || !json.id) {
|
|
39
|
+
throw new Error(`Meta graph POST ${resp.status} ${json.error?.message ?? "no id returned"}`);
|
|
40
|
+
}
|
|
41
|
+
return json;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Instagram publisher — Reels via the two-step container flow:
|
|
45
|
+
* 1. POST /{ig-user-id}/media (media_type=REELS, video_url, caption) → container
|
|
46
|
+
* 2. Poll /{container-id}?fields=status_code until FINISHED
|
|
47
|
+
* 3. POST /{ig-user-id}/media_publish (creation_id) → media id
|
|
48
|
+
* IG has no native API scheduling — the worker schedules via BullMQ delay, so we
|
|
49
|
+
* always publish immediately here.
|
|
50
|
+
*/
|
|
51
|
+
class InstagramPublisher {
|
|
52
|
+
constructor() {
|
|
53
|
+
this.provider = types_1.ESocialProvider.INSTAGRAM;
|
|
54
|
+
this.maxPolls = 30;
|
|
55
|
+
this.pollDelayMs = 5000;
|
|
56
|
+
}
|
|
57
|
+
async publish(input) {
|
|
58
|
+
const igUserId = input.providerAccountId;
|
|
59
|
+
if (!igUserId) {
|
|
60
|
+
throw new Error("InstagramPublisher: missing providerAccountId (IG user id)");
|
|
61
|
+
}
|
|
62
|
+
// 1. Create the media container.
|
|
63
|
+
const container = await postForm(graph(`/${igUserId}/media`), new URLSearchParams({
|
|
64
|
+
media_type: "REELS",
|
|
65
|
+
video_url: input.mediaUrl,
|
|
66
|
+
caption: buildCaption(input),
|
|
67
|
+
access_token: input.accessToken,
|
|
68
|
+
}));
|
|
69
|
+
const creationId = container.id;
|
|
70
|
+
// 2. Poll until the upload/transcode finishes.
|
|
71
|
+
await this.waitForContainer(creationId, input.accessToken);
|
|
72
|
+
// 3. Publish the container.
|
|
73
|
+
const published = await postForm(graph(`/${igUserId}/media_publish`), new URLSearchParams({
|
|
74
|
+
creation_id: creationId,
|
|
75
|
+
access_token: input.accessToken,
|
|
76
|
+
}));
|
|
77
|
+
const mediaId = published.id;
|
|
78
|
+
logger_1.logger.info("InstagramPublisher: published", { igUserId, mediaId });
|
|
79
|
+
return {
|
|
80
|
+
providerPostId: mediaId,
|
|
81
|
+
publishedUrl: await this.resolvePermalink(mediaId, input.accessToken),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
async waitForContainer(containerId, accessToken) {
|
|
85
|
+
for (let i = 0; i < this.maxPolls; i++) {
|
|
86
|
+
const resp = await fetch(graph(`/${containerId}?fields=status_code,status&access_token=${encodeURIComponent(accessToken)}`));
|
|
87
|
+
const json = (await resp.json());
|
|
88
|
+
const code = json.status_code;
|
|
89
|
+
if (code === "FINISHED")
|
|
90
|
+
return;
|
|
91
|
+
if (code === "ERROR" || code === "EXPIRED") {
|
|
92
|
+
throw new Error(`InstagramPublisher: container ${code} ${json.status ?? ""}`.trim());
|
|
93
|
+
}
|
|
94
|
+
await sleep(this.pollDelayMs);
|
|
95
|
+
}
|
|
96
|
+
throw new Error(`InstagramPublisher: container not ready after ${this.maxPolls} polls`);
|
|
97
|
+
}
|
|
98
|
+
async resolvePermalink(mediaId, accessToken) {
|
|
99
|
+
try {
|
|
100
|
+
const resp = await fetch(graph(`/${mediaId}?fields=permalink&access_token=${encodeURIComponent(accessToken)}`));
|
|
101
|
+
const json = (await resp.json());
|
|
102
|
+
return json.permalink;
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
exports.InstagramPublisher = InstagramPublisher;
|
|
110
|
+
/**
|
|
111
|
+
* Facebook Page publisher — posts a video to the Page via /{page-id}/videos with
|
|
112
|
+
* a hosted `file_url` (Graph downloads it). Supports native scheduling through
|
|
113
|
+
* `published=false` + `scheduled_publish_time` (unix seconds, 10m–6mo out).
|
|
114
|
+
*/
|
|
115
|
+
class FacebookPublisher {
|
|
116
|
+
constructor() {
|
|
117
|
+
this.provider = types_1.ESocialProvider.FACEBOOK;
|
|
118
|
+
}
|
|
119
|
+
async publish(input) {
|
|
120
|
+
const pageId = input.providerAccountId;
|
|
121
|
+
if (!pageId) {
|
|
122
|
+
throw new Error("FacebookPublisher: missing providerAccountId (Page id)");
|
|
123
|
+
}
|
|
124
|
+
const form = new URLSearchParams({
|
|
125
|
+
file_url: input.mediaUrl,
|
|
126
|
+
description: buildCaption(input),
|
|
127
|
+
access_token: input.accessToken,
|
|
128
|
+
});
|
|
129
|
+
if (input.title)
|
|
130
|
+
form.set("title", input.title);
|
|
131
|
+
// Native scheduling: FB requires published=false + a unix-seconds timestamp.
|
|
132
|
+
if (input.scheduledAt && input.scheduledAt > Date.now()) {
|
|
133
|
+
form.set("published", "false");
|
|
134
|
+
form.set("scheduled_publish_time", String(Math.floor(input.scheduledAt / 1000)));
|
|
135
|
+
}
|
|
136
|
+
const result = await postForm(graph(`/${pageId}/videos`), form);
|
|
137
|
+
const videoId = result.id;
|
|
138
|
+
logger_1.logger.info("FacebookPublisher: published", {
|
|
139
|
+
pageId,
|
|
140
|
+
videoId,
|
|
141
|
+
scheduled: Boolean(input.scheduledAt),
|
|
142
|
+
});
|
|
143
|
+
return {
|
|
144
|
+
providerPostId: videoId,
|
|
145
|
+
publishedUrl: `https://www.facebook.com/watch/?v=${videoId}`,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
exports.FacebookPublisher = FacebookPublisher;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ESocialProvider } from "../../globals/types";
|
|
2
|
+
import { ISocialPublisher, PublishInput, PublishResult } from "./types";
|
|
3
|
+
export declare class PinterestPublisher implements ISocialPublisher {
|
|
4
|
+
readonly provider = ESocialProvider.PINTEREST;
|
|
5
|
+
private readonly maxPolls;
|
|
6
|
+
private readonly pollDelayMs;
|
|
7
|
+
publish(input: PublishInput): Promise<PublishResult>;
|
|
8
|
+
private firstBoardId;
|
|
9
|
+
private pollMedia;
|
|
10
|
+
private json;
|
|
11
|
+
private buildDescription;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=pinterest.publish.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pinterest.publish.d.ts","sourceRoot":"","sources":["../../../src/services/socialPublish/pinterest.publish.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAoCxE,qBAAa,kBAAmB,YAAW,gBAAgB;IACzD,QAAQ,CAAC,QAAQ,6BAA6B;IAE9C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAM;IAC/B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IAE9B,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;YA0E5C,YAAY;YAgBZ,SAAS;YAiBT,IAAI;IAQlB,OAAO,CAAC,gBAAgB;CAQzB"}
|