feat(google_photo): Add categories in root, add album support. (#2046)
* feat(google_photo): Add categories in root, add album support. * fix(google_photo): Remove else block in `drive/google_photo/types.go:60`
This commit is contained in:
parent
45cc0cedbd
commit
3db798a82a
@ -43,7 +43,7 @@ func (d *GooglePhoto) Drop(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *GooglePhoto) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
func (d *GooglePhoto) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||||
files, err := d.getFiles()
|
files, err := d.getFiles(dir.GetID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -58,7 +58,7 @@ func (d *GooglePhoto) List(ctx context.Context, dir model.Obj, args model.ListAr
|
|||||||
//}
|
//}
|
||||||
|
|
||||||
func (d *GooglePhoto) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *GooglePhoto) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
f, err := d.getFile(file.GetID())
|
f, err := d.getMedia(file.GetID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ type Addition struct {
|
|||||||
RefreshToken string `json:"refresh_token" required:"true"`
|
RefreshToken string `json:"refresh_token" required:"true"`
|
||||||
ClientID string `json:"client_id" required:"true" default:"202264815644.apps.googleusercontent.com"`
|
ClientID string `json:"client_id" required:"true" default:"202264815644.apps.googleusercontent.com"`
|
||||||
ClientSecret string `json:"client_secret" required:"true" default:"X4Z3ca8xfWDb1Voo-F9a7ZxJ"`
|
ClientSecret string `json:"client_secret" required:"true" default:"X4Z3ca8xfWDb1Voo-F9a7ZxJ"`
|
||||||
|
ShowArchive bool `json:"show_archive"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = driver.Config{
|
var config = driver.Config{
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package google_photo
|
package google_photo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
@ -11,17 +12,21 @@ type TokenError struct {
|
|||||||
ErrorDescription string `json:"error_description"`
|
ErrorDescription string `json:"error_description"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Files struct {
|
type Items struct {
|
||||||
NextPageToken string `json:"nextPageToken"`
|
NextPageToken string `json:"nextPageToken"`
|
||||||
MediaItems []MediaItem `json:"mediaItems"`
|
MediaItems []MediaItem `json:"mediaItems,omitempty"`
|
||||||
|
Albums []MediaItem `json:"albums,omitempty"`
|
||||||
|
SharedAlbums []MediaItem `json:"sharedAlbums,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type MediaItem struct {
|
type MediaItem struct {
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
BaseURL string `json:"baseUrl"`
|
Title string `json:"title,omitempty"`
|
||||||
MimeType string `json:"mimeType"`
|
BaseURL string `json:"baseUrl,omitempty"`
|
||||||
FileName string `json:"filename"`
|
CoverPhotoBaseUrl string `json:"coverPhotoBaseUrl,omitempty"`
|
||||||
MediaMetadata MediaMetadata `json:"mediaMetadata"`
|
MimeType string `json:"mimeType,omitempty"`
|
||||||
|
FileName string `json:"filename,omitempty"`
|
||||||
|
MediaMetadata MediaMetadata `json:"mediaMetadata,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type MediaMetadata struct {
|
type MediaMetadata struct {
|
||||||
@ -39,18 +44,29 @@ type Video struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func fileToObj(f MediaItem) *model.ObjThumb {
|
func fileToObj(f MediaItem) *model.ObjThumb {
|
||||||
//size, _ := strconv.ParseInt(f.Size, 10, 64)
|
if !reflect.DeepEqual(f.MediaMetadata, MediaMetadata{}){
|
||||||
|
return &model.ObjThumb{
|
||||||
|
Object: model.Object{
|
||||||
|
ID: f.Id,
|
||||||
|
Name: f.FileName,
|
||||||
|
Size: 0,
|
||||||
|
Modified: f.MediaMetadata.CreationTime,
|
||||||
|
IsFolder: false,
|
||||||
|
},
|
||||||
|
Thumbnail: model.Thumbnail{
|
||||||
|
Thumbnail: f.BaseURL + "=w100-h100-c",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
return &model.ObjThumb{
|
return &model.ObjThumb{
|
||||||
Object: model.Object{
|
Object: model.Object{
|
||||||
ID: f.Id,
|
ID: f.Id,
|
||||||
Name: f.FileName,
|
Name: f.Title,
|
||||||
Size: 0,
|
Size: 0,
|
||||||
Modified: f.MediaMetadata.CreationTime,
|
Modified: time.Time{},
|
||||||
IsFolder: false,
|
IsFolder: true,
|
||||||
},
|
|
||||||
Thumbnail: model.Thumbnail{
|
|
||||||
Thumbnail: f.BaseURL + "=w100-h100-c",
|
|
||||||
},
|
},
|
||||||
|
Thumbnail: model.Thumbnail{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,13 @@ import (
|
|||||||
|
|
||||||
// do others that not defined in Driver interface
|
// do others that not defined in Driver interface
|
||||||
|
|
||||||
|
const (
|
||||||
|
FETCH_ALL = "all"
|
||||||
|
FETCH_ALBUMS = "albums"
|
||||||
|
FETCH_ROOT = "root"
|
||||||
|
FETCH_SHARE_ALBUMS = "share_albums"
|
||||||
|
)
|
||||||
|
|
||||||
func (d *GooglePhoto) refreshToken() error {
|
func (d *GooglePhoto) refreshToken() error {
|
||||||
url := "https://www.googleapis.com/oauth2/v4/token"
|
url := "https://www.googleapis.com/oauth2/v4/token"
|
||||||
var resp base.TokenResp
|
var resp base.TokenResp
|
||||||
@ -34,6 +41,7 @@ func (d *GooglePhoto) refreshToken() error {
|
|||||||
func (d *GooglePhoto) request(url string, method string, callback base.ReqCallback, resp interface{}, headers map[string]string) ([]byte, error) {
|
func (d *GooglePhoto) request(url string, method string, callback base.ReqCallback, resp interface{}, headers map[string]string) ([]byte, error) {
|
||||||
req := base.RestyClient.R()
|
req := base.RestyClient.R()
|
||||||
req.SetHeader("Authorization", "Bearer "+d.AccessToken)
|
req.SetHeader("Authorization", "Bearer "+d.AccessToken)
|
||||||
|
req.SetHeader("Accept-Encoding", "gzip")
|
||||||
if headers != nil {
|
if headers != nil {
|
||||||
req.SetHeaders(headers)
|
req.SetHeaders(headers)
|
||||||
}
|
}
|
||||||
@ -63,32 +71,83 @@ func (d *GooglePhoto) request(url string, method string, callback base.ReqCallba
|
|||||||
return res.Body(), nil
|
return res.Body(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *GooglePhoto) getFiles() ([]MediaItem, error) {
|
func (d *GooglePhoto) getFiles(id string) ([]MediaItem, error) {
|
||||||
pageToken := "first"
|
switch id {
|
||||||
res := make([]MediaItem, 0)
|
case FETCH_ALL:
|
||||||
for pageToken != "" {
|
return d.getAllMedias()
|
||||||
if pageToken == "first" {
|
case FETCH_ALBUMS:
|
||||||
pageToken = ""
|
return d.getAlbums()
|
||||||
}
|
case FETCH_SHARE_ALBUMS:
|
||||||
var resp Files
|
return d.getShareAlbums()
|
||||||
query := map[string]string{
|
case FETCH_ROOT:
|
||||||
"fields": "mediaItems(id,baseUrl,mimeType,mediaMetadata,filename),nextPageToken",
|
return d.getFakeRoot()
|
||||||
"pageSize": "100",
|
default:
|
||||||
"pageToken": pageToken,
|
return d.getMedias(id)
|
||||||
}
|
|
||||||
_, err := d.request("https://photoslibrary.googleapis.com/v1/mediaItems", http.MethodGet, func(req *resty.Request) {
|
|
||||||
req.SetQueryParams(query)
|
|
||||||
}, &resp, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pageToken = resp.NextPageToken
|
|
||||||
res = append(res, resp.MediaItems...)
|
|
||||||
}
|
}
|
||||||
return res, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *GooglePhoto) getFile(id string) (MediaItem, error) {
|
func (d *GooglePhoto) getFakeRoot() ([]MediaItem, error) {
|
||||||
|
return []MediaItem{
|
||||||
|
{
|
||||||
|
Id: FETCH_ALL,
|
||||||
|
Title: "全部媒体",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Id: FETCH_ALBUMS,
|
||||||
|
Title: "全部影集",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Id: FETCH_SHARE_ALBUMS,
|
||||||
|
Title: "共享影集",
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *GooglePhoto) getAlbums() ([]MediaItem, error) {
|
||||||
|
return d.fetchItems(
|
||||||
|
"https://photoslibrary.googleapis.com/v1/albums",
|
||||||
|
map[string]string{
|
||||||
|
"fields": "albums(id,title,coverPhotoBaseUrl),nextPageToken",
|
||||||
|
"pageSize": "50",
|
||||||
|
"pageToken": "first",
|
||||||
|
},
|
||||||
|
http.MethodGet)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *GooglePhoto) getShareAlbums() ([]MediaItem, error) {
|
||||||
|
return d.fetchItems(
|
||||||
|
"https://photoslibrary.googleapis.com/v1/sharedAlbums",
|
||||||
|
map[string]string{
|
||||||
|
"fields": "sharedAlbums(id,title,coverPhotoBaseUrl),nextPageToken",
|
||||||
|
"pageSize": "50",
|
||||||
|
"pageToken": "first",
|
||||||
|
},
|
||||||
|
http.MethodGet)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *GooglePhoto) getMedias(albumId string) ([]MediaItem, error) {
|
||||||
|
return d.fetchItems(
|
||||||
|
"https://photoslibrary.googleapis.com/v1/mediaItems:search",
|
||||||
|
map[string]string{
|
||||||
|
"fields": "mediaItems(id,baseUrl,mimeType,mediaMetadata,filename),nextPageToken",
|
||||||
|
"pageSize": "100",
|
||||||
|
"albumId": albumId,
|
||||||
|
"pageToken": "first",
|
||||||
|
}, http.MethodPost)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *GooglePhoto) getAllMedias() ([]MediaItem, error) {
|
||||||
|
return d.fetchItems(
|
||||||
|
"https://photoslibrary.googleapis.com/v1/mediaItems",
|
||||||
|
map[string]string{
|
||||||
|
"fields": "mediaItems(id,baseUrl,mimeType,mediaMetadata,filename),nextPageToken",
|
||||||
|
"pageSize": "100",
|
||||||
|
"pageToken": "first",
|
||||||
|
},
|
||||||
|
http.MethodGet)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *GooglePhoto) getMedia(id string) (MediaItem, error) {
|
||||||
var resp MediaItem
|
var resp MediaItem
|
||||||
|
|
||||||
query := map[string]string{
|
query := map[string]string{
|
||||||
@ -103,3 +162,25 @@ func (d *GooglePhoto) getFile(id string) (MediaItem, error) {
|
|||||||
|
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *GooglePhoto) fetchItems(url string, query map[string]string, method string) ([]MediaItem, error){
|
||||||
|
res := make([]MediaItem, 0)
|
||||||
|
for query["pageToken"] != "" {
|
||||||
|
if query["pageToken"] == "first" {
|
||||||
|
query["pageToken"] = ""
|
||||||
|
}
|
||||||
|
var resp Items
|
||||||
|
|
||||||
|
_, err := d.request(url, method, func(req *resty.Request) {
|
||||||
|
req.SetQueryParams(query)
|
||||||
|
}, &resp, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
query["pageToken"] = resp.NextPageToken
|
||||||
|
res = append(res, resp.MediaItems...)
|
||||||
|
res = append(res, resp.Albums...)
|
||||||
|
res = append(res, resp.SharedAlbums...)
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user