UNPKG

picasa

Version:

Picasa web albums client for node

488 lines (397 loc) 17.1 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <title>picasa.js - Documentation</title> <script src="scripts/prettify/prettify.js"></script> <script src="scripts/prettify/lang-css.js"></script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css"> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <input type="checkbox" id="nav-trigger" class="nav-trigger" /> <label for="nav-trigger" class="navicon-button x"> <div class="navicon"></div> </label> <label for="nav-trigger" class="overlay"></label> <nav> <li class="nav-link nav-home-link"><a href="index.html">Home</a></li><li class="nav-heading">Classes</li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Picasa.html">Picasa</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Picasa.html#createAlbum">createAlbum</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Picasa.html#deletePhoto">deletePhoto</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Picasa.html#getAlbums">getAlbums</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Picasa.html#getAuthURL">getAuthURL</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Picasa.html#getPhotos">getPhotos</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Picasa.html#getTokens">getTokens</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Picasa.html#postPhoto">postPhoto</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Picasa.html#renewAccessToken">renewAccessToken</a></span></li><li class="nav-heading"><a href="global.html">Globals</a></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#getAccessToken">getAccessToken</a></span></li> </nav> <div id="main"> <h1 class="page-title">picasa.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>'use strict' const querystring = require('querystring') const promisify = require('./promisify') const executeRequest = require('./executeRequest') const GOOGLE_AUTH_ENDPOINT = 'https://accounts.google.com/o/oauth2/auth' const GOOGLE_API_HOST = 'https://www.googleapis.com' const GOOGLE_API_PATH = '/oauth2/v3/token' const GOOGLE_API_PATH_NEW = '/oauth2/v4/token' const PICASA_SCOPE = 'https://picasaweb.google.com/data' const PICASA_API_FEED_PATH = '/feed/api/user/default' const PICASA_API_ENTRY_PATH = '/entry/api/user/default' const FETCH_AS_JSON = 'json' /** Main class */ class Picasa { /** * Creates an instance of Picasa. */ constructor() { this.executeRequest = executeRequest this.getAccessToken = getAccessToken.bind(this) } /** * Get Photos * @param {string} accessToken - See {@link Picasa#getTokens} * @param {object} options - Can be empty object * @param {integer} options.maxResults - By default get all photos * @param {string} options.albumId - By default all photos are selected * @param {function} callback - (error, response). If not provided, a promise will be returned * @returns {Promise} */ getPhotos() { return promisify.bind(this)(getPhotos, arguments) } /** * Create Photos * @param {string} accessToken - See {@link Picasa#getTokens} * @param {string} albumId * @param {object} photoData - Photo's propperties * @param {string} photoData.title * @param {string} photoData.summary * @param {string} photoData.contentType - image/bmp, image/gif, image/png * @param {blob} photoData.binary - Blob binary * @param {function} callback - (error, response). If not provided, a promise will be returned * @returns {Promise} */ postPhoto() { return promisify.bind(this)(postPhoto, arguments) } /** * Delete Photo * @param {string} accessToken - See {@link Picasa#getTokens} * @param {string} albumId * @param {string} photoId * @param {function} callback - (error, response). If not provided, a promise will be returned * @returns {Promise} */ deletePhoto() { return promisify.bind(this)(deletePhoto, arguments) } /** * Get all Albums * @param {string} accessToken - See {@link Picasa#getTokens} * @param {object} options - Can be empty object * @param {integer} options.TODO - TODO * @param {function} callback - (error, response). If not provided, a promise will be returned * @returns {Promise} */ getAlbums() { return promisify.bind(this)(getAlbums, arguments) } /** * Create an albums * @param {string} accessToken - See {@link Picasa#getTokens} * @param {object} albumData - Can be empty object * @param {string} albumData.title * @param {string} albumData.summary * @param {function} callback - (error, response). If not provided, a promise will be returned * @returns {Promise} */ createAlbum() { return promisify.bind(this)(createAlbum, arguments) } /** * Get access token and refresh token * @param {object} config - Get config here: {@link https://console.developers.google.com/home/dashboard} (API Manager > Credentials) * @param {string} config.clientId * @param {string} config.redirectURI - URL that user was redirected. After google displays a consent screen to the user, user will be redirect to this URL with a `code` in the URL * @param {string} config.clientSecret * @param {string} code - Get code from URL param, when user is redirected from authURL. See {@link Picasa#getAuthURL} * @param {function} callback - (error, response{accessToken, refreshToken}). If not provided, a promise will be returned * @returns {Promise} - Object{accessToken, refreshToken} */ getTokens() { return promisify.bind(this)(getTokens, arguments) } /** * Renews access token * @param {object} config - Get config here: {@link https://console.developers.google.com/home/dashboard} (API Manager > Credentials) * @param {string} config.clientId * @param {string} config.redirectURI - URL that user was redirected. After google displays a consent screen to the user, user will be redirect to this URL with a `code` in the URL * @param {string} config.clientSecret * @param {string} refreshToken - The refreshToken is retrived after getTokens is executed. See {@link Picasa#getTokens} * @param {function} callback - (error, response). If not provided, a promise will be returned * @returns {Promise} */ renewAccessToken() { return promisify.bind(this)(renewAccessToken, arguments) } /** * Get Auth URL. Redirect user to this URL to get code. The code will be used later for {@link Picasa#getTokens} * @param {object} config - Get config here: https://console.developers.google.com/home/dashboard (API Manager > Credentials) * @param {string} config.clientId * @param {string} config.redirectURI - URL to user will be redirected. After google displays a consent screen to the user, user will be redirect to this URL with a `code` in the URL * @param {function} callback - (error, response). If not provided, a promise will be returned * @returns {Promise} */ getAuthURL(config) { const authenticationParams = { access_type: 'offline', scope: `${PICASA_SCOPE}`, response_type: 'code', client_id: config.clientId, redirect_uri: config.redirectURI } const authenticationQuery = querystring.stringify(authenticationParams) return `${GOOGLE_AUTH_ENDPOINT}?${authenticationQuery}` } } function getAlbums(accessToken, options, callback) { const accessTokenParams = { alt: FETCH_AS_JSON, access_token: accessToken } options = options || {} const requestQuery = querystring.stringify(accessTokenParams) const requestOptions = { url: `${PICASA_SCOPE}${PICASA_API_FEED_PATH}?${requestQuery}`, headers: { 'GData-Version': '2' } } this.executeRequest('get', requestOptions, (error, body) => { if (error) return callback(error) const albums = body.feed.entry.map( entry => parseEntry(entry, albumSchema) ) callback(null, albums) }) } function deletePhoto(accessToken, albumId, photoId, callback) { const requestQuery = querystring.stringify({ alt: FETCH_AS_JSON, access_token: accessToken }) const requestOptions = { url: `${PICASA_SCOPE}${PICASA_API_ENTRY_PATH}/albumid/${albumId}/photoid/${photoId}?${requestQuery}`, headers: { 'If-Match': '*' } } this.executeRequest('del', requestOptions, callback) } function createAlbum(accessToken, albumData, callback) { const requestQuery = querystring.stringify({ alt: FETCH_AS_JSON, access_token: accessToken }) const albumInfoAtom = `&lt;entry xmlns='http://www.w3.org/2005/Atom' xmlns:media='http://search.yahoo.com/mrss/' xmlns:gphoto='http://schemas.google.com/photos/2007'> &lt;title type='text'>${albumData.title}&lt;/title> &lt;summary type='text'>${albumData.summary}&lt;/summary> &lt;gphoto:access>private&lt;/gphoto:access> &lt;category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/photos/2007#album'>&lt;/category> &lt;/entry>` const requestOptions = { url: `${PICASA_SCOPE}${PICASA_API_FEED_PATH}?${requestQuery}`, body: albumInfoAtom, headers: { 'Content-Type': 'application/atom+xml' } } this.executeRequest('post', requestOptions, (error, body) => { if (error) return callback(error) const album = parseEntry(body.entry, albumSchema) callback(error, album) }) } function postPhoto(accessToken, albumId, photoData, callback) { const requestQuery = querystring.stringify({ alt: FETCH_AS_JSON, access_token: accessToken }) const photoInfoAtom = `&lt;entry xmlns="http://www.w3.org/2005/Atom"> &lt;title>${photoData.title}&lt;/title> &lt;summary>${photoData.summary}&lt;/summary> &lt;category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/photos/2007#photo"/> &lt;/entry>` const requestOptions = { url: `${PICASA_SCOPE}${PICASA_API_FEED_PATH}/albumid/${albumId}?${requestQuery}`, multipart: [ { 'Content-Type': 'application/atom+xml', body: photoInfoAtom }, { 'Content-Type': photoData.contentType, body: photoData.binary } ] } this.executeRequest('post', requestOptions, (error, body) => { if (error) return callback(error) const photo = parseEntry(body.entry, photoSchema) callback(error, photo) }) } function getPhotos(accessToken, options, callback) { const accessTokenParams = { alt: FETCH_AS_JSON, kind: 'photo', access_token: accessToken } options = options || {} if (options.maxResults) accessTokenParams['max-results'] = options.maxResults if (options.startIndex) accessTokenParams['start-index'] = options.startIndex if (options.imgMax) accessTokenParams['imgmax'] = options.imgMax const albumPart = options.albumId ? `/albumid/${options.albumId}` : '' const requestQuery = querystring.stringify(accessTokenParams) const requestOptions = { url: `${PICASA_SCOPE}${PICASA_API_FEED_PATH}${albumPart}?${requestQuery}`, headers: { 'GData-Version': '2' } } this.executeRequest('get', requestOptions, (error, body) => { if (error) return callback(error) const photos = body.feed.entry.map( entry => parseEntry(entry, photoSchema) ) callback(null, photos) }) } const albumSchema = { 'media$group.media$thumbnail': 'thumbnail', 'gphoto$id': 'id', 'gphoto$name': 'name', 'gphoto$numphotos': 'num_photos', 'published': 'published', 'title': 'title', 'summary': 'summary', 'gphoto$location': 'location', 'gphoto$nickname': 'nickname', 'rights': 'rights', 'gphoto$access': 'access' } const photoSchema = { 'gphoto$id': 'id', 'gphoto$albumid': 'album_id', 'gphoto$access': 'access', 'gphoto$width': 'width', 'gphoto$height': 'height', 'gphoto$size': 'size', 'gphoto$checksum': 'checksum', 'gphoto$timestamp': 'timestamp', 'gphoto$imageVersion': 'image_version', 'gphoto$commentingEnabled': 'commenting_enabled', 'gphoto$commentCount': 'comment_count', 'content': 'content', 'title': 'title', 'summary': 'summary' } function parseEntry(entry, schema) { let photo = {} Object.keys(schema).forEach(schemaKey => { const key = schema[schemaKey] if (key) { const value = extractValue(entry, schemaKey, key) photo[key] = value } }) return photo } function extractValue(entry, schemaKey) { if (schemaKey.indexOf('.') !== -1) { const tempKey = schemaKey.split('.')[0] return extractValue(checkParam(entry[tempKey]), schemaKey.replace(`${tempKey}.`, '')) } return checkParam(entry[schemaKey]) } function getAuthURL(config) { const authenticationParams = { access_type: 'offline', scope: `${PICASA_SCOPE}`, response_type: 'code', client_id: config.clientId, redirect_uri: config.redirectURI } const authenticationQuery = querystring.stringify(authenticationParams) return `${GOOGLE_AUTH_ENDPOINT}?${authenticationQuery}` } /** * Get access token. To be deprecated soon. Use {@link Picasa#getTokens} instead * @param {object} config - Get config here: {@link https://console.developers.google.com/home/dashboard} (API Manager > Credentials) * @param {string} config.clientId * @param {string} config.redirectURI - URL that user was redirected. After google displays a consent screen to the user, user will be redirect to this URL with a `code` in the URL * @param {string} config.clientSecret * @param {string} code - Get code from URL param, when user is redirected from authURL. See {@link Picasa#getAuthURL} * @param {function} callback - (error, response{accessToken, refreshToken}). If not provided, a promise will be returned * @returns {Promise} - String accessToken */ function getAccessToken(config, code, callback) { const accessTokenParams = { grant_type: 'authorization_code', code: code, redirect_uri: config.redirectURI, client_id: config.clientId, client_secret: config.clientSecret } const requestQuery = querystring.stringify(accessTokenParams) const options = { url: `${GOOGLE_API_HOST}${GOOGLE_API_PATH}?${requestQuery}` } this.executeRequest('post', options, (error, body) => { if (error) return callback(error) callback(null, body.access_token, body.refresh_token) }) } function getTokens(config, code, callback) { return getAccessToken(config, code, (error, accessToken, refreshToken) => { if (error) return callback(error) const tokens = { accessToken, refreshToken, } callback(null, tokens) }) } function renewAccessToken(config, refresh_token, callback) { const refreshTokenParams = { grant_type: 'refresh_token', client_id: config.clientId, client_secret: config.clientSecret, refresh_token: refresh_token } const requestQuery = querystring.stringify(refreshTokenParams) const options = { url: `${GOOGLE_API_HOST}${GOOGLE_API_PATH_NEW}?${requestQuery}` } this.executeRequest('post', options, (error, body) => { if (error) return callback(error) callback(null, body.access_token) }) } function checkParam(param) { if (param === undefined) return '' else if (isValidType(param)) return param else if (isValidType(param['$t'])) return param['$t'] else return param } function isValidType(value) { return typeof value === 'string' || typeof value === 'number' } module.exports = Picasa </code></pre> </article> </section> </div> <br class="clear"> <footer> Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Sun Mar 04 2018 20:34:29 GMT+0100 (CET) using the Minami theme. </footer> <script>prettyPrint();</script> <script src="scripts/linenumber.js"></script> </body> </html>