Compare commits

..

No commits in common. "ed93bf95fb648a7dc8a10e6994989ecc55a08ec0" and "c64475325b497a4e029085f6ca55712274210707" have entirely different histories.

5 changed files with 12 additions and 221 deletions

View file

@ -16,6 +16,4 @@ steps:
basedir: "." # optional, local base directory for files, defaults to . basedir: "." # optional, local base directory for files, defaults to .
chunksize: # optional, chunk size in bytes, defaults to 10485760, or 10 MiB chunksize: # optional, chunk size in bytes, defaults to 10485760, or 10 MiB
quiet: false # optional, whether to reduce output quiet: false # optional, whether to reduce output
tags: # optional, a set of tags to apply to uploaded files, tag is expected to already exist
- mytag
``` ```

View file

@ -7,11 +7,10 @@
"": { "": {
"name": "nextcloud-upload", "name": "nextcloud-upload",
"version": "1.0.0", "version": "1.0.0",
"license": "MIT", "license": "ISC",
"dependencies": { "dependencies": {
"glob": "^10.3.1", "glob": "^10.3.1",
"nextcloud-chunk-file-upload": "^1.1.1", "nextcloud-chunk-file-upload": "^1.1.1"
"xml2json": "^0.12.0"
} }
}, },
"node_modules/@isaacs/cliui": { "node_modules/@isaacs/cliui": {
@ -74,14 +73,6 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
}, },
"node_modules/bindings": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"dependencies": {
"file-uri-to-path": "1.0.0"
}
},
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
@ -129,11 +120,6 @@
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
}, },
"node_modules/file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
},
"node_modules/follow-redirects": { "node_modules/follow-redirects": {
"version": "1.15.2", "version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
@ -189,15 +175,6 @@
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
} }
}, },
"node_modules/hoek": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==",
"deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).",
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/is-fullwidth-code-point": { "node_modules/is-fullwidth-code-point": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
@ -206,17 +183,6 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/isemail": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz",
"integrity": "sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==",
"dependencies": {
"punycode": "2.x.x"
},
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/isexe": { "node_modules/isexe": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@ -239,29 +205,6 @@
"@pkgjs/parseargs": "^0.11.0" "@pkgjs/parseargs": "^0.11.0"
} }
}, },
"node_modules/joi": {
"version": "13.7.0",
"resolved": "https://registry.npmjs.org/joi/-/joi-13.7.0.tgz",
"integrity": "sha512-xuY5VkHfeOYK3Hdi91ulocfuFopwgbSORmIwzcwHKESQhC7w1kD5jaVSPnqDxS2I8t3RZ9omCKAxNwXN5zG1/Q==",
"deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).",
"dependencies": {
"hoek": "5.x.x",
"isemail": "3.x.x",
"topo": "3.x.x"
},
"engines": {
"node": ">=8.9.0"
}
},
"node_modules/joi/node_modules/hoek": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/hoek/-/hoek-5.0.4.tgz",
"integrity": "sha512-Alr4ZQgoMlnere5FZJsIyfIjORBqZll5POhDsF4q64dPuJR6rNxXdDxtHSQq8OXRurhmx+PWYEE8bXRROY8h0w==",
"deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).",
"engines": {
"node": ">=8.9.0"
}
},
"node_modules/lru-cache": { "node_modules/lru-cache": {
"version": "10.0.0", "version": "10.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.0.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.0.tgz",
@ -292,11 +235,6 @@
"node": ">=16 || 14 >=14.17" "node": ">=16 || 14 >=14.17"
} }
}, },
"node_modules/nan": {
"version": "2.17.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz",
"integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ=="
},
"node_modules/nextcloud-chunk-file-upload": { "node_modules/nextcloud-chunk-file-upload": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/nextcloud-chunk-file-upload/-/nextcloud-chunk-file-upload-1.1.1.tgz", "resolved": "https://registry.npmjs.org/nextcloud-chunk-file-upload/-/nextcloud-chunk-file-upload-1.1.1.tgz",
@ -305,16 +243,6 @@
"axios": "^0.24.0" "axios": "^0.24.0"
} }
}, },
"node_modules/node-expat": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/node-expat/-/node-expat-2.4.0.tgz",
"integrity": "sha512-X8Y/Zk/izfNgfayeOeUGqze7KlaOwVJ9SDTjHUMKd0hu0aFTRpLlLCBwmx79cTPiQWD24I1YOafF+U+rTvEMfQ==",
"hasInstallScript": true,
"dependencies": {
"bindings": "^1.5.0",
"nan": "^2.13.2"
}
},
"node_modules/path-key": { "node_modules/path-key": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
@ -338,14 +266,6 @@
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
} }
}, },
"node_modules/punycode": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
"engines": {
"node": ">=6"
}
},
"node_modules/shebang-command": { "node_modules/shebang-command": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@ -464,21 +384,6 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/topo": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/topo/-/topo-3.0.3.tgz",
"integrity": "sha512-IgpPtvD4kjrJ7CRA3ov2FhWQADwv+Tdqbsf1ZnPUSAtCJ9e1Z44MmoSGDXGk4IppoZA7jd/QRkNddlLJWlUZsQ==",
"deprecated": "This module has moved and is now available at @hapi/topo. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues.",
"dependencies": {
"hoek": "6.x.x"
}
},
"node_modules/topo/node_modules/hoek": {
"version": "6.1.3",
"resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz",
"integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==",
"deprecated": "This module has moved and is now available at @hapi/hoek. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues."
},
"node_modules/which": { "node_modules/which": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@ -576,19 +481,6 @@
"engines": { "engines": {
"node": ">=8" "node": ">=8"
} }
},
"node_modules/xml2json": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/xml2json/-/xml2json-0.12.0.tgz",
"integrity": "sha512-EPJHRWJnJUYbJlzR4pBhZODwWdi2IaYGtDdteJi0JpZ4OD31IplWALuit8r73dJuM4iHZdDVKY1tLqY2UICejg==",
"dependencies": {
"hoek": "^4.2.1",
"joi": "^13.1.2",
"node-expat": "^2.3.18"
},
"bin": {
"xml2json": "bin/xml2json"
}
} }
} }
} }

View file

@ -10,7 +10,6 @@
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"glob": "^10.3.1", "glob": "^10.3.1",
"nextcloud-chunk-file-upload": "^1.1.1", "nextcloud-chunk-file-upload": "^1.1.1"
"xml2json": "^0.12.0"
} }
} }

View file

@ -1,7 +1,6 @@
const Upload = require("nextcloud-chunk-file-upload"); const Upload = require("nextcloud-chunk-file-upload");
const glob = require("glob"); const glob = require("glob");
const axios = require("axios"); const axios = require("axios");
const xml = require('xml2json');
// parse arguments // parse arguments
const serverEnv = process.env.PLUGIN_SERVER; const serverEnv = process.env.PLUGIN_SERVER;
@ -23,58 +22,20 @@ if (!destEnv)
const baseDir = process.env.PLUGIN_BASEDIR || "."; const baseDir = process.env.PLUGIN_BASEDIR || ".";
const chunkSizeEnv = process.env.PLUGIN_CHUNKSIZE || 10 * 1024 * 1024; const chunkSizeEnv = process.env.PLUGIN_CHUNKSIZE || 10 * 1024 * 1024;
const quiet = process.env.PLUGIN_QUIET || false; const quiet = process.env.PLUGIN_QUIET || false;
const tags = process.env.PLUGIN_TAGS || "";
upload(); upload();
async function upload() { async function upload() {
let basePath = `${serverEnv}/remote.php/dav`; let basePath = `${serverEnv}/remote.php/dav`;
const upload = new Upload(basePath, userEnv, userEnv, tokenEnv);
// find ids for the tags we want to assign later
let tagIds = new Map();
if (tags) {
if (!quiet)
console.log(`Retrieving tag ids`);
// list tags and find the ones we want: https://doc.owncloud.com/server/next/developer_manual/webdav_api/tags.html#list-tags
let response = await axios.request({
method: "propfind",
url: `${basePath}/systemtags`,
auth: {
username: userEnv,
password: tokenEnv
},
data: `<?xml version="1.0"?>
<d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns" xmlns:nc="http://nextcloud.org/ns">
<d:prop>
<oc:display-name/>
<oc:id/>
</d:prop>
</d:propfind>`
});
var data = JSON.parse(xml.toJson(response.data))["d:multistatus"]["d:response"].map(e => e["d:propstat"]["d:prop"]);
for (let tag of tags.split(",")) {
let entry = data.find(e => e["oc:display-name"] == tag);
if (!entry) {
console.log(`Couldn't find tag with name ${tag}`);
process.exit(1);
}
let tagId = entry["oc:id"];
tagIds.set(tag, tagId);
if (!quiet)
console.log(`Tag id of tag ${tag} is ${tagId}`);
}
}
// collect and upload files
if (!quiet)
console.log(`Uploading files`);
let upload = new Upload(basePath, userEnv, userEnv, tokenEnv);
for (let pattern of filesEnv.split(",")) { for (let pattern of filesEnv.split(",")) {
let files = await glob.glob(pattern, { cwd: baseDir }); let files = await glob.glob(pattern, { cwd: baseDir });
if (!files.length) if (!files.length)
console.log(`No files found for pattern ${pattern}`); console.log(`No files found for pattern ${pattern}`);
for (let file of files) { for (let file of files) {
let dest = `${destEnv}/${file}`; let dest = `${destEnv}/${file}`;
if (!quiet)
console.log(`Uploading ${file} to ${dest}`);
// we have to explicitly create any directories that don't exist yet // we have to explicitly create any directories that don't exist yet
// (https://github.com/shiftpi/nextcloud-chunk-file-upload/issues/22) // (https://github.com/shiftpi/nextcloud-chunk-file-upload/issues/22)
@ -82,80 +43,29 @@ async function upload() {
for (let dir of dest.split("/").slice(0, -1)) { for (let dir of dest.split("/").slice(0, -1)) {
currDir += `${dir}/`; currDir += `${dir}/`;
try { try {
let response = await axios.request({ await axios.request({
method: 'mkcol', method: 'mkcol',
url: `${basePath}/files/${userEnv}/${currDir}`, url: `${basePath}/files/${userEnv}/${currDir}`,
auth: { auth: {
username: userEnv, username: userEnv,
password: tokenEnv password: tokenEnv
}, }
// 405 means the directory already exists
validateStatus: s => s == 201 || s == 405
}); });
if (response.status != 405 && !quiet) if (!quiet)
console.log(`Created directory ${currDir}`); console.log(`Created directory ${currDir}`);
} catch (error) { } catch (error) {
console.log(`Failed to create directory ${currDir} (${error})`); // this is fine since the directory likely already exists
process.exit(1);
} }
} }
// use lib to upload file // use lib to upload file
if (!quiet)
console.log(`Uploading ${file} to ${dest}`);
await upload.uploadFile(`${baseDir}/${file}`, dest, parseInt(chunkSizeEnv)).then(e => { await upload.uploadFile(`${baseDir}/${file}`, dest, parseInt(chunkSizeEnv)).then(e => {
if (!quiet) if (!quiet)
console.log(`Uploaded ${file} to ${dest}`); console.log(`Uploaded ${file} to ${dest} (${e})`);
}).catch(e => { }).catch(e => {
console.log(`Failed to upload file ${file} to ${dest} (${e})`); console.log(`Failed to upload file ${file} to ${dest} (${e}, error ${e.httpErrorCode}, ${e.httpErrorMessage})`);
process.exit(1); process.exit(1);
}); });
// add tags
if (tagIds.size) {
try {
// get file id: https://docs.nextcloud.com/server/latest/developer_manual/client_apis/WebDAV/basic.html#requesting-properties
let response = await axios.request({
method: "propfind",
url: `${basePath}/files/${userEnv}/${dest}`,
auth: {
username: userEnv,
password: tokenEnv
},
data: `<?xml version="1.0"?>
<d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns" xmlns:nc="http://nextcloud.org/ns">
<d:prop>
<oc:fileid/>
</d:prop>
</d:propfind>`
});
var data = JSON.parse(xml.toJson(response.data));
let fileId = data["d:multistatus"]["d:response"]["d:propstat"]["d:prop"]["oc:fileid"];
if (!quiet)
console.log(`File id of file ${file} is ${fileId}`);
// add tags: https://doc.owncloud.com/server/next/developer_manual/webdav_api/tags.html#assign-a-tag-to-a-file
for (let [tag, tagId] of tagIds.entries()) {
await axios.request({
method: "put",
url: `${basePath}/systemtags-relations/files/${fileId}/${tagId}`,
auth: {
username: userEnv,
password: tokenEnv
},
// 409 conflicted means the tag is already applied
validateStatus: s => s == 201 || s == 409
});
if (!quiet)
console.log(`Added tag ${tag} to file ${file}`);
}
} catch (error) {
console.log(`Failed to assign tags ${tags} to file ${file} (${error})`);
process.exit(1);
}
}
} }
} }
} }

View file

@ -1,8 +0,0 @@
export PLUGIN_SERVER=https://cloud.ellpeck.de
export PLUGIN_USER=EllBot
export PLUGIN_FILES=Dockerfile
export PLUGIN_DEST=Test/Testing
export PLUGIN_TAGS="Autoremove 1D"
npm install
node run.js