Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alist-org
GitHub Repository: alist-org/alist
Path: blob/main/drivers/google_photo/util.go
1987 views
1
package google_photo
2
3
import (
4
"fmt"
5
"net/http"
6
7
"github.com/alist-org/alist/v3/drivers/base"
8
"github.com/go-resty/resty/v2"
9
)
10
11
// do others that not defined in Driver interface
12
13
const (
14
FETCH_ALL = "all"
15
FETCH_ALBUMS = "albums"
16
FETCH_ROOT = "root"
17
FETCH_SHARE_ALBUMS = "share_albums"
18
)
19
20
func (d *GooglePhoto) refreshToken() error {
21
url := "https://www.googleapis.com/oauth2/v4/token"
22
var resp base.TokenResp
23
var e TokenError
24
_, err := base.RestyClient.R().SetResult(&resp).SetError(&e).
25
SetFormData(map[string]string{
26
"client_id": d.ClientID,
27
"client_secret": d.ClientSecret,
28
"refresh_token": d.RefreshToken,
29
"grant_type": "refresh_token",
30
}).Post(url)
31
if err != nil {
32
return err
33
}
34
if e.Error != "" {
35
return fmt.Errorf(e.Error)
36
}
37
d.AccessToken = resp.AccessToken
38
return nil
39
}
40
41
func (d *GooglePhoto) request(url string, method string, callback base.ReqCallback, resp interface{}, headers map[string]string) ([]byte, error) {
42
req := base.RestyClient.R()
43
req.SetHeader("Authorization", "Bearer "+d.AccessToken)
44
req.SetHeader("Accept-Encoding", "gzip")
45
if headers != nil {
46
req.SetHeaders(headers)
47
}
48
49
if callback != nil {
50
callback(req)
51
}
52
if resp != nil {
53
req.SetResult(resp)
54
}
55
var e Error
56
req.SetError(&e)
57
res, err := req.Execute(method, url)
58
if err != nil {
59
return nil, err
60
}
61
if e.Error.Code != 0 {
62
if e.Error.Code == 401 {
63
err = d.refreshToken()
64
if err != nil {
65
return nil, err
66
}
67
return d.request(url, method, callback, resp, headers)
68
}
69
return nil, fmt.Errorf("%s: %v", e.Error.Message, e.Error.Errors)
70
}
71
return res.Body(), nil
72
}
73
74
func (d *GooglePhoto) getFiles(id string) ([]MediaItem, error) {
75
switch id {
76
case FETCH_ALL:
77
return d.getAllMedias()
78
case FETCH_ALBUMS:
79
return d.getAlbums()
80
case FETCH_SHARE_ALBUMS:
81
return d.getShareAlbums()
82
case FETCH_ROOT:
83
return d.getFakeRoot()
84
default:
85
return d.getMedias(id)
86
}
87
}
88
89
func (d *GooglePhoto) getFakeRoot() ([]MediaItem, error) {
90
return []MediaItem{
91
{
92
Id: FETCH_ALL,
93
Title: "全部媒体",
94
},
95
{
96
Id: FETCH_ALBUMS,
97
Title: "全部影集",
98
},
99
{
100
Id: FETCH_SHARE_ALBUMS,
101
Title: "共享影集",
102
},
103
}, nil
104
}
105
106
func (d *GooglePhoto) getAlbums() ([]MediaItem, error) {
107
return d.fetchItems(
108
"https://photoslibrary.googleapis.com/v1/albums",
109
map[string]string{
110
"fields": "albums(id,title,coverPhotoBaseUrl),nextPageToken",
111
"pageSize": "50",
112
"pageToken": "first",
113
},
114
http.MethodGet)
115
}
116
117
func (d *GooglePhoto) getShareAlbums() ([]MediaItem, error) {
118
return d.fetchItems(
119
"https://photoslibrary.googleapis.com/v1/sharedAlbums",
120
map[string]string{
121
"fields": "sharedAlbums(id,title,coverPhotoBaseUrl),nextPageToken",
122
"pageSize": "50",
123
"pageToken": "first",
124
},
125
http.MethodGet)
126
}
127
128
func (d *GooglePhoto) getMedias(albumId string) ([]MediaItem, error) {
129
return d.fetchItems(
130
"https://photoslibrary.googleapis.com/v1/mediaItems:search",
131
map[string]string{
132
"fields": "mediaItems(id,baseUrl,mimeType,mediaMetadata,filename),nextPageToken",
133
"pageSize": "100",
134
"albumId": albumId,
135
"pageToken": "first",
136
}, http.MethodPost)
137
}
138
139
func (d *GooglePhoto) getAllMedias() ([]MediaItem, error) {
140
return d.fetchItems(
141
"https://photoslibrary.googleapis.com/v1/mediaItems",
142
map[string]string{
143
"fields": "mediaItems(id,baseUrl,mimeType,mediaMetadata,filename),nextPageToken",
144
"pageSize": "100",
145
"pageToken": "first",
146
},
147
http.MethodGet)
148
}
149
150
func (d *GooglePhoto) getMedia(id string) (MediaItem, error) {
151
var resp MediaItem
152
153
query := map[string]string{
154
"fields": "mediaMetadata,baseUrl,mimeType",
155
}
156
_, err := d.request(fmt.Sprintf("https://photoslibrary.googleapis.com/v1/mediaItems/%s", id), http.MethodGet, func(req *resty.Request) {
157
req.SetQueryParams(query)
158
}, &resp, nil)
159
if err != nil {
160
return resp, err
161
}
162
163
return resp, nil
164
}
165
166
func (d *GooglePhoto) fetchItems(url string, query map[string]string, method string) ([]MediaItem, error){
167
res := make([]MediaItem, 0)
168
for query["pageToken"] != "" {
169
if query["pageToken"] == "first" {
170
query["pageToken"] = ""
171
}
172
var resp Items
173
174
_, err := d.request(url, method, func(req *resty.Request) {
175
req.SetQueryParams(query)
176
}, &resp, nil)
177
if err != nil {
178
return nil, err
179
}
180
query["pageToken"] = resp.NextPageToken
181
res = append(res, resp.MediaItems...)
182
res = append(res, resp.Albums...)
183
res = append(res, resp.SharedAlbums...)
184
}
185
return res, nil
186
}
187
188