diff --git a/apps/backend/src/api/routes/analytics.controller.ts b/apps/backend/src/api/routes/analytics.controller.ts index 1a685174..dbe35036 100644 --- a/apps/backend/src/api/routes/analytics.controller.ts +++ b/apps/backend/src/api/routes/analytics.controller.ts @@ -62,82 +62,6 @@ export class AnalyticsController { @Param('integration') integration: string, @Query('date') date: string ) { - const getIntegration = await this._integrationService.getIntegrationById( - org.id, - integration - ); - - if (!getIntegration) { - throw new Error('Invalid integration'); - } - - if (getIntegration.type !== 'social') { - return {}; - } - - const integrationProvider = this._integrationManager.getSocialIntegration( - getIntegration.providerIdentifier - ); - - if (dayjs(getIntegration?.tokenExpiration).isBefore(dayjs())) { - const { accessToken, expiresIn, refreshToken } = - await integrationProvider.refreshToken(getIntegration.refreshToken!); - - if (accessToken) { - await this._integrationService.createOrUpdateIntegration( - getIntegration.organizationId, - getIntegration.name, - getIntegration.picture!, - 'social', - getIntegration.internalId, - getIntegration.providerIdentifier, - accessToken, - refreshToken, - expiresIn - ); - - getIntegration.token = accessToken; - - if (integrationProvider.refreshWait) { - await timer(10000); - } - } - } - - const getIntegrationData = await ioRedis.get( - `integration:${org.id}:${integration}:${date}` - ); - if (getIntegrationData) { - return JSON.parse(getIntegrationData); - } - - if (integrationProvider.analytics) { - try { - const loadAnalytics = await integrationProvider.analytics( - getIntegration.internalId, - getIntegration.token, - +date - ); - await ioRedis.set( - `integration:${org.id}:${integration}:${date}`, - JSON.stringify(loadAnalytics), - 'EX', - !process.env.NODE_ENV || process.env.NODE_ENV === 'development' - ? 1 - : 3600 - ); - return loadAnalytics; - } catch (e) { - if (e instanceof RefreshToken) { - await this._integrationService.disconnectChannel( - org.id, - getIntegration - ); - return []; - } - } - } - - return []; + return this._integrationService.checkAnalytics(org, integration, date); } } diff --git a/libraries/nestjs-libraries/src/database/prisma/integrations/integration.service.ts b/libraries/nestjs-libraries/src/database/prisma/integrations/integration.service.ts index 111d20d9..5b7fc3ce 100644 --- a/libraries/nestjs-libraries/src/database/prisma/integrations/integration.service.ts +++ b/libraries/nestjs-libraries/src/database/prisma/integrations/integration.service.ts @@ -1,15 +1,26 @@ -import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; +import { + HttpException, + HttpStatus, + Injectable, + Param, + Query, +} 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 { AnalyticsData, SocialProvider } from '@gitroom/nestjs-libraries/integrations/social/social.integrations.interface'; +import { Integration, Organization } 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'; import { simpleUpload } from '@gitroom/nestjs-libraries/upload/r2.uploader'; import axios from 'axios'; import { makeId } from '@gitroom/nestjs-libraries/services/make.is'; +import { GetOrgFromRequest } from '@gitroom/nestjs-libraries/user/org.from.request'; +import dayjs from 'dayjs'; +import { timer } from '@gitroom/helpers/utils/timer'; +import { ioRedis } from '@gitroom/nestjs-libraries/redis/redis.service'; +import { RefreshToken } from '@gitroom/nestjs-libraries/integrations/social.abstract'; @Injectable() export class IntegrationService { @@ -33,7 +44,11 @@ export class IntegrationService { refresh?: string ) { const loadImage = await axios.get(picture, { responseType: 'arraybuffer' }); - const uploadedPicture = await simpleUpload(loadImage.data, `${makeId(10)}.png`, 'image/png'); + const uploadedPicture = await simpleUpload( + loadImage.data, + `${makeId(10)}.png`, + 'image/png' + ); return this._integrationRepository.createOrUpdateIntegration( org, @@ -267,4 +282,80 @@ export class IntegrationService { return { success: true }; } + + async checkAnalytics(org: Organization, integration: string, date: string, forceRefresh = false): Promise { + const getIntegration = await this.getIntegrationById(org.id, integration); + + if (!getIntegration) { + throw new Error('Invalid integration'); + } + + if (getIntegration.type !== 'social') { + return []; + } + + const integrationProvider = this._integrationManager.getSocialIntegration( + getIntegration.providerIdentifier + ); + + if (dayjs(getIntegration?.tokenExpiration).isBefore(dayjs()) || forceRefresh) { + const { accessToken, expiresIn, refreshToken } = + await integrationProvider.refreshToken(getIntegration.refreshToken!); + + if (accessToken) { + await this.createOrUpdateIntegration( + getIntegration.organizationId, + getIntegration.name, + getIntegration.picture!, + 'social', + getIntegration.internalId, + getIntegration.providerIdentifier, + accessToken, + refreshToken, + expiresIn + ); + + getIntegration.token = accessToken; + + if (integrationProvider.refreshWait) { + await timer(10000); + } + } else { + await this.disconnectChannel(org.id, getIntegration); + return []; + } + } + + const getIntegrationData = await ioRedis.get( + `integration:${org.id}:${integration}:${date}` + ); + if (getIntegrationData) { + return JSON.parse(getIntegrationData); + } + + if (integrationProvider.analytics) { + try { + const loadAnalytics = await integrationProvider.analytics( + getIntegration.internalId, + getIntegration.token, + +date + ); + await ioRedis.set( + `integration:${org.id}:${integration}:${date}`, + JSON.stringify(loadAnalytics), + 'EX', + !process.env.NODE_ENV || process.env.NODE_ENV === 'development' + ? 1 + : 3600 + ); + return loadAnalytics; + } catch (e) { + if (e instanceof RefreshToken) { + return this.checkAnalytics(org, integration, date); + } + } + } + + return []; + } }