@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 +27 -159
- package/package.json +1 -1
- package/src/commands/linkedin.ts +31 -177
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
|
|
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
|
|
1314
|
-
$ blink linkedin
|
|
1315
|
-
$ blink linkedin post "
|
|
1316
|
-
$ blink linkedin
|
|
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,
|
|
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("
|
|
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
|
|
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("
|
|
1419
|
-
<postUrn> is the LinkedIn post URN
|
|
1420
|
-
|
|
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
|
|
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
|
-
|
|
1430
|
-
"
|
|
1431
|
-
() => liExec(`
|
|
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(
|
|
1530
|
-
console.log(chalk7.green("\u2713 Post
|
|
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
package/src/commands/linkedin.ts
CHANGED
|
@@ -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 —
|
|
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
|
|
41
|
-
$ blink linkedin
|
|
42
|
-
$ blink linkedin post "
|
|
43
|
-
$ blink linkedin
|
|
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,
|
|
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)
|
|
71
|
-
if (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>', '
|
|
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
|
|
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
|
|
160
|
-
li.command('
|
|
161
|
-
.description('
|
|
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
|
|
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
|
|
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
|
-
|
|
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(
|
|
252
|
-
console.log(chalk.green('✓ Post
|
|
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
|
}
|