@florydev/linkedin-api-voyager 1.3.6 → 1.3.8
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/README.md +30 -0
- package/lib/config.d.ts +4 -1
- package/lib/config.js +9 -7
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/lib/linkedin-realtime-query-map.d.ts +1 -0
- package/lib/linkedin-realtime-query-map.js +56 -0
- package/lib/linkedin-realtime-topic.d.ts +30 -0
- package/lib/linkedin-realtime-topic.js +34 -0
- package/lib/linkedin-sse-parser.d.ts +8 -0
- package/lib/linkedin-sse-parser.js +37 -0
- package/lib/linkedin-sse-topics.d.ts +4 -0
- package/lib/linkedin-sse-topics.js +12 -0
- package/lib/linkedin-sse.d.ts +43 -0
- package/lib/linkedin-sse.js +122 -0
- package/lib/message.d.ts +30 -0
- package/lib/message.js +178 -0
- package/lib/messaging-example.d.ts +1 -0
- package/lib/messaging-example.js +18 -0
- package/lib/messaging-inbox.d.ts +6 -0
- package/lib/messaging-inbox.js +70 -0
- package/lib/messaging-parsers.d.ts +2 -0
- package/lib/messaging-parsers.js +27 -0
- package/lib/messaging-response.d.ts +2 -0
- package/lib/messaging-response.js +61 -0
- package/lib/messaging-types.d.ts +17 -0
- package/lib/messaging-types.js +2 -0
- package/lib/messaging-utils.d.ts +11 -0
- package/lib/messaging-utils.js +81 -0
- package/lib/messaging.d.ts +1 -0
- package/lib/messaging.js +17 -0
- package/lib/teste.js +18 -10
- package/lib/types.d.ts +37 -0
- package/lib/utils.d.ts +1 -0
- package/lib/utils.js +4 -0
- package/package.json +26 -1
package/README.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# LinkedIn API Voyager
|
|
2
2
|
|
|
3
|
+
> ⚠️ **MUDANÇA DE PACOTE:** Esta biblioteca foi renomeada e movida de `linkedin-api-voyager` para `@florydev/linkedin-api-voyager`.
|
|
4
|
+
> Por favor, atualize suas dependências. A versão antiga não receberá novas atualizações.
|
|
5
|
+
|
|
6
|
+
[](https://www.npmjs.com/package/@florydev/linkedin-api-voyager)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
|
|
3
9
|
Biblioteca TypeScript para interagir com endpoints internos do LinkedIn (Voyager). Esta não é uma API oficial.
|
|
4
10
|
|
|
5
11
|
## Instalação
|
|
@@ -81,6 +87,22 @@ const comments = await getCommentsByPostUrl(
|
|
|
81
87
|
|
|
82
88
|
- `Client(config: { JSESSIONID: string; li_at: string })`: Configura a instância global do axios. Deve ser chamado antes de qualquer outra função.
|
|
83
89
|
- `API_BASE_URL`: `https://www.linkedin.com/voyager/api`
|
|
90
|
+
- `linkedinSSE(topics?: LinkedInRealtimeTopicsParam)`: Abre uma conexão SSE com o realtime do LinkedIn e emite somente os eventos dos tópicos desejados.
|
|
91
|
+
|
|
92
|
+
Exemplo:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import { Client, linkedinSSE } from "@florydev/linkedin-api-voyager";
|
|
96
|
+
|
|
97
|
+
Client({
|
|
98
|
+
JSESSIONID: process.env.LINKEDIN_JSESSIONID!,
|
|
99
|
+
li_at: process.env.LINKEDIN_LI_AT!,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
await linkedinSSE(["Messages", "TypingIndicators"]);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Tópicos disponíveis (param): keys do enum `LinkedInRealtimeTopic` (ex.: `"Messages"`, `"TypingIndicators"`, `"Conversations"`).
|
|
84
106
|
|
|
85
107
|
### Módulos Disponíveis
|
|
86
108
|
|
|
@@ -92,6 +114,14 @@ A biblioteca exporta funções dos seguintes módulos:
|
|
|
92
114
|
- `search`: Busca de pessoas e empresas.
|
|
93
115
|
- `utils`: Utilitários gerais.
|
|
94
116
|
|
|
117
|
+
## Autor
|
|
118
|
+
|
|
119
|
+
**Flory Muenge Tshiteya**
|
|
120
|
+
|
|
121
|
+
- Github: [@Floryvibla](https://github.com/Floryvibla)
|
|
122
|
+
- LinkedIn: [Flory Muenge Tshiteya](https://www.linkedin.com/in/florymignon/)
|
|
123
|
+
- 🐦 X (Twitter): [@DevFlory](https://x.com/DevFlory)
|
|
124
|
+
|
|
95
125
|
````
|
|
96
126
|
|
|
97
127
|
### `src/user.ts`
|
package/lib/config.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { AxiosInstance } from "axios";
|
|
2
2
|
export declare const API_BASE_URL = "https://www.linkedin.com/voyager/api";
|
|
3
|
+
export declare let apiInstance: AxiosInstance | null;
|
|
3
4
|
export declare const Client: (providedCookies: {
|
|
4
5
|
JSESSIONID: string;
|
|
5
6
|
li_at: string;
|
|
6
7
|
}) => AxiosInstance;
|
|
7
|
-
export declare const fetchData: (endpoint: string
|
|
8
|
+
export declare const fetchData: (endpoint: string, options?: {
|
|
9
|
+
headers?: Record<string, string>;
|
|
10
|
+
}) => Promise<any>;
|
package/lib/config.js
CHANGED
|
@@ -9,12 +9,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.fetchData = exports.Client = exports.API_BASE_URL = void 0;
|
|
12
|
+
exports.fetchData = exports.Client = exports.apiInstance = exports.API_BASE_URL = void 0;
|
|
13
13
|
const axios_1 = require("axios");
|
|
14
14
|
exports.API_BASE_URL = "https://www.linkedin.com/voyager/api";
|
|
15
|
-
|
|
15
|
+
exports.apiInstance = null;
|
|
16
16
|
const Client = (providedCookies) => {
|
|
17
|
-
apiInstance = axios_1.default.create({
|
|
17
|
+
exports.apiInstance = axios_1.default.create({
|
|
18
18
|
baseURL: exports.API_BASE_URL,
|
|
19
19
|
headers: {
|
|
20
20
|
"accept-language": "pt-BR,pt;q=0.9,fr-FR;q=0.8,fr;q=0.7,en-US;q=0.6,en;q=0.5",
|
|
@@ -23,14 +23,16 @@ const Client = (providedCookies) => {
|
|
|
23
23
|
"csrf-token": `ajax:${providedCookies.JSESSIONID}`,
|
|
24
24
|
},
|
|
25
25
|
});
|
|
26
|
-
return apiInstance;
|
|
26
|
+
return exports.apiInstance;
|
|
27
27
|
};
|
|
28
28
|
exports.Client = Client;
|
|
29
|
-
const fetchData = (endpoint) => __awaiter(void 0, void 0, void 0, function* () {
|
|
30
|
-
if (!apiInstance) {
|
|
29
|
+
const fetchData = (endpoint, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
30
|
+
if (!exports.apiInstance) {
|
|
31
31
|
throw new Error("Client not initialized. Please call Client({ JSESSIONID, li_at }) first.");
|
|
32
32
|
}
|
|
33
|
-
const response = yield apiInstance.get(endpoint
|
|
33
|
+
const response = yield exports.apiInstance.get(endpoint, {
|
|
34
|
+
headers: options === null || options === void 0 ? void 0 : options.headers,
|
|
35
|
+
});
|
|
34
36
|
return response.data;
|
|
35
37
|
});
|
|
36
38
|
exports.fetchData = fetchData;
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -20,3 +20,5 @@ __exportStar(require("./posts"), exports);
|
|
|
20
20
|
__exportStar(require("./search"), exports);
|
|
21
21
|
__exportStar(require("./utils"), exports);
|
|
22
22
|
__exportStar(require("./config"), exports);
|
|
23
|
+
__exportStar(require("./message"), exports);
|
|
24
|
+
__exportStar(require("./types"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getLinkedInRealtimeQueryMap: () => string;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getLinkedInRealtimeQueryMap = void 0;
|
|
4
|
+
const LINKEDIN_QUERY_MAP_BASE64 = `
|
|
5
|
+
eyAidG9waWNUb0dyYXBoUUxRdWVyeVBhcmFtcyI6IHsgImNvbnZlcnNhdGlvbnNUb3BpYyI6IHsg
|
|
6
|
+
InF1ZXJ5SWQiOiAidm95YWdlck1lc3NhZ2luZ0Rhc2hNZXNzZW5nZXJSZWFsdGltZURlY29yYXRp
|
|
7
|
+
b24uZjg1NTA0OGIzOTBiMjg2ZTUxM2Q3YjIzYzU5ZWZlZTMiLCAidmFyaWFibGVzIjoge30sICJl
|
|
8
|
+
eHRlbnNpb25zIjoge30gfSwgImNvbnZlcnNhdGlvbkRlbGV0ZXNUb3BpYyI6IHsgInF1ZXJ5SWQi
|
|
9
|
+
OiAidm95YWdlck1lc3NhZ2luZ0Rhc2hNZXNzZW5nZXJSZWFsdGltZURlY29yYXRpb24uMjgyYWJl
|
|
10
|
+
NWZhMWEyNDJjYjc2ODI1YzMyZGJiZmFlZGUiLCAidmFyaWFibGVzIjoge30sICJleHRlbnNpb25z
|
|
11
|
+
Ijoge30gfSwgIm1lc3NhZ2VSZWFjdGlvblN1bW1hcmllc1RvcGljIjogeyAicXVlcnlJZCI6ICJ2
|
|
12
|
+
b3lhZ2VyTWVzc2FnaW5nRGFzaE1lc3NlbmdlclJlYWx0aW1lRGVjb3JhdGlvbi44NWZmNWExYWFi
|
|
13
|
+
ZjdjNTJmNDBhYTg1Y2NjODRlM2JmNSIsICJ2YXJpYWJsZXMiOiB7fSwgImV4dGVuc2lvbnMiOiB7
|
|
14
|
+
fSB9LCAibWVzc2FnZVNlZW5SZWNlaXB0c1RvcGljIjogeyAicXVlcnlJZCI6ICJ2b3lhZ2VyTWVz
|
|
15
|
+
c2FnaW5nRGFzaE1lc3NlbmdlclJlYWx0aW1lRGVjb3JhdGlvbi5lMjNkMzk3MWRjODNhMTE1YjAz
|
|
16
|
+
NTg0Y2YyMzgxMjU2YyIsICJ2YXJpYWJsZXMiOiB7fSwgImV4dGVuc2lvbnMiOiB7fSB9LCAibWVz
|
|
17
|
+
c2FnZXNUb3BpYyI6IHsgInF1ZXJ5SWQiOiAidm95YWdlck1lc3NhZ2luZ0Rhc2hNZXNzZW5nZXJS
|
|
18
|
+
ZWFsdGltZURlY29yYXRpb24uZGIwZjFkM2Y1Mzc0N2Y0OWYzZmQ4N2IxMzlkZjllZGEiLCAidmFy
|
|
19
|
+
aWFibGVzIjoge30sICJleHRlbnNpb25zIjoge30gfSwgInJlcGx5U3VnZ2VzdGlvblRvcGljVjIi
|
|
20
|
+
OiB7ICJxdWVyeUlkIjogInZveWFnZXJNZXNzYWdpbmdEYXNoTWVzc2VuZ2VyUmVhbHRpbWVEZWNv
|
|
21
|
+
cmF0aW9uLjQxMjk2NGMzZjdmNWE2N2ZiMGU1NmI2YmIzYTAwMDI4IiwgInZhcmlhYmxlcyI6IHt9
|
|
22
|
+
LCAiZXh0ZW5zaW9ucyI6IHt9IH0sICJ0eXBpbmdJbmRpY2F0b3JzVG9waWMiOiB7ICJxdWVyeUlk
|
|
23
|
+
IjogInZveWFnZXJNZXNzYWdpbmdEYXNoTWVzc2VuZ2VyUmVhbHRpbWVEZWNvcmF0aW9uLjIzNGNl
|
|
24
|
+
MDNjZDA2MmIyNDM4ZGFlMDYwY2E4NTRhNmQyIiwgInZhcmlhYmxlcyI6IHt9LCAiZXh0ZW5zaW9u
|
|
25
|
+
cyI6IHt9IH0sICJyZWFjdGlvbnNUb3BpYyI6IHsgInF1ZXJ5SWQiOiAibGl2ZVZpZGVvVm95YWdl
|
|
26
|
+
clNvY2lhbERhc2hSZWFsdGltZURlY29yYXRpb24uYjhiMzNkZWRjYTdlZmJlMzRmMWQ3ZTg0YzNi
|
|
27
|
+
M2FhODEiLCAidmFyaWFibGVzIjoge30sICJleHRlbnNpb25zIjoge30gfSwgImNvbW1lbnRzVG9w
|
|
28
|
+
aWMiOiB7ICJxdWVyeUlkIjogImxpdmVWaWRlb1ZveWFnZXJTb2NpYWxEYXNoUmVhbHRpbWVEZWNv
|
|
29
|
+
cmF0aW9uLjBkMjMzMzUyZDZhYWYzNWZmMDBiOGU2N2U5Y2Q0ODU5IiwgInZhcmlhYmxlcyI6IHt9
|
|
30
|
+
LCAiZXh0ZW5zaW9ucyI6IHt9IH0sICJyZWFjdGlvbnNPbkNvbW1lbnRzVG9waWMiOiB7ICJxdWVy
|
|
31
|
+
eUlkIjogImxpdmVWaWRlb1ZveWFnZXJTb2NpYWxEYXNoUmVhbHRpbWVEZWNvcmF0aW9uLjBhMTgx
|
|
32
|
+
YjA1YjM3NTFmNzJhZTNlYjQ4OWI3N2UzMjQ1IiwgInZhcmlhYmxlcyI6IHt9LCAiZXh0ZW5zaW9u
|
|
33
|
+
cyI6IHt9IH0sICJzb2NpYWxQZXJtaXNzaW9uc1BlcnNvbmFsVG9waWMiOiB7ICJxdWVyeUlkIjog
|
|
34
|
+
ImxpdmVWaWRlb1ZveWFnZXJTb2NpYWxEYXNoUmVhbHRpbWVEZWNvcmF0aW9uLjE3MGJmM2JmYmNj
|
|
35
|
+
YTFkYTMyMmUzNGYzNGYzN2ZiOTU0IiwgInZhcmlhYmxlcyI6IHt9LCAiZXh0ZW5zaW9ucyI6IHt9
|
|
36
|
+
IH0sICJsaXZlVmlkZW9Qb3N0VG9waWMiOiB7ICJxdWVyeUlkIjogImxpdmVWaWRlb1ZveWFnZXJG
|
|
37
|
+
ZWVkRGFzaExpdmVVcGRhdGVzUmVhbHRpbWVEZWNvcmF0aW9uLjU0ZDYzNWRhMDAwOGVjZjY4NzFm
|
|
38
|
+
Y2Y4NDA4NWU1M2RlIiwgInZhcmlhYmxlcyI6IHt9LCAiZXh0ZW5zaW9ucyI6IHt9IH0sICJtZXNz
|
|
39
|
+
YWdlRHJhZnRzVG9waWMiOiB7ICJxdWVyeUlkIjogInZveWFnZXJNZXNzYWdpbmdEYXNoTWVzc2Vu
|
|
40
|
+
Z2VyUmVhbHRpbWVEZWNvcmF0aW9uLmZjZjdiNTRkMjU4YzI3Nzk5YTY5Mzc4NWJkNGZjYzExIiwg
|
|
41
|
+
InZhcmlhYmxlcyI6IHt9LCAiZXh0ZW5zaW9ucyI6IHt9IH0sICJjb252ZXJzYXRpb25EcmFmdHNU
|
|
42
|
+
b3BpYyI6IHsgInF1ZXJ5SWQiOiAidm95YWdlck1lc3NhZ2luZ0Rhc2hNZXNzZW5nZXJSZWFsdGlt
|
|
43
|
+
ZURlY29yYXRpb24uYTQzY2UxNTdkNzExNGIxYTBmOGRhNWUwMmE2MGNlMzgiLCAidmFyaWFibGVz
|
|
44
|
+
Ijoge30sICJleHRlbnNpb25zIjoge30gfSwgIm1lc3NhZ2VEcmFmdERlbGV0ZXNUb3BpYyI6IHsg
|
|
45
|
+
InF1ZXJ5SWQiOiAidm95YWdlck1lc3NhZ2luZ0Rhc2hNZXNzZW5nZXJSZWFsdGltZURlY29yYXRp
|
|
46
|
+
b24uZTNlNGM3MTIxODM4MzIxYTQyNzUyYjU1ZjQ4N2E3M2UiLCAidmFyaWFibGVzIjoge30sICJl
|
|
47
|
+
eHRlbnNpb25zIjoge30gfSwgImNvbnZlcnNhdGlvbkRyYWZ0RGVsZXRlc1RvcGljIjogeyAicXVl
|
|
48
|
+
cnlJZCI6ICJ2b3lhZ2VyTWVzc2FnaW5nRGFzaE1lc3NlbmdlclJlYWx0aW1lRGVjb3JhdGlvbi41
|
|
49
|
+
Mjg4MDM2YTJjMGU2M2Y0OWQzNGVlMzJiMTM5OTc2YyIsICJ2YXJpYWJsZXMiOiB7fSwgImV4dGVu
|
|
50
|
+
c2lvbnMiOiB7fSB9LCAicmVhbHRpbWVTZWFyY2hSZXN1bHRDbHVzdGVyc1RvcGljIjogeyAicXVl
|
|
51
|
+
cnlJZCI6ICJ2b3lhZ2VyU2VhcmNoRGFzaFJlYWx0aW1lRGVjb3JhdGlvbi4zYzhkMmNkNzMyOTg3
|
|
52
|
+
OTBmZWIzZDdmMzQyMWE4OGRmNCIsICJ2YXJpYWJsZXMiOiB7fSwgImV4dGVuc2lvbnMiOiB7fSB9
|
|
53
|
+
IH0gfQ==
|
|
54
|
+
`;
|
|
55
|
+
const getLinkedInRealtimeQueryMap = () => Buffer.from(LINKEDIN_QUERY_MAP_BASE64.replace(/\s+/g, ""), "base64").toString("utf8");
|
|
56
|
+
exports.getLinkedInRealtimeQueryMap = getLinkedInRealtimeQueryMap;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export declare enum LinkedInRealtimeTopic {
|
|
2
|
+
ConversationsBroadcast = "conversationsBroadcastTopic",
|
|
3
|
+
Conversations = "conversationsTopic",
|
|
4
|
+
ConversationDeletesBroadcast = "conversationDeletesBroadcastTopic",
|
|
5
|
+
ConversationDeletes = "conversationDeletesTopic",
|
|
6
|
+
MessageReactionSummariesBroadcast = "messageReactionSummariesBroadcastTopic",
|
|
7
|
+
MessageReactionSummaries = "messageReactionSummariesTopic",
|
|
8
|
+
MessageSeenReceiptsBroadcast = "messageSeenReceiptsBroadcastTopic",
|
|
9
|
+
MessageSeenReceipts = "messageSeenReceiptsTopic",
|
|
10
|
+
MessagesBroadcast = "messagesBroadcastTopic",
|
|
11
|
+
Messages = "messagesTopic",
|
|
12
|
+
ReplySuggestionBroadcast = "replySuggestionBroadcastTopic",
|
|
13
|
+
ReplySuggestionV2 = "replySuggestionTopicV2",
|
|
14
|
+
TypingIndicatorsBroadcast = "typingIndicatorsBroadcastTopic",
|
|
15
|
+
TypingIndicators = "typingIndicatorsTopic",
|
|
16
|
+
MessagingSecondaryPreviewBanner = "messagingSecondaryPreviewBannerTopic",
|
|
17
|
+
Reactions = "reactionsTopic",
|
|
18
|
+
Comments = "commentsTopic",
|
|
19
|
+
ReactionsOnComments = "reactionsOnCommentsTopic",
|
|
20
|
+
SocialPermissionsPersonal = "socialPermissionsPersonalTopic",
|
|
21
|
+
LiveVideoPost = "liveVideoPostTopic",
|
|
22
|
+
GeneratedJobDescriptions = "generatedJobDescriptionsTopic",
|
|
23
|
+
MessageDrafts = "messageDraftsTopic",
|
|
24
|
+
ConversationDrafts = "conversationDraftsTopic",
|
|
25
|
+
MessageDraftDeletes = "messageDraftDeletesTopic",
|
|
26
|
+
ConversationDraftDeletes = "conversationDraftDeletesTopic",
|
|
27
|
+
CoachStreamingResponses = "coachStreamingResponsesTopic",
|
|
28
|
+
RealtimeSearchResultClusters = "realtimeSearchResultClustersTopic",
|
|
29
|
+
MemberVerificationResultsPersonal = "memberVerificationResultsPersonalTopic"
|
|
30
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LinkedInRealtimeTopic = void 0;
|
|
4
|
+
var LinkedInRealtimeTopic;
|
|
5
|
+
(function (LinkedInRealtimeTopic) {
|
|
6
|
+
LinkedInRealtimeTopic["ConversationsBroadcast"] = "conversationsBroadcastTopic";
|
|
7
|
+
LinkedInRealtimeTopic["Conversations"] = "conversationsTopic";
|
|
8
|
+
LinkedInRealtimeTopic["ConversationDeletesBroadcast"] = "conversationDeletesBroadcastTopic";
|
|
9
|
+
LinkedInRealtimeTopic["ConversationDeletes"] = "conversationDeletesTopic";
|
|
10
|
+
LinkedInRealtimeTopic["MessageReactionSummariesBroadcast"] = "messageReactionSummariesBroadcastTopic";
|
|
11
|
+
LinkedInRealtimeTopic["MessageReactionSummaries"] = "messageReactionSummariesTopic";
|
|
12
|
+
LinkedInRealtimeTopic["MessageSeenReceiptsBroadcast"] = "messageSeenReceiptsBroadcastTopic";
|
|
13
|
+
LinkedInRealtimeTopic["MessageSeenReceipts"] = "messageSeenReceiptsTopic";
|
|
14
|
+
LinkedInRealtimeTopic["MessagesBroadcast"] = "messagesBroadcastTopic";
|
|
15
|
+
LinkedInRealtimeTopic["Messages"] = "messagesTopic";
|
|
16
|
+
LinkedInRealtimeTopic["ReplySuggestionBroadcast"] = "replySuggestionBroadcastTopic";
|
|
17
|
+
LinkedInRealtimeTopic["ReplySuggestionV2"] = "replySuggestionTopicV2";
|
|
18
|
+
LinkedInRealtimeTopic["TypingIndicatorsBroadcast"] = "typingIndicatorsBroadcastTopic";
|
|
19
|
+
LinkedInRealtimeTopic["TypingIndicators"] = "typingIndicatorsTopic";
|
|
20
|
+
LinkedInRealtimeTopic["MessagingSecondaryPreviewBanner"] = "messagingSecondaryPreviewBannerTopic";
|
|
21
|
+
LinkedInRealtimeTopic["Reactions"] = "reactionsTopic";
|
|
22
|
+
LinkedInRealtimeTopic["Comments"] = "commentsTopic";
|
|
23
|
+
LinkedInRealtimeTopic["ReactionsOnComments"] = "reactionsOnCommentsTopic";
|
|
24
|
+
LinkedInRealtimeTopic["SocialPermissionsPersonal"] = "socialPermissionsPersonalTopic";
|
|
25
|
+
LinkedInRealtimeTopic["LiveVideoPost"] = "liveVideoPostTopic";
|
|
26
|
+
LinkedInRealtimeTopic["GeneratedJobDescriptions"] = "generatedJobDescriptionsTopic";
|
|
27
|
+
LinkedInRealtimeTopic["MessageDrafts"] = "messageDraftsTopic";
|
|
28
|
+
LinkedInRealtimeTopic["ConversationDrafts"] = "conversationDraftsTopic";
|
|
29
|
+
LinkedInRealtimeTopic["MessageDraftDeletes"] = "messageDraftDeletesTopic";
|
|
30
|
+
LinkedInRealtimeTopic["ConversationDraftDeletes"] = "conversationDraftDeletesTopic";
|
|
31
|
+
LinkedInRealtimeTopic["CoachStreamingResponses"] = "coachStreamingResponsesTopic";
|
|
32
|
+
LinkedInRealtimeTopic["RealtimeSearchResultClusters"] = "realtimeSearchResultClustersTopic";
|
|
33
|
+
LinkedInRealtimeTopic["MemberVerificationResultsPersonal"] = "memberVerificationResultsPersonalTopic";
|
|
34
|
+
})(LinkedInRealtimeTopic || (exports.LinkedInRealtimeTopic = LinkedInRealtimeTopic = {}));
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type ParseLinkedInSSEChunkArgs = {
|
|
2
|
+
buffer: string;
|
|
3
|
+
chunk: Buffer;
|
|
4
|
+
topicsSet?: ReadonlySet<string>;
|
|
5
|
+
onEvent: (data: unknown) => void;
|
|
6
|
+
onError: (error: unknown) => void;
|
|
7
|
+
};
|
|
8
|
+
export declare const parseLinkedInSSEChunk: ({ buffer, chunk, topicsSet, onEvent, onError, }: ParseLinkedInSSEChunkArgs) => string;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseLinkedInSSEChunk = void 0;
|
|
4
|
+
const parseLinkedInSSEChunk = ({ buffer, chunk, topicsSet, onEvent, onError, }) => {
|
|
5
|
+
let nextBuffer = buffer + chunk.toString();
|
|
6
|
+
const parts = nextBuffer.split("\n\n");
|
|
7
|
+
nextBuffer = parts.pop() || "";
|
|
8
|
+
for (const part of parts) {
|
|
9
|
+
if (!part.trim().startsWith("data:"))
|
|
10
|
+
continue;
|
|
11
|
+
try {
|
|
12
|
+
const dataStr = part.replace("data:", "").trim();
|
|
13
|
+
const data = JSON.parse(dataStr);
|
|
14
|
+
if (!topicsSet) {
|
|
15
|
+
onEvent(data);
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
const topic = data === null || data === void 0 ? void 0 : data.topic;
|
|
19
|
+
if (typeof topic === "string" && topicsSet.has(topic)) {
|
|
20
|
+
onEvent(data);
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
const text = JSON.stringify(data);
|
|
24
|
+
for (const t of topicsSet) {
|
|
25
|
+
if (text.includes(t)) {
|
|
26
|
+
onEvent(data);
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
onError(error);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return nextBuffer;
|
|
36
|
+
};
|
|
37
|
+
exports.parseLinkedInSSEChunk = parseLinkedInSSEChunk;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { LinkedInRealtimeTopic } from "./linkedin-realtime-topic";
|
|
2
|
+
export type LinkedInRealtimeTopicKey = keyof typeof LinkedInRealtimeTopic;
|
|
3
|
+
export type LinkedInRealtimeTopicsParam = LinkedInRealtimeTopicKey | LinkedInRealtimeTopicKey[];
|
|
4
|
+
export declare const createLinkedInRealtimeTopicsSet: (topics?: LinkedInRealtimeTopicsParam) => ReadonlySet<string> | undefined;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createLinkedInRealtimeTopicsSet = void 0;
|
|
4
|
+
const linkedin_realtime_topic_1 = require("./linkedin-realtime-topic");
|
|
5
|
+
const createLinkedInRealtimeTopicsSet = (topics) => {
|
|
6
|
+
if (!topics)
|
|
7
|
+
return undefined;
|
|
8
|
+
const list = Array.isArray(topics) ? topics : [topics];
|
|
9
|
+
const values = list.map((t) => linkedin_realtime_topic_1.LinkedInRealtimeTopic[t]);
|
|
10
|
+
return new Set(values);
|
|
11
|
+
};
|
|
12
|
+
exports.createLinkedInRealtimeTopicsSet = createLinkedInRealtimeTopicsSet;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export declare enum LinkedInRealtimeTopic {
|
|
2
|
+
ConversationsBroadcast = "conversationsBroadcastTopic",
|
|
3
|
+
Conversations = "conversationsTopic",
|
|
4
|
+
ConversationDeletesBroadcast = "conversationDeletesBroadcastTopic",
|
|
5
|
+
ConversationDeletes = "conversationDeletesTopic",
|
|
6
|
+
MessageReactionSummariesBroadcast = "messageReactionSummariesBroadcastTopic",
|
|
7
|
+
MessageReactionSummaries = "messageReactionSummariesTopic",
|
|
8
|
+
MessageSeenReceiptsBroadcast = "messageSeenReceiptsBroadcastTopic",
|
|
9
|
+
MessageSeenReceipts = "messageSeenReceiptsTopic",
|
|
10
|
+
MessagesBroadcast = "messagesBroadcastTopic",
|
|
11
|
+
Messages = "messagesTopic",
|
|
12
|
+
ReplySuggestionBroadcast = "replySuggestionBroadcastTopic",
|
|
13
|
+
ReplySuggestionV2 = "replySuggestionTopicV2",
|
|
14
|
+
TypingIndicatorsBroadcast = "typingIndicatorsBroadcastTopic",
|
|
15
|
+
TypingIndicators = "typingIndicatorsTopic",
|
|
16
|
+
MessagingSecondaryPreviewBanner = "messagingSecondaryPreviewBannerTopic",
|
|
17
|
+
Reactions = "reactionsTopic",
|
|
18
|
+
Comments = "commentsTopic",
|
|
19
|
+
ReactionsOnComments = "reactionsOnCommentsTopic",
|
|
20
|
+
SocialPermissionsPersonal = "socialPermissionsPersonalTopic",
|
|
21
|
+
LiveVideoPost = "liveVideoPostTopic",
|
|
22
|
+
GeneratedJobDescriptions = "generatedJobDescriptionsTopic",
|
|
23
|
+
MessageDrafts = "messageDraftsTopic",
|
|
24
|
+
ConversationDrafts = "conversationDraftsTopic",
|
|
25
|
+
MessageDraftDeletes = "messageDraftDeletesTopic",
|
|
26
|
+
ConversationDraftDeletes = "conversationDraftDeletesTopic",
|
|
27
|
+
CoachStreamingResponses = "coachStreamingResponsesTopic",
|
|
28
|
+
RealtimeSearchResultClusters = "realtimeSearchResultClustersTopic",
|
|
29
|
+
MemberVerificationResultsPersonal = "memberVerificationResultsPersonalTopic"
|
|
30
|
+
}
|
|
31
|
+
export type LinkedInRealtimeTopicKey = keyof typeof LinkedInRealtimeTopic;
|
|
32
|
+
export type LinkedInRealtimeTopicsParam = LinkedInRealtimeTopicKey | LinkedInRealtimeTopicKey[];
|
|
33
|
+
export declare const getLinkedInRealtimeQueryMap: () => string;
|
|
34
|
+
export declare const createLinkedInRealtimeTopicsSet: (topics?: LinkedInRealtimeTopicsParam) => ReadonlySet<string> | undefined;
|
|
35
|
+
export type ParseLinkedInSSEChunkArgs = {
|
|
36
|
+
buffer: string;
|
|
37
|
+
chunk: Buffer;
|
|
38
|
+
topicsSet?: ReadonlySet<string>;
|
|
39
|
+
onEvent: (data: unknown) => void;
|
|
40
|
+
onError: (error: unknown) => void;
|
|
41
|
+
};
|
|
42
|
+
export declare const parseLinkedInSSEChunk: ({ buffer, chunk, topicsSet, onEvent, onError, }: ParseLinkedInSSEChunkArgs) => string;
|
|
43
|
+
export declare function linkedinSSE(topics?: LinkedInRealtimeTopicsParam): Promise<void>;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.parseLinkedInSSEChunk = exports.createLinkedInRealtimeTopicsSet = exports.getLinkedInRealtimeQueryMap = exports.LinkedInRealtimeTopic = void 0;
|
|
13
|
+
exports.linkedinSSE = linkedinSSE;
|
|
14
|
+
const config_1 = require("./config");
|
|
15
|
+
var LinkedInRealtimeTopic;
|
|
16
|
+
(function (LinkedInRealtimeTopic) {
|
|
17
|
+
LinkedInRealtimeTopic["ConversationsBroadcast"] = "conversationsBroadcastTopic";
|
|
18
|
+
LinkedInRealtimeTopic["Conversations"] = "conversationsTopic";
|
|
19
|
+
LinkedInRealtimeTopic["ConversationDeletesBroadcast"] = "conversationDeletesBroadcastTopic";
|
|
20
|
+
LinkedInRealtimeTopic["ConversationDeletes"] = "conversationDeletesTopic";
|
|
21
|
+
LinkedInRealtimeTopic["MessageReactionSummariesBroadcast"] = "messageReactionSummariesBroadcastTopic";
|
|
22
|
+
LinkedInRealtimeTopic["MessageReactionSummaries"] = "messageReactionSummariesTopic";
|
|
23
|
+
LinkedInRealtimeTopic["MessageSeenReceiptsBroadcast"] = "messageSeenReceiptsBroadcastTopic";
|
|
24
|
+
LinkedInRealtimeTopic["MessageSeenReceipts"] = "messageSeenReceiptsTopic";
|
|
25
|
+
LinkedInRealtimeTopic["MessagesBroadcast"] = "messagesBroadcastTopic";
|
|
26
|
+
LinkedInRealtimeTopic["Messages"] = "messagesTopic";
|
|
27
|
+
LinkedInRealtimeTopic["ReplySuggestionBroadcast"] = "replySuggestionBroadcastTopic";
|
|
28
|
+
LinkedInRealtimeTopic["ReplySuggestionV2"] = "replySuggestionTopicV2";
|
|
29
|
+
LinkedInRealtimeTopic["TypingIndicatorsBroadcast"] = "typingIndicatorsBroadcastTopic";
|
|
30
|
+
LinkedInRealtimeTopic["TypingIndicators"] = "typingIndicatorsTopic";
|
|
31
|
+
LinkedInRealtimeTopic["MessagingSecondaryPreviewBanner"] = "messagingSecondaryPreviewBannerTopic";
|
|
32
|
+
LinkedInRealtimeTopic["Reactions"] = "reactionsTopic";
|
|
33
|
+
LinkedInRealtimeTopic["Comments"] = "commentsTopic";
|
|
34
|
+
LinkedInRealtimeTopic["ReactionsOnComments"] = "reactionsOnCommentsTopic";
|
|
35
|
+
LinkedInRealtimeTopic["SocialPermissionsPersonal"] = "socialPermissionsPersonalTopic";
|
|
36
|
+
LinkedInRealtimeTopic["LiveVideoPost"] = "liveVideoPostTopic";
|
|
37
|
+
LinkedInRealtimeTopic["GeneratedJobDescriptions"] = "generatedJobDescriptionsTopic";
|
|
38
|
+
LinkedInRealtimeTopic["MessageDrafts"] = "messageDraftsTopic";
|
|
39
|
+
LinkedInRealtimeTopic["ConversationDrafts"] = "conversationDraftsTopic";
|
|
40
|
+
LinkedInRealtimeTopic["MessageDraftDeletes"] = "messageDraftDeletesTopic";
|
|
41
|
+
LinkedInRealtimeTopic["ConversationDraftDeletes"] = "conversationDraftDeletesTopic";
|
|
42
|
+
LinkedInRealtimeTopic["CoachStreamingResponses"] = "coachStreamingResponsesTopic";
|
|
43
|
+
LinkedInRealtimeTopic["RealtimeSearchResultClusters"] = "realtimeSearchResultClustersTopic";
|
|
44
|
+
LinkedInRealtimeTopic["MemberVerificationResultsPersonal"] = "memberVerificationResultsPersonalTopic";
|
|
45
|
+
})(LinkedInRealtimeTopic || (exports.LinkedInRealtimeTopic = LinkedInRealtimeTopic = {}));
|
|
46
|
+
const LINKEDIN_QUERY_MAP_BASE64 = "eyAidG9waWNUb0dyYXBoUUxRdWVyeVBhcmFtcyI6IHsgImNvbnZlcnNhdGlvbnNUb3BpYyI6IHsgInF1ZXJ5SWQiOiAidm95YWdlck1lc3NhZ2luZ0Rhc2hNZXNzZW5nZXJSZWFsdGltZURlY29yYXRpb24uZjg1NTA0OGIzOTBiMjg2ZTUxM2Q3YjIzYzU5ZWZlZTMiLCAidmFyaWFibGVzIjoge30sICJleHRlbnNpb25zIjoge30gfSwgImNvbnZlcnNhdGlvbkRlbGV0ZXNUb3BpYyI6IHsgInF1ZXJ5SWQiOiAidm95YWdlck1lc3NhZ2luZ0Rhc2hNZXNzZW5nZXJSZWFsdGltZURlY29yYXRpb24uMjgyYWJlNWZhMWEyNDJjYjc2ODI1YzMyZGJiZmFlZGUiLCAidmFyaWFibGVzIjoge30sICJleHRlbnNpb25zIjoge30gfSwgIm1lc3NhZ2VSZWFjdGlvblN1bW1hcmllc1RvcGljIjogeyAicXVlcnlJZCI6ICJ2b3lhZ2VyTWVzc2FnaW5nRGFzaE1lc3NlbmdlclJlYWx0aW1lRGVjb3JhdGlvbi44NWZmNWExYWFiZjdjNTJmNDBhYTg1Y2NjODRlM2JmNSIsICJ2YXJpYWJsZXMiOiB7fSwgImV4dGVuc2lvbnMiOiB7fSB9LCAibWVzc2FnZVNlZW5SZWNlaXB0c1RvcGljIjogeyAicXVlcnlJZCI6ICJ2b3lhZ2VyTWVzc2FnaW5nRGFzaE1lc3NlbmdlclJlYWx0aW1lRGVjb3JhdGlvbi5lMjNkMzk3MWRjODNhMTE1YjAzNTg0Y2YyMzgxMjU2YyIsICJ2YXJpYWJsZXMiOiB7fSwgImV4dGVuc2lvbnMiOiB7fSB9LCAibWVzc2FnZXNUb3BpYyI6IHsgInF1ZXJ5SWQiOiAidm95YWdlck1lc3NhZ2luZ0Rhc2hNZXNzZW5nZXJSZWFsdGltZURlY29yYXRpb24uZGIwZjFkM2Y1Mzc0N2Y0OWYzZmQ4N2IxMzlkZjllZGEiLCAidmFyaWFibGVzIjoge30sICJleHRlbnNpb25zIjoge30gfSwgInJlcGx5U3VnZ2VzdGlvblRvcGljVjIiOiB7ICJxdWVyeUlkIjogInZveWFnZXJNZXNzYWdpbmdEYXNoTWVzc2VuZ2VyUmVhbHRpbWVEZWNvcmF0aW9uLjQxMjk2NGMzZjdmNWE2N2ZiMGU1NmI2YmIzYTAwMDI4IiwgInZhcmlhYmxlcyI6IHt9LCAiZXh0ZW5zaW9ucyI6IHt9IH0sICJ0eXBpbmdJbmRpY2F0b3JzVG9waWMiOiB7ICJxdWVyeUlkIjogInZveWFnZXJNZXNzYWdpbmdEYXNoTWVzc2VuZ2VyUmVhbHRpbWVEZWNvcmF0aW9uLjIzNGNlMDNjZDA2MmIyNDM4ZGFlMDYwY2E4NTRhNmQyIiwgInZhcmlhYmxlcyI6IHt9LCAiZXh0ZW5zaW9ucyI6IHt9IH0sICJyZWFjdGlvbnNUb3BpYyI6IHsgInF1ZXJ5SWQiOiAibGl2ZVZpZGVvVm95YWdlclNvY2lhbERhc2hSZWFsdGltZURlY29yYXRpb24uYjhiMzNkZWRjYTdlZmJlMzRmMWQ3ZTg0YzNiM2FhODEiLCAidmFyaWFibGVzIjoge30sICJleHRlbnNpb25zIjoge30gfSwgImNvbW1lbnRzVG9waWMiOiB7ICJxdWVyeUlkIjogImxpdmVWaWRlb1ZveWFnZXJTb2NpYWxEYXNoUmVhbHRpbWVEZWNvcmF0aW9uLjBkMjMzMzUyZDZhYWYzNWZmMDBiOGU2N2U5Y2Q0ODU5IiwgInZhcmlhYmxlcyI6IHt9LCAiZXh0ZW5zaW9ucyI6IHt9IH0sICJyZWFjdGlvbnNPbkNvbW1lbnRzVG9waWMiOiB7ICJxdWVyeUlkIjogImxpdmVWaWRlb1ZveWFnZXJTb2NpYWxEYXNoUmVhbHRpbWVEZWNvcmF0aW9uLjBhMTgxYjA1YjM3NTFmNzJhZTNlYjQ4OWI3N2UzMjQ1IiwgInZhcmlhYmxlcyI6IHt9LCAiZXh0ZW5zaW9ucyI6IHt9IH0sICJzb2NpYWxQZXJtaXNzaW9uc1BlcnNvbmFsVG9waWMiOiB7ICJxdWVyeUlkIjogImxpdmVWaWRlb1ZveWFnZXJTb2NpYWxEYXNoUmVhbHRpbWVEZWNvcmF0aW9uLjE3MGJmM2JmYmNjYTFkYTMyMmUzNGYzNGYzN2ZiOTU0IiwgInZhcmlhYmxlcyI6IHt9LCAiZXh0ZW5zaW9ucyI6IHt9IH0sICJsaXZlVmlkZW9Qb3N0VG9waWMiOiB7ICJxdWVyeUlkIjogImxpdmVWaWRlb1ZveWFnZXJGZWVkRGFzaExpdmVVcGRhdGVzUmVhbHRpbWVEZWNvcmF0aW9uLjU0ZDYzNWRhMDAwOGVjZjY4NzFmY2Y4NDA4NWU1M2RlIiwgInZhcmlhYmxlcyI6IHt9LCAiZXh0ZW5zaW9ucyI6IHt9IH0sICJtZXNzYWdlRHJhZnRzVG9waWMiOiB7ICJxdWVyeUlkIjogInZveWFnZXJNZXNzYWdpbmdEYXNoTWVzc2VuZ2VyUmVhbHRpbWVEZWNvcmF0aW9uLmZjZjdiNTRkMjU4YzI3Nzk5YTY5Mzc4NWJkNGZjYzExIiwgInZhcmlhYmxlcyI6IHt9LCAiZXh0ZW5zaW9ucyI6IHt9IH0sICJjb252ZXJzYXRpb25EcmFmdHNUb3BpYyI6IHsgInF1ZXJ5SWQiOiAidm95YWdlck1lc3NhZ2luZ0Rhc2hNZXNzZW5nZXJSZWFsdGltZURlY29yYXRpb24uYTQzY2UxNTdkNzExNGIxYTBmOGRhNWUwMmE2MGNlMzgiLCAidmFyaWFibGVzIjoge30sICJleHRlbnNpb25zIjoge30gfSwgIm1lc3NhZ2VEcmFmdERlbGV0ZXNUb3BpYyI6IHsgInF1ZXJ5SWQiOiAidm95YWdlck1lc3NhZ2luZ0Rhc2hNZXNzZW5nZXJSZWFsdGltZURlY29yYXRpb24uZTNlNGM3MTIxODM4MzIxYTQyNzUyYjU1ZjQ4N2E3M2UiLCAidmFyaWFibGVzIjoge30sICJleHRlbnNpb25zIjoge30gfSwgImNvbnZlcnNhdGlvbkRyYWZ0RGVsZXRlc1RvcGljIjogeyAicXVlcnlJZCI6ICJ2b3lhZ2VyTWVzc2FnaW5nRGFzaE1lc3NlbmdlclJlYWx0aW1lRGVjb3JhdGlvbi41Mjg4MDM2YTJjMGU2M2Y0OWQzNGVlMzJiMTM5OTc2YyIsICJ2YXJpYWJsZXMiOiB7fSwgImV4dGVuc2lvbnMiOiB7fSB9LCAicmVhbHRpbWVTZWFyY2hSZXN1bHRDbHVzdGVyc1RvcGljIjogeyAicXVlcnlJZCI6ICJ2b3lhZ2VyU2VhcmNoRGFzaFJlYWx0aW1lRGVjb3JhdGlvbi4zYzhkMmNkNzMyOTg3OTBmZWIzZDdmMzQyMWE4OGRmNCIsICJ2YXJpYWJsZXMiOiB7fSwgImV4dGVuc2lvbnMiOiB7fSB9IH0gfQ==";
|
|
47
|
+
const getLinkedInRealtimeQueryMap = () => Buffer.from(LINKEDIN_QUERY_MAP_BASE64, "base64").toString("utf8");
|
|
48
|
+
exports.getLinkedInRealtimeQueryMap = getLinkedInRealtimeQueryMap;
|
|
49
|
+
const createLinkedInRealtimeTopicsSet = (topics) => {
|
|
50
|
+
if (!topics)
|
|
51
|
+
return undefined;
|
|
52
|
+
const list = Array.isArray(topics) ? topics : [topics];
|
|
53
|
+
return new Set(list.map((t) => LinkedInRealtimeTopic[t]));
|
|
54
|
+
};
|
|
55
|
+
exports.createLinkedInRealtimeTopicsSet = createLinkedInRealtimeTopicsSet;
|
|
56
|
+
const parseLinkedInSSEChunk = ({ buffer, chunk, topicsSet, onEvent, onError, }) => {
|
|
57
|
+
let nextBuffer = buffer + chunk.toString();
|
|
58
|
+
const parts = nextBuffer.split("\n\n");
|
|
59
|
+
nextBuffer = parts.pop() || "";
|
|
60
|
+
for (const part of parts) {
|
|
61
|
+
if (!part.trim().startsWith("data:"))
|
|
62
|
+
continue;
|
|
63
|
+
try {
|
|
64
|
+
const dataStr = part.replace("data:", "").trim();
|
|
65
|
+
const data = JSON.parse(dataStr);
|
|
66
|
+
if (!topicsSet) {
|
|
67
|
+
onEvent(data);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const topic = data === null || data === void 0 ? void 0 : data.topic;
|
|
71
|
+
if (typeof topic === "string" && topicsSet.has(topic)) {
|
|
72
|
+
onEvent(data);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const text = JSON.stringify(data);
|
|
76
|
+
for (const t of topicsSet)
|
|
77
|
+
if (text.includes(t))
|
|
78
|
+
onEvent(data);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
onError(error);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return nextBuffer;
|
|
85
|
+
};
|
|
86
|
+
exports.parseLinkedInSSEChunk = parseLinkedInSSEChunk;
|
|
87
|
+
function linkedinSSE(topics) {
|
|
88
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
89
|
+
if (!config_1.apiInstance) {
|
|
90
|
+
throw new Error("Client not initialized. Please call Client({ JSESSIONID, li_at }) first.");
|
|
91
|
+
}
|
|
92
|
+
const topicsSet = (0, exports.createLinkedInRealtimeTopicsSet)(topics);
|
|
93
|
+
const response = yield config_1.apiInstance.get("/connect?rc=1", {
|
|
94
|
+
baseURL: "https://www.linkedin.com/realtime",
|
|
95
|
+
responseType: "stream",
|
|
96
|
+
headers: {
|
|
97
|
+
Accept: "text/event-stream",
|
|
98
|
+
"x-li-accept": "application/vnd.linkedin.normalized+json+2.1",
|
|
99
|
+
"x-li-page-instance": "urn:li:page:feed_index_index;6b2b39e4-d1c7-4afd-83a6-29297d4f436b",
|
|
100
|
+
"x-li-query-accept": "application/graphql",
|
|
101
|
+
"x-li-query-map": (0, exports.getLinkedInRealtimeQueryMap)(),
|
|
102
|
+
"x-li-realtime-session": "401dc8e6-3c15-49e0-aa9d-7c6dec4a3318",
|
|
103
|
+
"x-li-recipe-accept": "application/vnd.linkedin.normalized+json+2.1",
|
|
104
|
+
"x-li-recipe-map": '{"inAppAlertsTopic":"com.linkedin.voyager.dash.deco.identity.notifications.InAppAlert-52","professionalEventsTopic":"com.linkedin.voyager.dash.deco.events.ProfessionalEventDetailPage-63","tabBadgeUpdateTopic":"com.linkedin.voyager.dash.deco.notifications.RealtimeBadgingItemCountsEvent-1","topCardLiveVideoTopic":"com.linkedin.voyager.dash.deco.video.TopCardLiveVideo-10"}',
|
|
105
|
+
"x-li-track": '{"clientVersion":"1.13.42636","mpVersion":"1.13.42636","osName":"web","timezoneOffset":-3,"timezone":"America/Sao_Paulo","deviceFormFactor":"DESKTOP","mpName":"voyager-web","displayDensity":2,"displayWidth":2880,"displayHeight":1800}',
|
|
106
|
+
"x-restli-protocol-version": "2.0.0",
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
let buffer = "";
|
|
110
|
+
const onEvent = (data) => console.log("data: ", JSON.stringify(data, null, 2));
|
|
111
|
+
const onError = (error) => console.log("error parsing part: ", error);
|
|
112
|
+
response.data.on("data", (chunk) => {
|
|
113
|
+
buffer = (0, exports.parseLinkedInSSEChunk)({
|
|
114
|
+
buffer,
|
|
115
|
+
chunk,
|
|
116
|
+
topicsSet,
|
|
117
|
+
onEvent,
|
|
118
|
+
onError,
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
}
|
package/lib/message.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { LinkedInMessage } from "./types";
|
|
2
|
+
interface LinkedInConversation {
|
|
3
|
+
urn: string;
|
|
4
|
+
identifier: string;
|
|
5
|
+
fullName: string;
|
|
6
|
+
firstName: string;
|
|
7
|
+
lastName: string;
|
|
8
|
+
headline: string;
|
|
9
|
+
profilePicture: string | null;
|
|
10
|
+
lastMessage: {
|
|
11
|
+
text: string;
|
|
12
|
+
sentAt: Date;
|
|
13
|
+
isRead: boolean;
|
|
14
|
+
};
|
|
15
|
+
unreadCount: number;
|
|
16
|
+
isGroup: boolean;
|
|
17
|
+
participants: any[];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Organiza o payload bruto do messengerConversations do LinkedIn
|
|
21
|
+
* em uma lista de objetos limpos e tipados.
|
|
22
|
+
*/
|
|
23
|
+
export declare const organizeInbox: (rawPayload: any) => LinkedInConversation[];
|
|
24
|
+
export declare const getMessagingInboxConversations: (input: {
|
|
25
|
+
mailboxUrn?: string;
|
|
26
|
+
identifier?: string;
|
|
27
|
+
queryId?: string;
|
|
28
|
+
}) => Promise<LinkedInConversation[]>;
|
|
29
|
+
export declare const getMessages: (conversationUrn: string) => Promise<LinkedInMessage[]>;
|
|
30
|
+
export {};
|
package/lib/message.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.getMessages = exports.getMessagingInboxConversations = exports.organizeInbox = void 0;
|
|
13
|
+
const config_1 = require("./config");
|
|
14
|
+
const user_1 = require("./user");
|
|
15
|
+
const utils_1 = require("./utils");
|
|
16
|
+
const DEFAULT_INBOX_QUERY_ID = "messengerConversations.0d5e6781bbee71c3e51c8843c6519f48";
|
|
17
|
+
/**
|
|
18
|
+
* Organiza o payload bruto do messengerConversations do LinkedIn
|
|
19
|
+
* em uma lista de objetos limpos e tipados.
|
|
20
|
+
*/
|
|
21
|
+
const organizeInbox = (rawPayload) => {
|
|
22
|
+
var _a, _b;
|
|
23
|
+
const elements = ((_b = (_a = rawPayload === null || rawPayload === void 0 ? void 0 : rawPayload.data) === null || _a === void 0 ? void 0 : _a.messengerConversationsBySyncToken) === null || _b === void 0 ? void 0 : _b.elements) || [];
|
|
24
|
+
return elements.map((conv) => {
|
|
25
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
|
|
26
|
+
// 1. Identifica o outro participante (que não é o usuário logado)
|
|
27
|
+
// Geralmente o primeiro participante que não tem a URN do mailbox
|
|
28
|
+
const otherParticipant = ((_b = (_a = conv.conversationParticipants.find((p) => { var _a, _b; return ((_b = (_a = p.participantType) === null || _a === void 0 ? void 0 : _a.member) === null || _b === void 0 ? void 0 : _b.distance) !== "SELF"; })) === null || _a === void 0 ? void 0 : _a.participantType) === null || _b === void 0 ? void 0 : _b.member) ||
|
|
29
|
+
((_d = (_c = conv.conversationParticipants[0]) === null || _c === void 0 ? void 0 : _c.participantType) === null || _d === void 0 ? void 0 : _d.member);
|
|
30
|
+
const memberInfo = otherParticipant;
|
|
31
|
+
// 2. Extrai a URN e o Identifier numérico
|
|
32
|
+
const conversationUrn = conv.entityUrn;
|
|
33
|
+
const identifier = ((_g = (_f = (_e = conversationUrn.split(":")) === null || _e === void 0 ? void 0 : _e[6]) === null || _f === void 0 ? void 0 : _f.split(",")) === null || _g === void 0 ? void 0 : _g[0]) || "";
|
|
34
|
+
// 3. Processa a Imagem (Pega o artifact com maior largura/qualidade)
|
|
35
|
+
let profilePic = null;
|
|
36
|
+
if ((_h = memberInfo === null || memberInfo === void 0 ? void 0 : memberInfo.profilePicture) === null || _h === void 0 ? void 0 : _h.artifacts) {
|
|
37
|
+
const bestArtifact = memberInfo.profilePicture.artifacts.reduce((prev, current) => {
|
|
38
|
+
return prev.width > current.width ? prev : current;
|
|
39
|
+
});
|
|
40
|
+
profilePic = `${memberInfo.profilePicture.rootUrl}${bestArtifact.fileIdentifyingUrlPathSegment}`;
|
|
41
|
+
}
|
|
42
|
+
// 4. Pega a última mensagem
|
|
43
|
+
const lastMsgElement = (_k = (_j = conv.messages) === null || _j === void 0 ? void 0 : _j.elements) === null || _k === void 0 ? void 0 : _k[0];
|
|
44
|
+
return {
|
|
45
|
+
urn: conversationUrn,
|
|
46
|
+
identifier: identifier,
|
|
47
|
+
fullName: `${((_l = memberInfo === null || memberInfo === void 0 ? void 0 : memberInfo.firstName) === null || _l === void 0 ? void 0 : _l.text) || ""} ${((_m = memberInfo === null || memberInfo === void 0 ? void 0 : memberInfo.lastName) === null || _m === void 0 ? void 0 : _m.text) || ""}`.trim(),
|
|
48
|
+
firstName: ((_o = memberInfo === null || memberInfo === void 0 ? void 0 : memberInfo.firstName) === null || _o === void 0 ? void 0 : _o.text) || "",
|
|
49
|
+
lastName: ((_p = memberInfo === null || memberInfo === void 0 ? void 0 : memberInfo.lastName) === null || _p === void 0 ? void 0 : _p.text) || "",
|
|
50
|
+
headline: ((_q = memberInfo === null || memberInfo === void 0 ? void 0 : memberInfo.headline) === null || _q === void 0 ? void 0 : _q.text) || "",
|
|
51
|
+
profilePicture: profilePic,
|
|
52
|
+
lastMessage: {
|
|
53
|
+
text: ((_r = lastMsgElement === null || lastMsgElement === void 0 ? void 0 : lastMsgElement.body) === null || _r === void 0 ? void 0 : _r.text) || "",
|
|
54
|
+
sentAt: new Date(conv.lastActivityAt),
|
|
55
|
+
isRead: conv.read,
|
|
56
|
+
},
|
|
57
|
+
unreadCount: conv.unreadCount || 0,
|
|
58
|
+
isGroup: conv.groupChat,
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
exports.organizeInbox = organizeInbox;
|
|
63
|
+
function resolveMailboxUrn(input) {
|
|
64
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
65
|
+
if (input.mailboxUrn)
|
|
66
|
+
return input.mailboxUrn;
|
|
67
|
+
if (!input.identifier)
|
|
68
|
+
throw new Error("mailboxUrn or identifier is required");
|
|
69
|
+
if (input.identifier.startsWith("urn:li:"))
|
|
70
|
+
return input.identifier;
|
|
71
|
+
const profileId = yield (0, user_1.extractProfileIdLinkedin)(input.identifier);
|
|
72
|
+
if (!profileId)
|
|
73
|
+
throw new Error("Profile not found");
|
|
74
|
+
return `urn:li:fsd_profile:${profileId}`;
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
const getMessagingInboxConversations = (input) => __awaiter(void 0, void 0, void 0, function* () {
|
|
78
|
+
var _a;
|
|
79
|
+
const mailboxUrn = yield resolveMailboxUrn(input);
|
|
80
|
+
const queryId = (_a = input.queryId) !== null && _a !== void 0 ? _a : DEFAULT_INBOX_QUERY_ID;
|
|
81
|
+
const response = yield (0, config_1.fetchData)(`/voyagerMessagingGraphQL/graphql?queryId=${queryId}&variables=(mailboxUrn:${encodeURIComponent(mailboxUrn)})`, { headers: { accept: "application/graphql" } });
|
|
82
|
+
const conversations = (0, exports.organizeInbox)(response);
|
|
83
|
+
return conversations;
|
|
84
|
+
});
|
|
85
|
+
exports.getMessagingInboxConversations = getMessagingInboxConversations;
|
|
86
|
+
const getMessages = (conversationUrn) => __awaiter(void 0, void 0, void 0, function* () {
|
|
87
|
+
var _a, _b, _c;
|
|
88
|
+
const response = yield (0, config_1.fetchData)(`/voyagerMessagingGraphQL/graphql?queryId=messengerMessages.5846eeb71c981f11e0134cb6626cc314&variables=(conversationUrn:${(0, utils_1.encodeLinkedinUrn)(conversationUrn)})`);
|
|
89
|
+
const included = (response === null || response === void 0 ? void 0 : response.included) || [];
|
|
90
|
+
const messageUrns = ((_c = (_b = (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.messengerMessagesBySyncToken) === null || _c === void 0 ? void 0 : _c["*elements"]) || [];
|
|
91
|
+
// 1. Criamos mapas para busca rápida dentro do array 'included'
|
|
92
|
+
const messageMap = new Map();
|
|
93
|
+
const participantMap = new Map();
|
|
94
|
+
const mediaMap = new Map();
|
|
95
|
+
included.forEach((item) => {
|
|
96
|
+
if (item.$type === "com.linkedin.messenger.Message") {
|
|
97
|
+
messageMap.set(item.entityUrn, item);
|
|
98
|
+
}
|
|
99
|
+
else if (item.$type === "com.linkedin.messenger.MessagingParticipant") {
|
|
100
|
+
participantMap.set(item.entityUrn, item);
|
|
101
|
+
}
|
|
102
|
+
else if (item.$type === "com.linkedin.videocontent.VideoPlayMetadata") {
|
|
103
|
+
mediaMap.set(item.entityUrn, item);
|
|
104
|
+
}
|
|
105
|
+
// Adicione outros tipos de mídia aqui se necessário (File, Image, etc)
|
|
106
|
+
});
|
|
107
|
+
// 2. Montamos a lista final baseada na ordem do array principal (*elements)
|
|
108
|
+
return messageUrns
|
|
109
|
+
.map((urn) => {
|
|
110
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
111
|
+
const msg = messageMap.get(urn);
|
|
112
|
+
if (!msg)
|
|
113
|
+
return null;
|
|
114
|
+
const senderUrn = msg["*sender"];
|
|
115
|
+
const senderRaw = participantMap.get(senderUrn);
|
|
116
|
+
const memberInfo = (_a = senderRaw === null || senderRaw === void 0 ? void 0 : senderRaw.participantType) === null || _a === void 0 ? void 0 : _a.member;
|
|
117
|
+
// Processamento de Foto do Remetente
|
|
118
|
+
let profilePic = null;
|
|
119
|
+
if ((_b = memberInfo === null || memberInfo === void 0 ? void 0 : memberInfo.profilePicture) === null || _b === void 0 ? void 0 : _b.artifacts) {
|
|
120
|
+
const bestArtifact = memberInfo.profilePicture.artifacts.reduce((prev, curr) => (prev.width > curr.width ? prev : curr));
|
|
121
|
+
profilePic = `${memberInfo.profilePicture.rootUrl}${bestArtifact.fileIdentifyingUrlPathSegment}`;
|
|
122
|
+
}
|
|
123
|
+
// Processamento de Mídia (Video, Imagem, File)
|
|
124
|
+
let mediaContent = null;
|
|
125
|
+
const renderContent = (_c = msg.renderContent) === null || _c === void 0 ? void 0 : _c[0];
|
|
126
|
+
if (renderContent) {
|
|
127
|
+
// Caso seja Vídeo (URN referenciada)
|
|
128
|
+
if (renderContent["*video"]) {
|
|
129
|
+
const videoData = mediaMap.get(renderContent["*video"]);
|
|
130
|
+
const stream = (_f = (_e = (_d = videoData === null || videoData === void 0 ? void 0 : videoData.progressiveStreams) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.streamingLocations) === null || _f === void 0 ? void 0 : _f[0];
|
|
131
|
+
mediaContent = {
|
|
132
|
+
type: "VIDEO",
|
|
133
|
+
url: (stream === null || stream === void 0 ? void 0 : stream.url) || null,
|
|
134
|
+
thumbnail: ((_j = (_h = (_g = videoData === null || videoData === void 0 ? void 0 : videoData.thumbnail) === null || _g === void 0 ? void 0 : _g.artifacts) === null || _h === void 0 ? void 0 : _h[0]) === null || _j === void 0 ? void 0 : _j.fileIdentifyingUrlPathSegment) || null,
|
|
135
|
+
duration: videoData === null || videoData === void 0 ? void 0 : videoData.duration,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
// Caso seja Imagem (Objeto direto)
|
|
139
|
+
else if (renderContent.vectorImage) {
|
|
140
|
+
mediaContent = {
|
|
141
|
+
type: "IMAGE",
|
|
142
|
+
url: renderContent.vectorImage.rootUrl +
|
|
143
|
+
(((_l = (_k = renderContent.vectorImage.artifacts) === null || _k === void 0 ? void 0 : _k[0]) === null || _l === void 0 ? void 0 : _l.fileIdentifyingUrlPathSegment) || ""),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
// Caso seja Arquivo (Objeto direto)
|
|
147
|
+
else if (renderContent.file) {
|
|
148
|
+
mediaContent = {
|
|
149
|
+
type: "FILE",
|
|
150
|
+
url: renderContent.file.url,
|
|
151
|
+
fileName: renderContent.file.name,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
else if (renderContent.audio) {
|
|
155
|
+
mediaContent = {
|
|
156
|
+
type: "AUDIO",
|
|
157
|
+
url: renderContent.audio.url,
|
|
158
|
+
duration: renderContent.audio.duration,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return {
|
|
163
|
+
id: msg.backendUrn,
|
|
164
|
+
text: ((_m = msg.body) === null || _m === void 0 ? void 0 : _m.text) || null,
|
|
165
|
+
sentAt: msg.deliveredAt,
|
|
166
|
+
media: mediaContent,
|
|
167
|
+
sender: {
|
|
168
|
+
urn: (senderRaw === null || senderRaw === void 0 ? void 0 : senderRaw.hostIdentityUrn) || null,
|
|
169
|
+
fullName: `${((_o = memberInfo === null || memberInfo === void 0 ? void 0 : memberInfo.firstName) === null || _o === void 0 ? void 0 : _o.text) || "LinkedIn User"} ${((_p = memberInfo === null || memberInfo === void 0 ? void 0 : memberInfo.lastName) === null || _p === void 0 ? void 0 : _p.text) || ""}`.trim(),
|
|
170
|
+
profilePicture: profilePic,
|
|
171
|
+
isSelf: (memberInfo === null || memberInfo === void 0 ? void 0 : memberInfo.distance) === "SELF",
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
})
|
|
175
|
+
.filter(Boolean)
|
|
176
|
+
.sort((a, b) => b.sentAt - a.sentAt);
|
|
177
|
+
});
|
|
178
|
+
exports.getMessages = getMessages;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const config_1 = require("./config");
|
|
4
|
+
const messaging_1 = require("./messaging");
|
|
5
|
+
const JSESSIONID = process.env.LINKEDIN_JSESSIONID;
|
|
6
|
+
const LI_AT = process.env.LINKEDIN_LI_AT;
|
|
7
|
+
const MAILBOX_URN = process.env.LINKEDIN_MAILBOX_URN;
|
|
8
|
+
if (!JSESSIONID || !LI_AT || !MAILBOX_URN) {
|
|
9
|
+
throw new Error("Missing env vars: LINKEDIN_JSESSIONID, LINKEDIN_LI_AT, LINKEDIN_MAILBOX_URN");
|
|
10
|
+
}
|
|
11
|
+
(0, config_1.Client)({ JSESSIONID, li_at: LI_AT });
|
|
12
|
+
(0, messaging_1.getMessagingInboxConversations)({ mailboxUrn: MAILBOX_URN })
|
|
13
|
+
.then((conversations) => {
|
|
14
|
+
console.log(JSON.stringify(conversations, null, 2));
|
|
15
|
+
})
|
|
16
|
+
.catch((error) => {
|
|
17
|
+
console.error(error);
|
|
18
|
+
});
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.getMessagingInboxConversations = void 0;
|
|
13
|
+
const config_1 = require("./config");
|
|
14
|
+
const utils_1 = require("./utils");
|
|
15
|
+
const messaging_utils_1 = require("./messaging-utils");
|
|
16
|
+
const messaging_parsers_1 = require("./messaging-parsers");
|
|
17
|
+
const user_1 = require("./user");
|
|
18
|
+
const messaging_response_1 = require("./messaging-response");
|
|
19
|
+
const DEFAULT_INBOX_QUERY_ID = "messengerConversations.0d5e6781bbee71c3e51c8843c6519f48";
|
|
20
|
+
function resolveMailboxUrn(input) {
|
|
21
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22
|
+
if (input.mailboxUrn)
|
|
23
|
+
return input.mailboxUrn;
|
|
24
|
+
if (!input.identifier)
|
|
25
|
+
throw new Error("mailboxUrn or identifier is required");
|
|
26
|
+
if (input.identifier.startsWith("urn:li:"))
|
|
27
|
+
return input.identifier;
|
|
28
|
+
const profileId = yield (0, user_1.extractProfileIdLinkedin)(input.identifier);
|
|
29
|
+
if (!profileId)
|
|
30
|
+
throw new Error("Profile not found");
|
|
31
|
+
return `urn:li:fsd_profile:${profileId}`;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
const getMessagingInboxConversations = (input) => __awaiter(void 0, void 0, void 0, function* () {
|
|
35
|
+
var _a;
|
|
36
|
+
const mailboxUrn = yield resolveMailboxUrn(input);
|
|
37
|
+
const queryId = (_a = input.queryId) !== null && _a !== void 0 ? _a : DEFAULT_INBOX_QUERY_ID;
|
|
38
|
+
const response = yield (0, config_1.fetchData)(`/voyagerMessagingGraphQL/graphql?queryId=${queryId}&variables=(mailboxUrn:${encodeURIComponent(mailboxUrn)})`, { headers: { accept: "application/graphql" } });
|
|
39
|
+
const included = (0, messaging_response_1.extractIncluded)(response);
|
|
40
|
+
const byUrn = new Map();
|
|
41
|
+
for (const item of included) {
|
|
42
|
+
if (!(0, messaging_utils_1.isRecord)(item))
|
|
43
|
+
continue;
|
|
44
|
+
const urn = (0, messaging_utils_1.asString)(item.entityUrn);
|
|
45
|
+
if (urn)
|
|
46
|
+
byUrn.set(urn, item);
|
|
47
|
+
}
|
|
48
|
+
const elementUrns = (0, messaging_response_1.findBestElementUrns)(response, new Set(byUrn.keys()));
|
|
49
|
+
if (!(elementUrns === null || elementUrns === void 0 ? void 0 : elementUrns.length))
|
|
50
|
+
throw new Error("Inbox elements not found");
|
|
51
|
+
return elementUrns
|
|
52
|
+
.map((urn) => byUrn.get(urn))
|
|
53
|
+
.filter((v) => v !== undefined)
|
|
54
|
+
.map((thread) => (0, utils_1.resolveReferences)(thread, included))
|
|
55
|
+
.map((thread) => {
|
|
56
|
+
var _a, _b, _c;
|
|
57
|
+
const participantsRaw = (_a = (0, messaging_utils_1.pickFirstArray)(thread, ["participants", "conversationParticipants", "participants.elements"])) !== null && _a !== void 0 ? _a : [];
|
|
58
|
+
const participants = participantsRaw.map(messaging_parsers_1.parseInboxParticipant).filter((p) => Boolean(p.profileUrn || p.publicIdentifier || p.fullName));
|
|
59
|
+
const lastMessageAt = (0, messaging_utils_1.normalizeEpochMillis)((0, messaging_utils_1.pickFirstNumber)(thread, ["lastActivityAt", "lastActivityTime", "updatedAt", "lastMessageAt", "lastMessage.createdAt"]));
|
|
60
|
+
return {
|
|
61
|
+
threadUrn: (_b = (0, messaging_utils_1.pickFirstString)(thread, ["entityUrn", "backendUrn", "threadUrn"])) !== null && _b !== void 0 ? _b : "urn:li:unknown",
|
|
62
|
+
participants,
|
|
63
|
+
primaryParticipant: (_c = participants[0]) !== null && _c !== void 0 ? _c : null,
|
|
64
|
+
lastMessageText: (0, messaging_utils_1.pickFirstString)(thread, ["lastMessage.eventContent.attributedBody.text", "lastMessage.eventContent.text", "lastMessage.attributedBody.text", "lastMessage.body.text", "lastMessage.text", "snippet.text", "snippet"]),
|
|
65
|
+
lastMessageAt,
|
|
66
|
+
lastMessageAtISO: lastMessageAt ? new Date(lastMessageAt).toISOString() : null,
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
exports.getMessagingInboxConversations = getMessagingInboxConversations;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseInboxParticipant = parseInboxParticipant;
|
|
4
|
+
const utils_1 = require("./utils");
|
|
5
|
+
const messaging_utils_1 = require("./messaging-utils");
|
|
6
|
+
function parseInboxParticipant(participant) {
|
|
7
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
8
|
+
const miniProfile = (_a = (0, utils_1.getNestedValue)(participant, "miniProfile")) !== null && _a !== void 0 ? _a : participant;
|
|
9
|
+
const firstName = (_b = (0, messaging_utils_1.pickFirstString)(miniProfile, ["firstName"])) !== null && _b !== void 0 ? _b : null;
|
|
10
|
+
const lastName = (_c = (0, messaging_utils_1.pickFirstString)(miniProfile, ["lastName"])) !== null && _c !== void 0 ? _c : null;
|
|
11
|
+
const fullName = (_e = (_d = (firstName || lastName ? `${firstName !== null && firstName !== void 0 ? firstName : ""} ${lastName !== null && lastName !== void 0 ? lastName : ""}`.trim() : null)) !== null && _d !== void 0 ? _d : (0, messaging_utils_1.pickFirstString)(miniProfile, ["fullName", "name", "title.text"])) !== null && _e !== void 0 ? _e : null;
|
|
12
|
+
const vectorImage = (_g = (_f = (0, utils_1.getNestedValue)(miniProfile, "picture.vectorImage")) !== null && _f !== void 0 ? _f : (0, utils_1.getNestedValue)(miniProfile, "picture.displayImageReferenceResolutionResult.vectorImage")) !== null && _g !== void 0 ? _g : (0, utils_1.getNestedValue)(participant, "image.attributes.0.detailData.nonEntityProfilePicture.vectorImage");
|
|
13
|
+
return {
|
|
14
|
+
profileUrn: (_j = (_h = (0, messaging_utils_1.pickFirstString)(miniProfile, ["entityUrn", "objectUrn"])) !== null && _h !== void 0 ? _h : (0, messaging_utils_1.pickFirstString)(participant, ["entityUrn"])) !== null && _j !== void 0 ? _j : null,
|
|
15
|
+
publicIdentifier: (_l = (_k = (0, messaging_utils_1.pickFirstString)(miniProfile, ["publicIdentifier"])) !== null && _k !== void 0 ? _k : (0, messaging_utils_1.pickFirstString)(participant, ["publicIdentifier"])) !== null && _l !== void 0 ? _l : null,
|
|
16
|
+
firstName,
|
|
17
|
+
lastName,
|
|
18
|
+
fullName,
|
|
19
|
+
headline: (_m = (0, messaging_utils_1.pickFirstString)(miniProfile, [
|
|
20
|
+
"headline",
|
|
21
|
+
"occupation",
|
|
22
|
+
"subtitle.text",
|
|
23
|
+
"headline.text",
|
|
24
|
+
])) !== null && _m !== void 0 ? _m : null,
|
|
25
|
+
pictureUrl: (0, messaging_utils_1.buildVectorImageUrl)(vectorImage),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractIncluded = extractIncluded;
|
|
4
|
+
exports.findBestElementUrns = findBestElementUrns;
|
|
5
|
+
const messaging_utils_1 = require("./messaging-utils");
|
|
6
|
+
function collectElementUrnCandidates(dataRoot) {
|
|
7
|
+
var _a;
|
|
8
|
+
const candidates = [];
|
|
9
|
+
const queue = [dataRoot];
|
|
10
|
+
while (queue.length) {
|
|
11
|
+
const node = queue.shift();
|
|
12
|
+
if (!(0, messaging_utils_1.isRecord)(node))
|
|
13
|
+
continue;
|
|
14
|
+
const rawElements = (_a = node["*elements"]) !== null && _a !== void 0 ? _a : node.elements;
|
|
15
|
+
if (Array.isArray(rawElements) &&
|
|
16
|
+
rawElements.length > 0 &&
|
|
17
|
+
rawElements.every((v) => typeof v === "string")) {
|
|
18
|
+
candidates.push(rawElements);
|
|
19
|
+
}
|
|
20
|
+
for (const value of Object.values(node))
|
|
21
|
+
queue.push(value);
|
|
22
|
+
}
|
|
23
|
+
return candidates;
|
|
24
|
+
}
|
|
25
|
+
function scoreCandidate(urns, includedUrnSet) {
|
|
26
|
+
let hits = 0;
|
|
27
|
+
for (const urn of urns)
|
|
28
|
+
if (includedUrnSet.has(urn))
|
|
29
|
+
hits += 1;
|
|
30
|
+
return hits;
|
|
31
|
+
}
|
|
32
|
+
function extractIncluded(response) {
|
|
33
|
+
if ((0, messaging_utils_1.isRecord)(response) && Array.isArray(response.included))
|
|
34
|
+
return response.included;
|
|
35
|
+
if ((0, messaging_utils_1.isRecord)(response) && (0, messaging_utils_1.isRecord)(response.data) && Array.isArray(response.data.included)) {
|
|
36
|
+
return response.data.included;
|
|
37
|
+
}
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
function findBestElementUrns(response, includedUrnSet) {
|
|
41
|
+
var _a;
|
|
42
|
+
const roots = [];
|
|
43
|
+
if ((0, messaging_utils_1.isRecord)(response) && (0, messaging_utils_1.isRecord)(response.data))
|
|
44
|
+
roots.push(response.data);
|
|
45
|
+
roots.push(response);
|
|
46
|
+
const allCandidates = roots.flatMap(collectElementUrnCandidates);
|
|
47
|
+
if (allCandidates.length === 0)
|
|
48
|
+
return null;
|
|
49
|
+
let best = null;
|
|
50
|
+
let bestScore = -1;
|
|
51
|
+
for (const candidate of allCandidates) {
|
|
52
|
+
const score = scoreCandidate(candidate, includedUrnSet);
|
|
53
|
+
if (score > bestScore) {
|
|
54
|
+
bestScore = score;
|
|
55
|
+
best = candidate;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (best && bestScore === 0)
|
|
59
|
+
return (_a = allCandidates[0]) !== null && _a !== void 0 ? _a : null;
|
|
60
|
+
return best;
|
|
61
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface MessagingInboxParticipant {
|
|
2
|
+
profileUrn: string | null;
|
|
3
|
+
publicIdentifier: string | null;
|
|
4
|
+
firstName: string | null;
|
|
5
|
+
lastName: string | null;
|
|
6
|
+
fullName: string | null;
|
|
7
|
+
headline: string | null;
|
|
8
|
+
pictureUrl: string | null;
|
|
9
|
+
}
|
|
10
|
+
export interface MessagingInboxConversation {
|
|
11
|
+
threadUrn: string;
|
|
12
|
+
participants: MessagingInboxParticipant[];
|
|
13
|
+
primaryParticipant: MessagingInboxParticipant | null;
|
|
14
|
+
lastMessageText: string | null;
|
|
15
|
+
lastMessageAt: number | null;
|
|
16
|
+
lastMessageAtISO: string | null;
|
|
17
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type JsonRecord = Record<string, unknown>;
|
|
2
|
+
export declare function isRecord(value: unknown): value is JsonRecord;
|
|
3
|
+
export declare function asString(value: unknown): string | null;
|
|
4
|
+
export declare function asNumber(value: unknown): number | null;
|
|
5
|
+
export declare function normalizeEpochMillis(value: unknown): number | null;
|
|
6
|
+
export declare function pickFirstString(obj: unknown, paths: string[]): string | null;
|
|
7
|
+
export declare function pickFirstNumber(obj: unknown, paths: string[]): number | null;
|
|
8
|
+
export declare function pickFirstArray(obj: unknown, paths: string[]): unknown[] | null;
|
|
9
|
+
export declare function buildVectorImageUrl(vectorImage: unknown): string | null;
|
|
10
|
+
export declare function findElementUrns(dataRoot: unknown): string[] | null;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isRecord = isRecord;
|
|
4
|
+
exports.asString = asString;
|
|
5
|
+
exports.asNumber = asNumber;
|
|
6
|
+
exports.normalizeEpochMillis = normalizeEpochMillis;
|
|
7
|
+
exports.pickFirstString = pickFirstString;
|
|
8
|
+
exports.pickFirstNumber = pickFirstNumber;
|
|
9
|
+
exports.pickFirstArray = pickFirstArray;
|
|
10
|
+
exports.buildVectorImageUrl = buildVectorImageUrl;
|
|
11
|
+
exports.findElementUrns = findElementUrns;
|
|
12
|
+
const utils_1 = require("./utils");
|
|
13
|
+
function isRecord(value) {
|
|
14
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15
|
+
}
|
|
16
|
+
function asString(value) {
|
|
17
|
+
return typeof value === "string" && value.trim().length > 0 ? value : null;
|
|
18
|
+
}
|
|
19
|
+
function asNumber(value) {
|
|
20
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
21
|
+
}
|
|
22
|
+
function normalizeEpochMillis(value) {
|
|
23
|
+
const num = asNumber(value);
|
|
24
|
+
if (num === null)
|
|
25
|
+
return null;
|
|
26
|
+
return num < 10000000000 ? num * 1000 : num;
|
|
27
|
+
}
|
|
28
|
+
function pickFirstString(obj, paths) {
|
|
29
|
+
for (const path of paths) {
|
|
30
|
+
const candidate = asString((0, utils_1.getNestedValue)(obj, path));
|
|
31
|
+
if (candidate)
|
|
32
|
+
return candidate;
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
function pickFirstNumber(obj, paths) {
|
|
37
|
+
for (const path of paths) {
|
|
38
|
+
const candidate = asNumber((0, utils_1.getNestedValue)(obj, path));
|
|
39
|
+
if (candidate !== null)
|
|
40
|
+
return candidate;
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
function pickFirstArray(obj, paths) {
|
|
45
|
+
for (const path of paths) {
|
|
46
|
+
const candidate = (0, utils_1.getNestedValue)(obj, path);
|
|
47
|
+
if (Array.isArray(candidate))
|
|
48
|
+
return candidate;
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
function buildVectorImageUrl(vectorImage) {
|
|
53
|
+
if (!isRecord(vectorImage))
|
|
54
|
+
return null;
|
|
55
|
+
const rootUrl = asString(vectorImage.rootUrl);
|
|
56
|
+
if (!rootUrl)
|
|
57
|
+
return null;
|
|
58
|
+
const artifacts = vectorImage.artifacts;
|
|
59
|
+
if (!Array.isArray(artifacts) || artifacts.length === 0)
|
|
60
|
+
return null;
|
|
61
|
+
const last = artifacts.at(-1);
|
|
62
|
+
if (!isRecord(last))
|
|
63
|
+
return null;
|
|
64
|
+
const seg = asString(last.fileIdentifyingUrlPathSegment);
|
|
65
|
+
return seg ? `${rootUrl}${seg}` : null;
|
|
66
|
+
}
|
|
67
|
+
function findElementUrns(dataRoot) {
|
|
68
|
+
const queue = [dataRoot];
|
|
69
|
+
while (queue.length) {
|
|
70
|
+
const node = queue.shift();
|
|
71
|
+
if (!isRecord(node))
|
|
72
|
+
continue;
|
|
73
|
+
const elements = node["*elements"];
|
|
74
|
+
if (Array.isArray(elements) && elements.every((v) => typeof v === "string")) {
|
|
75
|
+
return elements;
|
|
76
|
+
}
|
|
77
|
+
for (const value of Object.values(node))
|
|
78
|
+
queue.push(value);
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./messaging-inbox";
|
package/lib/messaging.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./messaging-inbox"), exports);
|
package/lib/teste.js
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
2
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
12
|
const config_1 = require("./config");
|
|
4
|
-
const
|
|
13
|
+
const linkedin_sse_1 = require("./linkedin-sse");
|
|
5
14
|
(0, config_1.Client)({
|
|
6
|
-
JSESSIONID: "
|
|
7
|
-
li_at: "
|
|
8
|
-
});
|
|
9
|
-
(0, user_1.getUserMiniProfile)("wesbush")
|
|
10
|
-
.then((profile) => {
|
|
11
|
-
console.log("profile: ", profile);
|
|
12
|
-
})
|
|
13
|
-
.catch((error) => {
|
|
14
|
-
console.log("error: ", error);
|
|
15
|
+
JSESSIONID: "0466411065031579456",
|
|
16
|
+
li_at: "AQEDAU9C-sMEobZ6AAABmgzAd04AAAGc5X6rR04Ab8DYREgT31dxDOoVSZ86b0QnMvC5LTO2hSQcC5_A8qISIL9l-DdYFs9yPYZS4osBMOkDS6Q3wpkQ5Y_Wd8piLcBsF8dNJ22XBoVYRG6w2ZjpHgxb",
|
|
15
17
|
});
|
|
18
|
+
function start() {
|
|
19
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
20
|
+
yield (0, linkedin_sse_1.linkedinSSE)(["Messages", "TypingIndicators"]);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
start();
|
package/lib/types.d.ts
CHANGED
|
@@ -792,3 +792,40 @@ export type EntitySearchResult = {
|
|
|
792
792
|
$type: string;
|
|
793
793
|
};
|
|
794
794
|
};
|
|
795
|
+
export interface LinkedInConversation {
|
|
796
|
+
urn: string;
|
|
797
|
+
identifier: string;
|
|
798
|
+
fullName: string;
|
|
799
|
+
firstName: string;
|
|
800
|
+
lastName: string;
|
|
801
|
+
headline: string;
|
|
802
|
+
profilePicture: string | null;
|
|
803
|
+
lastMessage: {
|
|
804
|
+
text: string;
|
|
805
|
+
sentAt: Date;
|
|
806
|
+
isRead: boolean;
|
|
807
|
+
};
|
|
808
|
+
unreadCount: number;
|
|
809
|
+
isGroup: boolean;
|
|
810
|
+
participants: any[];
|
|
811
|
+
}
|
|
812
|
+
export interface LinkedInMessage {
|
|
813
|
+
id: string;
|
|
814
|
+
text: string;
|
|
815
|
+
sentAt: number;
|
|
816
|
+
media?: {
|
|
817
|
+
type: "VIDEO" | "IMAGE" | "FILE" | "AUDIO";
|
|
818
|
+
url: string | null;
|
|
819
|
+
thumbnail?: string | null;
|
|
820
|
+
duration?: number;
|
|
821
|
+
fileName?: string;
|
|
822
|
+
} | null;
|
|
823
|
+
sender: {
|
|
824
|
+
urn: string;
|
|
825
|
+
fullName: string;
|
|
826
|
+
firstName: string;
|
|
827
|
+
lastName: string;
|
|
828
|
+
profilePicture: string | null;
|
|
829
|
+
isSelf: boolean;
|
|
830
|
+
};
|
|
831
|
+
}
|
package/lib/utils.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ interface Experience {
|
|
|
20
20
|
time_period?: string | null;
|
|
21
21
|
duration?: string | null;
|
|
22
22
|
}
|
|
23
|
+
export declare function encodeLinkedinUrn(raw: string): string;
|
|
23
24
|
export declare const getDataIncludedForEntity: (jsonData: AnyObject, entityUrn: string) => any;
|
|
24
25
|
export declare function extractExperiences(jsonData: AnyObject): Experience[];
|
|
25
26
|
export declare function assert(value: unknown, message?: string | Error): asserts value;
|
package/lib/utils.js
CHANGED
|
@@ -24,6 +24,7 @@ exports.extractDataWithReferences = extractDataWithReferences;
|
|
|
24
24
|
exports.debugResolvedStructure = debugResolvedStructure;
|
|
25
25
|
exports.extractFieldsFromIncluded = extractFieldsFromIncluded;
|
|
26
26
|
exports.mergeExtraFields = mergeExtraFields;
|
|
27
|
+
exports.encodeLinkedinUrn = encodeLinkedinUrn;
|
|
27
28
|
exports.extractExperiences = extractExperiences;
|
|
28
29
|
exports.assert = assert;
|
|
29
30
|
exports.getIdFromUrn = getIdFromUrn;
|
|
@@ -212,6 +213,9 @@ function mergeExtraFields(mainData, extraData, matchKey = "companyUrn") {
|
|
|
212
213
|
return item;
|
|
213
214
|
});
|
|
214
215
|
}
|
|
216
|
+
function encodeLinkedinUrn(raw) {
|
|
217
|
+
return encodeURIComponent(raw).replace(/\(/g, "%28").replace(/\)/g, "%29");
|
|
218
|
+
}
|
|
215
219
|
const getDataIncludedForEntity = (jsonData, entityUrn) => {
|
|
216
220
|
const data = jsonData === null || jsonData === void 0 ? void 0 : jsonData.included;
|
|
217
221
|
if (data.length) {
|
package/package.json
CHANGED
|
@@ -1,10 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@florydev/linkedin-api-voyager",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.8",
|
|
4
4
|
"description": "Uma biblioteca TypeScript para interagir com a API interna do LinkedIn (Voyager)",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
7
7
|
"license": "MIT",
|
|
8
|
+
"author": {
|
|
9
|
+
"name": "Flory Muenge Tshiteya",
|
|
10
|
+
"url": "https://github.com/Floryvibla"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/Floryvibla/linkedin-api-voyager#readme",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/Floryvibla/linkedin-api-voyager.git"
|
|
16
|
+
},
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/Floryvibla/linkedin-api-voyager/issues"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"linkedin",
|
|
22
|
+
"api",
|
|
23
|
+
"voyager",
|
|
24
|
+
"typescript",
|
|
25
|
+
"scraper",
|
|
26
|
+
"crawler",
|
|
27
|
+
"nodejs",
|
|
28
|
+
"profile",
|
|
29
|
+
"company",
|
|
30
|
+
"search"
|
|
31
|
+
],
|
|
8
32
|
"files": [
|
|
9
33
|
"lib/**/*"
|
|
10
34
|
],
|
|
@@ -12,6 +36,7 @@
|
|
|
12
36
|
"build": "tsc",
|
|
13
37
|
"prepare": "npm run build",
|
|
14
38
|
"dev": "nodemon src/teste.ts",
|
|
39
|
+
"release": "npm run build && npm version patch --no-git-tag-version && npm publish --access public",
|
|
15
40
|
"prepublishOnly": "npm run build"
|
|
16
41
|
},
|
|
17
42
|
"devDependencies": {
|