Skip to content

feat(instagram): add post, reel, story, and note publishing#671

Open
Zezi-Ray wants to merge 10 commits intojackwener:mainfrom
Zezi-Ray:instagram-post
Open

feat(instagram): add post, reel, story, and note publishing#671
Zezi-Ray wants to merge 10 commits intojackwener:mainfrom
Zezi-Ray:instagram-post

Conversation

@Zezi-Ray
Copy link
Copy Markdown

@Zezi-Ray Zezi-Ray commented Apr 1, 2026

Summary

Expanded Instagram publishing support related to #626.

Status

This PR is now ready for review.

Included in this branch

  • Added instagram post --media ... as the unified feed-post entrypoint
  • Added private-first publishing for single image, image carousel, and mixed-media carousel posts
  • Added instagram reel --video ... for Reel publishing
  • Added instagram story --media ... for single image/video Story publishing
  • Added instagram note "..." using the real desktop web inbox mutation
  • Added Browser Bridge support needed for native file input, network capture, and related Instagram publishing flows
  • Added adapter tests for the new Instagram commands and publishing helpers

Current behavior

  • instagram post supports:
    • single image
    • image carousel
    • mixed image/video carousel
  • instagram reel supports single-video Reel publishing
  • instagram story supports single image or single video Story publishing
  • instagram note supports publishing a short text Note

Verification

  • npx vitest run src/clis/instagram/post.test.ts src/clis/instagram/_shared/private-publish.test.ts src/clis/instagram/reel.test.ts src/clis/instagram/story.test.ts src/clis/instagram/note.test.ts
  • npm run typecheck
  • npm run build
  • Real browser validation for Instagram post / reel / story / note flows on the current branch

Issue

Refs #626

@Zezi-Ray Zezi-Ray changed the title [Draft] Add Instagram posting flow for issue #626 [Draft] Expand Instagram publishing support for issue #626 Apr 3, 2026
@Zezi-Ray Zezi-Ray marked this pull request as ready for review April 3, 2026 09:28
Copilot AI review requested due to automatic review settings April 3, 2026 09:28
@Zezi-Ray Zezi-Ray changed the title [Draft] Expand Instagram publishing support for issue #626 Expand Instagram publishing support for issue #626 Apr 3, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Expands opencli’s Instagram automation surface area (feed posts, reels, stories, notes) and adds Browser Bridge capabilities needed for richer publishing flows (native file input, network capture, native text insertion).

Changes:

  • Added new Instagram CLI commands: instagram post --media ..., instagram reel --video ..., instagram story --media ..., and instagram note "..." with corresponding adapter tests.
  • Introduced CLI arg enhancements (valueRequired) and a command-level validateArgs hook wired into execution and Commander parsing.
  • Added Browser Bridge protocol + implementation support for insert-text and network capture start/read, enabling private-route publishing helpers to extract needed request context.

Reviewed changes

Copilot reviewed 25 out of 26 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/types.ts Extends IPage with optional network capture + native insertText capabilities.
src/serialization.ts Serializes new valueRequired arg metadata.
src/registry.ts Adds valueRequired for args and validateArgs for commands.
src/execution.ts Runs cmd.validateArgs after coercion/validation and before any execution.
src/commanderAdapter.ts Updates option syntax based on valueRequired and invokes validateArgs in adapter flow.
src/commanderAdapter.test.ts Adds coverage for “optional option but value required” behavior and early validation.
src/clis/instagram/story.ts Implements instagram story --media ... via private publish route with URL resolution.
src/clis/instagram/story.test.ts Adds unit tests for story arg validation + private publish integration.
src/clis/instagram/reel.ts Implements instagram reel --video ... UI automation flow with upload + caption handling.
src/clis/instagram/reel.test.ts Adds unit tests for reel flow (upload, caption, safe filename handling).
src/clis/instagram/post.ts Implements instagram post --media ... with private-first publish + UI fallback and protocol capture.
src/clis/instagram/note.ts Implements instagram note publishing via web inbox GraphQL mutation.
src/clis/instagram/note.test.ts Adds unit tests for note validation and publish happy-path.
src/clis/instagram/_shared/runtime-info.ts Adds runtime info extraction helpers (appId/csrf/ajax) used by private routes.
src/clis/instagram/_shared/protocol-capture.ts Adds protocol/network capture utilities and instagramPrivateApiFetch.
src/clis/instagram/_shared/protocol-capture.test.ts Adds tests for capture installation/read + private fetch behavior.
src/clis/instagram/_shared/private-publish.ts Adds private-route publishing implementation (feed, sidecar, story) and supporting media prep.
src/clis/instagram/_shared/private-publish.test.ts Adds extensive tests for private publish helpers (payloads, retries, story publishing).
src/build-manifest.ts Emits valueRequired into the build-time CLI manifest.
src/browser/page.ts Implements startNetworkCapture, readNetworkCapture, and insertText via daemon commands.
src/browser/daemon-client.ts Extends daemon command union with insert-text + network capture actions/params.
extension/src/protocol.ts Extends extension protocol to include insert-text and network capture actions.
extension/src/cdp.ts Implements CDP Input.insertText and CDP-driven network capture buffering.
extension/src/background.ts Routes new actions to CDP executor: insert-text + network capture start/read.
extension/dist/background.js Updates compiled extension artifact to include new actions and adjusted reconnect behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

const v = optionsRecord[arg.name] ?? optionsRecord[camelName];
if (v !== undefined) kwargs[arg.name] = normalizeArgValue(arg.type, v, arg.name);
}
cmd.validateArgs?.(kwargs);
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cmd.validateArgs is invoked here and also inside executeCommand() (src/execution.ts:158-160). This causes validation to run twice on every Commander invocation and can change error typing/formatting (errors thrown here won’t be wrapped into ArgumentError like they are in executeCommand). Consider removing this call and relying on executeCommand’s early validation (it runs before any browser session work), or ensure validation is only performed in one place consistently.

Suggested change
cmd.validateArgs?.(kwargs);

Copilot uses AI. Check for mistakes.
Comment on lines +50 to +62
function validateVideoPath(input: unknown): string {
const resolved = path.resolve(String(input || '').trim());
if (!resolved) {
throw new ArgumentError('Video path cannot be empty');
}
if (!fs.existsSync(resolved)) {
throw new ArgumentError(`Video file not found: ${resolved}`);
}
const ext = path.extname(resolved).toLowerCase();
if (!SUPPORTED_VIDEO_EXTENSIONS.has(ext)) {
throw new ArgumentError(`Unsupported video format: ${ext}`, 'Supported formats: .mp4');
}
return resolved;
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validateVideoPath() calls path.resolve() on an empty/blank input, but path.resolve('') returns the current working directory. This means an empty --video ""/blank value won’t hit the "cannot be empty" branch and can produce misleading errors (or pass existsSync on a directory). Consider checking the trimmed raw string before path.resolve, and also verify the resolved path is a file (e.g., via statSync().isFile()).

Copilot uses AI. Check for mistakes.
Comment on lines +89 to +92
function buildSafeTempVideoPath(filePath: string): string {
const ext = path.extname(filePath).toLowerCase() || '.mp4';
return path.join(os.tmpdir(), `opencli-instagram-video-real${ext}`);
}
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

buildSafeTempVideoPath() returns a fixed filename in the OS temp directory. Parallel executions (or retries) can clobber each other’s temp uploads and/or upload the wrong file. Use a unique name per invocation (e.g., include crypto.randomUUID()/Date.now() + random suffix) and consider preserving the original basename for easier debugging.

Copilot uses AI. Check for mistakes.
Comment on lines +178 to +193
for (let attempt = 0; attempt < INSTAGRAM_PRIVATE_CONFIG_RETRY_BUDGET; attempt += 1) {
try {
if (typeof page.startNetworkCapture === 'function') {
await page.startNetworkCapture(INSTAGRAM_PRIVATE_CAPTURE_PATTERN);
}
await page.goto(`${INSTAGRAM_HOME_URL}?__opencli_private_probe=${Date.now()}`);
await page.wait({ time: 2 });

const [cookies, runtime, entries] = await Promise.all([
page.getCookies({ domain: 'instagram.com' }),
page.evaluate(buildReadInstagramRuntimeInfoJs()) as Promise<InstagramRuntimeInfo>,
typeof page.readNetworkCapture === 'function'
? page.readNetworkCapture() as Promise<unknown[]>
: Promise.resolve([]),
]);

Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolveInstagramPrivatePublishConfig() starts native network capture for every attempt using a very broad pattern (/api/v1/|/graphql/). Given the extension capture currently records request/response previews, this can collect and transmit a lot of data (including potentially sensitive payload snippets) even though only a few headers are needed to derive context. Consider narrowing the capture pattern to the minimal endpoints needed for header discovery, and/or disabling body/response preview capture unless an explicit debug/capture flag is enabled.

Copilot uses AI. Check for mistakes.
@Zezi-Ray Zezi-Ray changed the title Expand Instagram publishing support for issue #626 feat(instagram): add post, reel, story, and note publishing Apr 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants