1
1
import * as coda from "@codahq/packs-sdk" ;
2
- export const pack = coda . newPack ( ) ;
2
+ import * as helpers from "./helpers" ;
3
+ import * as params from "./params" ;
4
+ import * as schemas from "./schemas" ;
3
5
4
- const ApiBaseUrl = "https://photoslibrary.googleapis.com/v1" ;
6
+ export const pack = coda . newPack ( ) ;
5
7
6
8
pack . addNetworkDomain ( "googleapis.com" ) ;
7
9
@@ -17,112 +19,24 @@ pack.setUserAuthentication({
17
19
access_type : "offline" ,
18
20
prompt : "consent" ,
19
21
} ,
20
-
21
- // Determines the display name of the connected account.
22
- getConnectionName : async function ( context ) {
23
- let response = await context . fetcher . fetch ( {
24
- method : "GET" ,
25
- url : "https://www.googleapis.com/oauth2/v1/userinfo" ,
26
- } ) ;
27
- let user = response . body ;
28
- return user . name ;
29
- } ,
30
- } ) ;
31
-
32
- const MediaSchema = coda . makeObjectSchema ( {
33
- properties : {
34
- mediaId : {
35
- type : coda . ValueType . String ,
36
- fromKey : "id" ,
37
- required : true
38
- } ,
39
- filename : { type : coda . ValueType . String , required : true } ,
40
- description : { type : coda . ValueType . String } ,
41
- creationTime : {
42
- type : coda . ValueType . String ,
43
- codaType : coda . ValueHintType . DateTime
44
- } ,
45
- width : { type : coda . ValueType . Number } ,
46
- height : { type : coda . ValueType . Number } ,
47
- image : {
48
- type : coda . ValueType . String ,
49
- codaType : coda . ValueHintType . ImageReference ,
50
- } ,
51
- url : {
52
- type : coda . ValueType . String ,
53
- description : "Google Photos URL for the media." ,
54
- codaType : coda . ValueHintType . Url ,
55
- fromKey : "productUrl" ,
56
- } ,
57
- } ,
58
- displayProperty : "filename" ,
59
- idProperty : "mediaId" ,
60
- featuredProperties : [
61
- "image"
62
- ] ,
63
- } ) ;
64
-
65
- const MediaDateRangeParam = coda . makeParameter ( {
66
- type : coda . ParameterType . DateArray ,
67
- name : "dateRange" ,
68
- description : "The date range over which data should be fetched." ,
69
- suggestedValue : coda . PrecannedDateRange . LastWeek ,
70
- } ) ;
71
-
72
- const MediasContentCategoriesList = {
73
- Animals : "ANIMALS" ,
74
- Fashion : "FASHION" ,
75
- Landmarks : "LANDMARKS" ,
76
- Receipts : "RECEIPTS" ,
77
- Weddings : "WEDDINGS" ,
78
- Arts : "ARTS" ,
79
- Flowers : "FLOWERS" ,
80
- Landscapes : "LANDSCAPES" ,
81
- Screenshots : "SCREENSHOTS" ,
82
- Whiteboards : "WHITEBOARDS" ,
83
- Birthdays : "BIRTHDAYS" ,
84
- Food : "FOOD" ,
85
- Night : "NIGHT" ,
86
- Selfies : "SELFIES" ,
87
- Cityscapes : "CITYSCAPES" ,
88
- Gardens : "GARDENS" ,
89
- People : "PEOPLE" ,
90
- Sport : "SPORT" ,
91
- Crafts : "CRAFTS" ,
92
- Holidays : "HOLIDAYS" ,
93
- Performances : "PERFORMANCES" ,
94
- Travel : "TRAVEL" ,
95
- Documents : "DOCUMENTS" ,
96
- Houses : "HOUSES" ,
97
- Pets : "PETS" ,
98
- Utility : "UTILITY"
99
- }
100
-
101
- const MediaCategoriesParam = coda . makeParameter ( {
102
- type : coda . ParameterType . StringArray ,
103
- name : "categories" ,
104
- description : "Filter by medias categories." ,
105
- optional : true ,
106
- autocomplete : Object . keys ( MediasContentCategoriesList )
107
- } ) ;
108
-
109
- const MediaFavoritesParam = coda . makeParameter ( {
110
- type : coda . ParameterType . Boolean ,
111
- name : "favorite" ,
112
- description : "Filter by favorites medias." ,
113
- optional : true ,
22
+ getConnectionName : helpers . getConnectionName ,
114
23
} ) ;
115
24
116
25
pack . addSyncTable ( {
117
26
name : "Medias" ,
118
- schema : MediaSchema ,
27
+ schema : schemas . MediaSchema ,
119
28
identityName : "Media" ,
120
29
formula : {
121
30
name : "SyncMedias" ,
122
31
description : "Sync medias from the user's library." ,
123
- parameters : [ MediaDateRangeParam , MediaCategoriesParam , MediaFavoritesParam ] ,
124
- execute : async function ( [ dateRange , categories , favorite ] , context ) {
125
- let url = `${ ApiBaseUrl } /mediaItems:search` ;
32
+ parameters : [
33
+ params . MediaDateRangeParam ,
34
+ params . MediaTypeParam ,
35
+ params . MediaCategoriesIncludeParam ,
36
+ params . MediaFavoritesParam
37
+ ] ,
38
+ execute : async function ( [ dateRange , mediaType , categories , favorite ] , context ) {
39
+ let url = `${ helpers . ApiUrl } /mediaItems:search` ;
126
40
127
41
function formatDate ( date : Date , dateFormatter : Intl . DateTimeFormat ) {
128
42
const dateParts = dateFormatter . formatToParts ( date ) ;
@@ -163,7 +77,7 @@ pack.addSyncTable({
163
77
includedContentCategories : string [ ] ,
164
78
} ;
165
79
} ;
166
- pageToken ?: string ;
80
+ pageToken ?: undefined | string ;
167
81
} ;
168
82
169
83
let payload : RequestPayload = {
@@ -176,7 +90,7 @@ pack.addSyncTable({
176
90
} ]
177
91
} ,
178
92
featureFilter : ( favorite ) ? { includedFeatures : [ "FAVORITES" ] } : undefined ,
179
- contentFilter : ( categories ) ? { includedContentCategories : categories . map ( category => ( MediasContentCategoriesList [ category ] ) ) } : undefined ,
93
+ contentFilter : ( categories ) ? { includedContentCategories : categories . map ( category => ( helpers . MediasContentCategoriesList [ category ] ) ) } : undefined ,
180
94
} ,
181
95
pageToken : ( context . sync . continuation ?. nextPageToken ) ? context . sync . continuation . nextPageToken : undefined ,
182
96
}
@@ -191,10 +105,20 @@ pack.addSyncTable({
191
105
let items = response . body . mediaItems ;
192
106
if ( items && items . length > 0 ) {
193
107
for ( let item of items ) {
108
+ // the api returns item.mediaMetadata.photo and item.mediaMetadata.video, we want to have a single mediaType property.
109
+ item . mediaType = ( item . mediaMetadata . photo ) ? "Photo" : "Video" ;
194
110
item . creationTime = item . mediaMetadata . creationTime
195
111
item . width = item . mediaMetadata . width
196
112
item . height = item . mediaMetadata . height
197
- item . image = item . baseUrl + "=w2048-h1024"
113
+ } ;
114
+ } ;
115
+ if ( mediaType ) {
116
+ items = items . filter ( item => ( item . mediaType === mediaType ) ) ;
117
+ }
118
+ if ( items && items . length > 0 ) {
119
+ for ( let item of items ) {
120
+ // We get the image only after we have filtered the items since it can become quite costly in ressources.
121
+ item . image = item . baseUrl + "=w2048-h1024" //TODO: add parameter for image sizes.
198
122
} ;
199
123
} ;
200
124
let continuation ;
@@ -211,47 +135,16 @@ pack.addSyncTable({
211
135
} ,
212
136
} ) ;
213
137
214
- const MediaReferenceSchema = coda . makeReferenceSchemaFromObjectSchema ( MediaSchema , "Media" ) ;
215
-
216
- const AlbumSchema = coda . makeObjectSchema ( {
217
- properties : {
218
- albumId : {
219
- type : coda . ValueType . String ,
220
- fromKey : "id" ,
221
- } ,
222
- title : { type : coda . ValueType . String } ,
223
- // medias: {
224
- // type: coda.ValueType.Array,
225
- // items: MediaReferenceSchema
226
- // },
227
- url : {
228
- type : coda . ValueType . String ,
229
- description : "Google Photos URL for the album." ,
230
- codaType : coda . ValueHintType . Url ,
231
- fromKey : "productUrl" ,
232
- } ,
233
- coverPhoto : {
234
- type : coda . ValueType . String ,
235
- codaType : coda . ValueHintType . ImageReference ,
236
- } ,
237
- } ,
238
- displayProperty : "title" ,
239
- idProperty : "albumId" ,
240
- featuredProperties : [
241
- "coverPhoto"
242
- ]
243
- } ) ;
244
-
245
138
pack . addSyncTable ( {
246
139
name : "Albums" ,
247
- schema : AlbumSchema ,
140
+ schema : schemas . AlbumSchema ,
248
141
identityName : "Album" ,
249
142
formula : {
250
143
name : "SyncAlbums" ,
251
144
description : "Sync all albums." ,
252
145
parameters : [ ] ,
253
146
execute : async function ( [ ] , context ) {
254
- let url = `${ ApiBaseUrl } /albums` ;
147
+ let url = `${ helpers . ApiUrl } /albums` ;
255
148
256
149
if ( context . sync . continuation ) {
257
150
url = coda . withQueryParams ( url , { pageToken : context . sync . continuation } )
@@ -270,7 +163,7 @@ pack.addSyncTable({
270
163
const Albums = await AlbumsResponse . body . albums ;
271
164
for ( const album of Albums ) {
272
165
// we want to search for all medias in the current album.
273
- // let url = coda.withQueryParams(`${ApiBaseUrl }/mediaItems:search`, { pageSize: 5 });
166
+ // let url = coda.withQueryParams(`${helpers.ApiUrl }/mediaItems:search`, { pageSize: 5 });
274
167
// let body = { albumId: album.id };
275
168
// let mediaItemsInAlbum = [];
276
169
// let mediaItemsNextPageToken;
0 commit comments