2021-04-05 03:29:26 -07:00
import {
IExecuteFunctions ,
} from 'n8n-core' ;
import {
IDataObject ,
ILoadOptionsFunctions ,
INodeExecutionData ,
INodePropertyOptions ,
INodeType ,
INodeTypeDescription ,
} from 'n8n-workflow' ;
import {
googleApiRequest ,
} from './GenericFunctions' ;
export class GoogleSlides implements INodeType {
description : INodeTypeDescription = {
displayName : 'Google Slides' ,
name : 'googleSlides' ,
icon : 'file:googleslides.svg' ,
group : [ 'input' , 'output' ] ,
version : 1 ,
subtitle : '={{$parameter["operation"] + ": " + $parameter["resource"]}}' ,
description : 'Consume the Google Slides API' ,
defaults : {
name : 'Google Slides' ,
color : '#edba25' ,
} ,
inputs : [ 'main' ] ,
outputs : [ 'main' ] ,
credentials : [
{
name : 'googleApi' ,
required : true ,
displayOptions : {
show : {
authentication : [
'serviceAccount' ,
] ,
} ,
} ,
} ,
{
name : 'googleSlidesOAuth2Api' ,
required : true ,
displayOptions : {
show : {
authentication : [
'oAuth2' ,
] ,
} ,
} ,
} ,
] ,
properties : [
{
displayName : 'Authentication' ,
name : 'authentication' ,
type : 'options' ,
options : [
{
name : 'OAuth2' ,
value : 'oAuth2' ,
} ,
{
name : 'Service Account' ,
value : 'serviceAccount' ,
} ,
] ,
default : 'serviceAccount' ,
} ,
{
displayName : 'Resource' ,
name : 'resource' ,
type : 'options' ,
options : [
{
name : 'Page' ,
value : 'page' ,
} ,
{
name : 'Presentation' ,
value : 'presentation' ,
} ,
] ,
default : 'presentation' ,
description : 'Resource to operate on' ,
} ,
{
displayName : 'Operation' ,
name : 'operation' ,
type : 'options' ,
options : [
{
name : 'Create' ,
value : 'create' ,
description : 'Create a presentation' ,
} ,
{
name : 'Get' ,
value : 'get' ,
description : 'Get a presentation' ,
} ,
{
name : 'Get Slides' ,
value : 'getSlides' ,
description : 'Get presentation slides' ,
} ,
{
name : 'Replace Text' ,
value : 'replaceText' ,
description : 'Replace text in a presentation' ,
} ,
] ,
displayOptions : {
show : {
resource : [
'presentation' ,
] ,
} ,
} ,
default : 'create' ,
description : 'Operation to perform' ,
} ,
{
displayName : 'Operation' ,
name : 'operation' ,
type : 'options' ,
options : [
{
name : 'Get' ,
value : 'get' ,
description : 'Get a page' ,
} ,
{
name : 'Get Thumbnail' ,
value : 'getThumbnail' ,
description : 'Get a thumbnail' ,
} ,
] ,
displayOptions : {
show : {
resource : [
'page' ,
] ,
} ,
} ,
default : 'get' ,
description : 'Operation to perform' ,
} ,
{
displayName : 'Title' ,
name : 'title' ,
description : 'Title of the presentation to create.' ,
type : 'string' ,
default : '' ,
required : true ,
displayOptions : {
show : {
resource : [
'presentation' ,
] ,
operation : [
'create' ,
] ,
} ,
} ,
} ,
{
displayName : 'Presentation ID' ,
name : 'presentationId' ,
description : 'ID of the presentation to retrieve. Found in the presentation URL:<br><code>https://docs.google.com/presentation/d/PRESENTATION_ID/edit</code>' ,
placeholder : '1wZtNFZ8MO-WKrxhYrOLMvyiqSgFwdSz5vn8_l_7eNqw' ,
type : 'string' ,
default : '' ,
required : true ,
displayOptions : {
show : {
resource : [
'presentation' ,
'page' ,
] ,
operation : [
'get' ,
'getThumbnail' ,
'getSlides' ,
'replaceText' ,
] ,
} ,
} ,
} ,
{
displayName : 'Return All' ,
name : 'returnAll' ,
type : 'boolean' ,
displayOptions : {
show : {
operation : [
'getSlides' ,
] ,
resource : [
'presentation' ,
] ,
} ,
} ,
default : false ,
description : 'If all results should be returned or only up to a given limit.' ,
} ,
{
displayName : 'Limit' ,
name : 'limit' ,
type : 'number' ,
displayOptions : {
show : {
operation : [
'getSlides' ,
] ,
resource : [
'presentation' ,
] ,
returnAll : [
false ,
] ,
} ,
} ,
typeOptions : {
minValue : 1 ,
maxValue : 500 ,
} ,
default : 100 ,
description : 'How many results to return.' ,
} ,
{
displayName : 'Page Object ID' ,
name : 'pageObjectId' ,
description : 'ID of the page object to retrieve.' ,
type : 'string' ,
default : '' ,
required : true ,
displayOptions : {
show : {
resource : [
'page' ,
] ,
operation : [
'get' ,
'getThumbnail' ,
] ,
} ,
} ,
} ,
{
displayName : 'Texts To Replace' ,
name : 'textUi' ,
placeholder : 'Add Text' ,
type : 'fixedCollection' ,
typeOptions : {
multipleValues : true ,
} ,
displayOptions : {
show : {
resource : [
'presentation' ,
] ,
operation : [
'replaceText' ,
] ,
} ,
} ,
default : { } ,
options : [
{
name : 'textValues' ,
displayName : 'Text' ,
values : [
{
displayName : 'Match Case' ,
name : 'matchCase' ,
type : 'boolean' ,
default : false ,
description : 'Indicates whether the search should respect case. True : the search is case sensitive. False : the search is case insensitive.' ,
} ,
{
displayName : 'Page IDs' ,
name : 'pageObjectIds' ,
type : 'multiOptions' ,
default : [ ] ,
typeOptions : {
loadOptionsMethod : 'getPages' ,
loadOptionsDependsOn : [
'presentationId' ,
] ,
} ,
description : 'If non-empty, limits the matches to page elements only on the given pages.' ,
} ,
{
displayName : 'Replace Text' ,
name : 'replaceText' ,
type : 'string' ,
default : '' ,
description : 'The text that will replace the matched text.' ,
} ,
{
displayName : 'Text' ,
name : 'text' ,
type : 'string' ,
default : '' ,
description : 'The text to search for in the shape or table.' ,
} ,
] ,
} ,
] ,
} ,
{
displayName : 'Options' ,
name : 'options' ,
type : 'collection' ,
placeholder : 'Add Option' ,
displayOptions : {
show : {
operation : [
'replaceText' ,
] ,
resource : [
'presentation' ,
] ,
} ,
} ,
default : { } ,
options : [
{
displayName : 'Revision ID' ,
name : 'revisionId' ,
type : 'string' ,
default : '' ,
description : ` The revision ID of the presentation required for the write request.</br>
If specified and the requiredRevisionId doesn 't exactly match the presentation' s < / br >
current revisionId , the request will not be processed and will return a 400 bad request error . ` ,
} ,
] ,
} ,
{
displayName : 'Download' ,
name : 'download' ,
type : 'boolean' ,
default : false ,
displayOptions : {
show : {
resource : [
'page' ,
] ,
operation : [
'getThumbnail' ,
] ,
} ,
} ,
2021-10-27 13:00:13 -07:00
description : 'Name of the binary property to which to write the data of the read page.' ,
2021-04-05 03:29:26 -07:00
} ,
{
displayName : 'Binary Property' ,
name : 'binaryProperty' ,
type : 'string' ,
required : true ,
default : 'data' ,
description : 'Name of the binary property to which to write to.' ,
displayOptions : {
show : {
resource : [
'page' ,
] ,
operation : [
'getThumbnail' ,
] ,
download : [
true ,
] ,
} ,
} ,
} ,
] ,
} ;
methods = {
loadOptions : {
// Get all the pages to display them to user so that he can
// select them easily
async getPages (
this : ILoadOptionsFunctions ,
) : Promise < INodePropertyOptions [ ] > {
const returnData : INodePropertyOptions [ ] = [ ] ;
const presentationId = this . getCurrentNodeParameter ( 'presentationId' ) as string ;
const { slides } = await googleApiRequest . call ( this , 'GET' , ` /presentations/ ${ presentationId } ` , { } , { fields : 'slides' } ) ;
for ( const slide of slides ) {
returnData . push ( {
name : slide.objectId ,
value : slide.objectId ,
} ) ;
}
return returnData ;
} ,
} ,
} ;
async execute ( this : IExecuteFunctions ) : Promise < INodeExecutionData [ ] [ ] > {
const items = this . getInputData ( ) ;
const resource = this . getNodeParameter ( 'resource' , 0 ) as string ;
const operation = this . getNodeParameter ( 'operation' , 0 ) as string ;
let responseData ;
const returnData : INodeExecutionData [ ] = [ ] ;
for ( let i = 0 ; i < items . length ; i ++ ) {
2021-07-19 23:58:54 -07:00
try {
if ( resource === 'page' ) {
// *********************************************************************
// page
// *********************************************************************
if ( operation === 'get' ) {
// ----------------------------------
// page: get
// ----------------------------------
const presentationId = this . getNodeParameter ( 'presentationId' , i ) as string ;
const pageObjectId = this . getNodeParameter ( 'pageObjectId' , i ) as string ;
responseData = await googleApiRequest . call ( this , 'GET' , ` /presentations/ ${ presentationId } /pages/ ${ pageObjectId } ` ) ;
2021-04-05 03:29:26 -07:00
returnData . push ( { json : responseData } ) ;
2021-07-19 23:58:54 -07:00
} else if ( operation === 'getThumbnail' ) {
// ----------------------------------
// page: getThumbnail
// ----------------------------------
const presentationId = this . getNodeParameter ( 'presentationId' , i ) as string ;
const pageObjectId = this . getNodeParameter ( 'pageObjectId' , i ) as string ;
responseData = await googleApiRequest . call ( this , 'GET' , ` /presentations/ ${ presentationId } /pages/ ${ pageObjectId } /thumbnail ` ) ;
const download = this . getNodeParameter ( 'download' , 0 ) as boolean ;
if ( download === true ) {
const binaryProperty = this . getNodeParameter ( 'binaryProperty' , i ) as string ;
const data = await this . helpers . request ( {
uri : responseData.contentUrl ,
method : 'GET' ,
json : false ,
encoding : null ,
} ) ;
const fileName = pageObjectId + '.png' ;
const binaryData = await this . helpers . prepareBinaryData ( data , fileName || fileName ) ;
returnData . push ( {
json : responseData ,
binary : {
[ binaryProperty ] : binaryData ,
} ,
} ) ;
} else {
returnData . push ( { json : responseData } ) ;
}
}
2021-04-05 03:29:26 -07:00
2021-07-19 23:58:54 -07:00
} else if ( resource === 'presentation' ) {
2021-04-05 03:29:26 -07:00
2021-07-19 23:58:54 -07:00
// *********************************************************************
// presentation
// *********************************************************************
2021-04-05 03:29:26 -07:00
2021-07-19 23:58:54 -07:00
if ( operation === 'create' ) {
2021-04-05 03:29:26 -07:00
2021-07-19 23:58:54 -07:00
// ----------------------------------
// presentation: create
// ----------------------------------
2021-04-05 03:29:26 -07:00
2021-07-19 23:58:54 -07:00
const body = {
title : this.getNodeParameter ( 'title' , i ) as string ,
} ;
2021-04-05 03:29:26 -07:00
2021-07-19 23:58:54 -07:00
responseData = await googleApiRequest . call ( this , 'POST' , '/presentations' , body ) ;
returnData . push ( { json : responseData } ) ;
2021-04-05 03:29:26 -07:00
2021-07-19 23:58:54 -07:00
} else if ( operation === 'get' ) {
2021-04-05 03:29:26 -07:00
2021-07-19 23:58:54 -07:00
// ----------------------------------
// presentation: get
// ----------------------------------
2021-04-05 03:29:26 -07:00
2021-07-19 23:58:54 -07:00
const presentationId = this . getNodeParameter ( 'presentationId' , i ) as string ;
responseData = await googleApiRequest . call ( this , 'GET' , ` /presentations/ ${ presentationId } ` ) ;
returnData . push ( { json : responseData } ) ;
2021-04-05 03:29:26 -07:00
2021-07-19 23:58:54 -07:00
} else if ( operation === 'getSlides' ) {
// ----------------------------------
// presentation: getSlides
// ----------------------------------
const returnAll = this . getNodeParameter ( 'returnAll' , 0 ) as boolean ;
const presentationId = this . getNodeParameter ( 'presentationId' , i ) as string ;
responseData = await googleApiRequest . call ( this , 'GET' , ` /presentations/ ${ presentationId } ` , { } , { fields : 'slides' } ) ;
responseData = responseData . slides ;
if ( returnAll === false ) {
const limit = this . getNodeParameter ( 'limit' , i ) as number ;
responseData = responseData . slice ( 0 , limit ) ;
}
returnData . push ( . . . this . helpers . returnJsonArray ( responseData ) ) ;
} else if ( operation === 'replaceText' ) {
// ----------------------------------
// presentation: replaceText
// ----------------------------------
const presentationId = this . getNodeParameter ( 'presentationId' , i ) as string ;
const texts = this . getNodeParameter ( 'textUi.textValues' , i , [ ] ) as IDataObject [ ] ;
const options = this . getNodeParameter ( 'options' , i ) as IDataObject ;
const requests = texts . map ( ( text = > {
return {
replaceAllText : {
replaceText : text.replaceText ,
pageObjectIds : text.pageObjectIds || [ ] ,
containsText : {
text : text.text ,
matchCase : text.matchCase ,
} ,
2021-04-05 03:29:26 -07:00
} ,
2021-07-19 23:58:54 -07:00
} ;
} ) ) ;
const body : IDataObject = {
requests ,
2021-04-05 03:29:26 -07:00
} ;
2021-07-19 23:58:54 -07:00
if ( options . revisionId ) {
body [ 'writeControl' ] = {
requiredRevisionId : options.revisionId as string ,
} ;
}
2021-04-05 03:29:26 -07:00
2021-07-19 23:58:54 -07:00
responseData = await googleApiRequest . call ( this , 'POST' , ` /presentations/ ${ presentationId } :batchUpdate ` , { requests } ) ;
returnData . push ( { json : responseData } ) ;
2021-04-05 03:29:26 -07:00
2021-07-19 23:58:54 -07:00
}
}
2021-04-05 03:29:26 -07:00
2021-07-19 23:58:54 -07:00
} catch ( error ) {
if ( this . continueOnFail ( ) ) {
returnData . push ( { json : { error : error.message } } ) ;
continue ;
2021-04-05 03:29:26 -07:00
}
2021-07-19 23:58:54 -07:00
throw error ;
2021-04-05 03:29:26 -07:00
}
}
return [ returnData ] ;
}
}