se agrego drive correctamente

This commit is contained in:
evenegas
2026-01-07 12:10:45 -06:00
parent 016297760f
commit 2ed657caf2
4 changed files with 146 additions and 39 deletions
+4 -1
View File
@@ -15,6 +15,7 @@ import { StatusModule } from './status/status.module';
import { TipoUsuarioModule } from './tipo-usuario/tipo-usuario.module';
import { UsuarioModule } from './usuario/usuario.module';
import { AuthModule } from './auth/auth.module';
import { DriveModule } from './drive/drive.module';
@Module({
imports: [
@@ -57,8 +58,10 @@ import { AuthModule } from './auth/auth.module';
TipoUsuarioModule,
UsuarioModule,
DriveModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
export class AppModule { }
+87
View File
@@ -0,0 +1,87 @@
// src/drive/drive.controller.ts
import {
BadRequestException,
Body,
Controller,
Delete,
Get,
Param,
Post,
Query,
} from '@nestjs/common';
import { DriveService } from './drive.service';
import * as fs from 'fs';
@Controller('drive-test')
export class DriveController {
constructor(private readonly driveService: DriveService) { }
// ✅ Listar archivos/carpetas
@Get('list')
async list(@Query('pageToken') pageToken?: string) {
return this.driveService.list(pageToken || '');
}
// ✅ Crear carpeta dentro de CARPETA
@Post('mkdir')
async createFolder(@Body('name') name: string) {
if (!name) {
throw new BadRequestException('El nombre es obligatorio');
}
const folderId = await this.driveService.mkDir(name);
return { folderId };
}
// ✅ Obtener carpeta (buscar o crear)
@Get('folder/:numeroCuenta')
async getOrCreateFolder(
@Param('numeroCuenta') numeroCuenta: string,
) {
const folderId = await this.driveService.folder(numeroCuenta);
return { folderId };
}
// ✅ Subir archivo (archivo dummy para pruebas)
@Post('upload')
async uploadFile(
@Body('parent') parent: string,
) {
if (!parent) {
throw new BadRequestException('Parent es obligatorio');
}
// Archivo temporal para prueba
const tempPath = './temp-test.txt';
fs.writeFileSync(tempPath, 'Archivo de prueba DriveService');
const fileId = await this.driveService.uploadFile(
tempPath,
'test-drive.txt',
'text/plain',
parent,
);
return { fileId };
}
// ✅ Mover archivo (update)
@Post('update')
async updateFile(
@Body('fileId') fileId: string,
@Body('addParents') addParents: string,
@Body('removeParents') removeParents: string,
) {
if (!fileId || !addParents || !removeParents) {
throw new BadRequestException('Datos incompletos');
}
return this.driveService.update(fileId, addParents, removeParents);
}
// ✅ Eliminar archivo
@Delete('delete/:fileId')
async deleteFile(@Param('fileId') fileId: string) {
await this.driveService.deleteFile(fileId);
return { message: 'Archivo eliminado correctamente' };
}
}
+3 -2
View File
@@ -1,9 +1,10 @@
// src/drive/drive.module.ts
import { Module } from '@nestjs/common';
import { DriveService } from './drive.service';
import { DriveController } from './drive.controller';
@Module({
controllers: [DriveController],
providers: [DriveService],
exports: [DriveService],
})
export class DriveModule {}
export class DriveModule { }
+52 -36
View File
@@ -1,27 +1,28 @@
// src/drive/drive.service.ts
import { BadRequestException, Injectable, InternalServerErrorException } from '@nestjs/common';
import {
BadRequestException,
Injectable,
InternalServerErrorException,
} from '@nestjs/common';
import { google } from 'googleapis';
import * as fs from 'fs';
import * as path from 'path';
import { error } from 'console';
@Injectable()
export class DriveService {
private SCOPES = ['https://www.googleapis.com/auth/drive'];
private SCOPES = ['https://www.googleapis.com/auth/drive.file'];
private loadCredentials() {
try {
const credenciales = JSON.parse(
fs.readFileSync(path.resolve(process.cwd(), 'cred.json'), 'utf8'),
const oAuth2Client = new google.auth.OAuth2(
process.env.CLIENT_ID,
process.env.CLIENT_SECRET,
);
credenciales.private_key = credenciales.private_key.replace(/\\n/g, '\n');
return new google.auth.JWT({
email: credenciales.client_email,
key: credenciales.private_key,
scopes: this.SCOPES,
oAuth2Client.setCredentials({
refresh_token: process.env.REFRESH_TOKEN,
});
return oAuth2Client;
} catch (err) {
throw new InternalServerErrorException(
'Error al cargar credenciales de Google Drive',
@@ -30,14 +31,14 @@ export class DriveService {
}
async list(pageToken = '') {
const authClient = await this.loadCredentials();
const authClient = this.loadCredentials();
const drive = google.drive({ version: 'v3', auth: authClient });
try {
const res = await drive.files.list({
corpora: 'user',
supportsTeamDrives: true,
includeTeamDriveItems: true,
supportsAllDrives: true,
includeItemsFromAllDrives: true,
spaces: 'drive',
pageSize: 1000,
pageToken,
@@ -53,9 +54,12 @@ export class DriveService {
async deleteFile(fileId: string) {
if (fileId === process.env.CARPETA) {
throw new Error('No se puede eliminar este archivo/carpeta.');
throw new BadRequestException(
'No se puede eliminar este archivo/carpeta.',
);
}
const authClient = await this.loadCredentials();
const authClient = this.loadCredentials();
const drive = google.drive({ version: 'v3', auth: authClient });
try {
@@ -67,14 +71,20 @@ export class DriveService {
}
}
async uploadFile(filePath: string, name: string, mimeType: string, parent: string) {
const authClient = await this.loadCredentials();
async uploadFile(
filePath: string,
name: string,
mimeType: string,
parent: string,
) {
const authClient = this.loadCredentials();
const drive = google.drive({ version: 'v3', auth: authClient });
const requestBody = {
name,
parents: [parent],
};
const media = {
mimeType,
body: fs.createReadStream(filePath),
@@ -85,9 +95,11 @@ export class DriveService {
requestBody,
media,
fields: 'id',
supportsAllDrives: true,
});
fs.unlinkSync(filePath);
return res.data.id;
return res.data.id!;
} catch (err) {
throw new InternalServerErrorException(
'Error al subir archivo: ' + err.message,
@@ -96,37 +108,35 @@ export class DriveService {
}
async mkDir(name: string): Promise<string> {
const authClient = await this.loadCredentials();
const drive = google.drive({ version: 'v3', auth: authClient });
if (!name) {
throw new BadRequestException('Nombre de carpeta inválido');
}
if (!process.env.CARPETA) {
throw new Error()
throw new InternalServerErrorException('CARPETA no configurada');
}
const authClient = this.loadCredentials();
const drive = google.drive({ version: 'v3', auth: authClient });
const requestBody = {
name,
mimeType: 'application/vnd.google-apps.folder',
parents: [process.env.CARPETA],
};
try {
const res = await drive.files.create({
requestBody,
fields: 'id',
supportsAllDrives: true,
});
if (!res.data.id) {
throw new Error()
throw new Error('No se pudo crear la carpeta');
}
return res.data.id;
} catch (err) {
throw new InternalServerErrorException(
'Error al crear carpeta: ' + err.message,
@@ -135,7 +145,7 @@ export class DriveService {
}
async update(fileId: string, addParents: string, removeParents: string) {
const authClient = await this.loadCredentials();
const authClient = this.loadCredentials();
const drive = google.drive({ version: 'v3', auth: authClient });
try {
@@ -143,6 +153,7 @@ export class DriveService {
fileId,
addParents,
removeParents,
supportsAllDrives: true,
});
return res.data;
} catch (err) {
@@ -153,17 +164,23 @@ export class DriveService {
}
async folder(numeroCuenta: string): Promise<string> {
const authClient = await this.loadCredentials();
if (!process.env.CARPETA) {
throw new InternalServerErrorException('CARPETA no configurada');
}
const authClient = this.loadCredentials();
const drive = google.drive({ version: 'v3', auth: authClient });
const res = await drive.files.list({
q: `
mimeType='application/vnd.google-apps.folder'
and name='${numeroCuenta}'
and '${process.env.CARPETA}' in parents
and trashed=false
`,
mimeType='application/vnd.google-apps.folder'
and name='${numeroCuenta}'
and '${process.env.CARPETA}' in parents
and trashed=false
`,
fields: 'files(id, name)',
supportsAllDrives: true,
includeItemsFromAllDrives: true,
});
if (res.data.files?.length) {
@@ -172,5 +189,4 @@ export class DriveService {
return this.mkDir(numeroCuenta);
}
}