File size: 4,551 Bytes
ffebaa3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d201b18
ffebaa3
 
 
d201b18
ffebaa3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import {
  Controller,
  Post,
  Delete,
  Get,
  Res,
  UploadedFile,
  UseInterceptors,
  Query,
  BadRequestException,
  HttpStatus,
  HttpCode,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import {
  ApiTags,
  ApiOperation,
  ApiConsumes,
  ApiBody,
  ApiQuery,
  ApiExcludeEndpoint,
} from '@nestjs/swagger';
import type { Response } from 'express';
import { GoogleDriveService } from './google-drive.service';
import { FileTypeEnum } from './enums/file-type.enum';
import { LogToDiscord } from 'src/shared/decorators/log-to-discord.decorator';

@ApiTags('Upload: Google Drive Storage')
@Controller('google-drive')
@LogToDiscord()
export class GoogleDriveController {
  constructor(private readonly googleDriveService: GoogleDriveService) {}

  @Get('oauth2/authorize')
  @ApiExcludeEndpoint()
  async getAuthUrl() {
    return this.googleDriveService.getAuthorizationUrl();
  }

  @Get('oauth2callback')
  @ApiExcludeEndpoint()
  async oauth2Callback(@Query('code') code: string, @Res() res: Response) {
    const result = await this.googleDriveService.handleOAuthCallback(code);
    return res.send(`
        <!DOCTYPE html>
        <html>
        <head>
          <title>Authorization ${result.success ? 'Success' : 'Failed'}</title>
          <style>
            body { font-family: Arial, sans-serif; max-width: 800px; margin: 50px auto; padding: 20px; }
            .success { background: #d4edda; border: 1px solid #c3e6cb; padding: 20px; border-radius: 5px; }
            .error { background: #f8d7da; border: 1px solid #f5c6cb; padding: 20px; border-radius: 5px; }
            code { color: #e83e8c; }
            h1 { color: #28a745; }
            .warning { background: #fff3cd; border: 1px solid #ffc107; padding: 15px; margin: 20px 0; border-radius: 5px; }
          </style>
        </head>
        <body>
          <div class="${result.success ? 'success' : 'error'}">
            <h1>${result.success ? '✅ Authorization Successful!' : '❌ Authorization Failed'}</h1>
            <p>${result.success ? 'Your Google account has been authorized.' : result.error}</p>
          </div>
          ${
            result.success
              ? `
          <h2>🔑 Your Refresh Token:</h2>
          <div class="code-block">
            <code>${result.refreshToken}</code>
          </div>
          <div class="warning">
            <h3>⚠️ IMPORTANT: Save this refresh token!</h3>
            <p>Add to your <code>.env</code> file:</p>
            <div class="code-block">
              <code>GOOGLE_OAUTH2_REFRESH_TOKEN="${result.refreshToken}"</code>
            </div>
          </div>
          <h3>🚀 Next Steps:</h3>
          <ol>
            <li>Copy the refresh token above</li>
            <li>Add it to your <code>.env</code> file</li>
            <li>Restart your application</li>
            <li>Try uploading a file!</li>
          </ol>
          `
              : `<p><a href="/google-drive/oauth2/authorize">Try again</a></p>`
          }
        </body>
        </html>
      `);
  }

  @Post('upload')
  @ApiOperation({ summary: 'Upload file to Google Drive' })
  @ApiConsumes('multipart/form-data')
  @ApiQuery({ name: 'fileType', enum: FileTypeEnum, required: false })
  @ApiQuery({
    name: 'customFilename',
    required: false,
    description: 'Custom filename (optional)',
  })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        file: {
          type: 'string',
          format: 'binary',
        },
      },
    },
  })
  @UseInterceptors(FileInterceptor('file'))
  async uploadFile(
    @UploadedFile() file: any,
    @Query('fileType') fileType?: FileTypeEnum,
    @Query('customFilename') customFilename?: string,
  ) {
    if (!file) {
      throw new BadRequestException('No file uploaded');
    }

    return this.googleDriveService.uploadFile({
      fileBuffer: file.buffer,
      filename: file.originalname,
      fileType: fileType || FileTypeEnum.IMAGE,
      customFilename: customFilename,
      mimetype: file.mimetype,
    });
  }

  @Delete('by-url')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Delete file by public URL' })
  @ApiQuery({
    name: 'url',
    required: true,
    description:
      'Public URL of the file to delete (e.g., https://drive.google.com/uc?id=FILE_ID)',
    type: 'string',
  })
  async deleteFileByUrl(@Query('url') url: string) {
    if (!url) {
      throw new BadRequestException('URL is required');
    }
    return this.googleDriveService.handleFileDelete(url);
  }
}