File size: 5,135 Bytes
4865997
 
 
 
 
 
 
 
 
 
fdb7ab1
4865997
 
fdb7ab1
 
 
4865997
 
 
fdb7ab1
4865997
fdb7ab1
 
a835a2e
fdb7ab1
9f45509
fdb7ab1
9f45509
fdb7ab1
4865997
 
 
 
a835a2e
 
 
 
 
 
 
 
 
 
 
 
 
 
3f6b45b
 
 
 
 
 
 
577130b
 
 
 
 
 
 
 
 
 
 
fdb7ab1
4865997
 
 
fdb7ab1
 
a835a2e
fdb7ab1
4865997
 
 
 
 
a835a2e
fdb7ab1
4865997
a835a2e
4865997
 
a835a2e
 
 
 
 
 
 
9f45509
4865997
 
fdb7ab1
 
a835a2e
fdb7ab1
 
4865997
fdb7ab1
9f45509
4865997
a835a2e
4865997
fdb7ab1
4865997
 
 
 
fdb7ab1
 
4e2a4d3
a835a2e
4e2a4d3
fdb7ab1
 
4e2a4d3
fdb7ab1
4e2a4d3
 
 
 
fdb7ab1
 
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
require('dotenv').config();
const express = require('express');
const multer = require('multer');
const { google } = require('googleapis');
const fs = require('fs');
const cors = require('cors');

const app = express();
const upload = multer({ dest: 'uploads/' });

app.use(cors({ origin: '*', credentials: true, allowedHeaders: ['Content-Type', 'Authorization', 'x-refresh-token'] }));
app.use(express.json());

const GOOGLE_CLIENT_ID = process.env.GOOGLE_CLIENT_ID;
const GOOGLE_CLIENT_SECRET = process.env.GOOGLE_CLIENT_SECRET;
const REDIRECT_URI = process.env.REDIRECT_URI;

let adminRefreshToken = null;

const oauth2Client = new google.auth.OAuth2(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, REDIRECT_URI);

async function getAccessToken(req) {
    if (!adminRefreshToken && req && req.headers['x-refresh-token']) {
        console.log('Restoring session from client header...');
        adminRefreshToken = req.headers['x-refresh-token'];
    }
    if (!adminRefreshToken) throw new Error('Chưa đăng nhập Admin (Session expired)');
    
    oauth2Client.setCredentials({ refresh_token: adminRefreshToken });
    const { credentials } = await oauth2Client.refreshAccessToken();
    return credentials.access_token;
}

// Hàm Tìm hoặc Tạo Folder (Đã khôi phục)
async function findOrCreateFolder(drive, name, parentId = 'root') {
    const q = `mimeType='application/vnd.google-apps.folder' and name='${name}' and '${parentId}' in parents and trashed=false`;
    const res = await drive.files.list({ q, fields: 'files(id, name)' });
    
    if (res.data.files.length > 0) return res.data.files[0];

    const folder = await drive.files.create({
        resource: { name, mimeType: 'application/vnd.google-apps.folder', parents: [parentId] },
        fields: 'id, name'
    });
    return folder.data;
}

// === CẤU HÌNH CHO UPTIMEROBOT & TRANG CHỦ ===
// 1. Xử lý HEAD request (UptimeRobot ping): Trả về 200 OK nhanh, không tốn tài nguyên render HTML
app.head('/', (req, res) => {
    res.status(200).end();
});

// 2. Xử lý GET request (Người dùng truy cập): Hiển thị giao diện chào mừng
app.get('/', (req, res) => {
    res.send(`
        <div style="font-family: sans-serif; text-align: center; padding-top: 50px;">
            <h1 style="color: green;">QLVB Server is Running! 🚀</h1>
            <p>Backend API đang hoạt động bình thường.</p>
            <p>Trạng thái Google Auth: ${adminRefreshToken ? '<b style="color:blue">Đã kết nối</b>' : '<b style="color:red">Chưa đăng nhập</b>'}</p>
        </div>
    `);
});
// ================================================

// 1. Login
app.post('/api/oauth/token', async (req, res) => {
    try {
        const { code, redirect_uri } = req.body;
        const client = new google.auth.OAuth2(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, redirect_uri || REDIRECT_URI);
        const { tokens } = await client.getToken(code);
        if (tokens.refresh_token) adminRefreshToken = tokens.refresh_token;
        res.json(tokens);
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
});

// 2. Upload (Đã sửa logic tạo thư mục lồng nhau)
app.post('/api/upload', upload.array('files'), async (req, res) => {
    try {
        await getAccessToken(req); // Khôi phục session
        const drive = google.drive({ version: 'v3', auth: oauth2Client });
        
        const { docName, type, month } = req.body;
        
        // Tạo cấu trúc thư mục
        const rootFolder = await findOrCreateFolder(drive, 'QLVB-DATA');
        const typeFolder = await findOrCreateFolder(drive, type === 'incoming' ? 'VanBanDen' : 'VanBanDi', rootFolder.id);
        const monthFolder = await findOrCreateFolder(drive, month || 'Khac', typeFolder.id);
        const docFolder = await findOrCreateFolder(drive, `${docName} - ${Date.now()}`, monthFolder.id);

        const uploadedFiles = [];
        for (const file of req.files) {
            const media = { mimeType: file.mimetype, body: fs.createReadStream(file.path) };
            const driveFile = await drive.files.create({
                resource: { name: file.originalname, parents: [docFolder.id] },
                media: media,
                fields: 'id, name, webViewLink, webContentLink'
            });
            uploadedFiles.push(driveFile.data);
            fs.unlinkSync(file.path);
        }
        res.json({ folderId: docFolder.id, files: uploadedFiles });
    } catch (error) {
        console.error(error);
        res.status(500).json({ error: error.message });
    }
});

// 3. Delete
app.delete('/api/delete/:fileId', async (req, res) => {
    try {
        await getAccessToken(req);
        const drive = google.drive({ version: 'v3', auth: oauth2Client });
        await drive.files.delete({ fileId: req.params.fileId });
        res.json({ success: true });
    } catch (error) {
        console.error(error);
        res.status(500).json({ error: error.message });
    }
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));