diff options
Diffstat (limited to 'src/server')
-rw-r--r-- | src/server/apis/google/GooglePhotosUploadUtils.ts | 119 | ||||
-rw-r--r-- | src/server/credentials/google_docs_token.json | 2 | ||||
-rw-r--r-- | src/server/index.ts | 27 |
3 files changed, 106 insertions, 42 deletions
diff --git a/src/server/apis/google/GooglePhotosUploadUtils.ts b/src/server/apis/google/GooglePhotosUploadUtils.ts index 9b3e68761..5ac3eaef7 100644 --- a/src/server/apis/google/GooglePhotosUploadUtils.ts +++ b/src/server/apis/google/GooglePhotosUploadUtils.ts @@ -4,6 +4,9 @@ import * as fs from 'fs'; import { Utils } from '../../../Utils'; import * as path from 'path'; import { Opt } from '../../../new_fields/Doc'; +import * as sharp from 'sharp'; + +const uploadDirectory = path.join(__dirname, "../../public/files/"); export namespace GooglePhotosUploadUtils { @@ -18,13 +21,6 @@ export namespace GooglePhotosUploadUtils { description: string; } - export interface DownloadInformation { - mediaPath: string; - fileName: string; - contentType?: string; - contentSize?: string; - } - const prepend = (extension: string) => `https://photoslibrary.googleapis.com/v1/${extension}`; const headers = (type: string) => ({ 'Content-Type': `application/${type}`, @@ -76,35 +72,92 @@ export namespace GooglePhotosUploadUtils { }); }; - export namespace IOUtils { +} - export const Download = async (url: string, filename?: string, prefix = ""): Promise<Opt<DownloadInformation>> => { - const resolved = filename || `${prefix}upload_${Utils.GenerateGuid()}${path.extname(url).toLowerCase()}`; - const mediaPath = Paths.uploadDirectory + resolved; - return new Promise<DownloadInformation>((resolve, reject) => { - request.head(url, (error, res) => { - if (error) { - return reject(error); - } - const information: DownloadInformation = { - fileName: resolved, - contentSize: res.headers['content-length'], - contentType: res.headers['content-type'], - mediaPath - }; - request(url).pipe(fs.createWriteStream(mediaPath)).on('close', () => resolve(information)); - }); - }); - }; +export namespace DownloadUtils { - 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 interface Size { + width: number; + suffix: string; + } - export const Destroy = (mediaPath: string) => new Promise<boolean>(resolve => fs.unlink(mediaPath, error => resolve(error === null))); + export const Sizes: { [size: string]: Size } = { + SMALL: { width: 100, suffix: "_s" }, + MEDIUM: { width: 400, suffix: "_m" }, + LARGE: { width: 900, suffix: "_l" }, + }; + + const png = ".png"; + const pngs = [".png", ".PNG"]; + const jpg = [".jpg", ".JPG", ".jpeg", ".JPEG"]; + const size = "content-length"; + const type = "content-type"; + + export interface DownloadInformation { + mediaPaths: string[]; + fileNames: { [key: string]: string }; + contentSize?: string; + contentType?: string; } + const generate = (prefix: string, url: string) => `${prefix}upload_${Utils.GenerateGuid()}${path.extname(url).toLowerCase()}`; + const sanitize = (filename: string) => filename.replace(/\s+/g, "_"); + + export const Download = async (url: string, filename?: string, prefix = ""): Promise<Opt<DownloadInformation>> => { + const resolved = filename ? sanitize(filename) : generate(prefix, url); + const extension = path.extname(url) || path.extname(resolved) || png; + return new Promise<DownloadInformation>((resolve, reject) => { + request.head(url, async (error, res) => { + if (error) { + return reject(error); + } + const information: DownloadInformation = { + fileNames: { clean: resolved }, + contentSize: res.headers[size], + contentType: res.headers[type], + mediaPaths: [] + }; + const resizers = [ + { resizer: sharp().rotate(), suffix: "_o" }, + ...Object.values(Sizes).map(size => ({ + resizer: sharp().resize(size.width, undefined, { withoutEnlargement: true }).rotate(), + suffix: size.suffix + })) + ]; + let validated = true; + if (pngs.includes(extension)) { + resizers.forEach(element => element.resizer = element.resizer.png()); + } else if (jpg.includes(extension)) { + resizers.forEach(element => element.resizer = element.resizer.jpeg()); + } else { + validated = false; + } + if (validated) { + for (let resizer of resizers) { + const suffix = resizer.suffix; + let mediaPath: string; + await new Promise<void>(resolve => { + const filename = resolved.substring(0, resolved.length - extension.length) + suffix + extension; + information.mediaPaths.push(mediaPath = uploadDirectory + filename); + information.fileNames[suffix] = filename; + request(url) + .pipe(resizer.resizer) + .pipe(fs.createWriteStream(mediaPath)) + .on('close', resolve); + }); + } + 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 diff --git a/src/server/credentials/google_docs_token.json b/src/server/credentials/google_docs_token.json index a1c23ea35..4f911f7e0 100644 --- a/src/server/credentials/google_docs_token.json +++ b/src/server/credentials/google_docs_token.json @@ -1 +1 @@ -{"access_token":"ya29.Glx9B3Fumh3qHpgasQvHNNrwNXtmTVWJR9XckFsnUjOswDOO91ccF3FhD4ko7Z-3rvxEljpP1Qj5BgNq305pt-pgIquoLPWYiaEtinHNF7IXGPz4s4raqJWEJPJxow","refresh_token":"1/HTv_xFHszu2Nf3iiFrUTaeKzC_Vp2-6bpIB06xW_WHI","scope":"https://www.googleapis.com/auth/presentations.readonly https://www.googleapis.com/auth/documents.readonly https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/documents https://www.googleapis.com/auth/photoslibrary https://www.googleapis.com/auth/photoslibrary.appendonly https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/presentations https://www.googleapis.com/auth/photoslibrary.sharing","token_type":"Bearer","expiry_date":1567913435149}
\ No newline at end of file +{"access_token":"ya29.Glx9B3_l5JbKNtvzx378Nsz917bP-OTKf6VZzc2K8QDBm-Y0j_-c8v7bL8LCEM3wF8d7JauF-5Z4Uq4v7wPwUQUlDO1uPyoHeSF6iz98xkgJr9OW4KzJo2Ij722gpQ","refresh_token":"1/HTv_xFHszu2Nf3iiFrUTaeKzC_Vp2-6bpIB06xW_WHI","scope":"https://www.googleapis.com/auth/presentations.readonly https://www.googleapis.com/auth/documents.readonly https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/documents https://www.googleapis.com/auth/photoslibrary https://www.googleapis.com/auth/photoslibrary.appendonly https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/presentations https://www.googleapis.com/auth/photoslibrary.sharing","token_type":"Bearer","expiry_date":1567931641928}
\ No newline at end of file diff --git a/src/server/index.ts b/src/server/index.ts index 49010e7e2..013345a76 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -42,7 +42,7 @@ var AdmZip = require('adm-zip'); import * as YoutubeApi from "./apis/youtube/youtubeApiSample"; import { Response } from 'express-serve-static-core'; import { GoogleApiServerUtils } from "./apis/google/GoogleApiServerUtils"; -import { GooglePhotosUploadUtils } from './apis/google/GooglePhotosUploadUtils'; +import { GooglePhotosUploadUtils, DownloadUtils } from './apis/google/GooglePhotosUploadUtils'; const MongoStore = require('connect-mongo')(session); const mongoose = require('mongoose'); const probe = require("probe-image-size"); @@ -154,6 +154,11 @@ app.get("/buxton", (req, res) => { command_line('python scraper.py', cwd).then(onResolved, tryPython3); }); +const STATUS = { + OK: 200, + BAD_REQUEST: 400 +}; + const command_line = (command: string, fromDirectory?: string) => { return new Promise<string>((resolve, reject) => { let options: ExecOptions = {}; @@ -848,16 +853,22 @@ app.post(RouteStore.googlePhotosMediaUpload, async (req, res) => { ); }); +interface MediaItem { + baseUrl: string; + filename: string; +} const prefix = "google_photos_"; + app.post(RouteStore.googlePhotosMediaDownload, async (req, res) => { - const contents = req.body; - if (!contents) { - return res.send(undefined); + const contents: { mediaItems: MediaItem[] } = req.body; + if (contents) { + const downloads = contents.mediaItems.map(item => + DownloadUtils.Download(item.baseUrl, item.filename, prefix) + ); + res.status(STATUS.OK).send(await Promise.all(downloads)); + return; } - await GooglePhotosUploadUtils.initialize({ uploadDirectory, credentialsPath, tokenPath }); - res.send(await Promise.all(contents.mediaItems.map((item: any) => - GooglePhotosUploadUtils.IOUtils.Download(item.baseUrl, undefined, prefix))) - ); + res.status(STATUS.BAD_REQUEST).send(); }); const suffixMap: { [type: string]: (string | [string, string | ((json: any) => any)]) } = { |