aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/DocServer.ts1
-rw-r--r--src/client/apis/google_docs/GoogleApiClientUtils.ts85
-rw-r--r--src/client/views/MainView.tsx11
-rw-r--r--src/server/Message.ts1
-rw-r--r--src/server/RouteStore.ts3
-rw-r--r--src/server/apis/google/GoogleApiServerUtils.ts109
-rw-r--r--src/server/apis/youtube/youtubeApiSample.d.ts (renamed from src/server/youtubeApi/youtubeApiSample.d.ts)0
-rw-r--r--src/server/apis/youtube/youtubeApiSample.js (renamed from src/server/youtubeApi/youtubeApiSample.js)0
-rw-r--r--src/server/credentials/google_docs_credentials.json1
-rw-r--r--src/server/credentials/google_docs_token.json1
-rw-r--r--src/server/index.ts33
11 files changed, 236 insertions, 9 deletions
diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts
index bf5168c22..47aff2bb6 100644
--- a/src/client/DocServer.ts
+++ b/src/client/DocServer.ts
@@ -5,6 +5,7 @@ import { Utils, emptyFunction } from '../Utils';
import { SerializationHelper } from './util/SerializationHelper';
import { RefField } from '../new_fields/RefField';
import { Id, HandleUpdate } from '../new_fields/FieldSymbols';
+import { docs_v1 } from 'googleapis';
/**
* This class encapsulates the transfer and cross-client synchronization of
diff --git a/src/client/apis/google_docs/GoogleApiClientUtils.ts b/src/client/apis/google_docs/GoogleApiClientUtils.ts
new file mode 100644
index 000000000..42e621f6b
--- /dev/null
+++ b/src/client/apis/google_docs/GoogleApiClientUtils.ts
@@ -0,0 +1,85 @@
+import { docs_v1 } from "googleapis";
+import { PostToServer } from "../../../Utils";
+import { RouteStore } from "../../../server/RouteStore";
+
+export namespace GoogleApiClientUtils {
+
+ export namespace Docs {
+
+ export enum Actions {
+ Create = "create",
+ Retrieve = "retrieve"
+ }
+
+ export namespace Helpers {
+
+ export const fromRgb = (red: number, green: number, blue: number) => {
+ return { color: { rgbColor: { red, green, blue } } };
+ };
+
+ }
+
+ export const ExampleDocumentSchema = {
+ title: "This is a Google Doc Created From Dash Web",
+ body: {
+ content: [
+ {
+ paragraph: {
+ elements: [
+ {
+ textRun: {
+ content: "And this is its bold, blue text!!!",
+ textStyle: {
+ bold: true,
+ backgroundColor: Helpers.fromRgb(0, 0, 1)
+ }
+ }
+ }
+ ]
+ }
+ }
+ ] as docs_v1.Schema$StructuralElement[]
+ }
+ } as docs_v1.Schema$Document;
+
+ /**
+ * After following the authentication routine, which connects this API call to the current signed in account
+ * and grants the appropriate permissions, this function programmatically creates an arbitrary Google Doc which
+ * should appear in the user's Google Doc library instantaneously.
+ *
+ * @param schema whatever subset of a docs_v1.Schema$Document is required to properly initialize your
+ * Google Doc. This schema defines all aspects of a Google Doc, from the title to headers / footers to the
+ * actual document body and its styling!
+ * @returns the documentId of the newly generated document, or undefined if the creation process fails.
+ */
+ export const Create = async (schema?: docs_v1.Schema$Document): Promise<string | undefined> => {
+ let path = RouteStore.googleDocs + Actions.Create;
+ let parameters = { requestBody: schema || ExampleDocumentSchema };
+ let generatedId: string | undefined;
+ try {
+ generatedId = await PostToServer(path, parameters);
+ } catch (e) {
+ console.error(e);
+ generatedId = undefined;
+ } finally {
+ return generatedId;
+ }
+ };
+
+ let path = RouteStore.googleDocs + Actions.Retrieve;
+ export const Retrieve = async (documentId: string): Promise<any> => {
+ let parameters = { documentId };
+ let documentContents: any;
+ try {
+ documentContents = await PostToServer(path, parameters);
+ } catch (e) {
+ console.error(e);
+ documentContents = undefined;
+ } finally {
+ return documentContents;
+ }
+ };
+
+ }
+
+} \ No newline at end of file
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 031478477..0a987de4a 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -15,7 +15,7 @@ import { listSpec } from '../../new_fields/Schema';
import { Cast, FieldValue, NumCast, BoolCast, StrCast } from '../../new_fields/Types';
import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
import { RouteStore } from '../../server/RouteStore';
-import { emptyFunction, returnOne, returnTrue, Utils, returnEmptyString } from '../../Utils';
+import { emptyFunction, returnOne, returnTrue, Utils, returnEmptyString, PostToServer } from '../../Utils';
import { DocServer } from '../DocServer';
import { Docs } from '../documents/Documents';
import { SetupDrag } from '../util/DragManager';
@@ -40,6 +40,8 @@ import { CollectionTreeView } from './collections/CollectionTreeView';
import { ClientUtils } from '../util/ClientUtils';
import { SchemaHeaderField, RandomPastel } from '../../new_fields/SchemaHeaderField';
import { DictationManager } from '../util/DictationManager';
+import { docs_v1 } from 'googleapis';
+import { GoogleApiClientUtils } from '../apis/google_docs/GoogleApiClientUtils';
@observer
export class MainView extends React.Component {
@@ -130,6 +132,8 @@ export class MainView extends React.Component {
window.removeEventListener("keydown", KeyManager.Instance.handle);
window.addEventListener("keydown", KeyManager.Instance.handle);
+ GoogleApiClientUtils.Docs.Create().then(id => console.log(id));
+
reaction(() => {
let workspaces = CurrentUserUtils.UserDocument.workspaces;
let recent = CurrentUserUtils.UserDocument.recentlyClosed;
@@ -569,6 +573,11 @@ export class MainView extends React.Component {
render() {
return (
<div id="main-div">
+ <input style={{ position: "absolute", zIndex: 100000 }} onKeyPress={e => {
+ if (e.which === 13) {
+ GoogleApiClientUtils.Docs.Retrieve(e.currentTarget.value.trim()).then((res: any) => console.log(res));
+ }
+ }} />
{this.dictationOverlay}
<DocumentDecorations />
{this.mainContent}
diff --git a/src/server/Message.ts b/src/server/Message.ts
index aaee143e8..4ec390ade 100644
--- a/src/server/Message.ts
+++ b/src/server/Message.ts
@@ -1,4 +1,5 @@
import { Utils } from "../Utils";
+import { google, docs_v1 } from "googleapis";
export class Message<T> {
private _name: string;
diff --git a/src/server/RouteStore.ts b/src/server/RouteStore.ts
index e30015e39..5d977006a 100644
--- a/src/server/RouteStore.ts
+++ b/src/server/RouteStore.ts
@@ -30,6 +30,7 @@ export enum RouteStore {
reset = "/reset/:token",
// APIS
- cognitiveServices = "/cognitiveservices"
+ cognitiveServices = "/cognitiveservices",
+ googleDocs = "/googleDocs/"
} \ No newline at end of file
diff --git a/src/server/apis/google/GoogleApiServerUtils.ts b/src/server/apis/google/GoogleApiServerUtils.ts
new file mode 100644
index 000000000..817b2b696
--- /dev/null
+++ b/src/server/apis/google/GoogleApiServerUtils.ts
@@ -0,0 +1,109 @@
+import { google, docs_v1 } from "googleapis";
+import { createInterface } from "readline";
+import { readFile, writeFile } from "fs";
+import { OAuth2Client } from "google-auth-library";
+
+/**
+ * Server side authentication for Google Api queries.
+ */
+export namespace GoogleApiServerUtils {
+
+ // If modifying these scopes, delete token.json.
+ const prefix = 'https://www.googleapis.com/auth/';
+ const SCOPES = [
+ 'documents.readonly',
+ 'documents',
+ 'drive',
+ 'drive.file',
+ ];
+ // The file token.json stores the user's access and refresh tokens, and is
+ // created automatically when the authorization flow completes for the first
+ // time.
+ export const parseBuffer = (data: Buffer) => JSON.parse(data.toString());
+
+ export namespace Docs {
+
+ export interface CredentialPaths {
+ credentials: string;
+ token: string;
+ }
+
+ export type Endpoint = docs_v1.Docs;
+
+ export const GetEndpoint = async (paths: CredentialPaths) => {
+ return new Promise<Endpoint>((resolve, reject) => {
+ readFile(paths.credentials, (err, credentials) => {
+ if (err) {
+ reject(err);
+ return console.log('Error loading client secret file:', err);
+ }
+ return authorize(parseBuffer(credentials), paths.token).then(auth => {
+ resolve(google.docs({ version: "v1", auth }));
+ });
+ });
+ });
+ };
+
+ }
+
+ /**
+ * Create an OAuth2 client with the given credentials, and returns the promise resolving to the authenticated client
+ * @param {Object} credentials The authorization client credentials.
+ */
+ export function authorize(credentials: any, token_path: string): Promise<OAuth2Client> {
+ const { client_secret, client_id, redirect_uris } = credentials.installed;
+ const oAuth2Client = new google.auth.OAuth2(
+ client_id, client_secret, redirect_uris[0]);
+
+ return new Promise<OAuth2Client>((resolve, reject) => {
+ readFile(token_path, (err, token) => {
+ // Check if we have previously stored a token.
+ if (err) {
+ return getNewToken(oAuth2Client, token_path).then(resolve, reject);
+ }
+ oAuth2Client.setCredentials(parseBuffer(token));
+ resolve(oAuth2Client);
+ });
+ });
+ }
+
+ /**
+ * Get and store new token after prompting for user authorization, and then
+ * execute the given callback with the authorized OAuth2 client.
+ * @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for.
+ * @param {getEventsCallback} callback The callback for the authorized client.
+ */
+ function getNewToken(oAuth2Client: OAuth2Client, token_path: string) {
+ return new Promise<OAuth2Client>((resolve, reject) => {
+ const authUrl = oAuth2Client.generateAuthUrl({
+ access_type: 'offline',
+ scope: SCOPES.map(relative => prefix + relative),
+ });
+ console.log('Authorize this app by visiting this url:', authUrl);
+ const rl = createInterface({
+ input: process.stdin,
+ output: process.stdout,
+ });
+ rl.question('Enter the code from that page here: ', (code) => {
+ rl.close();
+ oAuth2Client.getToken(code, (err, token) => {
+ if (err || !token) {
+ reject(err);
+ return console.error('Error retrieving access token', err);
+ }
+ oAuth2Client.setCredentials(token);
+ // Store the token to disk for later program executions
+ writeFile(token_path, JSON.stringify(token), (err) => {
+ if (err) {
+ console.error(err);
+ reject(err);
+ }
+ console.log('Token stored to', token_path);
+ });
+ resolve(oAuth2Client);
+ });
+ });
+ });
+ }
+
+} \ No newline at end of file
diff --git a/src/server/youtubeApi/youtubeApiSample.d.ts b/src/server/apis/youtube/youtubeApiSample.d.ts
index 427f54608..427f54608 100644
--- a/src/server/youtubeApi/youtubeApiSample.d.ts
+++ b/src/server/apis/youtube/youtubeApiSample.d.ts
diff --git a/src/server/youtubeApi/youtubeApiSample.js b/src/server/apis/youtube/youtubeApiSample.js
index 50b3c7b38..50b3c7b38 100644
--- a/src/server/youtubeApi/youtubeApiSample.js
+++ b/src/server/apis/youtube/youtubeApiSample.js
diff --git a/src/server/credentials/google_docs_credentials.json b/src/server/credentials/google_docs_credentials.json
new file mode 100644
index 000000000..8d097d363
--- /dev/null
+++ b/src/server/credentials/google_docs_credentials.json
@@ -0,0 +1 @@
+{"installed":{"client_id":"343179513178-ud6tvmh275r2fq93u9eesrnc66t6akh9.apps.googleusercontent.com","project_id":"quickstart-1565056383187","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"w8KIFSc0MQpmUYHed4qEzn8b","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}} \ No newline at end of file
diff --git a/src/server/credentials/google_docs_token.json b/src/server/credentials/google_docs_token.json
new file mode 100644
index 000000000..07c02d56c
--- /dev/null
+++ b/src/server/credentials/google_docs_token.json
@@ -0,0 +1 @@
+{"access_token":"ya29.GltjB4-x03xFpd2NY2555cxg1xlT_ajqRi78M9osOfdOF2jTIjlPkn_UZL8cUwVP0DPC8rH3vhhg8RpspFe8Vewx92shAO3RPos_uMH0CUqEiCiZlaaB5I3Jq3Mv","refresh_token":"1/teUKUqGKMLjVqs-eed0L8omI02pzSxMUYaxGc2QxBw0","scope":"https://www.googleapis.com/auth/documents https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/documents.readonly","token_type":"Bearer","expiry_date":1565654175862} \ No newline at end of file
diff --git a/src/server/index.ts b/src/server/index.ts
index eae018f13..9986e62d6 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -14,7 +14,6 @@ import * as mobileDetect from 'mobile-detect';
import * as passport from 'passport';
import * as path from 'path';
import * as request from 'request';
-import * as rp from 'request-promise';
import * as io from 'socket.io';
import { Socket } from 'socket.io';
import * as webpack from 'webpack';
@@ -36,19 +35,16 @@ const port = 1050; // default port to listen
const serverPort = 4321;
import expressFlash = require('express-flash');
import flash = require('connect-flash');
-import c = require("crypto");
import { Search } from './Search';
-import { debug } from 'util';
import _ = require('lodash');
import * as Archiver from 'archiver';
-import * as AdmZip from 'adm-zip';
-import * as YoutubeApi from './youtubeApi/youtubeApiSample.js';
+import AdmZip from 'adm-zip';
+import * as YoutubeApi from "./apis/youtube/youtubeApiSample";
import { Response } from 'express-serve-static-core';
+import { GoogleApiServerUtils } from "./apis/google/GoogleApiServerUtils";
const MongoStore = require('connect-mongo')(session);
const mongoose = require('mongoose');
const probe = require("probe-image-size");
-var SolrNode = require('solr-node');
-var shell = require('shelljs');
const download = (url: string, dest: fs.PathLike) => request.get(url).pipe(fs.createWriteStream(dest));
let youtubeApiKey: string;
@@ -790,6 +786,29 @@ function HandleYoutubeQuery([query, callback]: [YoutubeQueryInput, (result?: any
}
}
+const credentials = path.join(__dirname, "./credentials/google_docs_credentials.json");
+const token = path.join(__dirname, "./credentials/google_docs_token.json");
+
+app.post(RouteStore.googleDocs + ":action", (req, res) => {
+ let parameters = req.body;
+ console.log(parameters, req.params.action);
+
+ GoogleApiServerUtils.Docs.GetEndpoint({ credentials, token }).then(endpoint => {
+ let results: Promise<any> | undefined;
+ switch (req.params.action) {
+ case "create":
+ results = endpoint.documents.create(parameters).then(generated => generated.data.documentId);
+ break;
+ case "retrieve":
+ results = endpoint.documents.get(parameters).then(response => response.data);
+ break;
+ default:
+ results = undefined;
+ }
+ results && results.then(final => res.send(final));
+ });
+});
+
const suffixMap: { [type: string]: (string | [string, string | ((json: any) => any)]) } = {
"number": "_n",
"string": "_t",