Skip to content

Commit 33aaff9

Browse files
committed
feat: add robust profile banner upload/remove management (#614)
- Implement prepareRemoveBanner and RemoveProfileBannerActionExecutor - Add banner file size and dimension checks locally - Update CLI and MCP commands - Add unit/E2E tests for banner operations
1 parent 5b46685 commit 33aaff9

File tree

8 files changed

+337
-0
lines changed

8 files changed

+337
-0
lines changed

package-lock.json

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/cli/src/bin/linkedin.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7319,6 +7319,40 @@ async function runProfilePrepareUploadPhoto(
73197319
}
73207320
}
73217321

7322+
async function runProfilePrepareRemoveBanner(
7323+
input: {
7324+
profileName: string;
7325+
operatorNote?: string;
7326+
},
7327+
cdpUrl?: string,
7328+
): Promise<void> {
7329+
const runtime = createRuntime(cdpUrl);
7330+
7331+
try {
7332+
runtime.logger.log("info", "cli.profile.prepare_remove_banner.start", {
7333+
profileName: input.profileName,
7334+
});
7335+
7336+
const prepared = await runtime.profile.prepareRemoveBanner({
7337+
profileName: input.profileName,
7338+
...(input.operatorNote ? { operatorNote: input.operatorNote } : {}),
7339+
});
7340+
7341+
runtime.logger.log("info", "cli.profile.prepare_remove_banner.done", {
7342+
profileName: input.profileName,
7343+
preparedActionId: prepared.preparedActionId,
7344+
});
7345+
7346+
printPrepareResult({
7347+
run_id: runtime.runId,
7348+
profile_name: input.profileName,
7349+
...prepared,
7350+
});
7351+
} finally {
7352+
runtime.close();
7353+
}
7354+
}
7355+
73227356
async function runProfilePrepareUploadBanner(
73237357
input: {
73247358
profileName: string;
@@ -13383,6 +13417,31 @@ export function createCliProgram(): Command {
1338313417
},
1338413418
);
1338513419

13420+
profileCommand
13421+
.command("prepare-remove-banner")
13422+
.description("Prepare to remove a LinkedIn profile banner (two-phase)")
13423+
.option("-p, --profile <profile>", "Profile name", "default")
13424+
.option(
13425+
"--operator-note <note>",
13426+
"Optional note attached to the prepared action",
13427+
)
13428+
.action(
13429+
async (options: {
13430+
operatorNote?: string;
13431+
profile: string;
13432+
}) => {
13433+
await runProfilePrepareRemoveBanner(
13434+
{
13435+
profileName: options.profile,
13436+
...(options.operatorNote
13437+
? { operatorNote: options.operatorNote }
13438+
: {}),
13439+
},
13440+
readCdpUrl(),
13441+
);
13442+
},
13443+
);
13444+
1338613445
profileCommand
1338713446
.command("apply-spec")
1338813447
.description(

packages/core/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"dependencies": {
5050
"better-sqlite3": "^12.8.0",
5151
"fflate": "^0.8.2",
52+
"image-size": "^2.0.2",
5253
"playwright-core": "npm:patchright-core@^1.58.0",
5354
"playwright-extra": "^4.3.6",
5455
"pngjs": "^7.0.0",

packages/core/src/__tests__/e2e/helpers.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ import {
114114
LINKEDIN_PROFILE_PREPARE_REQUEST_RECOMMENDATION_TOOL,
115115
LINKEDIN_PROFILE_PREPARE_WRITE_RECOMMENDATION_TOOL,
116116
LINKEDIN_PROFILE_PREPARE_UPLOAD_BANNER_TOOL,
117+
LINKEDIN_PROFILE_PREPARE_REMOVE_BANNER_TOOL,
117118
LINKEDIN_PROFILE_PREPARE_UPLOAD_PHOTO_TOOL,
118119
LINKEDIN_PROFILE_PREPARE_REMOVE_PHOTO_TOOL,
119120
LINKEDIN_PROFILE_PREPARE_UPDATE_PUBLIC_PROFILE_TOOL,
@@ -1059,6 +1060,7 @@ export const MCP_TOOL_NAMES = {
10591060
profilePrepareUploadPhoto: LINKEDIN_PROFILE_PREPARE_UPLOAD_PHOTO_TOOL,
10601061
profilePrepareRemovePhoto: LINKEDIN_PROFILE_PREPARE_REMOVE_PHOTO_TOOL,
10611062
profilePrepareUploadBanner: LINKEDIN_PROFILE_PREPARE_UPLOAD_BANNER_TOOL,
1063+
profilePrepareRemoveBanner: LINKEDIN_PROFILE_PREPARE_REMOVE_BANNER_TOOL,
10621064
profilePrepareFeaturedAdd: LINKEDIN_PROFILE_PREPARE_FEATURED_ADD_TOOL,
10631065
profilePrepareFeaturedRemove: LINKEDIN_PROFILE_PREPARE_FEATURED_REMOVE_TOOL,
10641066
profilePrepareFeaturedReorder: LINKEDIN_PROFILE_PREPARE_FEATURED_REORDER_TOOL,

packages/core/src/__tests__/e2e/profile.e2e.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,15 @@ describe("Profile E2E", () => {
232232
expectRateLimitPreview(prepared.preview, "linkedin.profile.upload_banner");
233233
}, 60_000);
234234

235+
it("prepareRemoveBanner returns valid preview", async (context) => {
236+
skipIfE2EUnavailable(e2e, context);
237+
const runtime = e2e.runtime();
238+
const prepared = await runtime.profile.prepareRemoveBanner({});
239+
240+
expectPreparedAction(prepared);
241+
expectRateLimitPreview(prepared.preview, "linkedin.profile.remove_banner");
242+
}, 60_000);
243+
235244
it("prepareFeaturedAdd for link returns valid preview", async (context) => {
236245
skipIfE2EUnavailable(e2e, context);
237246
const runtime = e2e.runtime();

0 commit comments

Comments
 (0)