forked from maple3142/GDIndex
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgoogleDrive.js
171 lines (170 loc) · 4.19 KB
/
googleDrive.js
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import xf from './xfetch'
class GoogleDrive {
constructor(auth) {
this.auth = auth
this.expires = 0
this._getIdCache = new Map()
}
async initializeClient() {
// any method that do api call must call this beforehand
if (Date.now() < this.expires) return
const resp = await xf
.post('https://www.googleapis.com/oauth2/v4/token', {
urlencoded: {
client_id: this.auth.client_id,
client_secret: this.auth.client_secret,
refresh_token: this.auth.refresh_token,
grant_type: 'refresh_token'
}
})
.json()
this.client = xf.extend({
baseURI: 'https://www.googleapis.com/drive/v3/',
headers: {
Authorization: `Bearer ${resp.access_token}`
}
})
this.expires = Date.now() + 3500 * 1000 // normally, it should expiers after 3600 seconds
}
async listDrive() {
await this.initializeClient()
return this.client.get('drives').json()
}
async download(id, range = '') {
await this.initializeClient()
return this.client.get(`files/${id}`, {
qs: {
includeItemsFromAllDrives: true,
supportsAllDrives: true,
alt: 'media'
},
headers: {
Range: range
}
})
}
async downloadByPath(path, rootId = 'root', range = '') {
const id = await this.getId(path, rootId)
if (!id) return null
return this.download(id, range)
}
async getMeta(id) {
await this.initializeClient()
return this.client
.get(`files/${id}`, {
qs: {
includeItemsFromAllDrives: true,
supportsAllDrives: true,
fields: '*'
}
})
.json()
}
async getMetaByPath(path, rootId = 'root') {
const id = await this.getId(path, rootId)
if (!id) return null
return this.getMeta(id)
}
async listFolder(id) {
await this.initializeClient()
const getList = pageToken => {
const qs = {
includeItemsFromAllDrives: true,
supportsAllDrives: true,
q: `'${id}' in parents and trashed = false`,
orderBy: 'folder,name,modifiedTime desc',
fields:
'files(id,name,mimeType,size,modifiedTime),nextPageToken',
pageSize: 1000
}
if (pageToken) {
qs.pageToken = pageToken
}
return this.client
.get('files', {
qs
})
.json()
}
const files = []
let pageToken
do {
const resp = await getList(pageToken)
files.push(...resp.files)
pageToken = resp.nextPageToken
} while (pageToken)
return { files }
}
async listFolderByPath(path, rootId = 'root') {
const id = await this.getId(path, rootId)
if (!id) return null
return this.listFolder(id)
}
async getId(path, rootId = 'root') {
const toks = path.split('/').filter(Boolean)
let id = rootId
for (const tok of toks) {
id = await this._getId(id, tok)
}
return id
}
async _getId(parentId, childName) {
if (this._getIdCache.has(parentId + childName)) {
return this._getIdCache.get(parentId + childName)
}
await this.initializeClient()
childName = childName.replace(/\'/g, `\\'`) // escape single quote
const resp = await this.client
.get('files', {
qs: {
includeItemsFromAllDrives: true,
supportsAllDrives: true,
q: `'${parentId}' in parents and name = '${childName}' and trashed = false`,
fields: 'files(id)'
}
})
.json()
.catch(e => ({ files: [] })) // if error, make it empty
if (resp.files.length === 0) {
return null
}
this._getIdCache.has(parentId + childName)
return resp.files[0].id // when there are more than 1 items, simply return the first one
}
async upload(parentId, name, file) {
await this.initializeClient()
const createResp = await this.client.post(
'https://www.googleapis.com/upload/drive/v3/files',
{
qs: {
uploadType: 'resumable',
supportsAllDrives: true
},
json: {
name,
parents: [parentId]
}
}
)
const putUrl = createResp.headers.get('Location')
return this.client
.put(putUrl, {
body: file
})
.json()
}
async uploadByPath(path, name, file, rootId = 'root') {
const id = await this.getId(path, rootId)
if (!id) return null
return this.upload(id, name, file)
}
async delete(fileId) {
return this.client.delete(`files/${fileId}`)
}
async deleteByPath(path, rootId = 'root') {
const id = await this.getId(path, rootId)
if (!id) return null
return this.delete(id)
}
}
export default GoogleDrive