operand-meta-sdk 1.2.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.
- package/.eslintrc.js +25 -0
- package/.prettierrc +4 -0
- package/README.md +435 -0
- package/dist/jest.config.d.ts +3 -0
- package/dist/jest.config.js +14 -0
- package/dist/jest.config.js.map +1 -0
- package/dist/src/__test__/mocks/index.d.ts +2 -0
- package/dist/src/__test__/mocks/index.js +6 -0
- package/dist/src/__test__/mocks/index.js.map +1 -0
- package/dist/src/error/operand-error.d.ts +8 -0
- package/dist/src/error/operand-error.js +196 -0
- package/dist/src/error/operand-error.js.map +1 -0
- package/dist/src/index.d.ts +10 -0
- package/dist/src/index.js +22 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/interfaces/ing-publish.d.ts +53 -0
- package/dist/src/interfaces/ing-publish.js +3 -0
- package/dist/src/interfaces/ing-publish.js.map +1 -0
- package/dist/src/interfaces/meta-auth.d.ts +14 -0
- package/dist/src/interfaces/meta-auth.js +3 -0
- package/dist/src/interfaces/meta-auth.js.map +1 -0
- package/dist/src/interfaces/meta-mkt.d.ts +4 -0
- package/dist/src/interfaces/meta-mkt.js +3 -0
- package/dist/src/interfaces/meta-mkt.js.map +1 -0
- package/dist/src/interfaces/meta-response.d.ts +285 -0
- package/dist/src/interfaces/meta-response.js +3 -0
- package/dist/src/interfaces/meta-response.js.map +1 -0
- package/dist/src/interfaces/meta.d.ts +6 -0
- package/dist/src/interfaces/meta.js +3 -0
- package/dist/src/interfaces/meta.js.map +1 -0
- package/dist/src/interfaces/page-publish.d.ts +66 -0
- package/dist/src/interfaces/page-publish.js +3 -0
- package/dist/src/interfaces/page-publish.js.map +1 -0
- package/dist/src/modules/auth/meta-auth.d.ts +35 -0
- package/dist/src/modules/auth/meta-auth.js +131 -0
- package/dist/src/modules/auth/meta-auth.js.map +1 -0
- package/dist/src/modules/auth/meta-auth.spec.d.ts +1 -0
- package/dist/src/modules/auth/meta-auth.spec.js +76 -0
- package/dist/src/modules/auth/meta-auth.spec.js.map +1 -0
- package/dist/src/modules/comments/ing-comments.d.ts +7 -0
- package/dist/src/modules/comments/ing-comments.js +27 -0
- package/dist/src/modules/comments/ing-comments.js.map +1 -0
- package/dist/src/modules/comments/page-comments.d.ts +6 -0
- package/dist/src/modules/comments/page-comments.js +18 -0
- package/dist/src/modules/comments/page-comments.js.map +1 -0
- package/dist/src/modules/insights/ing-insights.d.ts +42 -0
- package/dist/src/modules/insights/ing-insights.js +150 -0
- package/dist/src/modules/insights/ing-insights.js.map +1 -0
- package/dist/src/modules/insights/mkt-insights.d.ts +10 -0
- package/dist/src/modules/insights/mkt-insights.js +46 -0
- package/dist/src/modules/insights/mkt-insights.js.map +1 -0
- package/dist/src/modules/insights/page-insights.d.ts +34 -0
- package/dist/src/modules/insights/page-insights.js +146 -0
- package/dist/src/modules/insights/page-insights.js.map +1 -0
- package/dist/src/modules/meta-ing.d.ts +5 -0
- package/dist/src/modules/meta-ing.js +11 -0
- package/dist/src/modules/meta-ing.js.map +1 -0
- package/dist/src/modules/meta-mkt.d.ts +5 -0
- package/dist/src/modules/meta-mkt.js +11 -0
- package/dist/src/modules/meta-mkt.js.map +1 -0
- package/dist/src/modules/meta-page.d.ts +5 -0
- package/dist/src/modules/meta-page.js +11 -0
- package/dist/src/modules/meta-page.js.map +1 -0
- package/dist/src/modules/meta.d.ts +10 -0
- package/dist/src/modules/meta.js +23 -0
- package/dist/src/modules/meta.js.map +1 -0
- package/dist/src/modules/publish/ing-publish.d.ts +39 -0
- package/dist/src/modules/publish/ing-publish.js +464 -0
- package/dist/src/modules/publish/ing-publish.js.map +1 -0
- package/dist/src/modules/publish/page-publish.d.ts +51 -0
- package/dist/src/modules/publish/page-publish.js +560 -0
- package/dist/src/modules/publish/page-publish.js.map +1 -0
- package/dist/src/modules/publish/page-publish.spec.d.ts +1 -0
- package/dist/src/modules/publish/page-publish.spec.js +280 -0
- package/dist/src/modules/publish/page-publish.spec.js.map +1 -0
- package/dist/src/modules/utils/meta-utils.d.ts +8 -0
- package/dist/src/modules/utils/meta-utils.js +28 -0
- package/dist/src/modules/utils/meta-utils.js.map +1 -0
- package/dist/src/utils/api.d.ts +8 -0
- package/dist/src/utils/api.js +36 -0
- package/dist/src/utils/api.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/jest.config.ts +198 -0
- package/package.json +39 -0
- package/src/__test__/mocks/image.jpeg +0 -0
- package/src/__test__/mocks/index.ts +5 -0
- package/src/__test__/mocks/video-to-post.mp4 +0 -0
- package/src/__test__/mocks/video-to-stories.mp4 +0 -0
- package/src/error/operand-error.ts +217 -0
- package/src/index.ts +21 -0
- package/src/interfaces/ing-publish.ts +58 -0
- package/src/interfaces/meta-auth.ts +52 -0
- package/src/interfaces/meta-mkt.ts +5 -0
- package/src/interfaces/meta-response.ts +319 -0
- package/src/interfaces/meta.ts +7 -0
- package/src/interfaces/page-publish.ts +72 -0
- package/src/modules/auth/meta-auth.spec.ts +93 -0
- package/src/modules/auth/meta-auth.ts +227 -0
- package/src/modules/comments/ing-comments.ts +38 -0
- package/src/modules/comments/page-comments.ts +20 -0
- package/src/modules/insights/ing-insights.ts +275 -0
- package/src/modules/insights/mkt-insights.ts +68 -0
- package/src/modules/insights/page-insights.ts +267 -0
- package/src/modules/meta-ing.ts +8 -0
- package/src/modules/meta-mkt.ts +8 -0
- package/src/modules/meta-page.ts +8 -0
- package/src/modules/meta.ts +31 -0
- package/src/modules/publish/ing-publish.ts +754 -0
- package/src/modules/publish/page-publish.spec.ts +386 -0
- package/src/modules/publish/page-publish.ts +881 -0
- package/src/modules/utils/meta-utils.ts +37 -0
- package/src/utils/api.ts +45 -0
- package/tsconfig.json +22 -0
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { ConstructorIng } from "../../interfaces/ing-publish";
|
|
2
|
+
import {
|
|
3
|
+
GetFollowersCountResponseCurrent,
|
|
4
|
+
GetInsightsAccountsEngagedResponse,
|
|
5
|
+
GetInsightsPageFollowersAndUnFollowersResponse,
|
|
6
|
+
GetInsightsResponse,
|
|
7
|
+
} from "../../interfaces/meta-response";
|
|
8
|
+
import { addDays, differenceInDays } from "date-fns";
|
|
9
|
+
import { IngComments } from "../comments/ing-comments";
|
|
10
|
+
import { formatInTimeZone } from "date-fns-tz";
|
|
11
|
+
import Axios from "axios";
|
|
12
|
+
|
|
13
|
+
export class IngInsights extends IngComments {
|
|
14
|
+
constructor(constructorIng: ConstructorIng) {
|
|
15
|
+
super({
|
|
16
|
+
...constructorIng,
|
|
17
|
+
isInstagramApi: constructorIng.typeToken === "ig",
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
private generateSinceAndUntil(startDate: Date, endDate: Date) {
|
|
22
|
+
const nextDay = addDays(endDate, 1);
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
since: formatInTimeZone(startDate, "UTC", "yyyy-MM-dd"),
|
|
26
|
+
until: formatInTimeZone(nextDay, "UTC", "yyyy-MM-dd"),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
private async generateWhileLoopToGetLikesAndCommentsAndShares(
|
|
31
|
+
startDate: Date,
|
|
32
|
+
endDate: Date,
|
|
33
|
+
metric: "likes" | "comments" | "shares",
|
|
34
|
+
): Promise<{ value: number; end_time?: string }[]> {
|
|
35
|
+
const results: { value: number; end_time?: string }[] = [];
|
|
36
|
+
|
|
37
|
+
let currentDate = startDate;
|
|
38
|
+
|
|
39
|
+
while (currentDate <= endDate) {
|
|
40
|
+
const response = await this.api.get<GetInsightsResponse>(
|
|
41
|
+
`/${this.ingId}/insights`,
|
|
42
|
+
{
|
|
43
|
+
params: {
|
|
44
|
+
metric,
|
|
45
|
+
period: "day",
|
|
46
|
+
metric_type: "total_value",
|
|
47
|
+
...this.generateSinceAndUntil(currentDate, currentDate),
|
|
48
|
+
access_token: this.pageAccessToken,
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const value = response.data.data[0]?.total_value?.value || 0;
|
|
54
|
+
const endTime = response.data.data[0]?.values?.[0]?.end_time;
|
|
55
|
+
|
|
56
|
+
results.push({ value, end_time: endTime });
|
|
57
|
+
|
|
58
|
+
currentDate = addDays(currentDate, 1);
|
|
59
|
+
|
|
60
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return results;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public async getFollowersCountCurrent() {
|
|
67
|
+
return (
|
|
68
|
+
await this.api.get<GetFollowersCountResponseCurrent>(`/${this.ingId}`, {
|
|
69
|
+
params: {
|
|
70
|
+
fields: "followers_count",
|
|
71
|
+
access_token: this.pageAccessToken,
|
|
72
|
+
},
|
|
73
|
+
})
|
|
74
|
+
).data.followers_count;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
public async getDayFollowersByDateInterval(startDate: Date, endDate: Date) {
|
|
78
|
+
const response = await this.api.get<GetInsightsResponse>(
|
|
79
|
+
`/${this.ingId}/insights`,
|
|
80
|
+
{
|
|
81
|
+
params: {
|
|
82
|
+
metric: "follower_count",
|
|
83
|
+
period: "day",
|
|
84
|
+
...this.generateSinceAndUntil(startDate, endDate),
|
|
85
|
+
access_token: this.pageAccessToken,
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
return response.data.data?.[0]?.values?.map((value, index) => ({
|
|
91
|
+
[formatInTimeZone(addDays(startDate, index), "UTC", "yyyy-MM-dd")]:
|
|
92
|
+
value.value,
|
|
93
|
+
}));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
public async getDayUnFollowersByDateInterval(startDate: Date, endDate: Date) {
|
|
97
|
+
const response =
|
|
98
|
+
await this.api.get<GetInsightsPageFollowersAndUnFollowersResponse>(
|
|
99
|
+
`/${this.ingId}/insights`,
|
|
100
|
+
{
|
|
101
|
+
params: {
|
|
102
|
+
metric: "follows_and_unfollows",
|
|
103
|
+
metric_type: "total_value",
|
|
104
|
+
period: "day",
|
|
105
|
+
...this.generateSinceAndUntil(startDate, endDate),
|
|
106
|
+
access_token: this.pageAccessToken,
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
return response.data.data?.[0]?.values?.map((value, index) => ({
|
|
112
|
+
[formatInTimeZone(addDays(startDate, index), "UTC", "yyyy-MM-dd")]:
|
|
113
|
+
value.value,
|
|
114
|
+
}));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
public async getDayAllViews(startDate: Date, endDate: Date) {
|
|
118
|
+
const days = differenceInDays(endDate, startDate);
|
|
119
|
+
const viewsArray: { [a: string]: number }[] = [];
|
|
120
|
+
let next: string | undefined = undefined;
|
|
121
|
+
|
|
122
|
+
for (let index = 0; index <= days; index++) {
|
|
123
|
+
const response = next
|
|
124
|
+
? await Axios.get<GetInsightsAccountsEngagedResponse>(next)
|
|
125
|
+
: await this.api.get<GetInsightsAccountsEngagedResponse>(
|
|
126
|
+
`/${this.ingId}/insights`,
|
|
127
|
+
{
|
|
128
|
+
params: {
|
|
129
|
+
metric: "views",
|
|
130
|
+
metric_type: "total_value",
|
|
131
|
+
period: "day",
|
|
132
|
+
since: formatInTimeZone(startDate, "UTC", "yyyy-MM-dd"),
|
|
133
|
+
until: formatInTimeZone(
|
|
134
|
+
addDays(startDate, 1),
|
|
135
|
+
"UTC",
|
|
136
|
+
"yyyy-MM-dd",
|
|
137
|
+
),
|
|
138
|
+
access_token: this.pageAccessToken,
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
const { data, paging } = response.data;
|
|
144
|
+
|
|
145
|
+
viewsArray.push({
|
|
146
|
+
[formatInTimeZone(addDays(startDate, index), "UTC", "yyyy-MM-dd")]:
|
|
147
|
+
Number(data?.[0]?.total_value?.value || 0),
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
next = paging?.next;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return viewsArray;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
public async getDayAllReaches(startDate: Date, endDate: Date) {
|
|
157
|
+
const response = await this.api.get<GetInsightsResponse>(
|
|
158
|
+
`/${this.ingId}/insights`,
|
|
159
|
+
{
|
|
160
|
+
params: {
|
|
161
|
+
metric: "reach",
|
|
162
|
+
period: "day",
|
|
163
|
+
...this.generateSinceAndUntil(startDate, endDate),
|
|
164
|
+
access_token: this.pageAccessToken,
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
return response.data.data[0].values.map((value, index) => ({
|
|
170
|
+
[formatInTimeZone(addDays(startDate, index), "UTC", "yyyy-MM-dd")]:
|
|
171
|
+
value.value,
|
|
172
|
+
}));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
public async getDayAllLikesInAllPosts(startDate: Date, endDate: Date) {
|
|
176
|
+
return this.generateWhileLoopToGetLikesAndCommentsAndShares(
|
|
177
|
+
startDate,
|
|
178
|
+
endDate,
|
|
179
|
+
"likes",
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
public async getDayAllCommentsInAllPosts(startDate: Date, endDate: Date) {
|
|
184
|
+
return this.generateWhileLoopToGetLikesAndCommentsAndShares(
|
|
185
|
+
startDate,
|
|
186
|
+
endDate,
|
|
187
|
+
"comments",
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
public async getDayAllSharesInAllPosts(startDate: Date, endDate: Date) {
|
|
192
|
+
return this.generateWhileLoopToGetLikesAndCommentsAndShares(
|
|
193
|
+
startDate,
|
|
194
|
+
endDate,
|
|
195
|
+
"shares",
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
public async getTotalLikesInAllPosts(startDate: Date, endDate: Date) {
|
|
200
|
+
const values = await this.generateWhileLoopToGetLikesAndCommentsAndShares(
|
|
201
|
+
startDate,
|
|
202
|
+
endDate,
|
|
203
|
+
"likes",
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
return values.reduce((acc, curr) => acc + curr.value, 0);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
public async getTotalCommentsInAllPosts(startDate: Date, endDate: Date) {
|
|
210
|
+
const values = await this.generateWhileLoopToGetLikesAndCommentsAndShares(
|
|
211
|
+
startDate,
|
|
212
|
+
endDate,
|
|
213
|
+
"comments",
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
return values.reduce((acc, curr) => acc + curr.value, 0);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
public async getTotalSharesInAllPosts(startDate: Date, endDate: Date) {
|
|
220
|
+
const values = await this.generateWhileLoopToGetLikesAndCommentsAndShares(
|
|
221
|
+
startDate,
|
|
222
|
+
endDate,
|
|
223
|
+
"shares",
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
return values.reduce((acc, curr) => acc + curr.value, 0);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
public async getTotalInteractionsInAllPosts(startDate: Date, endDate: Date) {
|
|
230
|
+
const likes = await this.getTotalLikesInAllPosts(startDate, endDate);
|
|
231
|
+
const comments = await this.getTotalCommentsInAllPosts(startDate, endDate);
|
|
232
|
+
const shares = await this.getTotalSharesInAllPosts(startDate, endDate);
|
|
233
|
+
|
|
234
|
+
return likes + comments + shares;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
public async getDayEngagementInAllPosts(startDate: Date, endDate: Date) {
|
|
238
|
+
const days = differenceInDays(endDate, startDate);
|
|
239
|
+
const engagementArray: { [a: string]: number }[] = [];
|
|
240
|
+
let next: string | undefined = undefined;
|
|
241
|
+
|
|
242
|
+
for (let index = 0; index <= days; index++) {
|
|
243
|
+
const response = next
|
|
244
|
+
? await Axios.get<GetInsightsAccountsEngagedResponse>(next)
|
|
245
|
+
: await this.api.get<GetInsightsAccountsEngagedResponse>(
|
|
246
|
+
`/${this.ingId}/insights`,
|
|
247
|
+
{
|
|
248
|
+
params: {
|
|
249
|
+
metric: "accounts_engaged",
|
|
250
|
+
metric_type: "total_value",
|
|
251
|
+
period: "day",
|
|
252
|
+
since: formatInTimeZone(startDate, "UTC", "yyyy-MM-dd"),
|
|
253
|
+
until: formatInTimeZone(
|
|
254
|
+
addDays(startDate, 1),
|
|
255
|
+
"UTC",
|
|
256
|
+
"yyyy-MM-dd",
|
|
257
|
+
),
|
|
258
|
+
access_token: this.pageAccessToken,
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
const { data, paging } = response.data;
|
|
264
|
+
|
|
265
|
+
engagementArray.push({
|
|
266
|
+
[formatInTimeZone(addDays(startDate, index), "UTC", "yyyy-MM-dd")]:
|
|
267
|
+
Number(data?.[0]?.total_value?.value || 0),
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
next = paging?.next;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return engagementArray;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Meta } from "../meta";
|
|
2
|
+
import { AdMetrics, AdMetricsResponse } from "../../interfaces/meta-response";
|
|
3
|
+
import { addDays } from "date-fns";
|
|
4
|
+
import { ConstructorMkt } from "../../interfaces/meta-mkt";
|
|
5
|
+
import { formatInTimeZone } from "date-fns-tz";
|
|
6
|
+
|
|
7
|
+
export class MktInsights extends Meta {
|
|
8
|
+
protected readonly adAAccountId: string;
|
|
9
|
+
|
|
10
|
+
constructor(constructorMkt: ConstructorMkt) {
|
|
11
|
+
super(constructorMkt);
|
|
12
|
+
this.adAAccountId = constructorMkt.adAAccountId;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
private generateSinceAndUntil(startDate: Date, endDate: Date) {
|
|
16
|
+
return {
|
|
17
|
+
time_range: {
|
|
18
|
+
since: formatInTimeZone(startDate, "UTC", "yyyy-MM-dd"),
|
|
19
|
+
until: formatInTimeZone(endDate, "UTC", "yyyy-MM-dd"),
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public async getDayPaidReaches(
|
|
25
|
+
startDate: Date,
|
|
26
|
+
endDate: Date,
|
|
27
|
+
platform: string,
|
|
28
|
+
) {
|
|
29
|
+
const reachArray: AdMetrics[] = [];
|
|
30
|
+
let afterCursor: string | undefined = undefined;
|
|
31
|
+
let hasNextPage = true;
|
|
32
|
+
|
|
33
|
+
while (hasNextPage) {
|
|
34
|
+
const response = await this.api.get<AdMetricsResponse>(
|
|
35
|
+
`/${this.adAAccountId}/insights`,
|
|
36
|
+
{
|
|
37
|
+
params: {
|
|
38
|
+
...this.generateSinceAndUntil(startDate, endDate),
|
|
39
|
+
time_increment: 1,
|
|
40
|
+
fields: "reach",
|
|
41
|
+
breakdowns: "publisher_platform",
|
|
42
|
+
access_token: this.pageAccessToken,
|
|
43
|
+
filtering: [
|
|
44
|
+
{
|
|
45
|
+
field: "publisher_platform",
|
|
46
|
+
operator: "IN",
|
|
47
|
+
value: [platform],
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
after: afterCursor,
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const { data, paging } = response.data;
|
|
56
|
+
|
|
57
|
+
reachArray.push(...data);
|
|
58
|
+
|
|
59
|
+
afterCursor = paging?.cursors?.after;
|
|
60
|
+
hasNextPage = Boolean(afterCursor);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return reachArray.map((value, index) => ({
|
|
64
|
+
[formatInTimeZone(addDays(startDate, index), "UTC", "yyyy-MM-dd")]:
|
|
65
|
+
Number(value.reach || 0),
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { ConstructorPage } from "../../interfaces/page-publish";
|
|
2
|
+
import {
|
|
3
|
+
GetInsightsResponse,
|
|
4
|
+
GetFollowersCountResponseCurrent,
|
|
5
|
+
GetInsightsPageActionsPostReactionsTotalResponse,
|
|
6
|
+
PostComment,
|
|
7
|
+
GetPostCommentsResponse,
|
|
8
|
+
} from "../../interfaces/meta-response";
|
|
9
|
+
import { addDays, endOfDay, isSameDay, startOfDay, subDays } from "date-fns";
|
|
10
|
+
import { formatInTimeZone, toZonedTime } from "date-fns-tz";
|
|
11
|
+
import { PageComments } from "../comments/page-comments";
|
|
12
|
+
|
|
13
|
+
export class PageInsights extends PageComments {
|
|
14
|
+
constructor(constructorPage: ConstructorPage) {
|
|
15
|
+
super(constructorPage);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
private splitArrayPromises(
|
|
19
|
+
arrayPromises: (() => Promise<void>)[],
|
|
20
|
+
size: number,
|
|
21
|
+
) {
|
|
22
|
+
const arrayPromisesSplited: (() => Promise<void>)[][] = [];
|
|
23
|
+
|
|
24
|
+
for (let i = 0; i < arrayPromises.length; i += size) {
|
|
25
|
+
arrayPromisesSplited.push(arrayPromises.slice(i, i + size));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return arrayPromisesSplited;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private generateSinceAndUntil(startDate: Date, endDate: Date) {
|
|
32
|
+
const nextDay = addDays(endDate, 1);
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
since: formatInTimeZone(startDate, "UTC", "yyyy-MM-dd"),
|
|
36
|
+
until: formatInTimeZone(nextDay, "UTC", "yyyy-MM-dd"),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public async getFollowersCountCurrent() {
|
|
41
|
+
return (
|
|
42
|
+
await this.api.get<GetFollowersCountResponseCurrent>(`/${this.pageId}`, {
|
|
43
|
+
params: {
|
|
44
|
+
fields: "followers_count",
|
|
45
|
+
access_token: this.pageAccessToken,
|
|
46
|
+
},
|
|
47
|
+
})
|
|
48
|
+
).data.followers_count;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public async getDayTotalFollowersByDateInterval(
|
|
52
|
+
startDate: Date,
|
|
53
|
+
endDate: Date,
|
|
54
|
+
) {
|
|
55
|
+
return (
|
|
56
|
+
await this.api.get<GetInsightsResponse>(`/${this.pageId}/insights`, {
|
|
57
|
+
params: {
|
|
58
|
+
metric: "page_follows",
|
|
59
|
+
period: "day",
|
|
60
|
+
...this.generateSinceAndUntil(startDate, endDate),
|
|
61
|
+
access_token: this.pageAccessToken,
|
|
62
|
+
},
|
|
63
|
+
})
|
|
64
|
+
).data.data[0].values.map((value, index) => ({
|
|
65
|
+
[formatInTimeZone(addDays(startDate, index), "UTC", "yyyy-MM-dd")]:
|
|
66
|
+
value.value,
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public async getDayFollowersByDateInterval(startDate: Date, endDate: Date) {
|
|
71
|
+
return (
|
|
72
|
+
await this.api.get<GetInsightsResponse>(`/${this.pageId}/insights`, {
|
|
73
|
+
params: {
|
|
74
|
+
metric: "page_daily_follows_unique",
|
|
75
|
+
period: "day",
|
|
76
|
+
...this.generateSinceAndUntil(startDate, endDate),
|
|
77
|
+
access_token: this.pageAccessToken,
|
|
78
|
+
},
|
|
79
|
+
})
|
|
80
|
+
).data.data[0].values.map((value, index) => ({
|
|
81
|
+
[formatInTimeZone(addDays(startDate, index), "UTC", "yyyy-MM-dd")]:
|
|
82
|
+
value.value,
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
public async getDayUnFollowersByDateInterval(startDate: Date, endDate: Date) {
|
|
87
|
+
return (
|
|
88
|
+
await this.api.get<GetInsightsResponse>(`/${this.pageId}/insights`, {
|
|
89
|
+
params: {
|
|
90
|
+
metric: "page_daily_unfollows_unique",
|
|
91
|
+
period: "day",
|
|
92
|
+
...this.generateSinceAndUntil(startDate, endDate),
|
|
93
|
+
access_token: this.pageAccessToken,
|
|
94
|
+
},
|
|
95
|
+
})
|
|
96
|
+
).data.data[0].values.map((value, index) => ({
|
|
97
|
+
[formatInTimeZone(addDays(startDate, index), "UTC", "yyyy-MM-dd")]:
|
|
98
|
+
value.value,
|
|
99
|
+
}));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
public async getDayAllImpressions(startDate: Date, endDate: Date) {
|
|
103
|
+
return (
|
|
104
|
+
await this.api.get<GetInsightsResponse>(`/${this.pageId}/insights`, {
|
|
105
|
+
params: {
|
|
106
|
+
metric: "page_impressions",
|
|
107
|
+
period: "day",
|
|
108
|
+
...this.generateSinceAndUntil(startDate, endDate),
|
|
109
|
+
access_token: this.pageAccessToken,
|
|
110
|
+
},
|
|
111
|
+
})
|
|
112
|
+
).data.data[0].values.map((value, index) => ({
|
|
113
|
+
[formatInTimeZone(addDays(startDate, index), "UTC", "yyyy-MM-dd")]:
|
|
114
|
+
value.value,
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
public async getDayAllImpressionsUnique(startDate: Date, endDate: Date) {
|
|
119
|
+
return (
|
|
120
|
+
await this.api.get<GetInsightsResponse>(`/${this.pageId}/insights`, {
|
|
121
|
+
params: {
|
|
122
|
+
metric: "page_impressions_unique",
|
|
123
|
+
period: "day",
|
|
124
|
+
...this.generateSinceAndUntil(startDate, endDate),
|
|
125
|
+
access_token: this.pageAccessToken,
|
|
126
|
+
},
|
|
127
|
+
})
|
|
128
|
+
).data.data[0].values.map((value, index) => ({
|
|
129
|
+
[formatInTimeZone(addDays(startDate, index), "UTC", "yyyy-MM-dd")]:
|
|
130
|
+
value.value,
|
|
131
|
+
}));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
public async getDayPaidImpressionsUnique(startDate: Date, endDate: Date) {
|
|
135
|
+
return (
|
|
136
|
+
await this.api.get<GetInsightsResponse>(`/${this.pageId}/insights`, {
|
|
137
|
+
params: {
|
|
138
|
+
metric: "page_impressions_paid_unique",
|
|
139
|
+
period: "day",
|
|
140
|
+
...this.generateSinceAndUntil(startDate, endDate),
|
|
141
|
+
access_token: this.pageAccessToken,
|
|
142
|
+
},
|
|
143
|
+
})
|
|
144
|
+
).data.data[0].values.map((value, index) => ({
|
|
145
|
+
[formatInTimeZone(addDays(startDate, index), "UTC", "yyyy-MM-dd")]:
|
|
146
|
+
value.value,
|
|
147
|
+
}));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
public async getDayAllLikesTypesInAllPosts(startDate: Date, endDate: Date) {
|
|
151
|
+
const response =
|
|
152
|
+
await this.api.get<GetInsightsPageActionsPostReactionsTotalResponse>(
|
|
153
|
+
`/${this.pageId}/insights/page_actions_post_reactions_total`,
|
|
154
|
+
{
|
|
155
|
+
params: {
|
|
156
|
+
period: "day",
|
|
157
|
+
...this.generateSinceAndUntil(startDate, endDate),
|
|
158
|
+
access_token: this.pageAccessToken,
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
return response.data.data[0].values.map((value, index) => ({
|
|
164
|
+
[formatInTimeZone(addDays(startDate, index), "UTC", "yyyy-MM-dd")]:
|
|
165
|
+
(value?.value.anger || 0) +
|
|
166
|
+
(value?.value.haha || 0) +
|
|
167
|
+
(value?.value.like || 0) +
|
|
168
|
+
(value?.value.love || 0) +
|
|
169
|
+
(value?.value.sorry || 0) +
|
|
170
|
+
(value?.value.wow || 0),
|
|
171
|
+
}));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
public async getTotalAllLikesTypesInAllPosts(startDate: Date, endDate: Date) {
|
|
175
|
+
const values = await this.getDayAllLikesTypesInAllPosts(startDate, endDate);
|
|
176
|
+
|
|
177
|
+
return values.reduce((acc, value) => acc + Object.values(value)[0], 0);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
public async getDayAllCommentsInAllPosts(startDate: Date, endDate: Date) {
|
|
181
|
+
startDate = startOfDay(toZonedTime(startDate, "UTC"));
|
|
182
|
+
endDate = endOfDay(toZonedTime(endDate, "UTC"));
|
|
183
|
+
|
|
184
|
+
const allIds = (await this.getAllPosts()).map((post) => post.id);
|
|
185
|
+
|
|
186
|
+
const values: PostComment[] = [];
|
|
187
|
+
|
|
188
|
+
const arrayPromises = allIds.map((id) => {
|
|
189
|
+
return async () => {
|
|
190
|
+
let nextUrl = `${this.api.getUri()}/${id}/comments?order=reverse_chronological&access_token=${this.pageAccessToken}`;
|
|
191
|
+
|
|
192
|
+
while (nextUrl) {
|
|
193
|
+
const response = (await (
|
|
194
|
+
await fetch(nextUrl)
|
|
195
|
+
).json()) as GetPostCommentsResponse;
|
|
196
|
+
|
|
197
|
+
values.push(
|
|
198
|
+
...response.data.filter((value) => {
|
|
199
|
+
const date = new Date(value.created_time);
|
|
200
|
+
|
|
201
|
+
return date >= startDate && date <= endDate;
|
|
202
|
+
}),
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
const isValidNext =
|
|
206
|
+
response.paging?.next && this.isValidUrl(response.paging.next);
|
|
207
|
+
|
|
208
|
+
const lastObjectDate = response.data[response.data.length - 1]
|
|
209
|
+
?.created_time
|
|
210
|
+
? new Date(response.data[response.data.length - 1].created_time)
|
|
211
|
+
: null;
|
|
212
|
+
|
|
213
|
+
if (
|
|
214
|
+
!isValidNext ||
|
|
215
|
+
!response.data.length ||
|
|
216
|
+
(lastObjectDate >= startDate && lastObjectDate <= endDate)
|
|
217
|
+
) {
|
|
218
|
+
nextUrl = "";
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
nextUrl = response.paging.next;
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
const splitArrayPromises = this.splitArrayPromises(arrayPromises, 50);
|
|
228
|
+
|
|
229
|
+
for (const arrayPromises of splitArrayPromises) {
|
|
230
|
+
await Promise.all(arrayPromises.map((promise) => promise()));
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const qtdDays = subDays(endDate, startDate.getDate()).getDate();
|
|
234
|
+
|
|
235
|
+
const valuesNumber: number[] = [];
|
|
236
|
+
|
|
237
|
+
for (let i = 0; i <= qtdDays; i++) {
|
|
238
|
+
const currentDay = addDays(startDate, i);
|
|
239
|
+
|
|
240
|
+
const comments = values.filter((value) => {
|
|
241
|
+
const date = new Date(value.created_time);
|
|
242
|
+
|
|
243
|
+
return isSameDay(date, currentDay);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
valuesNumber.push(comments.length);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return valuesNumber;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
public async getDayEngagementInAllPosts(startDate: Date, endDate: Date) {
|
|
253
|
+
return (
|
|
254
|
+
await this.api.get<GetInsightsResponse>(`/${this.pageId}/insights`, {
|
|
255
|
+
params: {
|
|
256
|
+
metric: "page_post_engagements",
|
|
257
|
+
period: "day",
|
|
258
|
+
...this.generateSinceAndUntil(startDate, endDate),
|
|
259
|
+
access_token: this.pageAccessToken,
|
|
260
|
+
},
|
|
261
|
+
})
|
|
262
|
+
).data.data[0].values.map((value, index) => ({
|
|
263
|
+
[formatInTimeZone(addDays(startDate, index), "UTC", "yyyy-MM-dd")]:
|
|
264
|
+
value.value,
|
|
265
|
+
}));
|
|
266
|
+
}
|
|
267
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ConstructorMain } from "../interfaces/meta";
|
|
2
|
+
import { generateAxiosInstance } from "../utils/api";
|
|
3
|
+
import { AxiosInstance } from "axios";
|
|
4
|
+
import * as fs from "fs";
|
|
5
|
+
import * as path from "path";
|
|
6
|
+
|
|
7
|
+
export class Meta {
|
|
8
|
+
protected readonly pageAccessToken: string;
|
|
9
|
+
protected readonly api: AxiosInstance;
|
|
10
|
+
protected readonly apiVideo: AxiosInstance;
|
|
11
|
+
protected readonly apiIng: AxiosInstance;
|
|
12
|
+
|
|
13
|
+
protected async createTempFolder() {
|
|
14
|
+
await fs.promises.mkdir(path.resolve(__dirname, "..", "temp"), {
|
|
15
|
+
recursive: true,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
constructor({
|
|
20
|
+
pageAccessToken,
|
|
21
|
+
apiVersion,
|
|
22
|
+
isInstagramApi,
|
|
23
|
+
}: ConstructorMain) {
|
|
24
|
+
this.pageAccessToken = pageAccessToken;
|
|
25
|
+
this.api = generateAxiosInstance({
|
|
26
|
+
apiVersion,
|
|
27
|
+
isInstagramApi,
|
|
28
|
+
});
|
|
29
|
+
this.apiVideo = generateAxiosInstance({ apiVersion, isVideoApi: true });
|
|
30
|
+
}
|
|
31
|
+
}
|