diff options
Diffstat (limited to 'src/server')
-rw-r--r-- | src/server/Message.ts | 11 | ||||
-rw-r--r-- | src/server/index.ts | 20 | ||||
-rw-r--r-- | src/server/youtubeApi/youtubeApiSample.d.ts | 2 | ||||
-rw-r--r-- | src/server/youtubeApi/youtubeApiSample.js | 179 |
4 files changed, 210 insertions, 2 deletions
diff --git a/src/server/Message.ts b/src/server/Message.ts index 19e0a48aa..aaee143e8 100644 --- a/src/server/Message.ts +++ b/src/server/Message.ts @@ -24,6 +24,16 @@ export interface Transferable { readonly data?: any; } +export enum YoutubeQueryTypes { + Channels, SearchVideo, VideoDetails +} + +export interface YoutubeQueryInput { + readonly type: YoutubeQueryTypes; + readonly userInput?: string; + readonly videoIds?: string; +} + export interface Reference { readonly id: string; } @@ -45,6 +55,7 @@ export namespace MessageStore { export const GetRefFields = new Message<string[]>("Get Ref Fields"); export const UpdateField = new Message<Diff>("Update Ref Field"); export const CreateField = new Message<Reference>("Create Ref Field"); + export const YoutubeApiQuery = new Message<YoutubeQueryInput>("Youtube Api Query"); export const DeleteField = new Message<string>("Delete field"); export const DeleteFields = new Message<string[]>("Delete fields"); } diff --git a/src/server/index.ts b/src/server/index.ts index 66c982adc..cf117b938 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -25,7 +25,7 @@ import { getForgot, getLogin, getLogout, getReset, getSignup, postForgot, postLo import { DashUserModel } from './authentication/models/user_model'; import { Client } from './Client'; import { Database } from './database'; -import { MessageStore, Transferable, Types, Diff, Message } from "./Message"; +import { MessageStore, Transferable, Types, Diff, YoutubeQueryTypes as YoutubeQueryType, YoutubeQueryInput } from "./Message"; import { RouteStore } from './RouteStore'; const app = express(); const config = require('../../webpack.config'); @@ -39,12 +39,15 @@ import c = require("crypto"); import { Search } from './Search'; import { debug } from 'util'; import _ = require('lodash'); +import * as YoutubeApi from './youtubeApi/youtubeApiSample.js'; import { Response } from 'express-serve-static-core'; const MongoStore = require('connect-mongo')(session); const mongoose = require('mongoose'); const probe = require("probe-image-size"); const download = (url: string, dest: fs.PathLike) => request.get(url).pipe(fs.createWriteStream(dest)); +let youtubeApiKey: string; +YoutubeApi.readApiKey((apiKey: string) => youtubeApiKey = apiKey); const release = process.env.RELEASE === "true"; if (process.env.RELEASE === "true") { @@ -483,6 +486,7 @@ server.on("connection", function (socket: Socket) { } Utils.AddServerHandler(socket, MessageStore.CreateField, CreateField); + Utils.AddServerHandlerCallback(socket, MessageStore.YoutubeApiQuery, HandleYoutubeQuery); Utils.AddServerHandler(socket, MessageStore.UpdateField, diff => UpdateField(socket, diff)); Utils.AddServerHandler(socket, MessageStore.DeleteField, id => DeleteField(socket, id)); Utils.AddServerHandler(socket, MessageStore.DeleteFields, ids => DeleteFields(socket, ids)); @@ -537,6 +541,17 @@ function GetRefFields([ids, callback]: [string[], (result?: Transferable[]) => v Database.Instance.getDocuments(ids, callback, "newDocuments"); } +function HandleYoutubeQuery([query, callback]: [YoutubeQueryInput, (result?: any[]) => void]) { + switch (query.type) { + case YoutubeQueryType.Channels: + YoutubeApi.authorizedGetChannel(youtubeApiKey); + break; + case YoutubeQueryType.SearchVideo: + YoutubeApi.authorizedGetVideos(youtubeApiKey, query.userInput, callback); + case YoutubeQueryType.VideoDetails: + YoutubeApi.authorizedGetVideoDetails(youtubeApiKey, query.videoIds, callback); + } +} const suffixMap: { [type: string]: (string | [string, string | ((json: any) => any)]) } = { "number": "_n", @@ -636,4 +651,5 @@ function CreateField(newValue: any) { } server.listen(serverPort); -console.log(`listening on port ${serverPort}`);
\ No newline at end of file +console.log(`listening on port ${serverPort}`); + diff --git a/src/server/youtubeApi/youtubeApiSample.d.ts b/src/server/youtubeApi/youtubeApiSample.d.ts new file mode 100644 index 000000000..427f54608 --- /dev/null +++ b/src/server/youtubeApi/youtubeApiSample.d.ts @@ -0,0 +1,2 @@ +declare const YoutubeApi: any; +export = YoutubeApi;
\ No newline at end of file diff --git a/src/server/youtubeApi/youtubeApiSample.js b/src/server/youtubeApi/youtubeApiSample.js new file mode 100644 index 000000000..ec532c78e --- /dev/null +++ b/src/server/youtubeApi/youtubeApiSample.js @@ -0,0 +1,179 @@ +const fs = require('fs'); +const readline = require('readline'); +const { google } = require('googleapis'); +const OAuth2 = google.auth.OAuth2; + + +// If modifying these scopes, delete your previously saved credentials +// at ~/.credentials/youtube-nodejs-quickstart.json +let SCOPES = ['https://www.googleapis.com/auth/youtube.readonly']; +let TOKEN_DIR = (process.env.HOME || process.env.HOMEPATH || + process.env.USERPROFILE) + '/.credentials/'; +let TOKEN_PATH = TOKEN_DIR + 'youtube-nodejs-quickstart.json'; + +module.exports.readApiKey = (callback) => { + fs.readFile('client_secret.json', function processClientSecrets(err, content) { + if (err) { + console.log('Error loading client secret file: ' + err); + return; + } + callback(content); + }); +} + +module.exports.authorizedGetChannel = (apiKey) => { + //this didnt get called + // Authorize a client with the loaded credentials, then call the YouTube API. + authorize(JSON.parse(apiKey), getChannel); +} + +module.exports.authorizedGetVideos = (apiKey, userInput, callBack) => { + authorize(JSON.parse(apiKey), getVideos, { userInput: userInput, callBack: callBack }); +} + +module.exports.authorizedGetVideoDetails = (apiKey, videoIds, callBack) => { + authorize(JSON.parse(apiKey), getVideoDetails, { videoIds: videoIds, callBack: callBack }); +} + + +/** + * Create an OAuth2 client with the given credentials, and then execute the + * given callback function. + * + * @param {Object} credentials The authorization client credentials. + * @param {function} callback The callback to call with the authorized client. + */ +function authorize(credentials, callback, args = {}) { + let clientSecret = credentials.installed.client_secret; + let clientId = credentials.installed.client_id; + let redirectUrl = credentials.installed.redirect_uris[0]; + let oauth2Client = new OAuth2(clientId, clientSecret, redirectUrl); + + // Check if we have previously stored a token. + fs.readFile(TOKEN_PATH, function (err, token) { + if (err) { + getNewToken(oauth2Client, callback); + } else { + oauth2Client.credentials = JSON.parse(token); + callback(oauth2Client, args); + } + }); +} + +/** + * 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 to call with the authorized + * client. + */ +function getNewToken(oauth2Client, callback) { + var authUrl = oauth2Client.generateAuthUrl({ + access_type: 'offline', + scope: SCOPES + }); + console.log('Authorize this app by visiting this url: ', authUrl); + var rl = readline.createInterface({ + input: process.stdin, + output: process.stdout + }); + rl.question('Enter the code from that page here: ', function (code) { + rl.close(); + oauth2Client.getToken(code, function (err, token) { + if (err) { + console.log('Error while trying to retrieve access token', err); + return; + } + oauth2Client.credentials = token; + storeToken(token); + callback(oauth2Client); + }); + }); +} + +/** + * Store token to disk be used in later program executions. + * + * @param {Object} token The token to store to disk. + */ +function storeToken(token) { + try { + fs.mkdirSync(TOKEN_DIR); + } catch (err) { + if (err.code != 'EEXIST') { + throw err; + } + } + fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => { + if (err) throw err; + console.log('Token stored to ' + TOKEN_PATH); + }); + console.log('Token stored to ' + TOKEN_PATH); +} + +/** + * Lists the names and IDs of up to 10 files. + * + * @param {google.auth.OAuth2} auth An authorized OAuth2 client. + */ +function getChannel(auth) { + var service = google.youtube('v3'); + service.channels.list({ + auth: auth, + part: 'snippet,contentDetails,statistics', + forUsername: 'GoogleDevelopers' + }, function (err, response) { + if (err) { + console.log('The API returned an error: ' + err); + return; + } + var channels = response.data.items; + if (channels.length == 0) { + console.log('No channel found.'); + } else { + console.log('This channel\'s ID is %s. Its title is \'%s\', and ' + + 'it has %s views.', + channels[0].id, + channels[0].snippet.title, + channels[0].statistics.viewCount); + } + }); +} + +function getVideos(auth, args) { + let service = google.youtube('v3'); + service.search.list({ + auth: auth, + part: 'id, snippet', + type: 'video', + q: args.userInput, + maxResults: 3 + }, function (err, response) { + if (err) { + console.log('The API returned an error: ' + err); + return; + } + let videos = response.data.items; + args.callBack(videos); + }); +} + +function getVideoDetails(auth, args) { + if (args.videoIds === undefined) { + return; + } + let service = google.youtube('v3'); + service.videos.list({ + auth: auth, + part: 'contentDetails, statistics', + id: args.videoIds + }, function (err, response) { + if (err) { + console.log('The API returned an error from details: ' + err); + return; + } + let videoDetails = response.data.items; + args.callBack(videoDetails); + }); +}
\ No newline at end of file |