@blinkdotnew/cli 0.2.6 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1305,20 +1305,26 @@ async function getPersonId(agentId) {
1305
1305
  return id;
1306
1306
  }
1307
1307
  function registerLinkedInCommands(program2) {
1308
- const li = program2.command("linkedin").description("LinkedIn connector \u2014 post content, manage comments, and view your profile").addHelpText("after", `
1308
+ const li = program2.command("linkedin").description("LinkedIn connector \u2014 publish posts and manage your profile").addHelpText("after", `
1309
1309
  LinkedIn must be linked to your agent via the Integrations tab at blink.new/claw.
1310
1310
  Agent ID defaults to BLINK_AGENT_ID (automatically set on Claw Fly machines).
1311
1311
 
1312
+ What works today (w_member_social scope):
1313
+ \u2705 blink linkedin me Show your LinkedIn profile
1314
+ \u2705 blink linkedin post "Excited to announce..." Publish a text post
1315
+ \u2705 blink linkedin delete <postUrn> Delete one of your posts
1316
+
1317
+ Not yet available (requires LinkedIn Partner API approval):
1318
+ \u2717 Reading posts, comments, likes (needs r_member_social \u2014 restricted scope)
1319
+ \u2717 Adding comments (needs Community Management API)
1320
+
1312
1321
  Examples:
1313
- $ blink linkedin me Show your LinkedIn profile
1314
- $ blink linkedin posts List your 10 most recent posts
1315
- $ blink linkedin post "Excited to announce..." Publish a text post
1316
- $ blink linkedin comments "urn:li:ugcPost:123" Read comments on a post
1317
- $ blink linkedin comment "urn:li:ugcPost:123" "Great post!" Add a comment
1318
- $ blink linkedin like "urn:li:ugcPost:123" Like a post
1319
- $ blink linkedin unlike "urn:li:ugcPost:123" Unlike a post
1322
+ $ blink linkedin me
1323
+ $ blink linkedin post "Our product just launched!"
1324
+ $ blink linkedin post "Team update" --visibility CONNECTIONS
1325
+ $ blink linkedin delete "urn:li:ugcPost:1234567890"
1320
1326
  `);
1321
- li.command("me").description("Show your LinkedIn profile (name, ID, vanity URL)").option("--agent <id>", "Agent ID (defaults to BLINK_AGENT_ID)").addHelpText("after", `
1327
+ li.command("me").description("Show your LinkedIn profile (name, ID, email)").option("--agent <id>", "Agent ID (defaults to BLINK_AGENT_ID)").addHelpText("after", `
1322
1328
  Examples:
1323
1329
  $ blink linkedin me
1324
1330
  $ blink linkedin me --json
@@ -1338,57 +1344,16 @@ Examples:
1338
1344
  if (name) console.log(` ${chalk7.dim("Name:")} ${name}`);
1339
1345
  if (data?.email) console.log(` ${chalk7.dim("Email:")} ${data.email}`);
1340
1346
  });
1341
- li.command("posts").description("List your most recent LinkedIn posts (last 10)").option("--agent <id>", "Agent ID (defaults to BLINK_AGENT_ID)").option("--limit <n>", "Number of posts to fetch (default: 10)", "10").addHelpText("after", `
1342
- Examples:
1343
- $ blink linkedin posts
1344
- $ blink linkedin posts --limit 5
1345
- $ blink linkedin posts --json | jq '.[].id'
1346
- `).action(async (opts) => {
1347
- requireToken();
1348
- const agentId = requireAgentId(opts.agent);
1349
- const personId = await withSpinner(
1350
- "Resolving your LinkedIn identity...",
1351
- () => getPersonId(agentId)
1352
- );
1353
- const authorUrn = encodeURIComponent(`urn:li:person:${personId}`);
1354
- const data = await withSpinner(
1355
- "Fetching posts...",
1356
- () => liExec(
1357
- `ugcPosts?q=authors&authors=List(${authorUrn})&sortBy=LAST_MODIFIED&count=${opts.limit}`,
1358
- "GET",
1359
- {},
1360
- agentId
1361
- )
1362
- );
1363
- const posts = data?.elements ?? (Array.isArray(data) ? data : []);
1364
- if (isJsonMode()) return printJson(posts);
1365
- if (!posts.length) {
1366
- console.log(chalk7.dim("No posts found."));
1367
- return;
1368
- }
1369
- for (const post of posts) {
1370
- const id = post.id ?? "\u2014";
1371
- const content = post.specificContent;
1372
- const share = content?.["com.linkedin.ugc.ShareContent"];
1373
- const commentary = share?.shareCommentary;
1374
- const text = commentary?.text ?? "(no text)";
1375
- const preview = text.length > 120 ? text.slice(0, 120) + "\u2026" : text;
1376
- console.log(chalk7.bold(id));
1377
- console.log(` ${chalk7.dim(preview)}`);
1378
- console.log();
1379
- }
1380
- console.log(chalk7.dim(`${posts.length} post(s)`));
1381
- });
1382
- li.command("post <text>").description("Publish a text post to LinkedIn").option("--agent <id>", "Agent ID (defaults to BLINK_AGENT_ID)").option("--visibility <vis>", "Post visibility: PUBLIC | CONNECTIONS (default: PUBLIC)", "PUBLIC").addHelpText("after", `
1347
+ li.command("post <text>").description("Publish a text post to LinkedIn").option("--agent <id>", "Agent ID (defaults to BLINK_AGENT_ID)").option("--visibility <vis>", "PUBLIC | CONNECTIONS (default: PUBLIC)", "PUBLIC").addHelpText("after", `
1383
1348
  Examples:
1384
1349
  $ blink linkedin post "Excited to share our latest update!"
1385
- $ blink linkedin post "Internal update" --visibility CONNECTIONS
1350
+ $ blink linkedin post "Internal team update" --visibility CONNECTIONS
1386
1351
  $ blink linkedin post "Hello LinkedIn" --json
1387
1352
  `).action(async (text, opts) => {
1388
1353
  requireToken();
1389
1354
  const agentId = requireAgentId(opts.agent);
1390
1355
  const personId = await withSpinner(
1391
- "Resolving your LinkedIn identity...",
1356
+ "Resolving LinkedIn identity...",
1392
1357
  () => getPersonId(agentId)
1393
1358
  );
1394
1359
  const visibilityMap = {
@@ -1415,119 +1380,22 @@ Examples:
1415
1380
  console.log(chalk7.green("\u2713 Post published"));
1416
1381
  if (data?.id) console.log(chalk7.dim(` URN: ${data.id}`));
1417
1382
  });
1418
- li.command("comments <postUrn>").description("Read comments on a LinkedIn post").option("--agent <id>", "Agent ID (defaults to BLINK_AGENT_ID)").addHelpText("after", `
1419
- <postUrn> is the LinkedIn post URN, e.g. urn:li:ugcPost:1234567890
1420
- Use "blink linkedin posts" to find your post URNs.
1383
+ li.command("delete <postUrn>").description("Delete one of your LinkedIn posts").option("--agent <id>", "Agent ID (defaults to BLINK_AGENT_ID)").addHelpText("after", `
1384
+ <postUrn> is the LinkedIn post URN returned when the post was created.
1385
+ e.g. urn:li:ugcPost:1234567890
1421
1386
 
1422
1387
  Examples:
1423
- $ blink linkedin comments "urn:li:ugcPost:1234567890"
1424
- $ blink linkedin comments "urn:li:ugcPost:1234567890" --json
1388
+ $ blink linkedin delete "urn:li:ugcPost:1234567890"
1425
1389
  `).action(async (postUrn, opts) => {
1426
1390
  requireToken();
1427
1391
  const agentId = requireAgentId(opts.agent);
1428
1392
  const encoded = encodeURIComponent(postUrn);
1429
- const data = await withSpinner(
1430
- "Fetching comments...",
1431
- () => liExec(`rest/socialActions/${encoded}/comments`, "GET", {}, agentId)
1432
- );
1433
- const comments = data?.elements ?? (Array.isArray(data) ? data : []);
1434
- if (isJsonMode()) return printJson(comments);
1435
- if (!comments.length) {
1436
- console.log(chalk7.dim("No comments."));
1437
- return;
1438
- }
1439
- for (const c of comments) {
1440
- const author = c.actor ?? "\u2014";
1441
- const msg = c.message;
1442
- const text = msg?.text ?? "(no text)";
1443
- console.log(chalk7.bold(author));
1444
- console.log(` ${text}`);
1445
- console.log();
1446
- }
1447
- console.log(chalk7.dim(`${comments.length} comment(s)`));
1448
- });
1449
- li.command("comment <postUrn> <text>").description("Add a comment to a LinkedIn post").option("--agent <id>", "Agent ID (defaults to BLINK_AGENT_ID)").addHelpText("after", `
1450
- <postUrn> is the LinkedIn post URN, e.g. urn:li:ugcPost:1234567890
1451
-
1452
- Examples:
1453
- $ blink linkedin comment "urn:li:ugcPost:1234567890" "Great post!"
1454
- $ blink linkedin comment "urn:li:ugcPost:1234567890" "Thanks for sharing" --json
1455
- `).action(async (postUrn, text, opts) => {
1456
- requireToken();
1457
- const agentId = requireAgentId(opts.agent);
1458
- const personId = await withSpinner(
1459
- "Resolving your LinkedIn identity...",
1460
- () => getPersonId(agentId)
1461
- );
1462
- const actor = `urn:li:person:${personId}`;
1463
- const encoded = encodeURIComponent(postUrn);
1464
- const data = await withSpinner(
1465
- "Adding comment...",
1466
- () => liExec(
1467
- `rest/socialActions/${encoded}/comments`,
1468
- "POST",
1469
- { actor, object: postUrn, message: { text } },
1470
- agentId
1471
- )
1472
- );
1473
- if (isJsonMode()) return printJson(data);
1474
- console.log(chalk7.green("\u2713 Comment added"));
1475
- if (data?.id) console.log(chalk7.dim(` ID: ${data.id}`));
1476
- });
1477
- li.command("like <postUrn>").description("Like a LinkedIn post").option("--agent <id>", "Agent ID (defaults to BLINK_AGENT_ID)").addHelpText("after", `
1478
- <postUrn> is the LinkedIn post URN, e.g. urn:li:ugcPost:1234567890
1479
-
1480
- Examples:
1481
- $ blink linkedin like "urn:li:ugcPost:1234567890"
1482
- $ blink linkedin like "urn:li:ugcPost:1234567890" --json
1483
- `).action(async (postUrn, opts) => {
1484
- requireToken();
1485
- const agentId = requireAgentId(opts.agent);
1486
- const personId = await withSpinner(
1487
- "Resolving your LinkedIn identity...",
1488
- () => getPersonId(agentId)
1489
- );
1490
- const actor = `urn:li:person:${personId}`;
1491
- const encoded = encodeURIComponent(postUrn);
1492
- const data = await withSpinner(
1493
- "Liking post...",
1494
- () => liExec(
1495
- `rest/socialActions/${encoded}/likes`,
1496
- "POST",
1497
- { actor, object: postUrn },
1498
- agentId
1499
- )
1500
- );
1501
- if (isJsonMode()) return printJson(data);
1502
- console.log(chalk7.green("\u2713 Post liked"));
1503
- });
1504
- li.command("unlike <postUrn>").description("Unlike a LinkedIn post").option("--agent <id>", "Agent ID (defaults to BLINK_AGENT_ID)").addHelpText("after", `
1505
- <postUrn> is the LinkedIn post URN, e.g. urn:li:ugcPost:1234567890
1506
-
1507
- Examples:
1508
- $ blink linkedin unlike "urn:li:ugcPost:1234567890"
1509
- $ blink linkedin unlike "urn:li:ugcPost:1234567890" --json
1510
- `).action(async (postUrn, opts) => {
1511
- requireToken();
1512
- const agentId = requireAgentId(opts.agent);
1513
- const personId = await withSpinner(
1514
- "Resolving your LinkedIn identity...",
1515
- () => getPersonId(agentId)
1516
- );
1517
- const actor = `urn:li:person:${personId}`;
1518
- const encodedPost = encodeURIComponent(postUrn);
1519
- const encodedActor = encodeURIComponent(actor);
1520
- const data = await withSpinner(
1521
- "Unliking post...",
1522
- () => liExec(
1523
- `rest/socialActions/${encodedPost}/likes/${encodedActor}?actor=${encodedActor}`,
1524
- "DELETE",
1525
- {},
1526
- agentId
1527
- )
1393
+ await withSpinner(
1394
+ "Deleting post...",
1395
+ () => liExec(`ugcPosts/${encoded}`, "DELETE", {}, agentId)
1528
1396
  );
1529
- if (isJsonMode()) return printJson(data);
1530
- console.log(chalk7.green("\u2713 Post unliked"));
1397
+ if (isJsonMode()) return printJson({ deleted: true, urn: postUrn });
1398
+ console.log(chalk7.green("\u2713 Post deleted"));
1531
1399
  });
1532
1400
  }
1533
1401
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blinkdotnew/cli",
3
- "version": "0.2.6",
3
+ "version": "0.2.7",
4
4
  "description": "Blink platform CLI — deploy apps, manage databases, generate AI content",
5
5
  "bin": {
6
6
  "blink": "dist/cli.js"
@@ -1,8 +1,8 @@
1
1
  import { Command } from 'commander'
2
- import { resourcesRequest } from '../lib/api-resources.js'
3
2
  import { requireToken } from '../lib/auth.js'
4
3
  import { requireAgentId } from '../lib/agent.js'
5
4
  import { printJson, isJsonMode, withSpinner } from '../lib/output.js'
5
+ import { resourcesRequest } from '../lib/api-resources.js'
6
6
  import chalk from 'chalk'
7
7
 
8
8
  const NOT_LINKED = 'LinkedIn not linked. Link it in the Agent Integrations tab at blink.new/claw'
@@ -22,7 +22,6 @@ async function liExec(
22
22
  }
23
23
 
24
24
  async function getPersonId(agentId: string): Promise<string> {
25
- // Use OpenID Connect userinfo — more reliable than deprecated /v2/me
26
25
  const data = await liExec('v2/userinfo', 'GET', {}, agentId)
27
26
  const id = data?.sub ?? data?.id
28
27
  if (!id) throw new Error('Could not resolve LinkedIn person ID')
@@ -31,24 +30,30 @@ async function getPersonId(agentId: string): Promise<string> {
31
30
 
32
31
  export function registerLinkedInCommands(program: Command) {
33
32
  const li = program.command('linkedin')
34
- .description('LinkedIn connector — post content, manage comments, and view your profile')
33
+ .description('LinkedIn connector — publish posts and manage your profile')
35
34
  .addHelpText('after', `
36
35
  LinkedIn must be linked to your agent via the Integrations tab at blink.new/claw.
37
36
  Agent ID defaults to BLINK_AGENT_ID (automatically set on Claw Fly machines).
38
37
 
38
+ What works today (w_member_social scope):
39
+ ✅ blink linkedin me Show your LinkedIn profile
40
+ ✅ blink linkedin post "Excited to announce..." Publish a text post
41
+ ✅ blink linkedin delete <postUrn> Delete one of your posts
42
+
43
+ Not yet available (requires LinkedIn Partner API approval):
44
+ ✗ Reading posts, comments, likes (needs r_member_social — restricted scope)
45
+ ✗ Adding comments (needs Community Management API)
46
+
39
47
  Examples:
40
- $ blink linkedin me Show your LinkedIn profile
41
- $ blink linkedin posts List your 10 most recent posts
42
- $ blink linkedin post "Excited to announce..." Publish a text post
43
- $ blink linkedin comments "urn:li:ugcPost:123" Read comments on a post
44
- $ blink linkedin comment "urn:li:ugcPost:123" "Great post!" Add a comment
45
- $ blink linkedin like "urn:li:ugcPost:123" Like a post
46
- $ blink linkedin unlike "urn:li:ugcPost:123" Unlike a post
48
+ $ blink linkedin me
49
+ $ blink linkedin post "Our product just launched!"
50
+ $ blink linkedin post "Team update" --visibility CONNECTIONS
51
+ $ blink linkedin delete "urn:li:ugcPost:1234567890"
47
52
  `)
48
53
 
49
54
  // blink linkedin me
50
55
  li.command('me')
51
- .description('Show your LinkedIn profile (name, ID, vanity URL)')
56
+ .description('Show your LinkedIn profile (name, ID, email)')
52
57
  .option('--agent <id>', 'Agent ID (defaults to BLINK_AGENT_ID)')
53
58
  .addHelpText('after', `
54
59
  Examples:
@@ -59,7 +64,6 @@ Examples:
59
64
  .action(async (opts) => {
60
65
  requireToken()
61
66
  const agentId = requireAgentId(opts.agent)
62
- // Use OpenID Connect userinfo endpoint — more reliable than /v2/me
63
67
  const data = await withSpinner('Fetching LinkedIn profile...', () =>
64
68
  liExec('v2/userinfo', 'GET', {}, agentId)
65
69
  )
@@ -67,69 +71,26 @@ Examples:
67
71
  const name = data?.name ?? [data?.given_name, data?.family_name].filter(Boolean).join(' ')
68
72
  const personId = data?.sub ?? data?.id
69
73
  console.log(chalk.bold('LinkedIn Profile'))
70
- if (personId) console.log(` ${chalk.dim('ID:')} ${personId}`)
71
- if (name) console.log(` ${chalk.dim('Name:')} ${name}`)
74
+ if (personId) console.log(` ${chalk.dim('ID:')} ${personId}`)
75
+ if (name) console.log(` ${chalk.dim('Name:')} ${name}`)
72
76
  if (data?.email) console.log(` ${chalk.dim('Email:')} ${data.email}`)
73
77
  })
74
78
 
75
- // blink linkedin posts
76
- li.command('posts')
77
- .description('List your most recent LinkedIn posts (last 10)')
78
- .option('--agent <id>', 'Agent ID (defaults to BLINK_AGENT_ID)')
79
- .option('--limit <n>', 'Number of posts to fetch (default: 10)', '10')
80
- .addHelpText('after', `
81
- Examples:
82
- $ blink linkedin posts
83
- $ blink linkedin posts --limit 5
84
- $ blink linkedin posts --json | jq '.[].id'
85
- `)
86
- .action(async (opts) => {
87
- requireToken()
88
- const agentId = requireAgentId(opts.agent)
89
- const personId = await withSpinner('Resolving your LinkedIn identity...', () =>
90
- getPersonId(agentId)
91
- )
92
- const authorUrn = encodeURIComponent(`urn:li:person:${personId}`)
93
- const data = await withSpinner('Fetching posts...', () =>
94
- liExec(
95
- `ugcPosts?q=authors&authors=List(${authorUrn})&sortBy=LAST_MODIFIED&count=${opts.limit}`,
96
- 'GET',
97
- {},
98
- agentId
99
- )
100
- )
101
- const posts: Array<Record<string, unknown>> = data?.elements ?? (Array.isArray(data) ? data : [])
102
- if (isJsonMode()) return printJson(posts)
103
- if (!posts.length) { console.log(chalk.dim('No posts found.')); return }
104
- for (const post of posts) {
105
- const id = (post.id ?? '—') as string
106
- const content = post.specificContent as Record<string, unknown> | undefined
107
- const share = content?.['com.linkedin.ugc.ShareContent'] as Record<string, unknown> | undefined
108
- const commentary = share?.shareCommentary as Record<string, unknown> | undefined
109
- const text = (commentary?.text ?? '(no text)') as string
110
- const preview = text.length > 120 ? text.slice(0, 120) + '…' : text
111
- console.log(chalk.bold(id))
112
- console.log(` ${chalk.dim(preview)}`)
113
- console.log()
114
- }
115
- console.log(chalk.dim(`${posts.length} post(s)`))
116
- })
117
-
118
79
  // blink linkedin post "text"
119
80
  li.command('post <text>')
120
81
  .description('Publish a text post to LinkedIn')
121
82
  .option('--agent <id>', 'Agent ID (defaults to BLINK_AGENT_ID)')
122
- .option('--visibility <vis>', 'Post visibility: PUBLIC | CONNECTIONS (default: PUBLIC)', 'PUBLIC')
83
+ .option('--visibility <vis>', 'PUBLIC | CONNECTIONS (default: PUBLIC)', 'PUBLIC')
123
84
  .addHelpText('after', `
124
85
  Examples:
125
86
  $ blink linkedin post "Excited to share our latest update!"
126
- $ blink linkedin post "Internal update" --visibility CONNECTIONS
87
+ $ blink linkedin post "Internal team update" --visibility CONNECTIONS
127
88
  $ blink linkedin post "Hello LinkedIn" --json
128
89
  `)
129
90
  .action(async (text: string, opts) => {
130
91
  requireToken()
131
92
  const agentId = requireAgentId(opts.agent)
132
- const personId = await withSpinner('Resolving your LinkedIn identity...', () =>
93
+ const personId = await withSpinner('Resolving LinkedIn identity...', () =>
133
94
  getPersonId(agentId)
134
95
  )
135
96
  const visibilityMap: Record<string, string> = {
@@ -156,132 +117,25 @@ Examples:
156
117
  if (data?.id) console.log(chalk.dim(` URN: ${data.id}`))
157
118
  })
158
119
 
159
- // blink linkedin comments <postUrn>
160
- li.command('comments <postUrn>')
161
- .description('Read comments on a LinkedIn post')
162
- .option('--agent <id>', 'Agent ID (defaults to BLINK_AGENT_ID)')
163
- .addHelpText('after', `
164
- <postUrn> is the LinkedIn post URN, e.g. urn:li:ugcPost:1234567890
165
- Use "blink linkedin posts" to find your post URNs.
166
-
167
- Examples:
168
- $ blink linkedin comments "urn:li:ugcPost:1234567890"
169
- $ blink linkedin comments "urn:li:ugcPost:1234567890" --json
170
- `)
171
- .action(async (postUrn: string, opts) => {
172
- requireToken()
173
- const agentId = requireAgentId(opts.agent)
174
- const encoded = encodeURIComponent(postUrn)
175
- const data = await withSpinner('Fetching comments...', () =>
176
- liExec(`rest/socialActions/${encoded}/comments`, 'GET', {}, agentId)
177
- )
178
- const comments: Array<Record<string, unknown>> = data?.elements ?? (Array.isArray(data) ? data : [])
179
- if (isJsonMode()) return printJson(comments)
180
- if (!comments.length) { console.log(chalk.dim('No comments.')); return }
181
- for (const c of comments) {
182
- const author = (c.actor ?? '—') as string
183
- const msg = c.message as Record<string, unknown> | undefined
184
- const text = (msg?.text ?? '(no text)') as string
185
- console.log(chalk.bold(author))
186
- console.log(` ${text}`)
187
- console.log()
188
- }
189
- console.log(chalk.dim(`${comments.length} comment(s)`))
190
- })
191
-
192
- // blink linkedin comment <postUrn> "text"
193
- li.command('comment <postUrn> <text>')
194
- .description('Add a comment to a LinkedIn post')
120
+ // blink linkedin delete <postUrn>
121
+ li.command('delete <postUrn>')
122
+ .description('Delete one of your LinkedIn posts')
195
123
  .option('--agent <id>', 'Agent ID (defaults to BLINK_AGENT_ID)')
196
124
  .addHelpText('after', `
197
- <postUrn> is the LinkedIn post URN, e.g. urn:li:ugcPost:1234567890
125
+ <postUrn> is the LinkedIn post URN returned when the post was created.
126
+ e.g. urn:li:ugcPost:1234567890
198
127
 
199
128
  Examples:
200
- $ blink linkedin comment "urn:li:ugcPost:1234567890" "Great post!"
201
- $ blink linkedin comment "urn:li:ugcPost:1234567890" "Thanks for sharing" --json
202
- `)
203
- .action(async (postUrn: string, text: string, opts) => {
204
- requireToken()
205
- const agentId = requireAgentId(opts.agent)
206
- const personId = await withSpinner('Resolving your LinkedIn identity...', () =>
207
- getPersonId(agentId)
208
- )
209
- const actor = `urn:li:person:${personId}`
210
- const encoded = encodeURIComponent(postUrn)
211
- const data = await withSpinner('Adding comment...', () =>
212
- liExec(
213
- `rest/socialActions/${encoded}/comments`,
214
- 'POST',
215
- { actor, object: postUrn, message: { text } },
216
- agentId
217
- )
218
- )
219
- if (isJsonMode()) return printJson(data)
220
- console.log(chalk.green('✓ Comment added'))
221
- if (data?.id) console.log(chalk.dim(` ID: ${data.id}`))
222
- })
223
-
224
- // blink linkedin like <postUrn>
225
- li.command('like <postUrn>')
226
- .description('Like a LinkedIn post')
227
- .option('--agent <id>', 'Agent ID (defaults to BLINK_AGENT_ID)')
228
- .addHelpText('after', `
229
- <postUrn> is the LinkedIn post URN, e.g. urn:li:ugcPost:1234567890
230
-
231
- Examples:
232
- $ blink linkedin like "urn:li:ugcPost:1234567890"
233
- $ blink linkedin like "urn:li:ugcPost:1234567890" --json
129
+ $ blink linkedin delete "urn:li:ugcPost:1234567890"
234
130
  `)
235
131
  .action(async (postUrn: string, opts) => {
236
132
  requireToken()
237
133
  const agentId = requireAgentId(opts.agent)
238
- const personId = await withSpinner('Resolving your LinkedIn identity...', () =>
239
- getPersonId(agentId)
240
- )
241
- const actor = `urn:li:person:${personId}`
242
134
  const encoded = encodeURIComponent(postUrn)
243
- const data = await withSpinner('Liking post...', () =>
244
- liExec(
245
- `rest/socialActions/${encoded}/likes`,
246
- 'POST',
247
- { actor, object: postUrn },
248
- agentId
249
- )
135
+ await withSpinner('Deleting post...', () =>
136
+ liExec(`ugcPosts/${encoded}`, 'DELETE', {}, agentId)
250
137
  )
251
- if (isJsonMode()) return printJson(data)
252
- console.log(chalk.green('✓ Post liked'))
253
- })
254
-
255
- // blink linkedin unlike <postUrn>
256
- li.command('unlike <postUrn>')
257
- .description('Unlike a LinkedIn post')
258
- .option('--agent <id>', 'Agent ID (defaults to BLINK_AGENT_ID)')
259
- .addHelpText('after', `
260
- <postUrn> is the LinkedIn post URN, e.g. urn:li:ugcPost:1234567890
261
-
262
- Examples:
263
- $ blink linkedin unlike "urn:li:ugcPost:1234567890"
264
- $ blink linkedin unlike "urn:li:ugcPost:1234567890" --json
265
- `)
266
- .action(async (postUrn: string, opts) => {
267
- requireToken()
268
- const agentId = requireAgentId(opts.agent)
269
- const personId = await withSpinner('Resolving your LinkedIn identity...', () =>
270
- getPersonId(agentId)
271
- )
272
- const actor = `urn:li:person:${personId}`
273
- const encodedPost = encodeURIComponent(postUrn)
274
- const encodedActor = encodeURIComponent(actor)
275
- // LinkedIn DELETE likes requires: DELETE /rest/socialActions/{postUrn}/likes/{actorUrn}?actor={actorUrn}
276
- const data = await withSpinner('Unliking post...', () =>
277
- liExec(
278
- `rest/socialActions/${encodedPost}/likes/${encodedActor}?actor=${encodedActor}`,
279
- 'DELETE',
280
- {},
281
- agentId
282
- )
283
- )
284
- if (isJsonMode()) return printJson(data)
285
- console.log(chalk.green('✓ Post unliked'))
138
+ if (isJsonMode()) return printJson({ deleted: true, urn: postUrn })
139
+ console.log(chalk.green('✓ Post deleted'))
286
140
  })
287
141
  }