amazondrive

20 August 2019 Link



Purpose

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

Dependencies


Installation

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

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 developer.amazon.com and go to the Drive API page. (Usually from Services and APIs ->Amazon Drive)
  2. Here you need to create an App. Create its security profile (Amazon needs a web page of the privacy policy before it lets you proceed when I did this).
  3. In the Apps security profile copy the data to create the creds file. All you need is the client ID, client secret and redirect URIs. The redirect URI can be https://localhost if you don't have a website to get the code. The access code can then be copied from the URL, Note that Amazon also requires that the redirect URI be on https and be registered in the app security profile in the Web Settings. With this the code is the part of the URL in between ?code= and &scope.
  4. Now execute the code

Example code from demo.lua in the test subdirectory:
  1. local ad = require 'amazondrive'
  2.  
  3. adrive,msg = ad.new{
  4. creds_file = 'creds.json', -- creds file created by the above instructions
  5. tokens_file = 'tokens.json' -- File name where the token will be saved
  6. }
  7.  
  8. if not adrive then
  9. print("Unable to initialize adrive: "..msg)
  10. else
  11. local stat, code, msg
  12. print('Acquire Token')
  13. stat = adrive.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 = adrive.root:list()
  25. for i = 1,#stat.items do
  26. print(stat.items[i]:getProperty("name"),stat.items[i]:getProperty("kind")==adrive.mimeType.folder and "folder" or "file")
  27. end
  28. end
  29. end


API Reference


Module


API

The amazondrive module exposes just 1 function:

new

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

Inputs:
config table to configure the new amazondrive 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
Two new keys different than the oAuth config table are:
  • endpoints_file: [OPTIONAL] Full path and name for the endpoints file. If this is given then the endpoints fetched from Amazon will be saved in that file otherwise they will only exist in memory in the config table.
  • endPoints: [OPTIONAL] Table containing the connection endpoints. This table should not be changed.
The other parameters used by default in the configuration, which are overwritten if provided in the input table, are:
  1. baseConfig = {
  2. auth_uri = "https://www.amazon.com/ap/oa",
  3. token_url = "https://api.amazon.com/auth/o2/token",
  4. scope = 'clouddrive:read_all clouddrive:write',
  5. getEndpoint = 'https://drive.amazonaws.com/drive/v1/account/endpoint',
  6. approval_prompt = 'force',
  7. access_type = 'offline',
  8. }


Returns:
  • nil and the error message in case of failure to create object and a second error message as the response from the server.
  • The amazondrive connection object

amazondrive 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((amazondrive Object: table),(name: string)[,(type: "file" or "folder")]) -> (item object: table)
Usage:
  1. item1,msg = ad:item("folder1/folder1a","folder")
  2. item2,msg = ad:item("folder1/file1a") -- type is 'file' buy default

Inputs:
  • amazondrive object. This can be the calling amazondrive 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 followed by the response given by the server
  • 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((amazondrive Object: table),(directory name: string)) -> (item object: table)
Usage:
  1. dir,msg = ad: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:
  • amazondrive object. This can be the calling amazondrive 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 followed by the response given by the server
  • 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 Amazon drive. The table below shows its members:
  1. mimetype = {
  2. file = "FILE",
  3. folder = "FOLDER"
  4. }

This can be used to test the type of item object you have like:
  1. if item:getProperty("kind") == ad.mimeType.folder then
  2. print(item:getProperty("name").." 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 Amazon 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 amazondrive 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 Amazon 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 ad.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 followed by the response by the server
  • 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 followed by the response by the server
  • 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 followed by the server response
  • 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 followed by the server response
  • folder object if success

upload

Function to upload file to the Amazon 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 followed by the server response
  • 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 followed by the server response
  • 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 followed by the server response
  • 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 followed by the server response
  • copied item object if success

delete

Function to delete an item from the Amazon 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 followed by the server response
  • 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 up till where to download
Returns:
  • nil and a error message if error followed by the server response
  • the return value of the sink function after passing data to it.

dirList Object

This object allows browsing a directory listing from Amazon 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 followed by the response from the server
  • 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