gdrive

20 August 2019 Link



Purpose

This module allows a Lua script to authenticate and access Google Drive. It allows browsing and managing the files and folders on Google Drive.

Dependencies


Installation

Either copy the gdrive.lua file in a directory in the Lua package.path or use LuaRocks to install it like:
> luarocks install gdrive

Basic Usage

The demo.lua file gets access to google drive and then prints out the response to the request to get the root directory listing in the drive.

To make the example code work below follow these steps to get the credentials file from Google API for your script:
  1. Log in to the google developer console.
  2. Go to the Drive API link under the Google Apps APIs
  3. Enable this API and download a credentials file
  4. From the credentials file take the 'installed' json table and paste in a new file creds.json and place the file in the same directory as this demo file
  5. Now execute the code

Example code from demo.lua in the test subdirectory:
  1. local gd = require 'gdrive'
  2.  
  3. gdrive,msg = gd.new{
  4. creds_file = [[creds.json]], -- creds file obtained from Google Developer console for this script
  5. tokens_file = 'tokens.json' -- File name where the token will be saved
  6. }
  7.  
  8. if not gdrive then
  9. print("Unable to initialize gdrive: "..msg)
  10. else
  11. local stat, code, msg
  12. print('Acquire Token')
  13. stat = gdrive.acquireToken
  14. print("Go to the following URL and grant permissions and get the authorization code:")
  15. print(stat[1])
  16. print("Enter the authorization code:")
  17. code = io.read()
  18. stat,msg = stat[2](code)
  19. if not stat then
  20. print("Code authorization failed: "..msg)
  21. else
  22. print('Token acquired successfully.')
  23. print("The root directory listing is:")
  24. stat = gdrive.root:list()
  25. for i = 1,#stat.items do
  26. print(stat.items[i]:getProperty("title"),stat.items[i]:getProperty("mimeType")==gdrive.mimeType.folder and "folder" or "file")
  27. end
  28. end
  29. end


API Reference


Module


API

The gdrive module exposes just 1 function:

new

To create a new gdrive object.
Syntax:
new((config: table)) -> (gdrive Object: table)
Usage:
  1. gd,msg = new(config)

Inputs:
config table to configure the new gdrive object. The configuration table can have all the same keys as required by the oauth2 module config input but all are optional except the credential keys:
  • creds_file: [OPTIONAL] Full path and name for the credentials file. This parameter if not given then the credentials must be provided in the creds table described below.
  • creds: [OPTIONAL] Table containing the connection credentials. This table must have the following keys:
    • client_id: String key for the client id.
    • client_secret: String key for the client secret.
    • redirect_uris: [OPTIONAL] Redirect URIs provided by the service
    • auth_uri or auth_url: [OPTIONAL] URL string for requesting authorization. NOTE: If this is given it will overwrite the auth_uri or auth_url given in the main config table
    • token_uri or token_url: [OPTIONAL] URL string for requesting token. NOTE: If this is given it will overwrite the token_uri or token_url given in the main config table

The other parameters used by default in the configuration, which are overwritten if provided in the input table, are:
  1. baseConfig = {
  2. auth_url = 'https://accounts.google.com/o/oauth2/auth',
  3. token_url = 'https://accounts.google.com/o/oauth2/token',
  4. scope = 'https://www.googleapis.com/auth/drive',
  5. endpoint = 'https://www.googleapis.com/drive/v2/',
  6. endpoint_upload = 'https://www.googleapis.com/upload/drive/v2/',
  7. approval_prompt = 'force',
  8. access_type = 'offline',
  9. }


Returns:
  • nil and the error message in case of failure to create object
  • The gdrive connection object

gdrive object


API

item

To check if an item exist on the drive and to get the item object to access and manipulate the item.
Syntax:
item((gdrive Object: table),(name: string)[,(type: "file" or "folder")]) -> (item object: table)
Usage:
  1. item1,msg = gd:item("folder1/folder1a","folder")
  2. item2,msg = gd:item("folder1/file1a") -- type is 'file' buy default

Inputs:
  • gdrive object. This can be the calling gdrive object using the colon operator
  • name - This is the name of the object with the full path from the root that we want to check or obtain the object of. "/folder1/folder1a", "\folder1\folder1a", "folder1/folder1a", "folder1\folder1a" are all valid names of the same folder1a object inside folder1 in root.
  • type - This is a string specifying whether we are specifying a 'file' or a 'folder'. Default is 'file'
Returns:
  • nil and a error message if error
  • false if such a item does not exist
  • item object for the file or folder item if success

mkdir

To make a directory hierarchy on the drive and get its object for accessing and manipulating the directory. If the folder already exist then it will return that folder's object and not create anything.
Syntax:
mkdir((gdrive Object: table),(directory name: string)) -> (item object: table)
Usage:
  1. dir,msg = gd:mkdir("folder1/folder1a/folder1aa") -- Note this command will create the whole hierarchy
  2. -- i.e. if folder1 and folder1/folder1a do not exist then they will be created as well

Inputs:
  • gdrive object. This can be the calling gdrive object using the colon operator
  • directory name - This is the name of the folder with the full path from the root that we want to create. "/folder1/folder1a/folder1aa", "\folder1\folder1a\folder1aa", "folder1/folder1a/folder1aa", "folder1\folder1a\folder1aa" are all valid names of the same folder1aa object inside folder1a in folder1 in root.
  • type - This is a string specifying whether we are specifying a 'file' or a 'folder'. Default is 'file'
Returns:
  • nil and a error message if error
  • folder object if success

Objects

config

This table contains all the configuration parameters of the oAuth 2.0 object. This table structure is the same as the config structure described in the config object input to the new function.

mimeType

This table contains definitions of types of items that can reside on the Google drive. The table below shows its members:
  1. mimetype = {
  2. audio = "application/vnd.google-apps.audio",
  3. document = "application/vnd.google-apps.document",
  4. drawing = "application/vnd.google-apps.drawing",
  5. file = "application/vnd.google-apps.file",
  6. folder = 'application/vnd.google-apps.folder',
  7. form = "application/vnd.google-apps.form",
  8. fusiontable = "application/vnd.google-apps.fusiontable",
  9. photo = "application/vnd.google-apps.photo",
  10. presentation = "application/vnd.google-apps.presentation",
  11. script = "application/vnd.google-apps.script",
  12. sites = "application/vnd.google-apps.sites",
  13. spreadsheet = "application/vnd.google-apps.spreadsheet",
  14. unknown = "application/vnd.google-apps.unknown",
  15. video = "application/vnd.google-apps.video"
  16. }

This can be used to test the type of item object you have like:
  1. if item:getProperty("mimeType") == gd.mimeType.folder then
  2. print(item:getProperty("title").." is a folder") --- See the item object documentation for usage of getProperty function
  3. end

tokenUpdated

This is a boolean flag. It is set to true whenever the access token is refreshed by the oAuth 2.0 protocol. If you want to detect when the token is updated set this to false and then poll it periodically or after each request to see if the token was updated. Note the token can be accessed by accessing gd.oauth2.token

root

This is an item object for the root folder for the Google drive. See the item object documentation below for more information on item objects.

oauth2

This is an oauth2 object used for the connection by the gdrive object. For more information on this object look here

acquireToken

This is a table array containing 2 elements:
  1. The URL string to access to get the access code from the Google Drive service so that the access token can be generated.
  2. The function to be called with the access code as the parameter to generate the access token and setup the connection
NOTE: If the access token was generated in a previous session and saved in a file (if tokens_file was given in the config) then there is no need to acquire the token again and the module will take care of refreshing the token itself. To find our whether you need to acquire the access code or not is to check whether gd.root object exists. If it does not then go ahead and acquire the token.

item Object

API

getProperty

Gets the value of any property name for the item object
Syntax:
getProperty((item Object: table), (property: string)) -> (property: table or string)
Usage:
  1. property,msg = item:getProperty(propertyName)

Inputs:
  • item object. This can be the calling item object using the colon operator
  • property name - The property name can be any string from the list of data available for an item. The full list can be seen here
Returns:
  • nil and a error message if error
  • property object which may be a string or a table depending on the property on success

setProperty

Sets the value of any property name for an item object
Syntax:
setProperty((item Object: table), (property: string),(value: table or string)) -> (true)
Usage:
  1. status,msg = item:setProperty(propertyName, propertyVal)

Inputs:
  • item object. This can be the calling item object using the colon operator
  • property name - The property name can be any string from the list of data available for an item. The full list can be seen here
  • value: This may either be a string or a table depending on the property whose value is being set
Returns:
  • nil and a error message if error
  • true if success setting the property

list

Gets the list of items inside a folder item. This function should only be called for a folder item otherwise it will return nil
Syntax:
list((item Object: table)[, (number of entries on page: number)]) -> (dirList object: table)
Usage:
  1. dirList,msg = item:list()

Inputs:
  • item object. This can be the calling item object using the colon operator
  • number of entries on page - This tells the number of entries on the dirList object page. Default is 100
Returns:
  • nil and a error message if error
  • dirList object with all the item objects in the 1st page of the listing on success.

item

To check if an item exist in the folder and to get the item object to access and manipulate the item. This should be called for folder items otherwise it will return a nil.
Syntax:
item((item Object: table),(name: string)[,(type: "file" or "folder")]) -> (item object: table)
Usage:
  1. item1,msg = item:item("folder1","folder")
  2. item2,msg = item:item("file1a") -- type is 'file' buy default

Inputs:
  • item object. This can be the calling folder item object using the colon operator
  • name - This is the name of the object that we want to retrieve or check
  • type - This is a string specifying whether we are specifying a 'file' or a 'folder'. Default is 'file'
Returns:
  • nil and a error message if error
  • false if such a item does not exist
  • item object for the file or folder item if success

mkdir

To make a directory in the folder and get its object for accessing and manipulating it. If the folder already exist then it will return that folder's object and not create anything.
Syntax:
mkdir((item Object: table),(directory name: string)) -> (item object: table)
Usage:
  1. dir,msg = item:mkdir("folder1aa")

Inputs:
  • item object. This can be the calling folder item object using the colon operator
  • directory name - This is the name of the folder that we want to create.
Returns:
  • nil and a error message if error
  • folder object if success

upload

Function to upload file to the Google drive folder
Syntax:
upload((item Object: table),(file name: string), (source: function)[, (force: boolean)]) -> (item object: table)
Usage:
  1. f = io.open("myfile")
  2. chunkLength = 1024
  3. function fileSourceFunc()
  4. return f:read(chunkLength)
  5. end
  6. file,msg = item:upload("file1aa",fileSourceFunc)
  7. f:close()

Inputs:
  • item object. This can be the calling folder item object using the colon operator
  • file name - This is the name of the file that is being uploaded.
  • source - is a function which on each call returns the next chunk of data
  • force - It will not upload if the file already exists unless force is true
Returns:
  • nil and a error message if error
  • file object of the uploaded file if success

move

Function to move an item from current parents to the given parent object
Syntax:
move((item Object: table),(destination object: table)[, (force: boolean)]) -> (true)
Usage:
  1. status,msg = item:move(parent2)

Inputs:
  • item object. This can be the calling folder item object using the colon operator
  • destination object - This is the destination folder object
  • force - It will not upload if the file already exists unless force is true
Returns:
  • nil and a error message if error
  • true if success

rename

Function to rename an item to a new name
Syntax:
rename((item Object: table),(new name: string)[, (force: boolean)]) -> (true)
Usage:
  1. status,msg = item:rename(newName)

Inputs:
  • item object. This can be the calling folder item object using the colon operator
  • new name - This is the new name for the item
  • force - It will not rename if another item with the same name exists in that folder unless force is true. In which case the old item is deleted.
Returns:
  • nil and a error message if error
  • true if success

copyto

Function to copy an item from current parents to the given parent object
Syntax:
copyto((item Object: table),(destination object: table)[, (force: boolean)]) -> (item object: table)
Usage:
  1. copyItem,msg = item:copyto(parent2)

Inputs:
  • item object. This can be the calling folder item object using the colon operator
  • destination object - This is the destination folder object
  • force - It will not copy if the file with same name already exists in the destination folder unless force is true
Returns:
  • nil and a error message if error
  • copied item object if success

delete

Function to delete an item from the Google Drive
Syntax:
delete((item Object: table)) -> (true)
Usage:
  1. status,msg = item:delete()

Inputs:
  • item object. This can be the calling folder item object using the colon operator
Returns:
  • nil and a error message if error
  • true if success

download

Function to download a file or a portion of it
Syntax:
download((item Object: table), (sink: function)[, (starting byte: number)][, (stopping byte: number)]) -> (true)
Usage:
  1. f = io.open("myfile","w+")
  2. function fileSourceFunc(chunk)
  3. f:write(chunk)
  4. return true
  5. end
  6. status,msg = item:download()
  7. f:close()

Inputs:
  • item object. This can be the calling folder item object using the colon operator
  • sink function - This is a function which is called and passed the file data to be used.
  • starting byte - The starting byte of the file data from where to start downloading
  • stopping byte - The stopping byte of the file data uptill where to download
Returns:
  • nil and a error message if error
  • the return value of the sink function after passing data to it.

dirList Object

This object allows browsing a directory listing from Google Drive

API

next

This function gets the next listing page if all the results did not fit in this page
Syntax:
next((dirList Object: table)) -> (dirList Object: table)
Usage:
  1. nextPage,msg = dirList:next()

Inputs:
  • dirList object. This should be the calling directory list object using the colon operator
Returns:
  • nil and a error message if error
  • directory list object for the next page

Objects

items

This table contains all the item objects for all the items in the directory listing page

parentID

This is the ID of the parent folder whose listing is provided and should not be changed

nextPageToken

This is a token needed to get the next page of the listing and should not be changed

num

This is the number of results intended to be on the page. If #dirList.items == dirList.num then there is a possibility that there may be more items in the next page.

Also See