adaria-ai 0.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/LICENSE +21 -0
- package/README.md +21 -0
- package/apps.example.yaml +65 -0
- package/dist/agent/audit.d.ts +16 -0
- package/dist/agent/audit.d.ts.map +1 -0
- package/dist/agent/audit.js +42 -0
- package/dist/agent/audit.js.map +1 -0
- package/dist/agent/claude.d.ts +62 -0
- package/dist/agent/claude.d.ts.map +1 -0
- package/dist/agent/claude.js +297 -0
- package/dist/agent/claude.js.map +1 -0
- package/dist/agent/conversation-summary.d.ts +29 -0
- package/dist/agent/conversation-summary.d.ts.map +1 -0
- package/dist/agent/conversation-summary.js +221 -0
- package/dist/agent/conversation-summary.js.map +1 -0
- package/dist/agent/core.d.ts +81 -0
- package/dist/agent/core.d.ts.map +1 -0
- package/dist/agent/core.js +527 -0
- package/dist/agent/core.js.map +1 -0
- package/dist/agent/mcp-launcher.d.ts +42 -0
- package/dist/agent/mcp-launcher.d.ts.map +1 -0
- package/dist/agent/mcp-launcher.js +38 -0
- package/dist/agent/mcp-launcher.js.map +1 -0
- package/dist/agent/mcp-manager.d.ts +81 -0
- package/dist/agent/mcp-manager.d.ts.map +1 -0
- package/dist/agent/mcp-manager.js +136 -0
- package/dist/agent/mcp-manager.js.map +1 -0
- package/dist/agent/memory.d.ts +10 -0
- package/dist/agent/memory.d.ts.map +1 -0
- package/dist/agent/memory.js +95 -0
- package/dist/agent/memory.js.map +1 -0
- package/dist/agent/safety.d.ts +45 -0
- package/dist/agent/safety.d.ts.map +1 -0
- package/dist/agent/safety.js +71 -0
- package/dist/agent/safety.js.map +1 -0
- package/dist/agent/session.d.ts +27 -0
- package/dist/agent/session.d.ts.map +1 -0
- package/dist/agent/session.js +124 -0
- package/dist/agent/session.js.map +1 -0
- package/dist/agent/tool-descriptions.d.ts +8 -0
- package/dist/agent/tool-descriptions.d.ts.map +1 -0
- package/dist/agent/tool-descriptions.js +26 -0
- package/dist/agent/tool-descriptions.js.map +1 -0
- package/dist/cli/analyze.d.ts +8 -0
- package/dist/cli/analyze.d.ts.map +1 -0
- package/dist/cli/analyze.js +114 -0
- package/dist/cli/analyze.js.map +1 -0
- package/dist/cli/daemon.d.ts +2 -0
- package/dist/cli/daemon.d.ts.map +1 -0
- package/dist/cli/daemon.js +91 -0
- package/dist/cli/daemon.js.map +1 -0
- package/dist/cli/doctor.d.ts +2 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/doctor.js +198 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/init.d.ts +3 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +459 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/logs.d.ts +4 -0
- package/dist/cli/logs.d.ts.map +1 -0
- package/dist/cli/logs.js +50 -0
- package/dist/cli/logs.js.map +1 -0
- package/dist/cli/monitor-cmd.d.ts +11 -0
- package/dist/cli/monitor-cmd.d.ts.map +1 -0
- package/dist/cli/monitor-cmd.js +59 -0
- package/dist/cli/monitor-cmd.js.map +1 -0
- package/dist/cli/start.d.ts +11 -0
- package/dist/cli/start.d.ts.map +1 -0
- package/dist/cli/start.js +103 -0
- package/dist/cli/start.js.map +1 -0
- package/dist/cli/status.d.ts +9 -0
- package/dist/cli/status.d.ts.map +1 -0
- package/dist/cli/status.js +49 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/stop.d.ts +2 -0
- package/dist/cli/stop.d.ts.map +1 -0
- package/dist/cli/stop.js +34 -0
- package/dist/cli/stop.js.map +1 -0
- package/dist/collectors/appstore.d.ts +51 -0
- package/dist/collectors/appstore.d.ts.map +1 -0
- package/dist/collectors/appstore.js +166 -0
- package/dist/collectors/appstore.js.map +1 -0
- package/dist/collectors/arden-tts.d.ts +60 -0
- package/dist/collectors/arden-tts.d.ts.map +1 -0
- package/dist/collectors/arden-tts.js +83 -0
- package/dist/collectors/arden-tts.js.map +1 -0
- package/dist/collectors/asomobile.d.ts +37 -0
- package/dist/collectors/asomobile.d.ts.map +1 -0
- package/dist/collectors/asomobile.js +88 -0
- package/dist/collectors/asomobile.js.map +1 -0
- package/dist/collectors/eodin-blog.d.ts +90 -0
- package/dist/collectors/eodin-blog.d.ts.map +1 -0
- package/dist/collectors/eodin-blog.js +238 -0
- package/dist/collectors/eodin-blog.js.map +1 -0
- package/dist/collectors/eodin-sdk.d.ts +60 -0
- package/dist/collectors/eodin-sdk.d.ts.map +1 -0
- package/dist/collectors/eodin-sdk.js +112 -0
- package/dist/collectors/eodin-sdk.js.map +1 -0
- package/dist/collectors/fridgify-recipes.d.ts +65 -0
- package/dist/collectors/fridgify-recipes.d.ts.map +1 -0
- package/dist/collectors/fridgify-recipes.js +111 -0
- package/dist/collectors/fridgify-recipes.js.map +1 -0
- package/dist/collectors/playstore.d.ts +46 -0
- package/dist/collectors/playstore.d.ts.map +1 -0
- package/dist/collectors/playstore.js +140 -0
- package/dist/collectors/playstore.js.map +1 -0
- package/dist/collectors/youtube.d.ts +44 -0
- package/dist/collectors/youtube.d.ts.map +1 -0
- package/dist/collectors/youtube.js +107 -0
- package/dist/collectors/youtube.js.map +1 -0
- package/dist/config/apps-schema.d.ts +94 -0
- package/dist/config/apps-schema.d.ts.map +1 -0
- package/dist/config/apps-schema.js +66 -0
- package/dist/config/apps-schema.js.map +1 -0
- package/dist/config/keychain.d.ts +14 -0
- package/dist/config/keychain.d.ts.map +1 -0
- package/dist/config/keychain.js +89 -0
- package/dist/config/keychain.js.map +1 -0
- package/dist/config/load-apps.d.ts +16 -0
- package/dist/config/load-apps.d.ts.map +1 -0
- package/dist/config/load-apps.js +38 -0
- package/dist/config/load-apps.js.map +1 -0
- package/dist/config/schema.d.ts +306 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +220 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/store.d.ts +38 -0
- package/dist/config/store.d.ts.map +1 -0
- package/dist/config/store.js +180 -0
- package/dist/config/store.js.map +1 -0
- package/dist/db/queries.d.ts +304 -0
- package/dist/db/queries.d.ts.map +1 -0
- package/dist/db/queries.js +327 -0
- package/dist/db/queries.js.map +1 -0
- package/dist/db/schema.d.ts +15 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +252 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +86 -0
- package/dist/index.js.map +1 -0
- package/dist/messenger/adapter.d.ts +63 -0
- package/dist/messenger/adapter.d.ts.map +1 -0
- package/dist/messenger/adapter.js +7 -0
- package/dist/messenger/adapter.js.map +1 -0
- package/dist/messenger/factory.d.ts +12 -0
- package/dist/messenger/factory.d.ts.map +1 -0
- package/dist/messenger/factory.js +9 -0
- package/dist/messenger/factory.js.map +1 -0
- package/dist/messenger/slack.d.ts +30 -0
- package/dist/messenger/slack.d.ts.map +1 -0
- package/dist/messenger/slack.js +309 -0
- package/dist/messenger/slack.js.map +1 -0
- package/dist/messenger/split.d.ts +17 -0
- package/dist/messenger/split.d.ts.map +1 -0
- package/dist/messenger/split.js +56 -0
- package/dist/messenger/split.js.map +1 -0
- package/dist/orchestrator/dashboard.d.ts +67 -0
- package/dist/orchestrator/dashboard.d.ts.map +1 -0
- package/dist/orchestrator/dashboard.js +113 -0
- package/dist/orchestrator/dashboard.js.map +1 -0
- package/dist/orchestrator/monitor.d.ts +37 -0
- package/dist/orchestrator/monitor.d.ts.map +1 -0
- package/dist/orchestrator/monitor.js +236 -0
- package/dist/orchestrator/monitor.js.map +1 -0
- package/dist/orchestrator/types.d.ts +82 -0
- package/dist/orchestrator/types.d.ts.map +1 -0
- package/dist/orchestrator/types.js +12 -0
- package/dist/orchestrator/types.js.map +1 -0
- package/dist/orchestrator/weekly.d.ts +66 -0
- package/dist/orchestrator/weekly.d.ts.map +1 -0
- package/dist/orchestrator/weekly.js +376 -0
- package/dist/orchestrator/weekly.js.map +1 -0
- package/dist/prompts/loader.d.ts +18 -0
- package/dist/prompts/loader.d.ts.map +1 -0
- package/dist/prompts/loader.js +28 -0
- package/dist/prompts/loader.js.map +1 -0
- package/dist/security/auth.d.ts +14 -0
- package/dist/security/auth.d.ts.map +1 -0
- package/dist/security/auth.js +14 -0
- package/dist/security/auth.js.map +1 -0
- package/dist/security/prompt-guard.d.ts +21 -0
- package/dist/security/prompt-guard.d.ts.map +1 -0
- package/dist/security/prompt-guard.js +54 -0
- package/dist/security/prompt-guard.js.map +1 -0
- package/dist/skills/aso.d.ts +60 -0
- package/dist/skills/aso.d.ts.map +1 -0
- package/dist/skills/aso.js +322 -0
- package/dist/skills/aso.js.map +1 -0
- package/dist/skills/content.d.ts +25 -0
- package/dist/skills/content.d.ts.map +1 -0
- package/dist/skills/content.js +90 -0
- package/dist/skills/content.js.map +1 -0
- package/dist/skills/index.d.ts +65 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +90 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/onboarding.d.ts +58 -0
- package/dist/skills/onboarding.d.ts.map +1 -0
- package/dist/skills/onboarding.js +274 -0
- package/dist/skills/onboarding.js.map +1 -0
- package/dist/skills/registry.d.ts +24 -0
- package/dist/skills/registry.d.ts.map +1 -0
- package/dist/skills/registry.js +66 -0
- package/dist/skills/registry.js.map +1 -0
- package/dist/skills/review.d.ts +33 -0
- package/dist/skills/review.d.ts.map +1 -0
- package/dist/skills/review.js +236 -0
- package/dist/skills/review.js.map +1 -0
- package/dist/skills/sdk-request.d.ts +30 -0
- package/dist/skills/sdk-request.d.ts.map +1 -0
- package/dist/skills/sdk-request.js +72 -0
- package/dist/skills/sdk-request.js.map +1 -0
- package/dist/skills/seo-blog.d.ts +64 -0
- package/dist/skills/seo-blog.d.ts.map +1 -0
- package/dist/skills/seo-blog.js +268 -0
- package/dist/skills/seo-blog.js.map +1 -0
- package/dist/skills/short-form.d.ts +28 -0
- package/dist/skills/short-form.d.ts.map +1 -0
- package/dist/skills/short-form.js +121 -0
- package/dist/skills/short-form.js.map +1 -0
- package/dist/skills/social-publish.d.ts +32 -0
- package/dist/skills/social-publish.d.ts.map +1 -0
- package/dist/skills/social-publish.js +133 -0
- package/dist/skills/social-publish.js.map +1 -0
- package/dist/social/base.d.ts +47 -0
- package/dist/social/base.d.ts.map +1 -0
- package/dist/social/base.js +26 -0
- package/dist/social/base.js.map +1 -0
- package/dist/social/facebook.d.ts +27 -0
- package/dist/social/facebook.d.ts.map +1 -0
- package/dist/social/facebook.js +166 -0
- package/dist/social/facebook.js.map +1 -0
- package/dist/social/factory.d.ts +26 -0
- package/dist/social/factory.d.ts.map +1 -0
- package/dist/social/factory.js +32 -0
- package/dist/social/factory.js.map +1 -0
- package/dist/social/linkedin.d.ts +26 -0
- package/dist/social/linkedin.d.ts.map +1 -0
- package/dist/social/linkedin.js +190 -0
- package/dist/social/linkedin.js.map +1 -0
- package/dist/social/threads.d.ts +21 -0
- package/dist/social/threads.d.ts.map +1 -0
- package/dist/social/threads.js +122 -0
- package/dist/social/threads.js.map +1 -0
- package/dist/social/tiktok.d.ts +23 -0
- package/dist/social/tiktok.d.ts.map +1 -0
- package/dist/social/tiktok.js +110 -0
- package/dist/social/tiktok.js.map +1 -0
- package/dist/social/twitter.d.ts +30 -0
- package/dist/social/twitter.d.ts.map +1 -0
- package/dist/social/twitter.js +189 -0
- package/dist/social/twitter.js.map +1 -0
- package/dist/social/youtube.d.ts +21 -0
- package/dist/social/youtube.d.ts.map +1 -0
- package/dist/social/youtube.js +108 -0
- package/dist/social/youtube.js.map +1 -0
- package/dist/tools/app-info.d.ts +7 -0
- package/dist/tools/app-info.d.ts.map +1 -0
- package/dist/tools/app-info.js +53 -0
- package/dist/tools/app-info.js.map +1 -0
- package/dist/tools/collector-fetch.d.ts +11 -0
- package/dist/tools/collector-fetch.d.ts.map +1 -0
- package/dist/tools/collector-fetch.js +101 -0
- package/dist/tools/collector-fetch.js.map +1 -0
- package/dist/tools/db-query.d.ts +29 -0
- package/dist/tools/db-query.d.ts.map +1 -0
- package/dist/tools/db-query.js +159 -0
- package/dist/tools/db-query.js.map +1 -0
- package/dist/tools/skill-result.d.ts +8 -0
- package/dist/tools/skill-result.d.ts.map +1 -0
- package/dist/tools/skill-result.js +63 -0
- package/dist/tools/skill-result.js.map +1 -0
- package/dist/tools/tool-host.d.ts +12 -0
- package/dist/tools/tool-host.d.ts.map +1 -0
- package/dist/tools/tool-host.js +124 -0
- package/dist/tools/tool-host.js.map +1 -0
- package/dist/types/collectors.d.ts +198 -0
- package/dist/types/collectors.d.ts.map +1 -0
- package/dist/types/collectors.js +28 -0
- package/dist/types/collectors.js.map +1 -0
- package/dist/types/skill.d.ts +60 -0
- package/dist/types/skill.d.ts.map +1 -0
- package/dist/types/skill.js +9 -0
- package/dist/types/skill.js.map +1 -0
- package/dist/utils/circuit-breaker.d.ts +26 -0
- package/dist/utils/circuit-breaker.d.ts.map +1 -0
- package/dist/utils/circuit-breaker.js +67 -0
- package/dist/utils/circuit-breaker.js.map +1 -0
- package/dist/utils/errors.d.ts +44 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +75 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/escape.d.ts +11 -0
- package/dist/utils/escape.d.ts.map +1 -0
- package/dist/utils/escape.js +19 -0
- package/dist/utils/escape.js.map +1 -0
- package/dist/utils/logger.d.ts +19 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +93 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/parse-json.d.ts +13 -0
- package/dist/utils/parse-json.d.ts.map +1 -0
- package/dist/utils/parse-json.js +61 -0
- package/dist/utils/parse-json.js.map +1 -0
- package/dist/utils/paths.d.ts +14 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +19 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/rate-limiter.d.ts +20 -0
- package/dist/utils/rate-limiter.d.ts.map +1 -0
- package/dist/utils/rate-limiter.js +47 -0
- package/dist/utils/rate-limiter.js.map +1 -0
- package/dist/utils/retry.d.ts +26 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +61 -0
- package/dist/utils/retry.js.map +1 -0
- package/launchd/.gitkeep +0 -0
- package/launchd/com.adaria-ai.daemon.plist.template +62 -0
- package/launchd/com.adaria-ai.monitor.plist.template +41 -0
- package/launchd/com.adaria-ai.weekly.plist.template +43 -0
- package/package.json +72 -0
- package/prompts/aso-description.md +44 -0
- package/prompts/aso-inapp-events.md +20 -0
- package/prompts/aso-metadata.md +34 -0
- package/prompts/aso-screenshots.md +20 -0
- package/prompts/onboarding-hypotheses.md +38 -0
- package/prompts/onboarding-review-timing.md +24 -0
- package/prompts/review-clustering.md +19 -0
- package/prompts/review-replies.md +18 -0
- package/prompts/review-sentiment.md +16 -0
- package/prompts/seo-blog-fridgify-recipe.md +116 -0
- package/prompts/seo-blog.md +69 -0
- package/prompts/short-form-ideas.md +50 -0
- package/prompts/social-publish.md +46 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared social media client interface.
|
|
3
|
+
*
|
|
4
|
+
* Every platform client (twitter, facebook, threads, tiktok, youtube,
|
|
5
|
+
* linkedin) implements this interface. The SocialPublishSkill dispatches
|
|
6
|
+
* through it without knowing which platform it's talking to.
|
|
7
|
+
*
|
|
8
|
+
* All `post()` implementations MUST check `ADARIA_DRY_RUN` before calling
|
|
9
|
+
* the API. When set, they log the full request payload and return a
|
|
10
|
+
* synthetic result with `dryRun: true`.
|
|
11
|
+
*/
|
|
12
|
+
export type SocialPlatform = "twitter" | "facebook" | "threads" | "tiktok" | "youtube" | "linkedin";
|
|
13
|
+
export interface SocialPostContent {
|
|
14
|
+
text: string;
|
|
15
|
+
hashtags?: string[];
|
|
16
|
+
imageUrl?: string;
|
|
17
|
+
link?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface SocialPostResult {
|
|
20
|
+
success: boolean;
|
|
21
|
+
platform: SocialPlatform;
|
|
22
|
+
postId?: string | undefined;
|
|
23
|
+
postUrl?: string | undefined;
|
|
24
|
+
error?: string | undefined;
|
|
25
|
+
dryRun?: boolean | undefined;
|
|
26
|
+
postedAt?: string | undefined;
|
|
27
|
+
}
|
|
28
|
+
export interface ValidationResult {
|
|
29
|
+
valid: boolean;
|
|
30
|
+
characterCount: number;
|
|
31
|
+
issues: string[];
|
|
32
|
+
suggestions: string[];
|
|
33
|
+
}
|
|
34
|
+
export interface SocialClient {
|
|
35
|
+
readonly platform: SocialPlatform;
|
|
36
|
+
/** Post content to the platform. Checks ADARIA_DRY_RUN. */
|
|
37
|
+
post(content: SocialPostContent): Promise<SocialPostResult>;
|
|
38
|
+
/** Validate content against platform-specific rules. */
|
|
39
|
+
validateContent(text: string): ValidationResult;
|
|
40
|
+
/** Delete a previously posted item by its platform-specific ID. */
|
|
41
|
+
deletePost(postId: string): Promise<boolean>;
|
|
42
|
+
}
|
|
43
|
+
/** Check whether dry-run mode is active. */
|
|
44
|
+
export declare function isDryRun(): boolean;
|
|
45
|
+
/** Build a dry-run result for any platform. */
|
|
46
|
+
export declare function dryRunResult(platform: SocialPlatform, _content: SocialPostContent): SocialPostResult;
|
|
47
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/social/base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,cAAc,GACtB,SAAS,GACT,UAAU,GACV,SAAS,GACT,QAAQ,GACR,SAAS,GACT,UAAU,CAAC;AAEf,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAElC,2DAA2D;IAC3D,IAAI,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAE5D,wDAAwD;IACxD,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAAC;IAEhD,mEAAmE;IACnE,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9C;AAED,4CAA4C;AAC5C,wBAAgB,QAAQ,IAAI,OAAO,CAElC;AAED,+CAA+C;AAC/C,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,iBAAiB,GAC1B,gBAAgB,CAQlB"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared social media client interface.
|
|
3
|
+
*
|
|
4
|
+
* Every platform client (twitter, facebook, threads, tiktok, youtube,
|
|
5
|
+
* linkedin) implements this interface. The SocialPublishSkill dispatches
|
|
6
|
+
* through it without knowing which platform it's talking to.
|
|
7
|
+
*
|
|
8
|
+
* All `post()` implementations MUST check `ADARIA_DRY_RUN` before calling
|
|
9
|
+
* the API. When set, they log the full request payload and return a
|
|
10
|
+
* synthetic result with `dryRun: true`.
|
|
11
|
+
*/
|
|
12
|
+
/** Check whether dry-run mode is active. */
|
|
13
|
+
export function isDryRun() {
|
|
14
|
+
return process.env["ADARIA_DRY_RUN"] === "1";
|
|
15
|
+
}
|
|
16
|
+
/** Build a dry-run result for any platform. */
|
|
17
|
+
export function dryRunResult(platform, _content) {
|
|
18
|
+
return {
|
|
19
|
+
success: true,
|
|
20
|
+
platform,
|
|
21
|
+
postId: `dry-run-${Date.now()}`,
|
|
22
|
+
dryRun: true,
|
|
23
|
+
postedAt: new Date().toISOString(),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/social/base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA+CH,4CAA4C;AAC5C,MAAM,UAAU,QAAQ;IACtB,OAAO,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,KAAK,GAAG,CAAC;AAC/C,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,YAAY,CAC1B,QAAwB,EACxB,QAA2B;IAE3B,OAAO;QACL,OAAO,EAAE,IAAI;QACb,QAAQ;QACR,MAAM,EAAE,WAAW,IAAI,CAAC,GAAG,EAAE,EAAE;QAC/B,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACnC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Facebook client — Graph API v19.0.
|
|
3
|
+
*
|
|
4
|
+
* Ported from linkgo `ai-service/src/social/facebook_client.py` patterns.
|
|
5
|
+
* Posts to a Facebook Page using a Page Access Token + appsecret_proof HMAC.
|
|
6
|
+
*/
|
|
7
|
+
import { type SocialClient, type SocialPostContent, type SocialPostResult, type ValidationResult } from "./base.js";
|
|
8
|
+
export interface FacebookConfig {
|
|
9
|
+
appId: string;
|
|
10
|
+
appSecret: string;
|
|
11
|
+
accessToken: string;
|
|
12
|
+
pageId: string;
|
|
13
|
+
}
|
|
14
|
+
export declare class FacebookClient implements SocialClient {
|
|
15
|
+
private readonly config;
|
|
16
|
+
readonly platform: "facebook";
|
|
17
|
+
private pageToken;
|
|
18
|
+
constructor(config: FacebookConfig);
|
|
19
|
+
post(content: SocialPostContent): Promise<SocialPostResult>;
|
|
20
|
+
validateContent(text: string): ValidationResult;
|
|
21
|
+
deletePost(postId: string): Promise<boolean>;
|
|
22
|
+
private buildText;
|
|
23
|
+
private computeProof;
|
|
24
|
+
private getPageToken;
|
|
25
|
+
private uploadPhoto;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=facebook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"facebook.d.ts","sourceRoot":"","sources":["../../src/social/facebook.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EAGtB,MAAM,WAAW,CAAC;AAMnB,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,cAAe,YAAW,YAAY;IAIrC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHnC,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IACxC,OAAO,CAAC,SAAS,CAAuB;gBAEX,MAAM,EAAE,cAAc;IAE7C,IAAI,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAmEjE,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB;IAyBzC,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAkBlD,OAAO,CAAC,SAAS;IAWjB,OAAO,CAAC,YAAY;YAON,YAAY;YAyBZ,WAAW;CAgC1B"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Facebook client — Graph API v19.0.
|
|
3
|
+
*
|
|
4
|
+
* Ported from linkgo `ai-service/src/social/facebook_client.py` patterns.
|
|
5
|
+
* Posts to a Facebook Page using a Page Access Token + appsecret_proof HMAC.
|
|
6
|
+
*/
|
|
7
|
+
import crypto from "node:crypto";
|
|
8
|
+
import { isDryRun, dryRunResult, } from "./base.js";
|
|
9
|
+
import * as logger from "../utils/logger.js";
|
|
10
|
+
const BASE_URL = "https://graph.facebook.com/v19.0";
|
|
11
|
+
const MAX_CHARS = 63_206;
|
|
12
|
+
export class FacebookClient {
|
|
13
|
+
config;
|
|
14
|
+
platform = "facebook";
|
|
15
|
+
pageToken = null;
|
|
16
|
+
constructor(config) {
|
|
17
|
+
this.config = config;
|
|
18
|
+
}
|
|
19
|
+
async post(content) {
|
|
20
|
+
if (isDryRun()) {
|
|
21
|
+
logger.info(`[facebook] DRY_RUN: would post: ${content.text.slice(0, 100)}`);
|
|
22
|
+
return dryRunResult("facebook", content);
|
|
23
|
+
}
|
|
24
|
+
const text = this.buildText(content);
|
|
25
|
+
const validation = this.validateContent(text);
|
|
26
|
+
if (!validation.valid) {
|
|
27
|
+
return {
|
|
28
|
+
success: false,
|
|
29
|
+
platform: "facebook",
|
|
30
|
+
error: validation.issues.join("; "),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
const token = await this.getPageToken();
|
|
35
|
+
const proof = this.computeProof(token);
|
|
36
|
+
// Upload photo if provided
|
|
37
|
+
let photoId = null;
|
|
38
|
+
if (content.imageUrl) {
|
|
39
|
+
photoId = await this.uploadPhoto(content.imageUrl, token, proof);
|
|
40
|
+
}
|
|
41
|
+
// Post to page feed
|
|
42
|
+
const params = new URLSearchParams({
|
|
43
|
+
message: text,
|
|
44
|
+
access_token: token,
|
|
45
|
+
appsecret_proof: proof,
|
|
46
|
+
});
|
|
47
|
+
if (photoId) {
|
|
48
|
+
params.set("attached_media", JSON.stringify([{ media_fbid: photoId }]));
|
|
49
|
+
}
|
|
50
|
+
else if (content.link) {
|
|
51
|
+
params.set("link", content.link);
|
|
52
|
+
}
|
|
53
|
+
const response = await fetch(`${BASE_URL}/${this.config.pageId}/feed`, {
|
|
54
|
+
method: "POST",
|
|
55
|
+
body: params,
|
|
56
|
+
});
|
|
57
|
+
if (!response.ok) {
|
|
58
|
+
const err = (await response.json());
|
|
59
|
+
throw new Error(err?.error?.message ?? `HTTP ${String(response.status)}`);
|
|
60
|
+
}
|
|
61
|
+
const result = (await response.json());
|
|
62
|
+
return {
|
|
63
|
+
success: true,
|
|
64
|
+
platform: "facebook",
|
|
65
|
+
postId: result.id,
|
|
66
|
+
postUrl: result.id
|
|
67
|
+
? `https://www.facebook.com/${result.id}`
|
|
68
|
+
: undefined,
|
|
69
|
+
postedAt: new Date().toISOString(),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
74
|
+
logger.error(`[facebook] Post failed: ${msg}`);
|
|
75
|
+
return { success: false, platform: "facebook", error: msg };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
validateContent(text) {
|
|
79
|
+
const issues = [];
|
|
80
|
+
const suggestions = [];
|
|
81
|
+
if (!text.trim()) {
|
|
82
|
+
issues.push("Text is empty");
|
|
83
|
+
return { valid: false, characterCount: 0, issues, suggestions };
|
|
84
|
+
}
|
|
85
|
+
if (text.length > MAX_CHARS) {
|
|
86
|
+
issues.push(`Text exceeds ${String(MAX_CHARS)} characters`);
|
|
87
|
+
}
|
|
88
|
+
if (text.length < 40) {
|
|
89
|
+
suggestions.push("Consider writing at least 40 characters for better engagement");
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
valid: issues.length === 0,
|
|
93
|
+
characterCount: text.length,
|
|
94
|
+
issues,
|
|
95
|
+
suggestions,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
async deletePost(postId) {
|
|
99
|
+
if (isDryRun()) {
|
|
100
|
+
logger.info(`[facebook] DRY_RUN: would delete post ${postId}`);
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
const token = await this.getPageToken();
|
|
105
|
+
const proof = this.computeProof(token);
|
|
106
|
+
const response = await fetch(`${BASE_URL}/${postId}?access_token=${encodeURIComponent(token)}&appsecret_proof=${encodeURIComponent(proof)}`, { method: "DELETE" });
|
|
107
|
+
return response.ok;
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
buildText(content) {
|
|
114
|
+
let text = content.text;
|
|
115
|
+
if (content.hashtags?.length) {
|
|
116
|
+
const tags = content.hashtags.map((t) => t.startsWith("#") ? t : `#${t}`);
|
|
117
|
+
text = `${text}\n\n${tags.join(" ")}`;
|
|
118
|
+
}
|
|
119
|
+
return text;
|
|
120
|
+
}
|
|
121
|
+
computeProof(token) {
|
|
122
|
+
return crypto
|
|
123
|
+
.createHmac("sha256", this.config.appSecret)
|
|
124
|
+
.update(token)
|
|
125
|
+
.digest("hex");
|
|
126
|
+
}
|
|
127
|
+
async getPageToken() {
|
|
128
|
+
if (this.pageToken)
|
|
129
|
+
return this.pageToken;
|
|
130
|
+
const proof = this.computeProof(this.config.accessToken);
|
|
131
|
+
const response = await fetch(`${BASE_URL}/me/accounts?access_token=${encodeURIComponent(this.config.accessToken)}&appsecret_proof=${encodeURIComponent(proof)}`);
|
|
132
|
+
if (!response.ok) {
|
|
133
|
+
throw new Error(`Failed to fetch page token: HTTP ${String(response.status)}`);
|
|
134
|
+
}
|
|
135
|
+
const result = (await response.json());
|
|
136
|
+
const page = result.data?.find((p) => p.id === this.config.pageId);
|
|
137
|
+
if (!page) {
|
|
138
|
+
throw new Error(`Page ${this.config.pageId} not found in managed pages`);
|
|
139
|
+
}
|
|
140
|
+
this.pageToken = page.access_token;
|
|
141
|
+
return page.access_token;
|
|
142
|
+
}
|
|
143
|
+
async uploadPhoto(imageUrl, token, proof) {
|
|
144
|
+
try {
|
|
145
|
+
const imgResponse = await fetch(imageUrl);
|
|
146
|
+
if (!imgResponse.ok)
|
|
147
|
+
return null;
|
|
148
|
+
const buffer = Buffer.from(await imgResponse.arrayBuffer());
|
|
149
|
+
const form = new FormData();
|
|
150
|
+
form.set("source", new Blob([buffer]), "image.jpg");
|
|
151
|
+
form.set("access_token", token);
|
|
152
|
+
form.set("appsecret_proof", proof);
|
|
153
|
+
form.set("published", "false");
|
|
154
|
+
const response = await fetch(`${BASE_URL}/${this.config.pageId}/photos`, { method: "POST", body: form });
|
|
155
|
+
if (!response.ok)
|
|
156
|
+
return null;
|
|
157
|
+
const result = (await response.json());
|
|
158
|
+
return result.id ?? null;
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
logger.error(`[facebook] Photo upload error: ${err instanceof Error ? err.message : String(err)}`);
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=facebook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"facebook.js","sourceRoot":"","sources":["../../src/social/facebook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Social client factory.
|
|
3
|
+
*
|
|
4
|
+
* Creates the appropriate SocialClient for a given platform + config.
|
|
5
|
+
*/
|
|
6
|
+
import type { SocialClient, SocialPlatform } from "./base.js";
|
|
7
|
+
import { type TwitterConfig } from "./twitter.js";
|
|
8
|
+
import { type FacebookConfig } from "./facebook.js";
|
|
9
|
+
import { type ThreadsConfig } from "./threads.js";
|
|
10
|
+
import { type TikTokConfig } from "./tiktok.js";
|
|
11
|
+
import { type YouTubeConfig } from "./youtube.js";
|
|
12
|
+
import { type LinkedInConfig } from "./linkedin.js";
|
|
13
|
+
export type SocialConfigs = {
|
|
14
|
+
twitter?: TwitterConfig | undefined;
|
|
15
|
+
facebook?: FacebookConfig | undefined;
|
|
16
|
+
threads?: ThreadsConfig | undefined;
|
|
17
|
+
tiktok?: TikTokConfig | undefined;
|
|
18
|
+
youtube?: YouTubeConfig | undefined;
|
|
19
|
+
linkedin?: LinkedInConfig | undefined;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Create a social client for the given platform. Returns null if the
|
|
23
|
+
* platform config is missing (credentials not configured).
|
|
24
|
+
*/
|
|
25
|
+
export declare function createSocialClient(platform: SocialPlatform, configs: SocialConfigs): SocialClient | null;
|
|
26
|
+
//# sourceMappingURL=factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/social/factory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpE,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACtC,OAAO,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IACpC,MAAM,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IAClC,OAAO,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;CACvC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,aAAa,GACrB,YAAY,GAAG,IAAI,CAerB"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Social client factory.
|
|
3
|
+
*
|
|
4
|
+
* Creates the appropriate SocialClient for a given platform + config.
|
|
5
|
+
*/
|
|
6
|
+
import { TwitterClient } from "./twitter.js";
|
|
7
|
+
import { FacebookClient } from "./facebook.js";
|
|
8
|
+
import { ThreadsClient } from "./threads.js";
|
|
9
|
+
import { TikTokClient } from "./tiktok.js";
|
|
10
|
+
import { YouTubeClient } from "./youtube.js";
|
|
11
|
+
import { LinkedInClient } from "./linkedin.js";
|
|
12
|
+
/**
|
|
13
|
+
* Create a social client for the given platform. Returns null if the
|
|
14
|
+
* platform config is missing (credentials not configured).
|
|
15
|
+
*/
|
|
16
|
+
export function createSocialClient(platform, configs) {
|
|
17
|
+
switch (platform) {
|
|
18
|
+
case "twitter":
|
|
19
|
+
return configs.twitter ? new TwitterClient(configs.twitter) : null;
|
|
20
|
+
case "facebook":
|
|
21
|
+
return configs.facebook ? new FacebookClient(configs.facebook) : null;
|
|
22
|
+
case "threads":
|
|
23
|
+
return configs.threads ? new ThreadsClient(configs.threads) : null;
|
|
24
|
+
case "tiktok":
|
|
25
|
+
return configs.tiktok ? new TikTokClient(configs.tiktok) : null;
|
|
26
|
+
case "youtube":
|
|
27
|
+
return configs.youtube ? new YouTubeClient(configs.youtube) : null;
|
|
28
|
+
case "linkedin":
|
|
29
|
+
return configs.linkedin ? new LinkedInClient(configs.linkedin) : null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/social/factory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,aAAa,EAAsB,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,cAAc,EAAuB,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,aAAa,EAAsB,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,YAAY,EAAqB,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAsB,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,cAAc,EAAuB,MAAM,eAAe,CAAC;AAWpE;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAChC,QAAwB,EACxB,OAAsB;IAEtB,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,SAAS;YACZ,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACrE,KAAK,UAAU;YACb,OAAO,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACxE,KAAK,SAAS;YACZ,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACrE,KAAK,QAAQ;YACX,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAClE,KAAK,SAAS;YACZ,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACrE,KAAK,UAAU;YACb,OAAO,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1E,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LinkedIn client — REST API v2.
|
|
3
|
+
*
|
|
4
|
+
* Ported from linkgo `ai-service/src/social/linkedin_client.py` patterns.
|
|
5
|
+
* Posts to an organization page with optional image upload (3-step flow).
|
|
6
|
+
*/
|
|
7
|
+
import { type SocialClient, type SocialPostContent, type SocialPostResult, type ValidationResult } from "./base.js";
|
|
8
|
+
export interface LinkedInConfig {
|
|
9
|
+
accessToken: string;
|
|
10
|
+
organizationId: string;
|
|
11
|
+
}
|
|
12
|
+
export declare class LinkedInClient implements SocialClient {
|
|
13
|
+
private readonly config;
|
|
14
|
+
readonly platform: "linkedin";
|
|
15
|
+
constructor(config: LinkedInConfig);
|
|
16
|
+
post(content: SocialPostContent): Promise<SocialPostResult>;
|
|
17
|
+
validateContent(text: string): ValidationResult;
|
|
18
|
+
deletePost(postId: string): Promise<boolean>;
|
|
19
|
+
/**
|
|
20
|
+
* 3-step image upload: initialize → PUT binary → return asset URN.
|
|
21
|
+
*/
|
|
22
|
+
private uploadImage;
|
|
23
|
+
private buildHeaders;
|
|
24
|
+
private buildText;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=linkedin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linkedin.d.ts","sourceRoot":"","sources":["../../src/social/linkedin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EAGtB,MAAM,WAAW,CAAC;AAOnB,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,cAAe,YAAW,YAAY;IAGrC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;gBAEX,MAAM,EAAE,cAAc;IAE7C,IAAI,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAyEjE,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB;IAiCzC,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAgBlD;;OAEG;YACW,WAAW;IA4DzB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,SAAS;CAUlB"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LinkedIn client — REST API v2.
|
|
3
|
+
*
|
|
4
|
+
* Ported from linkgo `ai-service/src/social/linkedin_client.py` patterns.
|
|
5
|
+
* Posts to an organization page with optional image upload (3-step flow).
|
|
6
|
+
*/
|
|
7
|
+
import { isDryRun, dryRunResult, } from "./base.js";
|
|
8
|
+
import * as logger from "../utils/logger.js";
|
|
9
|
+
const REST_URL = "https://api.linkedin.com/rest";
|
|
10
|
+
const MAX_CHARS = 3000;
|
|
11
|
+
const LINKEDIN_VERSION = "202411";
|
|
12
|
+
export class LinkedInClient {
|
|
13
|
+
config;
|
|
14
|
+
platform = "linkedin";
|
|
15
|
+
constructor(config) {
|
|
16
|
+
this.config = config;
|
|
17
|
+
}
|
|
18
|
+
async post(content) {
|
|
19
|
+
if (isDryRun()) {
|
|
20
|
+
logger.info(`[linkedin] DRY_RUN: would post: ${content.text.slice(0, 100)}`);
|
|
21
|
+
return dryRunResult("linkedin", content);
|
|
22
|
+
}
|
|
23
|
+
const text = this.buildText(content);
|
|
24
|
+
const validation = this.validateContent(text);
|
|
25
|
+
if (!validation.valid) {
|
|
26
|
+
return {
|
|
27
|
+
success: false,
|
|
28
|
+
platform: "linkedin",
|
|
29
|
+
error: validation.issues.join("; "),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const authorUrn = `urn:li:organization:${this.config.organizationId}`;
|
|
34
|
+
// Upload image if provided (3-step flow)
|
|
35
|
+
let assetUrn = null;
|
|
36
|
+
if (content.imageUrl) {
|
|
37
|
+
assetUrn = await this.uploadImage(content.imageUrl, authorUrn);
|
|
38
|
+
}
|
|
39
|
+
// Build post body
|
|
40
|
+
const body = {
|
|
41
|
+
author: authorUrn,
|
|
42
|
+
lifecycleState: "PUBLISHED",
|
|
43
|
+
visibility: "PUBLIC",
|
|
44
|
+
distribution: {
|
|
45
|
+
feedDistribution: "MAIN_FEED",
|
|
46
|
+
targetEntities: [],
|
|
47
|
+
thirdPartyDistributionChannels: [],
|
|
48
|
+
},
|
|
49
|
+
commentary: text,
|
|
50
|
+
isReshareDisabledByAuthor: false,
|
|
51
|
+
};
|
|
52
|
+
if (assetUrn) {
|
|
53
|
+
body["content"] = { media: { id: assetUrn } };
|
|
54
|
+
}
|
|
55
|
+
const response = await fetch(`${REST_URL}/posts`, {
|
|
56
|
+
method: "POST",
|
|
57
|
+
headers: this.buildHeaders(),
|
|
58
|
+
body: JSON.stringify(body),
|
|
59
|
+
});
|
|
60
|
+
if (!response.ok) {
|
|
61
|
+
const err = await response.text();
|
|
62
|
+
throw new Error(`LinkedIn API ${String(response.status)}: ${err}`);
|
|
63
|
+
}
|
|
64
|
+
// Post ID is in the response header, not the body
|
|
65
|
+
const postId = response.headers.get("x-linkedin-id") ?? undefined;
|
|
66
|
+
return {
|
|
67
|
+
success: true,
|
|
68
|
+
platform: "linkedin",
|
|
69
|
+
postId,
|
|
70
|
+
postUrl: postId
|
|
71
|
+
? `https://www.linkedin.com/feed/update/${postId}`
|
|
72
|
+
: undefined,
|
|
73
|
+
postedAt: new Date().toISOString(),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
78
|
+
logger.error(`[linkedin] Post failed: ${msg}`);
|
|
79
|
+
return { success: false, platform: "linkedin", error: msg };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
validateContent(text) {
|
|
83
|
+
const issues = [];
|
|
84
|
+
const suggestions = [];
|
|
85
|
+
if (!text.trim()) {
|
|
86
|
+
issues.push("Text is empty");
|
|
87
|
+
return { valid: false, characterCount: 0, issues, suggestions };
|
|
88
|
+
}
|
|
89
|
+
if (text.length > MAX_CHARS) {
|
|
90
|
+
issues.push(`Text exceeds ${String(MAX_CHARS)} characters (${String(text.length)})`);
|
|
91
|
+
}
|
|
92
|
+
if (text.length > 1300) {
|
|
93
|
+
suggestions.push("Consider keeping under 1,300 characters for better engagement");
|
|
94
|
+
}
|
|
95
|
+
const hashtagCount = (text.match(/#/g) ?? []).length;
|
|
96
|
+
if (hashtagCount > 5) {
|
|
97
|
+
suggestions.push("Consider using 3-5 hashtags for optimal reach");
|
|
98
|
+
}
|
|
99
|
+
if (hashtagCount === 0) {
|
|
100
|
+
suggestions.push("Consider adding 3-5 relevant hashtags");
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
valid: issues.length === 0,
|
|
104
|
+
characterCount: text.length,
|
|
105
|
+
issues,
|
|
106
|
+
suggestions,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
async deletePost(postId) {
|
|
110
|
+
if (isDryRun()) {
|
|
111
|
+
logger.info(`[linkedin] DRY_RUN: would delete post ${postId}`);
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
const response = await fetch(`${REST_URL}/posts/${postId}`, {
|
|
116
|
+
method: "DELETE",
|
|
117
|
+
headers: this.buildHeaders(),
|
|
118
|
+
});
|
|
119
|
+
return response.ok;
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* 3-step image upload: initialize → PUT binary → return asset URN.
|
|
127
|
+
*/
|
|
128
|
+
async uploadImage(imageUrl, authorUrn) {
|
|
129
|
+
try {
|
|
130
|
+
// Step 1: Download image
|
|
131
|
+
const imgResponse = await fetch(imageUrl);
|
|
132
|
+
if (!imgResponse.ok)
|
|
133
|
+
return null;
|
|
134
|
+
const buffer = Buffer.from(await imgResponse.arrayBuffer());
|
|
135
|
+
const contentType = imgResponse.headers.get("content-type") ?? "image/jpeg";
|
|
136
|
+
// Step 2: Initialize upload
|
|
137
|
+
const initResponse = await fetch(`${REST_URL}/images?action=initializeUpload`, {
|
|
138
|
+
method: "POST",
|
|
139
|
+
headers: this.buildHeaders(),
|
|
140
|
+
body: JSON.stringify({
|
|
141
|
+
initializeUploadRequest: { owner: authorUrn },
|
|
142
|
+
}),
|
|
143
|
+
});
|
|
144
|
+
if (!initResponse.ok) {
|
|
145
|
+
logger.error(`[linkedin] Image init failed: ${String(initResponse.status)}`);
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
const initResult = (await initResponse.json());
|
|
149
|
+
const uploadUrl = initResult.value?.uploadUrl;
|
|
150
|
+
const assetUrn = initResult.value?.image;
|
|
151
|
+
if (!uploadUrl || !assetUrn)
|
|
152
|
+
return null;
|
|
153
|
+
// Step 3: PUT binary
|
|
154
|
+
const putResponse = await fetch(uploadUrl, {
|
|
155
|
+
method: "PUT",
|
|
156
|
+
headers: {
|
|
157
|
+
Authorization: `Bearer ${this.config.accessToken}`,
|
|
158
|
+
"Content-Type": contentType,
|
|
159
|
+
},
|
|
160
|
+
body: buffer,
|
|
161
|
+
});
|
|
162
|
+
if (!putResponse.ok) {
|
|
163
|
+
logger.error(`[linkedin] Image PUT failed: ${String(putResponse.status)}`);
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
return assetUrn;
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
logger.error(`[linkedin] Image upload error: ${err instanceof Error ? err.message : String(err)}`);
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
buildHeaders() {
|
|
174
|
+
return {
|
|
175
|
+
Authorization: `Bearer ${this.config.accessToken}`,
|
|
176
|
+
"Content-Type": "application/json",
|
|
177
|
+
"X-Restli-Protocol-Version": "2.0.0",
|
|
178
|
+
"LinkedIn-Version": LINKEDIN_VERSION,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
buildText(content) {
|
|
182
|
+
let text = content.text;
|
|
183
|
+
if (content.hashtags?.length) {
|
|
184
|
+
const tags = content.hashtags.map((t) => t.startsWith("#") ? t : `#${t}`);
|
|
185
|
+
text = `${text}\n\n${tags.join(" ")}`;
|
|
186
|
+
}
|
|
187
|
+
return text;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=linkedin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linkedin.js","sourceRoot":"","sources":["../../src/social/linkedin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Threads client — Meta Threads API.
|
|
3
|
+
*
|
|
4
|
+
* Uses the two-step container → publish flow. Images require creating
|
|
5
|
+
* an image container first, then publishing it.
|
|
6
|
+
*/
|
|
7
|
+
import { type SocialClient, type SocialPostContent, type SocialPostResult, type ValidationResult } from "./base.js";
|
|
8
|
+
export interface ThreadsConfig {
|
|
9
|
+
accessToken: string;
|
|
10
|
+
userId: string;
|
|
11
|
+
}
|
|
12
|
+
export declare class ThreadsClient implements SocialClient {
|
|
13
|
+
private readonly config;
|
|
14
|
+
readonly platform: "threads";
|
|
15
|
+
constructor(config: ThreadsConfig);
|
|
16
|
+
post(content: SocialPostContent): Promise<SocialPostResult>;
|
|
17
|
+
validateContent(text: string): ValidationResult;
|
|
18
|
+
deletePost(postId: string): Promise<boolean>;
|
|
19
|
+
private buildText;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=threads.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"threads.d.ts","sourceRoot":"","sources":["../../src/social/threads.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EAGtB,MAAM,WAAW,CAAC;AAMnB,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,aAAc,YAAW,YAAY;IAGpC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,QAAQ,CAAC,QAAQ,EAAG,SAAS,CAAU;gBAEV,MAAM,EAAE,aAAa;IAE5C,IAAI,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAgFjE,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB;IAqBzC,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAgBlD,OAAO,CAAC,SAAS;CAUlB"}
|