@pipedream/linkupapi 0.2.0 → 1.0.1

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.
@@ -0,0 +1,85 @@
1
+ import { ConfigurationError } from "@pipedream/platform";
2
+ import app from "../../linkupapi.app.mjs";
3
+ import { DEFAULT_PLATFORM } from "../../common/constants.mjs";
4
+
5
+ export default {
6
+ key: "linkupapi-connect-account",
7
+ name: "Connect Account",
8
+ description: "Authenticate a LinkedIn account and obtain a persistent `account_id` to reuse across all other actions. Connect with either a login token or email + password. If a checkpoint/challenge is required, follow up with **Verify Code**. [See the documentation](https://docs.linkupapi.com/api-reference/v2/accounts/login)",
9
+ version: "0.0.2",
10
+ type: "action",
11
+ ai: "optimized",
12
+ annotations: {
13
+ readOnlyHint: false,
14
+ destructiveHint: false,
15
+ openWorldHint: true,
16
+ },
17
+ props: {
18
+ app,
19
+ loginToken: {
20
+ type: "string",
21
+ label: "Login Token",
22
+ description: "LinkedIn authentication token/cookie for direct, token-based connection. Alternative to Email + Password that skips the 2FA step. Provide this, or both **Email** and **Password**.",
23
+ secret: true,
24
+ optional: true,
25
+ },
26
+ email: {
27
+ propDefinition: [
28
+ app,
29
+ "email",
30
+ ],
31
+ description: "Account email address. Required (with **Password**) for credential-based login when no **Login Token** is provided.",
32
+ },
33
+ password: {
34
+ propDefinition: [
35
+ app,
36
+ "password",
37
+ ],
38
+ description: "Account password. Required (with **Email**) for credential-based login when no **Login Token** is provided.",
39
+ },
40
+ country: {
41
+ propDefinition: [
42
+ app,
43
+ "country",
44
+ ],
45
+ },
46
+ accountName: {
47
+ type: "string",
48
+ label: "Account Name",
49
+ description: "Display name for the account. Defaults to the email address.",
50
+ optional: true,
51
+ },
52
+ challengeType: {
53
+ type: "string",
54
+ label: "Challenge Type",
55
+ description: "Type of 2FA challenge to use if the account has two-factor authentication enabled. `code_challenge`: receive a verification code (email/SMS/authenticator) to submit via **Verify Code**. `app_challenge`: approve the login from the LinkedIn mobile app, then call **Verify Code** with only the account ID.",
56
+ optional: true,
57
+ options: [
58
+ "code_challenge",
59
+ "app_challenge",
60
+ ],
61
+ },
62
+ },
63
+ async run({ $ }) {
64
+ if (!this.loginToken && !(this.email && this.password)) {
65
+ throw new ConfigurationError("Provide a **Login Token**, or both **Email** and **Password**, to connect an account.");
66
+ }
67
+ const response = await this.app.connectAccount({
68
+ $,
69
+ data: {
70
+ platform: DEFAULT_PLATFORM,
71
+ email: this.email,
72
+ password: this.password,
73
+ login_token: this.loginToken,
74
+ country: this.country,
75
+ account_name: this.accountName,
76
+ challenge_type: this.challengeType,
77
+ },
78
+ });
79
+
80
+ $.export("$summary", `Successfully connected account${response.data?.account_id
81
+ ? `: ${response.data.account_id}`
82
+ : ""}`);
83
+ return response;
84
+ },
85
+ };
@@ -1,65 +1,68 @@
1
+ import { ConfigurationError } from "@pipedream/platform";
1
2
  import app from "../../linkupapi.app.mjs";
2
3
 
3
4
  export default {
4
5
  type: "action",
6
+ ai: "optimized",
5
7
  key: "linkupapi-connect-to-profile",
6
- name: "Connect to Profile",
7
- description: "Send a connection request to a LinkedIn profile. [See the documentation](https://docs.linkupapi.com/api-reference/linkup/Network/connect)",
8
- version: "0.0.2",
8
+ name: "Connect To Profile",
9
+ description: "Send a connection invitation to a LinkedIn profile. [See the documentation](https://docs.linkupapi.com/api-reference/v2/network/invite)",
10
+ version: "1.0.1",
11
+ annotations: {
12
+ readOnlyHint: false,
13
+ destructiveHint: false,
14
+ openWorldHint: true,
15
+ },
9
16
  props: {
10
17
  app,
18
+ accountId: {
19
+ propDefinition: [
20
+ app,
21
+ "accountId",
22
+ ],
23
+ },
11
24
  linkedinUrl: {
12
25
  propDefinition: [
13
26
  app,
14
27
  "linkedinUrl",
15
28
  ],
29
+ description: "LinkedIn profile URL. Eg. `https://www.linkedin.com/in/john-doe/`. Required unless **Identifier** is provided.",
30
+ optional: true,
16
31
  },
17
- loginToken: {
32
+ identifier: {
18
33
  propDefinition: [
19
34
  app,
20
- "loginToken",
35
+ "identifier",
21
36
  ],
37
+ description: "Unique identifier of the person to invite. Required unless **LinkedIn URL** is provided.",
22
38
  },
23
39
  message: {
24
40
  type: "string",
25
41
  label: "Message",
26
- description: "Optional custom message to include with connection request",
42
+ description: "Message to include with the connection request (max 300 chars).",
27
43
  optional: true,
28
44
  },
29
- country: {
30
- propDefinition: [
31
- app,
32
- "country",
33
- ],
34
- },
35
- },
36
- annotations: {
37
- readOnlyHint: false,
38
- destructiveHint: true,
39
- openWorldHint: true,
40
- idempotentHint: false,
41
45
  },
42
46
  async run({ $ }) {
43
- const {
44
- app,
45
- linkedinUrl,
46
- loginToken,
47
- message,
48
- country,
49
- } = this;
47
+ if (!this.linkedinUrl && !this.identifier) {
48
+ throw new ConfigurationError("Provide either a **LinkedIn URL** or an **Identifier** to invite.");
49
+ }
50
50
 
51
- const response = await app.connectToProfile({
51
+ if (this.message && this.message.length > 300) {
52
+ throw new ConfigurationError("Message must be less than 300 characters.");
53
+ }
54
+
55
+ const response = await this.app.connectToProfile({
52
56
  $,
53
- data: {
54
- linkedin_url: linkedinUrl,
55
- login_token: loginToken,
56
- message_text: message,
57
- country,
57
+ accountId: this.accountId,
58
+ params: {
59
+ profile_url: this.linkedinUrl,
60
+ identifier: this.identifier,
61
+ message: this.message,
58
62
  },
59
63
  });
60
64
 
61
- $.export("$summary", "Successfully sent connection request");
62
-
65
+ $.export("$summary", `Successfully sent connection invitation to ${this.linkedinUrl || this.identifier}`);
63
66
  return response;
64
67
  },
65
68
  };
@@ -1,61 +1,56 @@
1
- import linkupapi from "../../linkupapi.app.mjs";
1
+ import app from "../../linkupapi.app.mjs";
2
2
 
3
3
  export default {
4
4
  key: "linkupapi-create-comment",
5
5
  name: "Create Comment",
6
- description: "Create a comment on a post. [See the documentation](https://docs.linkupapi.com/api-reference/linkup/posts/comment)",
7
- version: "0.0.1",
6
+ description: "Post a comment on LinkedIn content. [See the documentation](https://docs.linkupapi.com/api-reference/v2/content/comment)",
7
+ version: "1.0.1",
8
8
  type: "action",
9
+ ai: "optimized",
9
10
  annotations: {
10
11
  destructiveHint: false,
11
12
  openWorldHint: true,
12
13
  readOnlyHint: false,
13
14
  },
14
15
  props: {
15
- linkupapi,
16
- postUrl: {
17
- type: "string",
18
- label: "Post URL",
19
- description: "LinkedIn post URL to comment on (must contain a valid activity URN)",
20
- },
21
- message: {
22
- type: "string",
23
- label: "Message",
24
- description: "Text content of the comment to post",
25
- },
26
- loginToken: {
16
+ app,
17
+ accountId: {
27
18
  propDefinition: [
28
- linkupapi,
29
- "loginToken",
19
+ app,
20
+ "accountId",
30
21
  ],
31
22
  },
32
- country: {
23
+ postUrl: {
24
+ type: "string",
25
+ label: "LinkedIn Post URL",
26
+ description: "LinkedIn post URL to comment on. Eg. `https://www.linkedin.com/feed/update/urn:li:activity:1234567890/`.",
27
+ },
28
+ messageText: {
33
29
  propDefinition: [
34
- linkupapi,
35
- "country",
30
+ app,
31
+ "messageText",
36
32
  ],
33
+ description: "Comment text content.",
37
34
  },
38
35
  companyUrl: {
39
- propDefinition: [
40
- linkupapi,
41
- "companyUrl",
42
- ],
36
+ type: "string",
37
+ label: "Company URL",
38
+ description: "Comment as a company page instead of your personal profile, by providing the company's LinkedIn URL. Eg. `https://www.linkedin.com/company/stripe/`.",
39
+ optional: true,
43
40
  },
44
41
  },
45
42
  async run({ $ }) {
46
- const response = await this.linkupapi.createComment({
43
+ const response = await this.app.createComment({
47
44
  $,
48
- data: {
45
+ accountId: this.accountId,
46
+ params: {
49
47
  post_url: this.postUrl,
50
- message: this.message,
51
- login_token: this.loginToken,
52
- country: this.country,
48
+ comment_text: this.messageText,
53
49
  company_url: this.companyUrl,
54
50
  },
55
51
  });
56
52
 
57
- $.export("$summary", "Successfully created comment");
58
-
53
+ $.export("$summary", `Successfully created comment on ${this.postUrl}`);
59
54
  return response;
60
55
  },
61
56
  };
@@ -0,0 +1,32 @@
1
+ import app from "../../linkupapi.app.mjs";
2
+
3
+ export default {
4
+ key: "linkupapi-get-account-details",
5
+ name: "Get Account Details",
6
+ description: "Retrieve details (status, active flag, platform, associated LinkedIn identifier, timestamps) for a connected LinkupAPI account. [See the documentation](https://docs.linkupapi.com/api-reference/v2/accounts/get-account)",
7
+ version: "0.0.1",
8
+ type: "action",
9
+ annotations: {
10
+ readOnlyHint: true,
11
+ destructiveHint: false,
12
+ openWorldHint: true,
13
+ },
14
+ props: {
15
+ app,
16
+ accountId: {
17
+ propDefinition: [
18
+ app,
19
+ "accountId",
20
+ ],
21
+ },
22
+ },
23
+ async run({ $ }) {
24
+ const response = await this.app.getAccountDetails({
25
+ $,
26
+ accountId: this.accountId,
27
+ });
28
+
29
+ $.export("$summary", `Successfully retrieved details for account ${this.accountId}`);
30
+ return response;
31
+ },
32
+ };
@@ -4,53 +4,37 @@ export default {
4
4
  type: "action",
5
5
  key: "linkupapi-get-company-info",
6
6
  name: "Get Company Info",
7
- description: "Extract detailed information about a company from LinkedIn. [See the documentation](https://docs.linkupapi.com/api-reference/linkup/Companies/company-info)",
8
- version: "0.0.2",
7
+ description: "Fetch details for a LinkedIn company. [See the documentation](https://docs.linkupapi.com/api-reference/v2/profiles/get-company)",
8
+ version: "1.0.0",
9
+ annotations: {
10
+ readOnlyHint: true,
11
+ destructiveHint: false,
12
+ openWorldHint: true,
13
+ },
9
14
  props: {
10
15
  app,
11
- companyUrl: {
12
- type: "string",
13
- label: "Company URL",
14
- description: "LinkedIn company URLs. Eg. `https://www.linkedin.com/company/stripe/`",
15
- optional: true,
16
- },
17
- loginToken: {
16
+ accountId: {
18
17
  propDefinition: [
19
18
  app,
20
- "loginToken",
19
+ "accountId",
21
20
  ],
22
21
  },
23
- country: {
24
- propDefinition: [
25
- app,
26
- "country",
27
- ],
22
+ companyUrl: {
23
+ type: "string",
24
+ label: "LinkedIn Company URL",
25
+ description: "LinkedIn company URL. Eg. `https://www.linkedin.com/company/stripe/`.",
28
26
  },
29
27
  },
30
- annotations: {
31
- readOnlyHint: true,
32
- destructiveHint: false,
33
- openWorldHint: true,
34
- idempotentHint: true,
35
- },
36
28
  async run({ $ }) {
37
- const {
38
- app,
39
- companyUrl,
40
- loginToken,
41
- country,
42
- } = this;
43
-
44
- const response = await app.getCompanyInfo({
29
+ const response = await this.app.getCompanyInfo({
45
30
  $,
46
- data: {
47
- company_url: companyUrl,
48
- login_token: loginToken,
49
- country,
31
+ accountId: this.accountId,
32
+ params: {
33
+ company_url: this.companyUrl,
50
34
  },
51
35
  });
52
36
 
53
- $.export("$summary", "Successfully retrieved company information");
37
+ $.export("$summary", `Successfully retrieved company information for ${this.companyUrl}`);
54
38
  return response;
55
39
  },
56
40
  };
@@ -3,81 +3,72 @@ import app from "../../linkupapi.app.mjs";
3
3
 
4
4
  export default {
5
5
  type: "action",
6
+ ai: "optimized",
6
7
  key: "linkupapi-get-conversation-messages",
7
8
  name: "Get Conversation Messages",
8
- description: "Retrieve messages from a LinkedIn conversation. [See the documentation](https://docs.linkupapi.com/api-reference/linkup/Messages/conversation)",
9
- version: "0.0.2",
9
+ description: "Retrieve messages from a LinkedIn conversation. Identify the conversation by its ID or by the recipient's profile URL. [See the documentation](https://docs.linkupapi.com/api-reference/v2/messages/get-conversation)",
10
+ version: "1.0.1",
11
+ annotations: {
12
+ readOnlyHint: true,
13
+ destructiveHint: false,
14
+ openWorldHint: true,
15
+ },
10
16
  props: {
11
17
  app,
12
- loginToken: {
18
+ accountId: {
13
19
  propDefinition: [
14
20
  app,
15
- "loginToken",
21
+ "accountId",
16
22
  ],
17
23
  },
18
- linkedinUrl: {
24
+ conversationId: {
19
25
  propDefinition: [
20
26
  app,
21
- "linkedinUrl",
27
+ "conversationId",
22
28
  ],
23
29
  optional: true,
24
- description: "LinkedIn URL of the other party (required if **Conversation ID** is not provided)",
30
+ description: "LinkedIn conversation identifier. Provide this or a **LinkedIn URL**. Pick from your inbox, or run **List Inbox** to find one.",
25
31
  },
26
- conversationId: {
32
+ linkedinUrl: {
27
33
  propDefinition: [
28
34
  app,
29
- "conversationId",
30
- ({ loginToken }) => ({
31
- loginToken,
32
- }),
35
+ "linkedinUrl",
33
36
  ],
37
+ description: "LinkedIn profile URL of the other participant; the conversation with that user is resolved automatically. Provide this or a **Conversation ID**.",
34
38
  optional: true,
35
- description: "LinkedIn conversation ID (required if **LinkedIn URL** is not provided)",
36
39
  },
37
40
  totalResults: {
38
- type: "integer",
39
- label: "Total Results",
40
- description: "Number of messages to retrieve when not in pagination mode (default: 10)",
41
- optional: true,
42
- },
43
- country: {
44
41
  propDefinition: [
45
42
  app,
46
- "country",
43
+ "totalResults",
47
44
  ],
48
45
  },
49
46
  },
50
- annotations: {
51
- readOnlyHint: true,
52
- destructiveHint: false,
53
- openWorldHint: true,
54
- idempotentHint: true,
55
- },
56
47
  async run({ $ }) {
57
- const {
58
- loginToken,
59
- linkedinUrl,
60
- conversationId,
61
- totalResults,
62
- country,
63
- } = this;
64
-
65
- if (!linkedinUrl && !conversationId) {
66
- throw new ConfigurationError("Either **LinkedIn URL** or **Conversation ID** is required");
48
+ if (!this.conversationId && !this.linkedinUrl) {
49
+ throw new ConfigurationError("Provide a **Conversation ID** or a **LinkedIn URL** to identify the conversation.");
67
50
  }
68
-
69
- const response = await this.app.getConversationMessages({
70
- $,
71
- data: {
72
- login_token: loginToken,
73
- linkedin_url: linkedinUrl,
74
- conversation_id: conversationId,
75
- country,
76
- total_results: totalResults,
77
- },
51
+ const messages = await this.app._paginate({
52
+ max: this.totalResults,
53
+ requestPage: ({
54
+ next, count,
55
+ }) => this.app.getConversationMessages({
56
+ $,
57
+ accountId: this.accountId,
58
+ params: {
59
+ conversation_id: this.conversationId,
60
+ profile_url: this.linkedinUrl,
61
+ count,
62
+ cursor: next,
63
+ },
64
+ }),
65
+ getItems: (res) => res.data?.messages,
66
+ getNext: (res) => res.data?.next_cursor,
78
67
  });
79
68
 
80
- $.export("$summary", "Successfully retrieved conversation messages");
81
- return response;
69
+ $.export("$summary", `Successfully retrieved ${messages.length} message${messages.length === 1
70
+ ? ""
71
+ : "s"} for conversation ${this.conversationId || this.linkedinUrl}`);
72
+ return messages;
82
73
  },
83
74
  };
@@ -2,56 +2,60 @@ import app from "../../linkupapi.app.mjs";
2
2
 
3
3
  export default {
4
4
  type: "action",
5
+ ai: "optimized",
5
6
  key: "linkupapi-get-invitations-status",
6
7
  name: "Get Invitations Status",
7
- description: "Check the status of connection invitations for a LinkedIn profile. [See the documentation](https://docs.linkupapi.com/api-reference/linkup/Network/get_invitations_status)",
8
- version: "0.0.2",
8
+ description: "List pending connection invitations **received** by the connected account. Note: this returns invitations received, not ones you have sent. [See the documentation](https://docs.linkupapi.com/api-reference/v2/network/list-invitations)",
9
+ version: "1.0.1",
10
+ annotations: {
11
+ readOnlyHint: true,
12
+ destructiveHint: false,
13
+ openWorldHint: true,
14
+ },
9
15
  props: {
10
16
  app,
11
- linkedinUrl: {
17
+ accountId: {
12
18
  propDefinition: [
13
19
  app,
14
- "linkedinUrl",
20
+ "accountId",
15
21
  ],
16
22
  },
17
- loginToken: {
23
+ totalResults: {
18
24
  propDefinition: [
19
25
  app,
20
- "loginToken",
26
+ "totalResults",
21
27
  ],
22
28
  },
23
- country: {
24
- propDefinition: [
25
- app,
26
- "country",
27
- ],
29
+ invitationType: {
30
+ type: "string",
31
+ label: "Invitation Type",
32
+ description: "Filter received invitations by type (e.g. `CONNECTION`). Omit for all types.",
33
+ optional: true,
28
34
  },
29
35
  },
30
- annotations: {
31
- readOnlyHint: true,
32
- destructiveHint: false,
33
- openWorldHint: true,
34
- idempotentHint: true,
35
- },
36
36
  async run({ $ }) {
37
- const {
38
- app,
39
- linkedinUrl,
40
- loginToken,
41
- country,
42
- } = this;
43
-
44
- const response = await app.getInvitationsStatus({
45
- $,
46
- data: {
47
- linkedin_url: linkedinUrl,
48
- login_token: loginToken,
49
- country,
50
- },
37
+ const invitations = await this.app._paginate({
38
+ max: this.totalResults,
39
+ requestPage: ({
40
+ next, count,
41
+ }) => this.app.getInvitations({
42
+ $,
43
+ accountId: this.accountId,
44
+ params: {
45
+ count,
46
+ offset: next || 0,
47
+ invitation_type: this.invitationType,
48
+ },
49
+ }),
50
+ getItems: (res) => res.data?.invitations,
51
+ getNext: (res) => res.data?.pagination?.has_more
52
+ ? res.data?.pagination?.next_offset
53
+ : null,
51
54
  });
52
55
 
53
- $.export("$summary", "Successfully retrieved invitation status");
54
-
55
- return response;
56
+ $.export("$summary", `Successfully retrieved ${invitations.length} received invitation${invitations.length === 1
57
+ ? ""
58
+ : "s"}`);
59
+ return invitations;
56
60
  },
57
61
  };