feat: plugs
This commit is contained in:
parent
74ad1410c7
commit
d87d83d89b
|
|
@ -12,7 +12,7 @@ export function Plug(params: {
|
|||
validation?: RegExp;
|
||||
}[];
|
||||
}) {
|
||||
return function (target: Object, propertyKey: string | symbol) {
|
||||
return function (target: Object, propertyKey: string | symbol, descriptor: any) {
|
||||
// Retrieve existing metadata or initialize an empty array
|
||||
const existingMetadata = Reflect.getMetadata('custom:plug', target) || [];
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ export class IntegrationRepository {
|
|||
constructor(
|
||||
private _integration: PrismaRepository<'integration'>,
|
||||
private _posts: PrismaRepository<'post'>,
|
||||
private _plugs: PrismaRepository<'plugs'>
|
||||
private _plugs: PrismaRepository<'plugs'>,
|
||||
private _exisingPlugData: PrismaRepository<'exisingPlugData'>
|
||||
) {}
|
||||
|
||||
async setTimes(org: string, id: string, times: IntegrationTimeDto) {
|
||||
|
|
@ -342,8 +343,8 @@ export class IntegrationRepository {
|
|||
data: JSON.stringify(body.fields),
|
||||
},
|
||||
select: {
|
||||
activated: true
|
||||
}
|
||||
activated: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -358,4 +359,34 @@ export class IntegrationRepository {
|
|||
},
|
||||
});
|
||||
}
|
||||
|
||||
async loadExisingData(
|
||||
methodName: string,
|
||||
integrationId: string,
|
||||
id: string[]
|
||||
) {
|
||||
return this._exisingPlugData.model.exisingPlugData.findMany({
|
||||
where: {
|
||||
integrationId,
|
||||
methodName,
|
||||
value: {
|
||||
in: id,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async saveExisingData(
|
||||
methodName: string,
|
||||
integrationId: string,
|
||||
value: string[]
|
||||
) {
|
||||
return this._exisingPlugData.model.exisingPlugData.createMany({
|
||||
data: value.map((p) => ({
|
||||
integrationId,
|
||||
methodName,
|
||||
value: p,
|
||||
})),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import { IntegrationTimeDto } from '@gitroom/nestjs-libraries/dtos/integrations/
|
|||
import { UploadFactory } from '@gitroom/nestjs-libraries/upload/upload.factory';
|
||||
import { PlugDto } from '@gitroom/nestjs-libraries/dtos/plugs/plug.dto';
|
||||
import { BullMqClient } from '@gitroom/nestjs-libraries/bull-mq-transport-new/client';
|
||||
import { difference } from 'lodash';
|
||||
|
||||
@Injectable()
|
||||
export class IntegrationService {
|
||||
|
|
@ -467,6 +468,12 @@ export class IntegrationService {
|
|||
return { id };
|
||||
}
|
||||
|
||||
async loadExisingData (methodName: string, integrationId: string, id: string[]) {
|
||||
const exisingData = await this._integrationRepository.loadExisingData(methodName, integrationId, id);
|
||||
const loadOnlyIds = exisingData.map(p => p.value);
|
||||
return difference(id, loadOnlyIds);
|
||||
}
|
||||
|
||||
async startPlug(data: {
|
||||
orgId: string;
|
||||
integrationId: string;
|
||||
|
|
@ -503,6 +510,7 @@ export class IntegrationService {
|
|||
);
|
||||
|
||||
// @ts-ignore
|
||||
return integrationInstance[data.funcName](integration, plugData);
|
||||
const ids = await integrationInstance[data.funcName](integration, plugData, this.loadExisingData.bind(this));
|
||||
return this._integrationRepository.saveExisingData(data.funcName, data.integrationId, ids);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -266,6 +266,7 @@ model Integration {
|
|||
postingTimes String @default("[{\"time\":120}, {\"time\":400}, {\"time\":700}]")
|
||||
customInstanceDetails String?
|
||||
plugs Plugs[]
|
||||
exisingPlugData ExisingPlugData[]
|
||||
|
||||
@@index([updatedAt])
|
||||
@@index([deletedAt])
|
||||
|
|
@ -455,6 +456,16 @@ model Plugs {
|
|||
@@index([organizationId])
|
||||
}
|
||||
|
||||
model ExisingPlugData {
|
||||
id String @id @default(uuid())
|
||||
integrationId String
|
||||
integration Integration @relation(fields: [integrationId], references: [id])
|
||||
methodName String
|
||||
value String
|
||||
|
||||
@@unique([integrationId, methodName, value])
|
||||
}
|
||||
|
||||
enum OrderStatus {
|
||||
PENDING
|
||||
ACCEPTED
|
||||
|
|
|
|||
|
|
@ -111,7 +111,6 @@ export class LinkedinPageProvider
|
|||
)
|
||||
).json();
|
||||
|
||||
console.log(all);
|
||||
return (elements || []).map((e: any) => ({
|
||||
id: e.organizationalTarget.split(':').pop(),
|
||||
page: e.organizationalTarget.split(':').pop(),
|
||||
|
|
@ -366,7 +365,7 @@ export class LinkedinPageProvider
|
|||
@Plug({
|
||||
title: 'Auto Repost Posts',
|
||||
description:
|
||||
'When a post reached a certain number of likes, repost it to increase engagement',
|
||||
'When a post reached a certain number of likes, repost it to increase engagement (1 week old posts)',
|
||||
runEveryMilliseconds: 7200000,
|
||||
fields: [
|
||||
{
|
||||
|
|
@ -378,24 +377,109 @@ export class LinkedinPageProvider
|
|||
},
|
||||
],
|
||||
})
|
||||
async autoAddPost(integration: Integration, fields: { likesAmount: number }) {
|
||||
const a = await fetch(
|
||||
`https://api.linkedin.com/rest/posts?author=${encodeURIComponent(
|
||||
`urn:li:organization:${integration.internalId}`
|
||||
)}&q=author&count=10&sortBy=LAST_MODIFIED`,
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'X-Restli-Protocol-Version': '2.0.0',
|
||||
'Content-Type': 'application/json',
|
||||
'LinkedIn-Version': '202402',
|
||||
Authorization: `Bearer ${integration.token}`,
|
||||
},
|
||||
}
|
||||
async autoRepostPost(
|
||||
integration: Integration,
|
||||
fields: { likesAmount: number },
|
||||
loadExisingData: (
|
||||
methodName: string,
|
||||
integrationId: string,
|
||||
id: string[]
|
||||
) => Promise<string[]>
|
||||
) {
|
||||
const all = await // const { elements } = await (
|
||||
(
|
||||
await this.fetch(
|
||||
`https://api.linkedin.com/rest/posts?author=${encodeURIComponent(
|
||||
`urn:li:organization:${integration.internalId}`
|
||||
)}&q=author&count=10&sortBy=LAST_MODIFIED`,
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'X-Restli-Protocol-Version': '2.0.0',
|
||||
'Content-Type': 'application/json',
|
||||
'LinkedIn-Version': '202402',
|
||||
Authorization: `Bearer ${integration.token}`,
|
||||
},
|
||||
}
|
||||
)
|
||||
).json();
|
||||
|
||||
// only post published in the last week
|
||||
const lastWeekPosts = all.elements.filter((element: any) => {
|
||||
const postDate = new Date(element.publishedAt).getTime();
|
||||
const weekAgo = new Date().getTime() - 604800000;
|
||||
return postDate > weekAgo;
|
||||
});
|
||||
|
||||
const getLastFiveLikes = await Promise.all(
|
||||
lastWeekPosts.map(async (element: any) => {
|
||||
const {
|
||||
likesSummary: { totalLikes },
|
||||
} = await (
|
||||
await this.fetch(
|
||||
`https://api.linkedin.com/v2/socialActions/${encodeURIComponent(
|
||||
element.id
|
||||
)}`,
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'X-Restli-Protocol-Version': '2.0.0',
|
||||
'Content-Type': 'application/json',
|
||||
'LinkedIn-Version': '202402',
|
||||
Authorization: `Bearer ${integration.token}`,
|
||||
},
|
||||
}
|
||||
)
|
||||
).json();
|
||||
|
||||
return { id: element.id, totalLikes };
|
||||
})
|
||||
);
|
||||
|
||||
console.log(await a.json());
|
||||
return;
|
||||
const findLikes = getLastFiveLikes.filter(
|
||||
(element) => element.totalLikes >= fields.likesAmount
|
||||
);
|
||||
|
||||
if (findLikes.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const checkIfAlreadyPosted = await loadExisingData(
|
||||
'autoRepostPost',
|
||||
integration.id,
|
||||
findLikes.map((p) => p.id)
|
||||
);
|
||||
|
||||
if (checkIfAlreadyPosted.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
await this.fetch(`https://api.linkedin.com/rest/posts`, {
|
||||
body: JSON.stringify({
|
||||
author: `urn:li:organization:${integration.internalId}`,
|
||||
commentary: '',
|
||||
visibility: 'PUBLIC',
|
||||
distribution: {
|
||||
feedDistribution: 'MAIN_FEED',
|
||||
targetEntities: [],
|
||||
thirdPartyDistributionChannels: [],
|
||||
},
|
||||
lifecycleState: 'PUBLISHED',
|
||||
isReshareDisabledByAuthor: false,
|
||||
reshareContext: {
|
||||
parent: checkIfAlreadyPosted[0],
|
||||
},
|
||||
}),
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Restli-Protocol-Version': '2.0.0',
|
||||
'Content-Type': 'application/json',
|
||||
'LinkedIn-Version': '202402',
|
||||
Authorization: `Bearer ${integration.token}`,
|
||||
},
|
||||
});
|
||||
|
||||
return [checkIfAlreadyPosted[0]];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue