postiz/libraries/nestjs-libraries/src/database/prisma/integrations/integration.service.ts

264 lines
8.1 KiB
TypeScript

import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { IntegrationRepository } from '@gitroom/nestjs-libraries/database/prisma/integrations/integration.repository';
import { IntegrationManager } from '@gitroom/nestjs-libraries/integrations/integration.manager';
import { InstagramProvider } from '@gitroom/nestjs-libraries/integrations/social/instagram.provider';
import { FacebookProvider } from '@gitroom/nestjs-libraries/integrations/social/facebook.provider';
import { SocialProvider } from '@gitroom/nestjs-libraries/integrations/social/social.integrations.interface';
import { Integration } from '@prisma/client';
import { NotificationService } from '@gitroom/nestjs-libraries/database/prisma/notifications/notification.service';
import { LinkedinPageProvider } from '@gitroom/nestjs-libraries/integrations/social/linkedin.page.provider';
@Injectable()
export class IntegrationService {
constructor(
private _integrationRepository: IntegrationRepository,
private _integrationManager: IntegrationManager,
private _notificationService: NotificationService
) {}
createOrUpdateIntegration(
org: string,
name: string,
picture: string,
type: 'article' | 'social',
internalId: string,
provider: string,
token: string,
refreshToken = '',
expiresIn?: number,
username?: string,
isBetweenSteps = false,
refresh?: string
) {
return this._integrationRepository.createOrUpdateIntegration(
org,
name,
picture,
type,
internalId,
provider,
token,
refreshToken,
expiresIn,
username,
isBetweenSteps,
refresh
);
}
getIntegrationsList(org: string) {
return this._integrationRepository.getIntegrationsList(org);
}
getIntegrationForOrder(id: string, order: string, user: string, org: string) {
return this._integrationRepository.getIntegrationForOrder(
id,
order,
user,
org
);
}
getIntegrationById(org: string, id: string) {
return this._integrationRepository.getIntegrationById(org, id);
}
async refreshToken(provider: SocialProvider, refresh: string) {
try {
const { refreshToken, accessToken, expiresIn } =
await provider.refreshToken(refresh);
if (!refreshToken || !accessToken || !expiresIn) {
return false;
}
return { refreshToken, accessToken, expiresIn };
} catch (e) {
return false;
}
}
async informAboutRefreshError(orgId: string, integration: Integration) {
await this._notificationService.inAppNotification(
orgId,
`Could not refresh your ${integration.providerIdentifier} channel`,
`Could not refresh your ${integration.providerIdentifier} channel. Please go back to the system and connect it again ${process.env.FRONTEND_URL}/launches`,
true
);
}
async refreshNeeded(org: string, id: string) {
return this._integrationRepository.refreshNeeded(org, id);
}
async refreshTokens() {
const integrations = await this._integrationRepository.needsToBeRefreshed();
for (const integration of integrations) {
const provider = this._integrationManager.getSocialIntegration(
integration.providerIdentifier
);
const data = await this.refreshToken(provider, integration.refreshToken!);
if (!data) {
await this.informAboutRefreshError(
integration.organizationId,
integration
);
await this._integrationRepository.refreshNeeded(
integration.organizationId,
integration.id
);
return;
}
const { refreshToken, accessToken, expiresIn } = data;
await this.createOrUpdateIntegration(
integration.organizationId,
integration.name,
integration.picture!,
'social',
integration.internalId,
integration.providerIdentifier,
accessToken,
refreshToken,
expiresIn
);
}
}
async disableChannel(org: string, id: string) {
return this._integrationRepository.disableChannel(org, id);
}
async enableChannel(org: string, totalChannels: number, id: string) {
const integrations = (
await this._integrationRepository.getIntegrationsList(org)
).filter((f) => !f.disabled);
if (integrations.length >= totalChannels) {
throw new Error('You have reached the maximum number of channels');
}
return this._integrationRepository.enableChannel(org, id);
}
async deleteChannel(org: string, id: string) {
const isTherePosts = await this._integrationRepository.countPostsForChannel(
org,
id
);
if (isTherePosts) {
throw new HttpException(
'There are posts for this channel',
HttpStatus.NOT_ACCEPTABLE
);
}
return this._integrationRepository.deleteChannel(org, id);
}
async disableIntegrations(org: string, totalChannels: number) {
return this._integrationRepository.disableIntegrations(org, totalChannels);
}
async checkForDeletedOnceAndUpdate(org: string, page: string) {
return this._integrationRepository.checkForDeletedOnceAndUpdate(org, page);
}
async saveInstagram(
org: string,
id: string,
data: { pageId: string; id: string }
) {
const getIntegration = await this._integrationRepository.getIntegrationById(
org,
id
);
if (getIntegration && !getIntegration.inBetweenSteps) {
throw new HttpException('Invalid request', HttpStatus.BAD_REQUEST);
}
const instagram = this._integrationManager.getSocialIntegration(
'instagram'
) as InstagramProvider;
const getIntegrationInformation = await instagram.fetchPageInformation(
getIntegration?.token!,
data
);
await this.checkForDeletedOnceAndUpdate(org, getIntegrationInformation.id);
await this._integrationRepository.updateIntegration(id, {
picture: getIntegrationInformation.picture,
internalId: getIntegrationInformation.id,
name: getIntegrationInformation.name,
inBetweenSteps: false,
token: getIntegrationInformation.access_token,
profile: getIntegrationInformation.username,
});
return { success: true };
}
async saveLinkedin(org: string, id: string, page: string) {
const getIntegration = await this._integrationRepository.getIntegrationById(
org,
id
);
if (getIntegration && !getIntegration.inBetweenSteps) {
throw new HttpException('Invalid request', HttpStatus.BAD_REQUEST);
}
const linkedin = this._integrationManager.getSocialIntegration(
'linkedin-page'
) as LinkedinPageProvider;
const getIntegrationInformation = await linkedin.fetchPageInformation(
getIntegration?.token!,
page
);
await this.checkForDeletedOnceAndUpdate(org, String(getIntegrationInformation.id));
await this._integrationRepository.updateIntegration(String(id), {
picture: getIntegrationInformation.picture,
internalId: String(getIntegrationInformation.id),
name: getIntegrationInformation.name,
inBetweenSteps: false,
token: getIntegrationInformation.access_token,
profile: getIntegrationInformation.username,
});
return { success: true };
}
async saveFacebook(org: string, id: string, page: string) {
const getIntegration = await this._integrationRepository.getIntegrationById(
org,
id
);
if (getIntegration && !getIntegration.inBetweenSteps) {
throw new HttpException('Invalid request', HttpStatus.BAD_REQUEST);
}
const facebook = this._integrationManager.getSocialIntegration(
'facebook'
) as FacebookProvider;
const getIntegrationInformation = await facebook.fetchPageInformation(
getIntegration?.token!,
page
);
await this.checkForDeletedOnceAndUpdate(org, getIntegrationInformation.id);
await this._integrationRepository.updateIntegration(id, {
picture: getIntegrationInformation.picture,
internalId: getIntegrationInformation.id,
name: getIntegrationInformation.name,
inBetweenSteps: false,
token: getIntegrationInformation.access_token,
profile: getIntegrationInformation.username,
});
return { success: true };
}
}