aboutsummaryrefslogtreecommitdiff
path: root/src/server/apis/google/GooglePhotosUploadUtils.ts
diff options
context:
space:
mode:
authorSam Wilkins <samwilkins333@gmail.com>2019-09-06 06:29:26 -0400
committerSam Wilkins <samwilkins333@gmail.com>2019-09-06 06:29:26 -0400
commit5d59e9a379417140e10778cd43e8f87ecb816c37 (patch)
tree3470286463c83ecd30cb436f1a46a5aa5543667a /src/server/apis/google/GooglePhotosUploadUtils.ts
parent0404047f5e747608b33474fa1c883a489cd6b403 (diff)
lightly tested functional export of any image doc (web url or stored in server public folder) to google photos, optionally stored in a given target album
Diffstat (limited to 'src/server/apis/google/GooglePhotosUploadUtils.ts')
-rw-r--r--src/server/apis/google/GooglePhotosUploadUtils.ts122
1 files changed, 108 insertions, 14 deletions
diff --git a/src/server/apis/google/GooglePhotosUploadUtils.ts b/src/server/apis/google/GooglePhotosUploadUtils.ts
index cd2a586eb..3b513aaf1 100644
--- a/src/server/apis/google/GooglePhotosUploadUtils.ts
+++ b/src/server/apis/google/GooglePhotosUploadUtils.ts
@@ -1,28 +1,122 @@
import request = require('request-promise');
-import { Authorization } from './GooglePhotosServerUtils';
+import { GoogleApiServerUtils } from './GoogleApiServerUtils';
+import * as fs from 'fs';
+import { Utils } from '../../../Utils';
+import * as path from 'path';
+import { Opt } from '../../../new_fields/Doc';
export namespace GooglePhotosUploadUtils {
- interface UploadInformation {
- title: string;
- MEDIA_BINARY_DATA: string;
+ export interface Paths {
+ uploadDirectory: string;
+ credentialsPath: string;
+ tokenPath: string;
}
- const apiEndpoint = "https://photoslibrary.googleapis.com/v1/uploads";
+ export interface MediaInput {
+ description: string;
+ source: string;
+ }
+
+ export interface DownloadInformation {
+ mediaPath: string;
+ contentType?: string;
+ contentSize?: string;
+ }
+
+ const prepend = (extension: string) => `https://photoslibrary.googleapis.com/v1/${extension}`;
+ const headers = (type: string) => ({
+ 'Content-Type': `application/${type}`,
+ 'Authorization': Bearer,
+ });
+
+ let Bearer: string;
+ let Paths: Paths;
- export const SubmitUpload = async (parameters: Authorization & UploadInformation) => {
- let options = {
+ export const initialize = async (paths: Paths) => {
+ Paths = paths;
+ const { tokenPath, credentialsPath } = paths;
+ const token = await GoogleApiServerUtils.RetrieveAccessToken({ tokenPath, credentialsPath });
+ Bearer = `Bearer ${token}`;
+ };
+
+ export const DispatchGooglePhotosUpload = async (filename: string) => {
+ let body: Buffer;
+ if (filename.includes('upload_')) {
+ const mediaPath = Paths.uploadDirectory + filename;
+ body = await new Promise<Buffer>((resolve, reject) => {
+ fs.readFile(mediaPath, (error, data) => error ? reject(error) : resolve(data));
+ });
+ } else {
+ body = await request(filename, { encoding: null });
+ }
+ const parameters = {
+ method: 'POST',
headers: {
- 'Content-Type': 'application/octet-stream',
- Authorization: `Bearer ${parameters.token}`,
- 'X-Goog-Upload-File-Name': parameters.title,
+ ...headers('octet-stream'),
+ 'X-Goog-Upload-File-Name': filename,
'X-Goog-Upload-Protocol': 'raw'
},
- body: { MEDIA_BINARY_DATA: parameters.MEDIA_BINARY_DATA },
- json: true
+ uri: prepend('uploads'),
+ body
};
- const result = await request.post(apiEndpoint, options);
- return result;
+ return new Promise<any>(resolve => request(parameters, (error, _response, body) => resolve(error ? undefined : body)));
+ };
+
+ export const CreateMediaItems = (newMediaItems: any[], album?: { id: string }) => {
+ return new Promise<any>((resolve, reject) => {
+ const parameters = {
+ method: 'POST',
+ headers: headers('json'),
+ uri: prepend('mediaItems:batchCreate'),
+ body: { newMediaItems } as any,
+ json: true
+ };
+ album && (parameters.body.albumId = album.id);
+ request(parameters, (error, _response, body) => {
+ if (error) {
+ reject(error);
+ } else {
+ resolve(body);
+ }
+ });
+ });
};
+ export namespace IOUtils {
+
+ export const Download = async (url: string): Promise<Opt<DownloadInformation>> => {
+ const filename = `temporary_upload_${Utils.GenerateGuid()}${path.extname(url).toLowerCase()}`;
+ const temporaryDirectory = Paths.uploadDirectory + "temporary/";
+ const mediaPath = temporaryDirectory + filename;
+
+ if (!(await createIfNotExists(temporaryDirectory))) {
+ return undefined;
+ }
+
+ return new Promise<DownloadInformation>((resolve, reject) => {
+ request.head(url, (error, res) => {
+ if (error) {
+ return reject(error);
+ }
+ const information: DownloadInformation = {
+ mediaPath,
+ contentType: res.headers['content-type'],
+ contentSize: res.headers['content-length'],
+ };
+ request(url).pipe(fs.createWriteStream(mediaPath)).on('close', () => resolve(information));
+ });
+ });
+ };
+
+ export const createIfNotExists = async (path: string) => {
+ if (await new Promise<boolean>(resolve => fs.exists(path, resolve))) {
+ return true;
+ }
+ return new Promise<boolean>(resolve => fs.mkdir(path, error => resolve(error === null)));
+ };
+
+ export const Destroy = (mediaPath: string) => new Promise<boolean>(resolve => fs.unlink(mediaPath, error => resolve(error === null)));
+ }
+
} \ No newline at end of file