Add workspacePreQueryHook module (#3879)
* rebase * reorganise messaging folders * fix * fix after review * fix yarn lock
This commit is contained in:
@ -0,0 +1,10 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { CreateCompanyService } from 'src/workspace/messaging/services/create-company/create-company.service';
|
||||
|
||||
@Module({
|
||||
imports: [],
|
||||
providers: [CreateCompanyService],
|
||||
exports: [CreateCompanyService],
|
||||
})
|
||||
export class CreateCompanyModule {}
|
||||
@ -0,0 +1,106 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { EntityManager } from 'typeorm';
|
||||
import axios, { AxiosInstance } from 'axios';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { DataSourceEntity } from 'src/metadata/data-source/data-source.entity';
|
||||
import { capitalize } from 'src/utils/capitalize';
|
||||
@Injectable()
|
||||
export class CreateCompanyService {
|
||||
private readonly httpService: AxiosInstance;
|
||||
|
||||
constructor() {
|
||||
this.httpService = axios.create({
|
||||
baseURL: 'https://companies.twenty.com',
|
||||
});
|
||||
}
|
||||
|
||||
async createCompanies(
|
||||
domainNames: string[],
|
||||
dataSourceMetadata: DataSourceEntity,
|
||||
manager: EntityManager,
|
||||
): Promise<{
|
||||
[domainName: string]: string;
|
||||
}> {
|
||||
const uniqueDomainNames = [...new Set(domainNames)];
|
||||
|
||||
const existingCompanies = await manager.query(
|
||||
`SELECT id, "domainName" FROM ${dataSourceMetadata.schema}.company WHERE "domainName" = ANY($1)`,
|
||||
[uniqueDomainNames],
|
||||
);
|
||||
|
||||
const companiesObject = existingCompanies.reduce(
|
||||
(
|
||||
acc: {
|
||||
[domainName: string]: string;
|
||||
},
|
||||
company: {
|
||||
domainName: string;
|
||||
id: string;
|
||||
},
|
||||
) => ({
|
||||
...acc,
|
||||
[company.domainName]: company.id,
|
||||
}),
|
||||
{},
|
||||
);
|
||||
|
||||
const filteredDomainNames = uniqueDomainNames.filter(
|
||||
(domainName) =>
|
||||
!existingCompanies.some(
|
||||
(company: { domainName: string }) =>
|
||||
company.domainName === domainName,
|
||||
),
|
||||
);
|
||||
|
||||
for (const domainName of filteredDomainNames) {
|
||||
companiesObject[domainName] = await this.createCompany(
|
||||
domainName,
|
||||
dataSourceMetadata,
|
||||
manager,
|
||||
);
|
||||
}
|
||||
|
||||
return companiesObject;
|
||||
}
|
||||
|
||||
async createCompany(
|
||||
domainName: string,
|
||||
dataSourceMetadata: DataSourceEntity,
|
||||
manager: EntityManager,
|
||||
): Promise<string> {
|
||||
const companyId = v4();
|
||||
|
||||
const { name, city } = await this.getCompanyInfoFromDomainName(domainName);
|
||||
|
||||
await manager.query(
|
||||
`INSERT INTO ${dataSourceMetadata.schema}.company (id, name, "domainName", address)
|
||||
VALUES ($1, $2, $3, $4)`,
|
||||
[companyId, name, domainName, city],
|
||||
);
|
||||
|
||||
return companyId;
|
||||
}
|
||||
|
||||
async getCompanyInfoFromDomainName(domainName: string): Promise<{
|
||||
name: string;
|
||||
city: string;
|
||||
}> {
|
||||
try {
|
||||
const response = await this.httpService.get(`/${domainName}`);
|
||||
|
||||
const data = response.data;
|
||||
|
||||
return {
|
||||
name: data.name,
|
||||
city: data.city,
|
||||
};
|
||||
} catch (e) {
|
||||
return {
|
||||
name: capitalize(domainName.split('.')[0]),
|
||||
city: '',
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { CreateContactService } from 'src/workspace/messaging/services/create-contact/create-contact.service';
|
||||
|
||||
@Module({
|
||||
imports: [],
|
||||
providers: [CreateContactService],
|
||||
exports: [CreateContactService],
|
||||
})
|
||||
export class CreateContactModule {}
|
||||
@ -0,0 +1,88 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { EntityManager } from 'typeorm';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { DataSourceEntity } from 'src/metadata/data-source/data-source.entity';
|
||||
import { capitalize } from 'src/utils/capitalize';
|
||||
|
||||
type ContactToCreate = {
|
||||
handle: string;
|
||||
displayName: string;
|
||||
companyId: string;
|
||||
};
|
||||
|
||||
type FormattedContactToCreate = {
|
||||
id: string;
|
||||
handle: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
companyId: string;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class CreateContactService {
|
||||
constructor() {}
|
||||
|
||||
formatContacts(
|
||||
contactsToCreate: ContactToCreate[],
|
||||
): FormattedContactToCreate[] {
|
||||
return contactsToCreate.map((contact) => {
|
||||
const { handle, displayName, companyId } = contact;
|
||||
|
||||
const contactFirstName = displayName.split(' ')[0];
|
||||
const contactLastName = displayName.split(' ')[1];
|
||||
|
||||
const contactFullNameFromHandle = handle.split('@')[0];
|
||||
const contactFirstNameFromHandle =
|
||||
contactFullNameFromHandle.split('.')[0];
|
||||
const contactLastNameFromHandle = contactFullNameFromHandle.split('.')[1];
|
||||
|
||||
const id = v4();
|
||||
|
||||
return {
|
||||
id,
|
||||
handle,
|
||||
firstName: capitalize(
|
||||
contactFirstName || contactFirstNameFromHandle || '',
|
||||
),
|
||||
lastName: capitalize(
|
||||
contactLastName || contactLastNameFromHandle || '',
|
||||
),
|
||||
companyId,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async createContacts(
|
||||
contactsToCreate: ContactToCreate[],
|
||||
dataSourceMetadata: DataSourceEntity,
|
||||
manager: EntityManager,
|
||||
): Promise<void> {
|
||||
if (contactsToCreate.length === 0) return;
|
||||
|
||||
const formattedContacts = this.formatContacts(contactsToCreate);
|
||||
|
||||
const valuesString = formattedContacts
|
||||
.map(
|
||||
(_, index) =>
|
||||
`($${index * 5 + 1}, $${index * 5 + 2}, $${index * 5 + 3}, $${
|
||||
index * 5 + 4
|
||||
}, $${index * 5 + 5})`,
|
||||
)
|
||||
.join(', ');
|
||||
|
||||
await manager.query(
|
||||
`INSERT INTO ${dataSourceMetadata.schema}.person (id, email, "nameFirstName", "nameLastName", "companyId") VALUES ${valuesString}`,
|
||||
formattedContacts
|
||||
.map((contact) => [
|
||||
contact.id,
|
||||
contact.handle,
|
||||
contact.firstName,
|
||||
contact.lastName,
|
||||
contact.companyId,
|
||||
])
|
||||
.flat(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,18 +1,18 @@
|
||||
import { Inject, Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { FetchMessagesByBatchesService } from 'src/workspace/messaging/services/fetch-messages-by-batches.service';
|
||||
import { GmailClientProvider } from 'src/workspace/messaging/providers/gmail/gmail-client.provider';
|
||||
import { GmailClientProvider } from 'src/workspace/messaging/services/providers/gmail/gmail-client.provider';
|
||||
import { MessageQueue } from 'src/integrations/message-queue/message-queue.constants';
|
||||
import { MessageQueueService } from 'src/integrations/message-queue/services/message-queue.service';
|
||||
import {
|
||||
GmailFullSyncJobData,
|
||||
GmailFullSyncJob,
|
||||
} from 'src/workspace/messaging/jobs/gmail-full-sync.job';
|
||||
import { ConnectedAccountService } from 'src/workspace/messaging/connected-account/connected-account.service';
|
||||
import { MessageChannelService } from 'src/workspace/messaging/message-channel/message-channel.service';
|
||||
import { MessageChannelMessageAssociationService } from 'src/workspace/messaging/message-channel-message-association/message-channel-message-association.service';
|
||||
import { ConnectedAccountService } from 'src/workspace/messaging/repositories/connected-account/connected-account.service';
|
||||
import { MessageChannelService } from 'src/workspace/messaging/repositories/message-channel/message-channel.service';
|
||||
import { MessageChannelMessageAssociationService } from 'src/workspace/messaging/repositories/message-channel-message-association/message-channel-message-association.service';
|
||||
import { WorkspaceDataSourceService } from 'src/workspace/workspace-datasource/workspace-datasource.service';
|
||||
import { MessageService } from 'src/workspace/messaging/message/message.service';
|
||||
import { MessageService } from 'src/workspace/messaging/repositories/message/message.service';
|
||||
import { createQueriesFromMessageIds } from 'src/workspace/messaging/utils/create-queries-from-message-ids.util';
|
||||
|
||||
@Injectable()
|
||||
|
||||
@ -3,17 +3,17 @@ import { Inject, Injectable, Logger } from '@nestjs/common';
|
||||
import { gmail_v1 } from 'googleapis';
|
||||
|
||||
import { FetchMessagesByBatchesService } from 'src/workspace/messaging/services/fetch-messages-by-batches.service';
|
||||
import { GmailClientProvider } from 'src/workspace/messaging/providers/gmail/gmail-client.provider';
|
||||
import { GmailClientProvider } from 'src/workspace/messaging/services/providers/gmail/gmail-client.provider';
|
||||
import { MessageQueueService } from 'src/integrations/message-queue/services/message-queue.service';
|
||||
import { MessageQueue } from 'src/integrations/message-queue/message-queue.constants';
|
||||
import {
|
||||
GmailFullSyncJob,
|
||||
GmailFullSyncJobData,
|
||||
} from 'src/workspace/messaging/jobs/gmail-full-sync.job';
|
||||
import { ConnectedAccountService } from 'src/workspace/messaging/connected-account/connected-account.service';
|
||||
import { ConnectedAccountService } from 'src/workspace/messaging/repositories/connected-account/connected-account.service';
|
||||
import { WorkspaceDataSourceService } from 'src/workspace/workspace-datasource/workspace-datasource.service';
|
||||
import { MessageChannelService } from 'src/workspace/messaging/message-channel/message-channel.service';
|
||||
import { MessageService } from 'src/workspace/messaging/message/message.service';
|
||||
import { MessageChannelService } from 'src/workspace/messaging/repositories/message-channel/message-channel.service';
|
||||
import { MessageService } from 'src/workspace/messaging/repositories/message/message.service';
|
||||
import { createQueriesFromMessageIds } from 'src/workspace/messaging/utils/create-queries-from-message-ids.util';
|
||||
|
||||
@Injectable()
|
||||
|
||||
@ -3,7 +3,7 @@ import { Injectable } from '@nestjs/common';
|
||||
import axios from 'axios';
|
||||
|
||||
import { EnvironmentService } from 'src/integrations/environment/environment.service';
|
||||
import { ConnectedAccountService } from 'src/workspace/messaging/connected-account/connected-account.service';
|
||||
import { ConnectedAccountService } from 'src/workspace/messaging/repositories/connected-account/connected-account.service';
|
||||
|
||||
@Injectable()
|
||||
export class GmailRefreshAccessTokenService {
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { OAuth2Client } from 'google-auth-library';
|
||||
import { gmail_v1, google } from 'googleapis';
|
||||
|
||||
import { EnvironmentService } from 'src/integrations/environment/environment.service';
|
||||
|
||||
@Injectable()
|
||||
export class GmailClientProvider {
|
||||
constructor(private readonly environmentService: EnvironmentService) {}
|
||||
|
||||
public async getGmailClient(refreshToken: string): Promise<gmail_v1.Gmail> {
|
||||
const oAuth2Client = await this.getOAuth2Client(refreshToken);
|
||||
|
||||
const gmailClient = google.gmail({
|
||||
version: 'v1',
|
||||
auth: oAuth2Client,
|
||||
});
|
||||
|
||||
return gmailClient;
|
||||
}
|
||||
|
||||
private async getOAuth2Client(refreshToken: string): Promise<OAuth2Client> {
|
||||
const gmailClientId = this.environmentService.getAuthGoogleClientId();
|
||||
const gmailClientSecret =
|
||||
this.environmentService.getAuthGoogleClientSecret();
|
||||
|
||||
const oAuth2Client = new google.auth.OAuth2(
|
||||
gmailClientId,
|
||||
gmailClientSecret,
|
||||
);
|
||||
|
||||
oAuth2Client.setCredentials({
|
||||
refresh_token: refreshToken,
|
||||
});
|
||||
|
||||
return oAuth2Client;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { EnvironmentModule } from 'src/integrations/environment/environment.module';
|
||||
import { GmailClientProvider } from 'src/workspace/messaging/services/providers/gmail/gmail-client.provider';
|
||||
|
||||
@Module({
|
||||
imports: [EnvironmentModule],
|
||||
providers: [GmailClientProvider],
|
||||
exports: [GmailClientProvider],
|
||||
})
|
||||
export class MessagingProvidersModule {}
|
||||
Reference in New Issue
Block a user