├── .github └── workflows │ └── codeql-analysis.yml ├── .gitignore ├── .idea ├── .gitignore ├── js-bindings.iml ├── misc.xml └── modules.xml ├── .npmignore ├── Readme.md ├── babel.config.json ├── package-lock.json ├── package.json └── src ├── axiosInstance.js ├── constants.js ├── endpoint.js ├── index.js └── tools.js /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: "Code scanning - action" 2 | 3 | on: 4 | push: 5 | pull_request: 6 | schedule: 7 | - cron: '0 18 * * 0' 8 | 9 | jobs: 10 | CodeQL-Build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - name: Checkout repository 16 | uses: actions/checkout@v2 17 | with: 18 | # We must fetch at least the immediate parents so that if this is 19 | # a pull request then we can checkout the head. 20 | fetch-depth: 2 21 | 22 | # If this run was triggered by a pull request event, then checkout 23 | # the head of the pull request instead of the merge commit. 24 | - run: git checkout HEAD^2 25 | if: ${{ github.event_name == 'pull_request' }} 26 | 27 | # Initializes the CodeQL tools for scanning. 28 | - name: Initialize CodeQL 29 | uses: github/codeql-action/init@v1 30 | # Override language selection by uncommenting this and choosing your languages 31 | # with: 32 | # languages: go, javascript, csharp, python, cpp, java 33 | 34 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 35 | # If this step fails, then you should remove it and run the build manually (see below) 36 | - name: Autobuild 37 | uses: github/codeql-action/autobuild@v1 38 | 39 | # ℹ️ Command-line programs to run using the OS shell. 40 | # 📚 https://git.io/JvXDl 41 | 42 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 43 | # and modify them (or add more) to build your code if your project 44 | # uses a compiled language 45 | 46 | #- run: | 47 | # make bootstrap 48 | # make release 49 | 50 | - name: Perform CodeQL Analysis 51 | uses: github/codeql-action/analyze@v1 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/node,intellij+all 3 | # Edit at https://www.gitignore.io/?templates=node,intellij+all 4 | 5 | ### Intellij+all ### 6 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 7 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 8 | 9 | # User-specific stuff 10 | .idea/**/workspace.xml 11 | .idea/**/tasks.xml 12 | .idea/**/usage.statistics.xml 13 | .idea/**/dictionaries 14 | .idea/**/shelf 15 | 16 | # Generated files 17 | .idea/**/contentModel.xml 18 | 19 | # Sensitive or high-churn files 20 | .idea/**/dataSources/ 21 | .idea/**/dataSources.ids 22 | .idea/**/dataSources.local.xml 23 | .idea/**/sqlDataSources.xml 24 | .idea/**/dynamic.xml 25 | .idea/**/uiDesigner.xml 26 | .idea/**/dbnavigator.xml 27 | 28 | # Gradle 29 | .idea/**/gradle.xml 30 | .idea/**/libraries 31 | 32 | # Gradle and Maven with auto-import 33 | # When using Gradle or Maven with auto-import, you should exclude module files, 34 | # since they will be recreated, and may cause churn. Uncomment if using 35 | # auto-import. 36 | # .idea/modules.xml 37 | # .idea/*.iml 38 | # .idea/modules 39 | # *.iml 40 | # *.ipr 41 | 42 | # CMake 43 | cmake-build-*/ 44 | 45 | # Mongo Explorer plugin 46 | .idea/**/mongoSettings.xml 47 | 48 | # File-based project format 49 | *.iws 50 | 51 | # IntelliJ 52 | out/ 53 | 54 | # mpeltonen/sbt-idea plugin 55 | .idea_modules/ 56 | 57 | # JIRA plugin 58 | atlassian-ide-plugin.xml 59 | 60 | # Cursive Clojure plugin 61 | .idea/replstate.xml 62 | 63 | # Crashlytics plugin (for Android Studio and IntelliJ) 64 | com_crashlytics_export_strings.xml 65 | crashlytics.properties 66 | crashlytics-build.properties 67 | fabric.properties 68 | 69 | # Editor-based Rest Client 70 | .idea/httpRequests 71 | 72 | # Android studio 3.1+ serialized cache file 73 | .idea/caches/build_file_checksums.ser 74 | 75 | ### Intellij+all Patch ### 76 | # Ignores the whole .idea folder and all .iml files 77 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 78 | 79 | .idea/ 80 | 81 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 82 | 83 | *.iml 84 | modules.xml 85 | .idea/misc.xml 86 | *.ipr 87 | 88 | # Sonarlint plugin 89 | .idea/sonarlint 90 | 91 | ### Node ### 92 | # Logs 93 | logs 94 | *.log 95 | npm-debug.log* 96 | yarn-debug.log* 97 | yarn-error.log* 98 | lerna-debug.log* 99 | 100 | # Diagnostic reports (https://nodejs.org/api/report.html) 101 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 102 | 103 | # Runtime data 104 | pids 105 | *.pid 106 | *.seed 107 | *.pid.lock 108 | 109 | # Directory for instrumented libs generated by jscoverage/JSCover 110 | lib-cov 111 | 112 | # Coverage directory used by tools like istanbul 113 | coverage 114 | *.lcov 115 | 116 | # nyc test coverage 117 | .nyc_output 118 | 119 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 120 | .grunt 121 | 122 | # Bower dependency directory (https://bower.io/) 123 | bower_components 124 | 125 | # node-waf configuration 126 | .lock-wscript 127 | 128 | # Compiled binary addons (https://nodejs.org/api/addons.html) 129 | build/Release 130 | 131 | # Dependency directories 132 | node_modules/ 133 | jspm_packages/ 134 | 135 | # TypeScript v1 declaration files 136 | typings/ 137 | 138 | # TypeScript cache 139 | *.tsbuildinfo 140 | 141 | # Optional npm cache directory 142 | .npm 143 | 144 | # Optional eslint cache 145 | .eslintcache 146 | 147 | # Optional REPL history 148 | .node_repl_history 149 | 150 | # Output of 'npm pack' 151 | *.tgz 152 | 153 | # Yarn Integrity file 154 | .yarn-integrity 155 | 156 | # dotenv environment variables file 157 | .env 158 | .env.test 159 | 160 | # parcel-bundler cache (https://parceljs.org/) 161 | .cache 162 | 163 | # next.js build output 164 | .next 165 | 166 | # nuxt.js build output 167 | .nuxt 168 | 169 | # rollup.js default build output 170 | dist/ 171 | 172 | # Uncomment the public line if your project uses Gatsby 173 | # https://nextjs.org/blog/next-9-1#public-directory-support 174 | # https://create-react-app.dev/docs/using-the-public-folder/#docsNav 175 | # public 176 | 177 | # Storybook build outputs 178 | .out 179 | .storybook-out 180 | 181 | # vuepress build output 182 | .vuepress/dist 183 | 184 | # Serverless directories 185 | .serverless/ 186 | 187 | # FuseBox cache 188 | .fusebox/ 189 | 190 | # DynamoDB Local files 191 | .dynamodb/ 192 | 193 | # Temporary folders 194 | tmp/ 195 | temp/ 196 | 197 | # End of https://www.gitignore.io/api/node,intellij+all 198 | 199 | /lib/ 200 | 201 | /.idea/ 202 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Datasource local storage ignored files 5 | /dataSources/ 6 | /dataSources.local.xml 7 | # Editor-based HTTP Client requests 8 | /httpRequests/ 9 | -------------------------------------------------------------------------------- /.idea/js-bindings.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /src/ -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # JavaScript api for rclone rc 2 | 3 | This is a javascript api to access the [rclone rc](https://rclone.org/rc) api. 4 | 5 | # How to install 6 | 7 | If you are using npm, 8 | ``` 9 | npm install rclone-api --save 10 | ``` 11 | or using yarn, 12 | ```shell script 13 | yarn install rclone-api 14 | ``` 15 | 16 | ## Usage 17 | 18 | Import the required function 19 | 20 | ```js 21 | import {getAllProviders} from "rclone-api"; 22 | ``` 23 | 24 | And then, 25 | 26 | ```js 27 | getAllProviders().then(res => { 28 | //... do something with the data 29 | }, error => { 30 | //... do something with the error 31 | //eg: alert(error) 32 | }); 33 | ``` 34 | 35 | OR 36 | 37 | ```js 38 | getAllProviders().then(res => { 39 | //... do something with the data 40 | }).catch( error => { 41 | //... do something with the error 42 | //eg: alert(error) 43 | }); 44 | ``` 45 | 46 | ## Supported calls 47 | 48 | 1. ```getStats()```: returns the current rclone stats. 49 | 1. ```getCurrentBandwidthSetting()```: fetches the current limit that is max which the rclone can send request at. 50 | 1. ```setCurrentBandwidthSetting(newRate)```: changes the current bandwidth limit of the rclone backend. 51 | @param newRate {string} Human readable format of size eg: 1M|2M|1.2G specifying 1MB, 2MB, 1.2GB respectively. 52 | 1. ```createPublicLink(remoteName, remotePath)``` creates a public link for a supported remote 53 | 1. ```getAllProviders()``` returns all the possible providers supported by the rclone backend 54 | 1. ```getAllConfigDump()``` return the configured remotes from the rclone backend 55 | 1. ```getFsInfo(remoteName)``` fetches the information regarding features, hashes from the rclone backend. 56 | 1. ```getFilesList(remoteName, remotePath)``` fetches the files for a specified remote path (remoteName + remotePath). 57 | 1. ```getRemoteInfo(remoteName)``` fetches the information about a provider. 58 | 1. ```getRcloneVersion()``` fetches the version and details about the running rclone version. 59 | 1. ```getAllRemoteNames()``` fetches all the remotes in the config. 60 | 1. 61 | -------------------------------------------------------------------------------- /babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "stage-2", 4 | "react" 5 | ] 6 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rclone-api", 3 | "version": "1.0.14", 4 | "description": "Java Script bindings for rclone rc api", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "test": "echo \"Skipping tests for now TODO\"", 8 | "compile:es": "babel src --out-dir lib", 9 | "compile": "npm run compile:es ", 10 | "prepare": "npm run compile" 11 | }, 12 | "babel": { 13 | "presets": [ 14 | "es2015" 15 | ] 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git@github.com:rclone/rclone-js-api.git" 20 | }, 21 | "keywords": [], 22 | "author": "rclone", 23 | "license": "ISC", 24 | "dependencies": { 25 | "axios": "^0.21.1" 26 | }, 27 | "devDependencies": { 28 | "babel-cli": "^6.26.0", 29 | "babel-core": "^6.26.3", 30 | "babel-preset-es2015": "^6.24.1" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/axiosInstance.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import {AUTH_KEY, IP_ADDRESS_KEY} from "./constants"; 3 | 4 | /** 5 | * Global level axios configuration. These settings are automatically used in other places by using an axiosInstance instead of axios directly 6 | */ 7 | export let axiosInstance = axios.create({ 8 | headers: {'Content-Type': 'application/json'}, 9 | responseType: "json" 10 | }); 11 | 12 | /** 13 | * Interceptor adds basic authentication to every axios request. 14 | */ 15 | axiosInstance.interceptors.request.use( 16 | config => { 17 | config.baseURL = localStorage.getItem(IP_ADDRESS_KEY); 18 | 19 | config.headers.Authorization = 'Basic ' + localStorage.getItem(AUTH_KEY); 20 | return config; 21 | }, 22 | error => Promise.reject(error) 23 | ); 24 | 25 | export default axiosInstance; -------------------------------------------------------------------------------- /src/constants.js: -------------------------------------------------------------------------------- 1 | export const USER_NAME_KEY = "userName"; 2 | export const AUTH_KEY = "authKey"; 3 | export const PASSWORD_KEY = "password"; 4 | export const IP_ADDRESS_KEY = "ipAddress"; 5 | -------------------------------------------------------------------------------- /src/endpoint.js: -------------------------------------------------------------------------------- 1 | const urls = { 2 | /** 3 | * Make Directory. 4 | */ 5 | mkdir: "operations/mkdir", 6 | /** 7 | * Purge a directory. 8 | */ 9 | purge: "operations/purge", 10 | /** 11 | * Delete a file. 12 | */ 13 | deleteFile: "operations/deletefile", 14 | /** 15 | * Create public link. 16 | */ 17 | createPublicLink: "operations/publiclink", 18 | /** 19 | * Stats for rclone backend. 20 | */ 21 | stats: "core/stats", 22 | /** 23 | * Check and set bwlimit. 24 | */ 25 | bwlimit: "core/bwlimit", 26 | /** 27 | * Move a directory. 28 | */ 29 | moveDir: "sync/move", 30 | /** 31 | * Move a file. 32 | */ 33 | moveFile: "operations/movefile", 34 | /** 35 | * Copy Directory 36 | */ 37 | copyDir: "sync/copy", 38 | /** 39 | * Copy Files. 40 | */ 41 | copyFile: "operations/copyfile", 42 | /** 43 | * Cleanup the remote recycle bin(trash). 44 | */ 45 | cleanUpRemote: "operations/cleanup", 46 | 47 | /** 48 | * Try to connect without any authentication headers. 49 | */ 50 | noopAuth: "rc/noopauth", 51 | /** 52 | * Check the version of the rclone. 53 | */ 54 | getRcloneVersion: "core/version", 55 | 56 | /** 57 | * Memstats for the rclone backend. 58 | */ 59 | getRcloneMemStats: "core/memstats", 60 | /** 61 | * Get options available in the backend. 62 | */ 63 | getOptions: "options/get", 64 | /** 65 | * Get providers configuration in the rclone backend. 66 | */ 67 | getProviders: "config/providers", 68 | /** 69 | * Get entire remote configuration dump from backend. 70 | */ 71 | getConfigDump: "config/dump", 72 | /** 73 | * List the currently running jobs. 74 | */ 75 | getRunningJobs: "job/list", 76 | /** 77 | * Get the status for a job. 78 | */ 79 | getStatusForJob: "job/status", 80 | /** 81 | * Get config for a specific remote. 82 | */ 83 | getConfigForRemote: "config/get", 84 | /** 85 | * Create a new config with parameters. 86 | */ 87 | createConfig: "config/create", 88 | /** 89 | * Update an existing config with parameters. 90 | */ 91 | updateConfig: "config/update", 92 | /** 93 | * Get File system information and supported features for a given remote time. 94 | */ 95 | getFsInfo: "operations/fsinfo", 96 | 97 | /** 98 | * List the remote names of created remotes. 99 | */ 100 | listRemotes: "config/listremotes", 101 | /** 102 | * Get the files for given remoteName and path. 103 | */ 104 | getFilesList: "operations/list", 105 | 106 | /** 107 | * Get information about the rclone backend. 108 | */ 109 | getAbout: "operations/about", 110 | /** 111 | * Delete a config with config name. 112 | */ 113 | deleteConfig: "config/delete", 114 | 115 | /** 116 | * Stop a running job by job id 117 | */ 118 | stopJob: "job/stop", 119 | 120 | /** 121 | * Send a command to backend through rc 122 | */ 123 | backendCommand: "backend/command", 124 | 125 | /** 126 | * Executes rclone in a seperate process for output 127 | */ 128 | coreCommand: "core/command", 129 | 130 | /** 131 | * Transferred jobs for rclone. 132 | */ 133 | transferred: 'core/transferred', 134 | 135 | /** 136 | * getSize of a fs 137 | */ 138 | getSize: 'operations/size', 139 | 140 | /** 141 | * This deletes entire stats group. 142 | */ 143 | statsDelete: 'core/stats-delete', 144 | 145 | 146 | /** 147 | * This clears counters, errors and finished transfers for all stats or specific stats group if group is provided. 148 | */ 149 | statsReset: 'core/stats-reset', 150 | 151 | }; 152 | export default urls; 153 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import {axiosInstance} from "./axiosInstance"; 2 | import urls from "./endpoint"; 3 | import {addColonAtLast, isLocalRemoteName} from "./tools"; 4 | 5 | /** 6 | * getStats returns the current rclone stats. 7 | * @returns {Promise} 8 | */ 9 | export const getStats = (group) => { 10 | let data = {}; 11 | if (group) { 12 | data = { 13 | group 14 | }; 15 | }; 16 | return new Promise((resolve, reject) => { 17 | axiosInstance.post(urls.stats, data).then(res => { 18 | resolve(res.data); 19 | }, error => { 20 | reject(error); 21 | }) 22 | }) 23 | } 24 | 25 | /** 26 | * getCurrentBandwidthSetting fetches the current limit that is max which the rclone can send request at. 27 | * @returns {Promise} 28 | */ 29 | export const getCurrentBandwidthSetting = () => { 30 | return new Promise((resolve, reject) => { 31 | axiosInstance.post(urls.bwlimit).then(res => { 32 | resolve(res.data); 33 | }, error => { 34 | reject(error); 35 | }) 36 | }) 37 | } 38 | 39 | /** 40 | * setCurrentBandwidthSetting changes the current bandwidth limit of the rclone backend. 41 | * @param newRate {string} Human readable format of size eg: 1M|2M|1.2G specifying 1MB, 2MB, 1.2GB respectively. 42 | * @returns {Promise} 43 | */ 44 | export const setCurrentBandwidthSetting = (newRate) => { 45 | return new Promise((resolve, reject) => { 46 | axiosInstance.post(urls.bwlimit, {rate: newRate}).then(res => { 47 | resolve(res.data); 48 | }, error => { 49 | reject(error); 50 | }) 51 | }) 52 | } 53 | 54 | /** 55 | * createPublicLink creates a public link for a supported remote 56 | * @param remoteName {string} 57 | * @param remotePath {string} 58 | * @returns {Function} 59 | */ 60 | export const createNewPublicLink = (remoteName, remotePath) => { 61 | if (!isLocalRemoteName(remoteName)) { 62 | remoteName = addColonAtLast(remoteName); 63 | } 64 | return new Promise((resolve, reject) => { 65 | axiosInstance.post(urls.createPublicLink, {fs: remoteName, remote: remotePath}).then(res => { 66 | resolve(res.data); 67 | }, error => { 68 | reject(error); 69 | }) 70 | }) 71 | }; 72 | 73 | /** 74 | * getAllProviders returns all the possible providers supported by the rclone backend 75 | * @returns {Promise} 76 | */ 77 | export const getAllProviders = () => { 78 | return new Promise((resolve, reject) => { 79 | axiosInstance.post(urls.getProviders).then(res => { 80 | resolve(res.data); 81 | }, error => { 82 | reject(error); 83 | }) 84 | }) 85 | } 86 | 87 | /** 88 | * getConfigDump return the configured remotes from the rclone backend 89 | * @returns {Promise} 90 | */ 91 | export const getAllConfigDump = () => { 92 | return new Promise((resolve, reject) => { 93 | axiosInstance.post(urls.getConfigDump).then(res => { 94 | resolve(res.data); 95 | }, error => { 96 | reject(error); 97 | }) 98 | }) 99 | } 100 | /** 101 | * getFsInfo fetches the information regarding features, hashes from the rclone backend. 102 | * @param remoteName {string} The name of the remote 103 | * @returns {Function} 104 | */ 105 | export const getFsInfo = (remoteName) => { 106 | let sentRemoteName; 107 | if(!isLocalRemoteName(remoteName)) { 108 | sentRemoteName = addColonAtLast(remoteName.split(':')[0]); 109 | } 110 | return new Promise((resolve, reject) => { 111 | axiosInstance.post(urls.getFsInfo, { 112 | fs: sentRemoteName 113 | }).then(res => { 114 | resolve(res.data); 115 | }, error => { 116 | reject(error); 117 | }) 118 | }) 119 | } 120 | 121 | /** 122 | * getFilesList fetches the files for a specified remote path (remoteName + remotePath). 123 | * @param fs {string} Name of the remote config/ ("/" for local path). May contain abc:bucketName for bucket based remotes 124 | * @param remotePath {string} Name of the path in the remote 125 | * @returns {Function} 126 | */ 127 | export const getFilesList = (fs, remotePath, options = {}) => { 128 | return new Promise((resolve, reject) => { 129 | if(!fs || fs === ""){ 130 | reject("Invalid fs specified"); 131 | return; 132 | } 133 | 134 | if (!isLocalRemoteName(fs)) { 135 | fs = addColonAtLast(fs); 136 | } 137 | 138 | axiosInstance.post(urls.getFilesList, { 139 | fs, 140 | remote: remotePath, 141 | opt: options 142 | }).then(res => { 143 | resolve(res.data); 144 | }, error => { 145 | reject(error); 146 | }) 147 | }) 148 | } 149 | 150 | /** 151 | * getRemoteInfo fetches the information about a provider. 152 | * @param remoteName 153 | * @returns {Promise} 154 | */ 155 | export const getRemoteInfo = (remoteName) => { 156 | 157 | return new Promise((resolve, reject) => { 158 | 159 | if(!remoteName) { 160 | reject("Invalid remote name specified"); 161 | return; 162 | } 163 | 164 | if (!isLocalRemoteName(remoteName)) { 165 | remoteName = addColonAtLast(remoteName); 166 | } 167 | axiosInstance.post(urls.getFsInfo, { 168 | fs: remoteName 169 | }).then(res => { 170 | resolve(res.data); 171 | }, error => { 172 | reject(error); 173 | }) 174 | }) 175 | 176 | } 177 | 178 | /** 179 | * getRcloneVersion fetches the version and details about the running rclone version. 180 | * @returns {Promise} 181 | */ 182 | export const getRcloneVersion = () => { 183 | return new Promise((resolve, reject) => { 184 | axiosInstance.post(urls.getRcloneVersion).then(res => { 185 | resolve(res.data); 186 | }, error => { 187 | reject(error); 188 | }) 189 | }) 190 | } 191 | 192 | 193 | /** 194 | * getAllRemoteNames fetches all the remotes in the config. 195 | * @returns {Promise} 196 | */ 197 | export const getAllRemoteNames = () => { 198 | return new Promise((resolve, reject) => { 199 | axiosInstance.post(urls.listRemotes).then(res => { 200 | resolve(res.data); 201 | }, error => { 202 | reject(error); 203 | }) 204 | }) 205 | } 206 | 207 | /** 208 | * getJobStatus returns the status of a job with jobId 209 | * @param jobId {number} Valid job id 210 | * @return {Promise} 211 | */ 212 | export const getJobStatus = (jobId) => { 213 | return new Promise((resolve, reject) => { 214 | axiosInstance.post(urls.getStatusForJob, {jobId}).then(res => { 215 | resolve(res.data); 216 | }, error => { 217 | reject(error); 218 | }) 219 | }) 220 | } 221 | 222 | /** 223 | * purgeDir deletes the directory with given fs and remote 224 | * @param fs {string} Name of fs 225 | * @param remote {string} path remoteName 226 | * @return {Promise} 227 | */ 228 | export const purgeDir = (fs , remote) => { 229 | if (!isLocalRemoteName(fs)) { 230 | fs = addColonAtLast(fs); 231 | } 232 | return new Promise((resolve, reject) => { 233 | axiosInstance.post(urls.purge, { 234 | fs, 235 | remote 236 | }).then(res => { 237 | resolve(res.data); 238 | }, error => { 239 | reject(error); 240 | }) 241 | }) 242 | } 243 | 244 | 245 | /** 246 | * deleteFile returns the status of a job with jobId 247 | * @param fs {string} Remote Name 248 | * @param remote {string} Remote Path 249 | * @return {Promise} 250 | */ 251 | export const deleteFile = (fs , remote) => { 252 | if (!isLocalRemoteName(fs)) { 253 | fs = addColonAtLast(fs); 254 | } 255 | return new Promise((resolve, reject) => { 256 | axiosInstance.post(urls.deleteFile, { 257 | fs, 258 | remote 259 | }).then(res => { 260 | resolve(res.data); 261 | }, error => { 262 | reject(error); 263 | }) 264 | }) 265 | } 266 | 267 | /** 268 | * cleanTrashForRemote cleans the trash for the remote with remote fs 269 | * @param fs {string} Remote Name 270 | * @return {Promise} 271 | */ 272 | export const cleanTrashForRemote = (fs) => { 273 | if (!isLocalRemoteName(fs)) { 274 | fs = addColonAtLast(fs); 275 | } 276 | return new Promise((resolve, reject) => { 277 | axiosInstance.post(urls.cleanUpRemote, { 278 | fs, 279 | }).then(res => { 280 | resolve(res.data); 281 | }, error => { 282 | reject(error); 283 | }) 284 | }) 285 | } 286 | 287 | /** 288 | * Get a downloadable url for an rclone object 289 | * @param ipAddress {string} IP address of running rclone instance 290 | * @param fsInfo {object} FsInfo of the remote 291 | * @param remoteName {string} name of the remote 292 | * @param remotePath {string} path of the file. Relative to remoteName 293 | * @param item {string} item details 294 | * @returns {string} url which can be used to download the required file. 295 | */ 296 | export const getDownloadURLForFile = (ipAddress, fsInfo, remoteName, remotePath, item) => { 297 | let downloadURL = ""; 298 | 299 | if (fsInfo.Features.BucketBased) { 300 | downloadURL = ipAddress + `[${remoteName}]/${remotePath}/${item.Name}`; 301 | 302 | } else { 303 | 304 | downloadURL = ipAddress + `[${remoteName}:${remotePath}]/${item.Name}`; 305 | 306 | } 307 | return downloadURL; 308 | } 309 | 310 | /** 311 | * Send a backend command and return the result. 312 | * @param command {string} string with the command name 313 | * @param arg {array} remote name string eg "drive:" 314 | * @param opt {$ObjMap} list of arguments for the backend command 315 | * @param fs {string} remote name string eg "drive:" 316 | * @returns {Promise<$ObjMap>} 317 | */ 318 | export const backendCommand = (command, arg, opt, fs) => { 319 | if(!fs) fs = "."; 320 | 321 | return new Promise((resolve, reject) => { 322 | if(!command || !arg || !opt) throw new Error(`One or more invalid arguments {${command}},{${arg}} {${opt}} {${fs}}`) 323 | axiosInstance.post(urls.backendCommand, { 324 | command, 325 | arg, 326 | opt, 327 | fs 328 | }).then(res => { 329 | resolve(res.data); 330 | }, error => { 331 | reject(error); 332 | }) 333 | }); 334 | } 335 | 336 | /** 337 | * Send a backend command and return the result. 338 | * @param arg {array} remote name string eg "drive:" 339 | * @param opt {$ObjMap} list of arguments for the backend command 340 | * @returns {Promise<$ObjMap>} 341 | */ 342 | export const coreCommand = ( arg, opt) => { 343 | return new Promise((resolve, reject) => { 344 | if(!arg || !opt) throw new Error(`One or more invalid arguments ,{${arg}} {${opt}}`) 345 | axiosInstance.post(urls.coreCommand, { 346 | arg, 347 | opt, 348 | }).then(res => { 349 | resolve(res.data); 350 | }, error => { 351 | reject(error); 352 | }) 353 | }); 354 | } 355 | 356 | 357 | /** 358 | * getTransferredStats returns transferred job stats. 359 | * @returns {Promise} 360 | */ 361 | export const getTransferredStats = (group) => { 362 | let data = {}; 363 | if (group) { 364 | data = { 365 | group 366 | }; 367 | }; 368 | return new Promise((resolve, reject) => { 369 | axiosInstance.post(urls.transferred, data).then(res => { 370 | resolve(res.data); 371 | }, error => { 372 | reject(error); 373 | }) 374 | }) 375 | } 376 | 377 | 378 | /** 379 | * stopJob stops a job with the specified jobId. 380 | * @returns {Promise} 381 | */ 382 | export const stopJob = (jobId) => { 383 | let data = {}; 384 | if (jobId) { 385 | data = { 386 | jobid: jobId, 387 | }; 388 | }; 389 | return new Promise((resolve, reject) => { 390 | axiosInstance.post(urls.stopJob, data).then(res => { 391 | resolve(res.data); 392 | }, error => { 393 | reject(error); 394 | }) 395 | }) 396 | } 397 | 398 | export const getSize = (srcFs, srcRemote) => { 399 | let data = { 400 | fs: `${srcFs}${srcRemote ? srcRemote : ''}` 401 | }; 402 | return new Promise((resolve, reject) => { 403 | axiosInstance.post(urls.getSize, data).then(res => { 404 | resolve(res.data); 405 | }, error => { 406 | reject(error); 407 | }) 408 | }) 409 | } 410 | 411 | export const statsDelete = (group) => { 412 | let data = { 413 | group 414 | }; 415 | return new Promise((resolve, reject) => { 416 | axiosInstance.post(urls.statsDelete, data).then(res => { 417 | resolve(res.data); 418 | }, error => { 419 | reject(error); 420 | }) 421 | }) 422 | } 423 | 424 | export const statsReset = (group) => { 425 | let data = { 426 | group 427 | }; 428 | return new Promise((resolve, reject) => { 429 | axiosInstance.post(urls.statsReset, data).then(res => { 430 | resolve(res.data); 431 | }, error => { 432 | reject(error); 433 | }) 434 | }) 435 | } -------------------------------------------------------------------------------- /src/tools.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks whether the remoteName is local or not. Returns true if it is a remote local path, false otherwise. 3 | * Behaviour: if the name starts with "/" it is a local name. 4 | * @param remoteName {string} Name of the remote to check for. 5 | * @returns {boolean} 6 | */ 7 | export function isLocalRemoteName(remoteName) { 8 | return (remoteName && remoteName !== "" && remoteName[0] === "/"); 9 | } 10 | 11 | /** 12 | * addColonAtLast is a helper function to add semicolon to the last. 13 | * Behaviour: if the passed in string does not have a semicolon at last, then insert it. 14 | * If there is a semicolon in the middle, skip insertion. 15 | * @param name 16 | * @returns {string} 17 | */ 18 | export function addColonAtLast(name) { 19 | if (name.indexOf(':') === -1) { 20 | if (name[name.length - 1] !== ":") { 21 | name = name + ":" 22 | } 23 | } 24 | 25 | return name; 26 | } 27 | --------------------------------------------------------------------------------