mirror of
https://github.com/Skylar-Tech/node-red-contrib-matrix-chat.git
synced 2025-04-20 13:03:12 -06:00
Merge pull request #103 from Skylar-Tech/102-upload-file
New file uploading node
This commit is contained in:
commit
fd174e32ff
250
package-lock.json
generated
250
package-lock.json
generated
@ -1,23 +1,27 @@
|
|||||||
{
|
{
|
||||||
"name": "node-red-contrib-matrix-chat",
|
"name": "node-red-contrib-matrix-chat",
|
||||||
"version": "0.7.0",
|
"version": "0.7.1",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "node-red-contrib-matrix-chat",
|
"name": "node-red-contrib-matrix-chat",
|
||||||
"version": "0.7.0",
|
"version": "0.7.1",
|
||||||
"license": "SEE LICENSE FILE",
|
"license": "SEE LICENSE FILE",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"abort-controller": "^3.0.0",
|
"abort-controller": "^3.0.0",
|
||||||
|
"fluent-ffmpeg": "^2.1.2",
|
||||||
"fs-extra": "^11.1.0",
|
"fs-extra": "^11.1.0",
|
||||||
"got": "^12.0.2",
|
"got": "^12.0.2",
|
||||||
|
"image-size": "^1.0.2",
|
||||||
"isomorphic-webcrypto": "^2.3.8",
|
"isomorphic-webcrypto": "^2.3.8",
|
||||||
"matrix-js-sdk": "^28.0.0",
|
"matrix-js-sdk": "^28.0.0",
|
||||||
|
"mime": "^3.0.0",
|
||||||
"node-fetch": "^3.3.0",
|
"node-fetch": "^3.3.0",
|
||||||
"node-localstorage": "^2.2.1",
|
"node-localstorage": "^2.2.1",
|
||||||
"olm": "https://gitlab.matrix.org/matrix-org/olm/-/package_files/2572/download",
|
"olm": "https://gitlab.matrix.org/matrix-org/olm/-/package_files/2572/download",
|
||||||
"request": "^2.88.2",
|
"request": "^2.88.2",
|
||||||
|
"tmp": "^0.2.1",
|
||||||
"utf8": "^3.0.0"
|
"utf8": "^3.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -3107,6 +3111,19 @@
|
|||||||
"ms": "^2.1.1"
|
"ms": "^2.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@expo/devcert/node_modules/tmp": {
|
||||||
|
"version": "0.0.33",
|
||||||
|
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||||
|
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"os-tmpdir": "~1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@expo/env": {
|
"node_modules/@expo/env": {
|
||||||
"version": "0.0.5",
|
"version": "0.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@expo/env/-/env-0.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/@expo/env/-/env-0.0.5.tgz",
|
||||||
@ -3167,6 +3184,19 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@expo/image-utils/node_modules/mime": {
|
||||||
|
"version": "2.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
|
||||||
|
"integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
|
"bin": {
|
||||||
|
"mime": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@expo/image-utils/node_modules/node-fetch": {
|
"node_modules/@expo/image-utils/node_modules/node-fetch": {
|
||||||
"version": "2.7.0",
|
"version": "2.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||||
@ -4992,6 +5022,19 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@react-native-community/cli-tools/node_modules/mime": {
|
||||||
|
"version": "2.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
|
||||||
|
"integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
|
"bin": {
|
||||||
|
"mime": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@react-native-community/cli-tools/node_modules/mimic-fn": {
|
"node_modules/@react-native-community/cli-tools/node_modules/mimic-fn": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
|
||||||
@ -5909,9 +5952,7 @@
|
|||||||
"node_modules/async": {
|
"node_modules/async": {
|
||||||
"version": "3.2.4",
|
"version": "3.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
|
||||||
"integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==",
|
"integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
|
||||||
"optional": true,
|
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/async-limiter": {
|
"node_modules/async-limiter": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@ -6168,9 +6209,7 @@
|
|||||||
"node_modules/balanced-match": {
|
"node_modules/balanced-match": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"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=="
|
||||||
"optional": true,
|
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/base-64": {
|
"node_modules/base-64": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
@ -6336,8 +6375,6 @@
|
|||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@ -6948,9 +6985,7 @@
|
|||||||
"node_modules/concat-map": {
|
"node_modules/concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||||
"optional": true,
|
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/connect": {
|
"node_modules/connect": {
|
||||||
"version": "3.7.0",
|
"version": "3.7.0",
|
||||||
@ -8137,6 +8172,18 @@
|
|||||||
"node": ">=0.4.0"
|
"node": ">=0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fluent-ffmpeg": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-IZTB4kq5GK0DPp7sGQ0q/BWurGHffRtQQwVkiqDgeO6wYJLLV5ZhgNOQ65loZxxuPMKZKZcICCUnaGtlxBiR0Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"async": ">=0.2.9",
|
||||||
|
"which": "^1.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fontfaceobserver": {
|
"node_modules/fontfaceobserver": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/fontfaceobserver/-/fontfaceobserver-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/fontfaceobserver/-/fontfaceobserver-2.3.0.tgz",
|
||||||
@ -8235,9 +8282,7 @@
|
|||||||
"node_modules/fs.realpath": {
|
"node_modules/fs.realpath": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
||||||
"optional": true,
|
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/fsevents": {
|
"node_modules/fsevents": {
|
||||||
"version": "2.3.3",
|
"version": "2.3.3",
|
||||||
@ -8339,8 +8384,6 @@
|
|||||||
"version": "7.1.6",
|
"version": "7.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
||||||
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fs.realpath": "^1.0.0",
|
"fs.realpath": "^1.0.0",
|
||||||
"inflight": "^1.0.4",
|
"inflight": "^1.0.4",
|
||||||
@ -8716,8 +8759,6 @@
|
|||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.2.tgz",
|
||||||
"integrity": "sha512-xfOoWjceHntRb3qFCrh5ZFORYH8XCdYpASltMhZ/Q0KZiOwjdE/Yl2QCiWdwD+lygV5bMCvauzgu5PxBX/Yerg==",
|
"integrity": "sha512-xfOoWjceHntRb3qFCrh5ZFORYH8XCdYpASltMhZ/Q0KZiOwjdE/Yl2QCiWdwD+lygV5bMCvauzgu5PxBX/Yerg==",
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"queue": "6.0.2"
|
"queue": "6.0.2"
|
||||||
},
|
},
|
||||||
@ -8781,8 +8822,6 @@
|
|||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"once": "^1.3.0",
|
"once": "^1.3.0",
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
@ -8791,9 +8830,7 @@
|
|||||||
"node_modules/inherits": {
|
"node_modules/inherits": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||||
"optional": true,
|
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/ini": {
|
"node_modules/ini": {
|
||||||
"version": "1.3.8",
|
"version": "1.3.8",
|
||||||
@ -9098,9 +9135,7 @@
|
|||||||
"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",
|
||||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
|
||||||
"optional": true,
|
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/isobject": {
|
"node_modules/isobject": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
@ -11453,16 +11488,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mime": {
|
"node_modules/mime": {
|
||||||
"version": "2.6.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
|
||||||
"integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
|
"integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"mime": "cli.js"
|
"mime": "cli.js"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=4.0.0"
|
"node": ">=10.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mime-db": {
|
"node_modules/mime-db": {
|
||||||
@ -11509,8 +11542,6 @@
|
|||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
},
|
},
|
||||||
@ -12022,8 +12053,6 @@
|
|||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
@ -12404,8 +12433,6 @@
|
|||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@ -12886,8 +12913,6 @@
|
|||||||
"version": "6.0.2",
|
"version": "6.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
|
||||||
"integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
|
"integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"inherits": "~2.0.3"
|
"inherits": "~2.0.3"
|
||||||
}
|
}
|
||||||
@ -14478,16 +14503,28 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tmp": {
|
"node_modules/tmp": {
|
||||||
"version": "0.0.33",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
|
||||||
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
|
"integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"os-tmpdir": "~1.0.2"
|
"rimraf": "^3.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.6.0"
|
"node": ">=8.17.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/tmp/node_modules/rimraf": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||||
|
"dependencies": {
|
||||||
|
"glob": "^7.1.3"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"rimraf": "bin.js"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tmpl": {
|
"node_modules/tmpl": {
|
||||||
@ -15002,8 +15039,6 @@
|
|||||||
"version": "1.3.1",
|
"version": "1.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
||||||
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
|
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"isexe": "^2.0.0"
|
"isexe": "^2.0.0"
|
||||||
},
|
},
|
||||||
@ -15059,9 +15094,7 @@
|
|||||||
"node_modules/wrappy": {
|
"node_modules/wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||||
"optional": true,
|
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/write-file-atomic": {
|
"node_modules/write-file-atomic": {
|
||||||
"version": "2.4.3",
|
"version": "2.4.3",
|
||||||
@ -17519,6 +17552,16 @@
|
|||||||
"requires": {
|
"requires": {
|
||||||
"ms": "^2.1.1"
|
"ms": "^2.1.1"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"tmp": {
|
||||||
|
"version": "0.0.33",
|
||||||
|
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||||
|
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
|
"requires": {
|
||||||
|
"os-tmpdir": "~1.0.2"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -17576,6 +17619,13 @@
|
|||||||
"universalify": "^1.0.0"
|
"universalify": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"mime": {
|
||||||
|
"version": "2.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
|
||||||
|
"integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
"node-fetch": {
|
"node-fetch": {
|
||||||
"version": "2.7.0",
|
"version": "2.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||||
@ -19191,6 +19241,13 @@
|
|||||||
"is-unicode-supported": "^0.1.0"
|
"is-unicode-supported": "^0.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"mime": {
|
||||||
|
"version": "2.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
|
||||||
|
"integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
"mimic-fn": {
|
"mimic-fn": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
|
||||||
@ -19753,9 +19810,7 @@
|
|||||||
"async": {
|
"async": {
|
||||||
"version": "3.2.4",
|
"version": "3.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
|
||||||
"integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==",
|
"integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
|
||||||
"optional": true,
|
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"async-limiter": {
|
"async-limiter": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@ -19981,9 +20036,7 @@
|
|||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"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=="
|
||||||
"optional": true,
|
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"base-64": {
|
"base-64": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
@ -20123,8 +20176,6 @@
|
|||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@ -20582,9 +20633,7 @@
|
|||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||||
"optional": true,
|
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"connect": {
|
"connect": {
|
||||||
"version": "3.7.0",
|
"version": "3.7.0",
|
||||||
@ -21524,6 +21573,15 @@
|
|||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
|
"fluent-ffmpeg": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-IZTB4kq5GK0DPp7sGQ0q/BWurGHffRtQQwVkiqDgeO6wYJLLV5ZhgNOQ65loZxxuPMKZKZcICCUnaGtlxBiR0Q==",
|
||||||
|
"requires": {
|
||||||
|
"async": ">=0.2.9",
|
||||||
|
"which": "^1.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"fontfaceobserver": {
|
"fontfaceobserver": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/fontfaceobserver/-/fontfaceobserver-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/fontfaceobserver/-/fontfaceobserver-2.3.0.tgz",
|
||||||
@ -21598,9 +21656,7 @@
|
|||||||
"fs.realpath": {
|
"fs.realpath": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
||||||
"optional": true,
|
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"fsevents": {
|
"fsevents": {
|
||||||
"version": "2.3.3",
|
"version": "2.3.3",
|
||||||
@ -21674,8 +21730,6 @@
|
|||||||
"version": "7.1.6",
|
"version": "7.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
||||||
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"fs.realpath": "^1.0.0",
|
"fs.realpath": "^1.0.0",
|
||||||
"inflight": "^1.0.4",
|
"inflight": "^1.0.4",
|
||||||
@ -21949,8 +22003,6 @@
|
|||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.2.tgz",
|
||||||
"integrity": "sha512-xfOoWjceHntRb3qFCrh5ZFORYH8XCdYpASltMhZ/Q0KZiOwjdE/Yl2QCiWdwD+lygV5bMCvauzgu5PxBX/Yerg==",
|
"integrity": "sha512-xfOoWjceHntRb3qFCrh5ZFORYH8XCdYpASltMhZ/Q0KZiOwjdE/Yl2QCiWdwD+lygV5bMCvauzgu5PxBX/Yerg==",
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"queue": "6.0.2"
|
"queue": "6.0.2"
|
||||||
}
|
}
|
||||||
@ -21998,8 +22050,6 @@
|
|||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"once": "^1.3.0",
|
"once": "^1.3.0",
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
@ -22008,9 +22058,7 @@
|
|||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||||
"optional": true,
|
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"ini": {
|
"ini": {
|
||||||
"version": "1.3.8",
|
"version": "1.3.8",
|
||||||
@ -22242,9 +22290,7 @@
|
|||||||
"isexe": {
|
"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",
|
||||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
|
||||||
"optional": true,
|
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"isobject": {
|
"isobject": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
@ -24103,11 +24149,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"mime": {
|
"mime": {
|
||||||
"version": "2.6.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
|
||||||
"integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
|
"integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="
|
||||||
"optional": true,
|
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"mime-db": {
|
"mime-db": {
|
||||||
"version": "1.52.0",
|
"version": "1.52.0",
|
||||||
@ -24138,8 +24182,6 @@
|
|||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
}
|
}
|
||||||
@ -24532,8 +24574,6 @@
|
|||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
@ -24824,9 +24864,7 @@
|
|||||||
"path-is-absolute": {
|
"path-is-absolute": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
|
||||||
"optional": true,
|
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"path-key": {
|
"path-key": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
@ -25193,8 +25231,6 @@
|
|||||||
"version": "6.0.2",
|
"version": "6.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
|
||||||
"integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
|
"integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"inherits": "~2.0.3"
|
"inherits": "~2.0.3"
|
||||||
}
|
}
|
||||||
@ -26474,13 +26510,21 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tmp": {
|
"tmp": {
|
||||||
"version": "0.0.33",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
|
||||||
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
|
"integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"os-tmpdir": "~1.0.2"
|
"rimraf": "^3.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"rimraf": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||||
|
"requires": {
|
||||||
|
"glob": "^7.1.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tmpl": {
|
"tmpl": {
|
||||||
@ -26887,8 +26931,6 @@
|
|||||||
"version": "1.3.1",
|
"version": "1.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
||||||
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
|
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"isexe": "^2.0.0"
|
"isexe": "^2.0.0"
|
||||||
}
|
}
|
||||||
@ -26934,9 +26976,7 @@
|
|||||||
"wrappy": {
|
"wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||||
"optional": true,
|
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"write-file-atomic": {
|
"write-file-atomic": {
|
||||||
"version": "2.4.3",
|
"version": "2.4.3",
|
||||||
|
@ -4,14 +4,18 @@
|
|||||||
"description": "Matrix chat server client for Node-RED",
|
"description": "Matrix chat server client for Node-RED",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"abort-controller": "^3.0.0",
|
"abort-controller": "^3.0.0",
|
||||||
|
"fluent-ffmpeg": "^2.1.2",
|
||||||
"fs-extra": "^11.1.0",
|
"fs-extra": "^11.1.0",
|
||||||
"got": "^12.0.2",
|
"got": "^12.0.2",
|
||||||
|
"image-size": "^1.0.2",
|
||||||
"isomorphic-webcrypto": "^2.3.8",
|
"isomorphic-webcrypto": "^2.3.8",
|
||||||
"matrix-js-sdk": "^28.0.0",
|
"matrix-js-sdk": "^28.0.0",
|
||||||
|
"mime": "^3.0.0",
|
||||||
"node-fetch": "^3.3.0",
|
"node-fetch": "^3.3.0",
|
||||||
"node-localstorage": "^2.2.1",
|
"node-localstorage": "^2.2.1",
|
||||||
"olm": "https://gitlab.matrix.org/matrix-org/olm/-/package_files/2572/download",
|
"olm": "https://gitlab.matrix.org/matrix-org/olm/-/package_files/2572/download",
|
||||||
"request": "^2.88.2",
|
"request": "^2.88.2",
|
||||||
|
"tmp": "^0.2.1",
|
||||||
"utf8": "^3.0.0"
|
"utf8": "^3.0.0"
|
||||||
},
|
},
|
||||||
"node-red": {
|
"node-red": {
|
||||||
@ -23,6 +27,7 @@
|
|||||||
"matrix-delete-event": "src/matrix-delete-event.js",
|
"matrix-delete-event": "src/matrix-delete-event.js",
|
||||||
"matrix-send-file": "src/matrix-send-file.js",
|
"matrix-send-file": "src/matrix-send-file.js",
|
||||||
"matrix-send-image": "src/matrix-send-image.js",
|
"matrix-send-image": "src/matrix-send-image.js",
|
||||||
|
"matrix-upload-file": "src/matrix-upload-file.js",
|
||||||
"matrix-react": "src/matrix-react.js",
|
"matrix-react": "src/matrix-react.js",
|
||||||
"matrix-create-room": "src/matrix-create-room.js",
|
"matrix-create-room": "src/matrix-create-room.js",
|
||||||
"matrix-invite-room": "src/matrix-invite-room.js",
|
"matrix-invite-room": "src/matrix-invite-room.js",
|
||||||
|
0
src/matrix-file-crypt.js
Normal file
0
src/matrix-file-crypt.js
Normal file
@ -43,6 +43,9 @@
|
|||||||
<label for="node-input-message"><i class="fa fa-comment"></i> Message</label>
|
<label for="node-input-message"><i class="fa fa-comment"></i> Message</label>
|
||||||
<textarea id="node-input-message" placeholder="msg.payload" style="width: 70%;"></textarea>
|
<textarea id="node-input-message" placeholder="msg.payload" style="width: 70%;"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-row form-tips">
|
||||||
|
If message is an object it sets the full content of the message.
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<input
|
<input
|
||||||
@ -104,9 +107,9 @@
|
|||||||
<dd> Room ID to send image to. Optional if configured on the node. If configured on the node this input will be overridden.</dd>
|
<dd> Room ID to send image to. Optional if configured on the node. If configured on the node this input will be overridden.</dd>
|
||||||
|
|
||||||
<dt>msg.payload
|
<dt>msg.payload
|
||||||
<span class="property-type">string</span>
|
<span class="property-type">string|object</span>
|
||||||
</dt>
|
</dt>
|
||||||
<dd> the message text. If configured on the node this is ignored otherwise it required. </dd>
|
<dd> the message text or an object to customize the full content. If configured on the node this is ignored otherwise it required. </dd>
|
||||||
|
|
||||||
<dt>msg.replace
|
<dt>msg.replace
|
||||||
<span class="property-type">bool</span>
|
<span class="property-type">bool</span>
|
||||||
|
@ -70,22 +70,6 @@ module.exports = function(RED) {
|
|||||||
let msgType = node.messageType,
|
let msgType = node.messageType,
|
||||||
msgFormat = node.messageFormat;
|
msgFormat = node.messageFormat;
|
||||||
|
|
||||||
if(msgType === 'msg.type') {
|
|
||||||
if(!msg.type) {
|
|
||||||
node.error("msg.type type is set to be passed in via msg.type but was not defined", msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
msgType = msg.type;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(msgFormat === 'msg.format') {
|
|
||||||
if(!msg.format) {
|
|
||||||
node.error("Message format is set to be passed in via msg.format but was not defined", msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
msgFormat = msg.format;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!node.server || !node.server.matrixClient) {
|
if (!node.server || !node.server.matrixClient) {
|
||||||
node.warn("No matrix server selected");
|
node.warn("No matrix server selected");
|
||||||
return;
|
return;
|
||||||
@ -109,7 +93,27 @@ module.exports = function(RED) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let content = {
|
let content = null;
|
||||||
|
if(typeof payload === 'object') {
|
||||||
|
content = payload;
|
||||||
|
} else {
|
||||||
|
if(msgType === 'msg.type') {
|
||||||
|
if(!msg.type) {
|
||||||
|
node.error("msg.type type is set to be passed in via msg.type but was not defined", msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
msgType = msg.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(msgFormat === 'msg.format') {
|
||||||
|
if(!msg.format) {
|
||||||
|
node.error("Message format is set to be passed in via msg.format but was not defined", msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
msgFormat = msg.format;
|
||||||
|
}
|
||||||
|
|
||||||
|
content = {
|
||||||
msgtype: msgType,
|
msgtype: msgType,
|
||||||
body: payload.toString()
|
body: payload.toString()
|
||||||
};
|
};
|
||||||
@ -140,6 +144,7 @@ module.exports = function(RED) {
|
|||||||
};
|
};
|
||||||
content['body'] = ' * ' + content['body'];
|
content['body'] = ' * ' + content['body'];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
node.server.matrixClient.sendMessage(msg.topic, content)
|
node.server.matrixClient.sendMessage(msg.topic, content)
|
||||||
.then(function(e) {
|
.then(function(e) {
|
||||||
|
@ -76,7 +76,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-row form-tips">
|
<div class="form-row form-tips">
|
||||||
Timeout MS is how many milliseconds the server should show the user typing for.
|
Timeout Milliseconds is how many milliseconds the server should show the user typing for. Ignored if setting typing to false.
|
||||||
</div>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
163
src/matrix-upload-file.html
Normal file
163
src/matrix-upload-file.html
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('matrix-upload-file',{
|
||||||
|
category: 'matrix',
|
||||||
|
color: '#00b7ca',
|
||||||
|
icon: "matrix.png",
|
||||||
|
outputLabels: ["success", "error"],
|
||||||
|
inputs:1,
|
||||||
|
outputs:2,
|
||||||
|
defaults: {
|
||||||
|
name: { value: null },
|
||||||
|
server: { type: "matrix-server-config" },
|
||||||
|
inputType: { value: "msg" },
|
||||||
|
inputValue: { value: "payload" },
|
||||||
|
fileNameType: { value: "msg" },
|
||||||
|
fileNameValue: { value: "filename" },
|
||||||
|
contentType: { value: null },
|
||||||
|
generateThumbnails: { type: "checkbox", value: true },
|
||||||
|
},
|
||||||
|
label: function() {
|
||||||
|
return this.name || "Upload File";
|
||||||
|
},
|
||||||
|
oneditprepare: function() {
|
||||||
|
$("#node-input-input").typedInput({
|
||||||
|
type: this.inputType,
|
||||||
|
types:['msg','flow','global','str'],
|
||||||
|
}).typedInput('value', this.inputValue);
|
||||||
|
|
||||||
|
$("#node-input-file-name").typedInput({
|
||||||
|
type: this.fileNameType,
|
||||||
|
types:['msg','flow','global','str'],
|
||||||
|
}).typedInput('value', this.fileNameValue);
|
||||||
|
},
|
||||||
|
oneditsave: function() {
|
||||||
|
this.inputType = $("#node-input-input").typedInput('type');
|
||||||
|
this.inputValue = $("#node-input-input").typedInput('value');
|
||||||
|
this.fileNameType = $("#node-input-file-name").typedInput('type');
|
||||||
|
this.fileNameValue = $("#node-input-file-name").typedInput('value');
|
||||||
|
},
|
||||||
|
paletteLabel: 'Upload File'
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/html" data-template-name="matrix-upload-file">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-server"><i class="fa fa-user"></i> Matrix Server Config</label>
|
||||||
|
<input type="text" id="node-input-server">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-input"><i class="fa fa-file"></i> File Input</label>
|
||||||
|
<input type="text" id="node-input-input">
|
||||||
|
</div>
|
||||||
|
<div class="form-tips" style="margin-bottom: 12px;">
|
||||||
|
Must be a buffer or string. If it is a string it assumes it is a path to a file on the filesystem.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-file-name"><i class="fa fa-file"></i> File Name</label>
|
||||||
|
<input type="text" id="node-input-file-name">
|
||||||
|
</div>
|
||||||
|
<div class="form-tips" style="margin-bottom: 12px;">
|
||||||
|
Name to give file on remote server. Required if file input is a buffer otherwise it uses the original file name.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-contentType"><i class="fa fa-user"></i> Content-Type</label>
|
||||||
|
<input type="text" id="node-input-contentType" placeholder="msg.contentType">
|
||||||
|
</div>
|
||||||
|
<div class="form-tips" style="margin-bottom: 12px;">
|
||||||
|
Must be a valid <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types" target="_blank">MIME Type</a> (ex: application/pdf) or left undefined to auto detect
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="node-input-generateThumbnails"
|
||||||
|
style="width: auto; margin-left: 125px; vertical-align: top"
|
||||||
|
/>
|
||||||
|
<label for="node-input-generateThumbnails" style="width: auto;max-width:50%;">
|
||||||
|
Generate m.video thumbnails using ffmpeg
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-tips">
|
||||||
|
ffmpeg & ffprobe must be installed for thumbnail generation, calculating duration of video or audio file, and getting width & height for videos. This functionality is disabled otherwise.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(function(){
|
||||||
|
$("#node-input-roomId").on("keyup", function() {
|
||||||
|
if($(this).val() && !$(this).val().startsWith("!")) {
|
||||||
|
$("#node-input-roomId-error").html(`Room IDs start with exclamation point "!"<br />Example: !OGEhHVWSdvArJzumhm:matrix.org`).show();
|
||||||
|
} else {
|
||||||
|
$("#node-input-roomId-error").hide();
|
||||||
|
}
|
||||||
|
}).trigger('keyup');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/html" data-help-name="matrix-upload-file">
|
||||||
|
<h3>Details</h3>
|
||||||
|
<p>This node will send a file to a Matrix chat room. Supports direct linking to a File In node.</p>
|
||||||
|
|
||||||
|
<h3>Inputs</h3>
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.payload
|
||||||
|
<span class="property-type">string | Buffer</span>
|
||||||
|
</dt>
|
||||||
|
<dd> If this is not a buffer it assumes it is a path to the file. </dd>
|
||||||
|
|
||||||
|
<dt>msg.topic
|
||||||
|
<span class="property-type">string</span>
|
||||||
|
</dt>
|
||||||
|
<dd> Room ID to send file to. Ignored if configured on the node, otherwise required.</dd>
|
||||||
|
|
||||||
|
<dt class="optional">msg.filename
|
||||||
|
<span class="property-type">string | null</span>
|
||||||
|
</dt>
|
||||||
|
<dd> name of the file to upload. You REALLY should pass this if you want the file type to be detected correctly. If no filename is provided it will be auto-detected but note that this is not perfect (for example: .doc word files are detected incorrectly as application/x-cfb) and only works with binary files.</dd>
|
||||||
|
|
||||||
|
<dt class="optional">msg.body
|
||||||
|
<span class="property-type">string | null</span>
|
||||||
|
</dt>
|
||||||
|
<dd> this will be the display name the client will see when rendered in their chat client. If this is left empty it will just display as "Attachment".</dd>
|
||||||
|
|
||||||
|
<dt class="optional">msg.contentType
|
||||||
|
<span class="property-type">string | null</span>
|
||||||
|
</dt>
|
||||||
|
<dd> Content <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types" target="_blank">MIME Type</a>. If set this forces the mime type. If you do not provide this it will try to be auto-detected.</dd>
|
||||||
|
|
||||||
|
<dt class="optional">msg.content
|
||||||
|
<span class="property-type">object | null</span>
|
||||||
|
</dt>
|
||||||
|
<dd> craft your own msg.content to send to the server. If defined then <code>msg.filename</code>, <code>msg.contentType</code>, <code>msg.body</code>, and <code>msg.payload</code> aren't required since the file already exists.</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<h3>Outputs</h3>
|
||||||
|
<ol class="node-ports">
|
||||||
|
<li>Success
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.eventId <span class="property-type">string</span></dt>
|
||||||
|
<dd>the eventId from the posted message.</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li>Error
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.error <span class="property-type">string</span></dt>
|
||||||
|
<dd>the error that occurred.</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h3>References</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types">MIME Types</a> - description of <code>msg.contentType</code> format</li>
|
||||||
|
</ul>
|
||||||
|
</script>
|
471
src/matrix-upload-file.js
Normal file
471
src/matrix-upload-file.js
Normal file
@ -0,0 +1,471 @@
|
|||||||
|
const crypto = require("isomorphic-webcrypto");
|
||||||
|
const ffmpeg = require('fluent-ffmpeg');
|
||||||
|
const getImageSize = require('image-size');
|
||||||
|
const tmp = require('tmp');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
module.exports = function(RED) {
|
||||||
|
function MatrixUploadFile(n) {
|
||||||
|
RED.nodes.createNode(this, n);
|
||||||
|
|
||||||
|
let node = this;
|
||||||
|
|
||||||
|
this.name = n.name;
|
||||||
|
this.server = RED.nodes.getNode(n.server);
|
||||||
|
this.inputType = n.inputType;
|
||||||
|
this.inputValue = n.inputValue;
|
||||||
|
this.fileNameType = n.fileNameType;
|
||||||
|
this.fileNameValue = n.fileNameValue;
|
||||||
|
this.contentType = n.contentType;
|
||||||
|
this.generateThumbnails = n.generateThumbnails;
|
||||||
|
|
||||||
|
if (!node.server) {
|
||||||
|
node.warn("No configuration node");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
node.server.register(node);
|
||||||
|
|
||||||
|
node.status({ fill: "red", shape: "ring", text: "disconnected" });
|
||||||
|
|
||||||
|
node.server.on("disconnected", function(){
|
||||||
|
node.status({ fill: "red", shape: "ring", text: "disconnected" });
|
||||||
|
});
|
||||||
|
|
||||||
|
node.server.on("connected", function() {
|
||||||
|
node.status({ fill: "green", shape: "ring", text: "connected" });
|
||||||
|
});
|
||||||
|
|
||||||
|
async function detectFileType(filename, bufferOrPath)
|
||||||
|
{
|
||||||
|
const Mime = require('mime');
|
||||||
|
let file = Buffer.isBuffer(bufferOrPath) ? filename : bufferOrPath;
|
||||||
|
|
||||||
|
if(file)
|
||||||
|
{
|
||||||
|
let type = Mime.getType(file);
|
||||||
|
let ext = Mime.getExtension(file);
|
||||||
|
if(type) {
|
||||||
|
return {ext: ext, mime: type}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFileBuffer(data)
|
||||||
|
{
|
||||||
|
if(Buffer.isBuffer(data)) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data && RED.settings.fileWorkingDirectory && !path.isAbsolute(data)) {
|
||||||
|
return fs.readFileSync(path.resolve(path.join(RED.settings.fileWorkingDirectory,data)));
|
||||||
|
}
|
||||||
|
return fs.readFileSync(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getToValue(msg, type, property) {
|
||||||
|
let value = property;
|
||||||
|
if (type === "msg") {
|
||||||
|
value = RED.util.getMessageProperty(msg, property);
|
||||||
|
} else if ((type === 'flow') || (type === 'global')) {
|
||||||
|
try {
|
||||||
|
value = RED.util.evaluateNodeProperty(property, type, node, msg);
|
||||||
|
} catch(e2) {
|
||||||
|
throw new Error("Invalid value evaluation");
|
||||||
|
}
|
||||||
|
} else if(type === "bool") {
|
||||||
|
value = (property === 'true');
|
||||||
|
} else if(type === "num") {
|
||||||
|
value = Number(property);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
node.on("input", onInput);
|
||||||
|
async function onInput(msg)
|
||||||
|
{
|
||||||
|
if (! node.server || ! node.server.matrixClient) {
|
||||||
|
node.warn("No matrix server selected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!node.server.isConnected()) {
|
||||||
|
node.error("Matrix server connection is currently closed", msg);
|
||||||
|
msg.error = "Matrix server connection is currently closed";
|
||||||
|
node.send([null, msg]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let bufferOrPath = getToValue(msg, node.inputType, node.inputValue);
|
||||||
|
if(!bufferOrPath) {
|
||||||
|
node.error('Missing file path/buffer input', msg);
|
||||||
|
msg.error = 'Missing file path/buffer input';
|
||||||
|
node.send([null, msg]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let filename = getToValue(msg, node.fileNameType, node.fileNameValue);
|
||||||
|
if(!filename || typeof filename !== 'string') {
|
||||||
|
if(!Buffer.isBuffer(bufferOrPath)) {
|
||||||
|
filename = path.basename(bufferOrPath);
|
||||||
|
} else {
|
||||||
|
node.error('Missing filename, this is required if input is a file buffer', msg);
|
||||||
|
msg.error = 'Missing filename, this is required if input is a file buffer';
|
||||||
|
node.send([null, msg]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.contentType = node.contentType || msg.contentType || null;
|
||||||
|
let detectedFileType = await detectFileType(filename, bufferOrPath);
|
||||||
|
node.log("Detected file type " + JSON.stringify(detectedFileType) + " for " + (Buffer.isBuffer(bufferOrPath) ? 'buffer' : `file ${bufferOrPath}`), msg);
|
||||||
|
|
||||||
|
let contentType = msg.contentType || detectedFileType?.mime || null,
|
||||||
|
msgtype = msg.msgtype || null;
|
||||||
|
if(!contentType) {
|
||||||
|
node.warn("Content-type failed to detect, falling back to text/plain", msg);
|
||||||
|
contentType = 'text/plain';
|
||||||
|
}
|
||||||
|
if(!msgtype) {
|
||||||
|
msgtype = autoDetectMatrixMessageType(detectedFileType);
|
||||||
|
}
|
||||||
|
|
||||||
|
let encryptedFile = null;
|
||||||
|
if(msg.encrypted) {
|
||||||
|
encryptedFile = await encryptAttachment(getFileBuffer(bufferOrPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
node.log("Uploading file ", msg);
|
||||||
|
let file;
|
||||||
|
try {
|
||||||
|
file = await node.server.matrixClient.uploadContent(
|
||||||
|
encryptedFile?.data || getFileBuffer(bufferOrPath),
|
||||||
|
{
|
||||||
|
name: filename, // Name to give the file on the server.
|
||||||
|
rawResponse: false, // Return the raw body, rather than parsing the JSON.
|
||||||
|
type: contentType, // Content-type for the upload. Defaults to file.type, or applicaton/octet-stream.
|
||||||
|
onlyContentUri: false // Just return the content URI, rather than the whole body. Defaults to false. Ignored if opts.rawResponse is true.
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
node.error("Upload content error " + e);
|
||||||
|
msg.error = e;
|
||||||
|
node.send([null, msg]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we call this method when we need a file and cannot use the buffer
|
||||||
|
// so if we get passed a buffer we write it to a tmp file and return that
|
||||||
|
// otherwise we just return the string because it's already a file
|
||||||
|
let tempFile = null;
|
||||||
|
function getFile(bufferOrFile) {
|
||||||
|
if(!Buffer.isBuffer(bufferOrFile)) {
|
||||||
|
return bufferOrFile; // already a file
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tempFile) {
|
||||||
|
return tempFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write buffer to tmp file and return path
|
||||||
|
let tmpObj = tmp.fileSync({ postfix: `.${detectedFileType.ext}` });
|
||||||
|
fs.writeFileSync(tmpObj.name, bufferOrFile);
|
||||||
|
tempFile = tmpObj.name;
|
||||||
|
return tmpObj.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteTempFile() {
|
||||||
|
if(!tempFile) return null;
|
||||||
|
fs.rmSync(tempFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get size of a buffer or file in bytes
|
||||||
|
function getFileSize(bufferOrPath) {
|
||||||
|
if(Buffer.isBuffer(bufferOrPath)) {
|
||||||
|
return Buffer.byteLength(bufferOrPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fs.statSync(bufferOrPath).size;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function addThumbnail(buffer) {
|
||||||
|
let imageSize = getImageSize(Buffer.isBuffer(buffer) ? buffer : buffer.data);
|
||||||
|
msg.payload.info.thumbnail_info = {
|
||||||
|
w: imageSize.width,
|
||||||
|
h: imageSize.height,
|
||||||
|
size: getFileSize(Buffer.isBuffer(buffer) ? buffer : buffer.data)
|
||||||
|
}
|
||||||
|
let uploadedThumbnail = await node.server.matrixClient.uploadContent(
|
||||||
|
Buffer.isBuffer(buffer) ? buffer : buffer.data,
|
||||||
|
{
|
||||||
|
name: "thumbnail.png", // Name to give the file on the server.
|
||||||
|
rawResponse: false, // Return the raw body, rather than parsing the JSON.
|
||||||
|
type: "image/png", // Content-type for the upload. Defaults to file.type, or applicaton/octet-stream.
|
||||||
|
onlyContentUri: false // Just return the content URI, rather than the whole body. Defaults to false. Ignored if opts.rawResponse is true.
|
||||||
|
});
|
||||||
|
// delete local file
|
||||||
|
if(msg.encrypted) {
|
||||||
|
msg.payload.info.thumbnail_file.url = uploadedThumbnail.content_uri;
|
||||||
|
} else {
|
||||||
|
msg.payload.info.thumbnail_url = uploadedThumbnail.content_uri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _ffmpegVideoThumbnail(filepath){
|
||||||
|
return new Promise((resolve,reject) => {
|
||||||
|
let filename = `${msg._msgid}-screenshot.png`;
|
||||||
|
ffmpeg(filepath)
|
||||||
|
.on('end', async function() {
|
||||||
|
let path = `/tmp/${filename}`;
|
||||||
|
let buffer = getFileBuffer(path);
|
||||||
|
let encryptedThumbnail = null;
|
||||||
|
if(msg.encrypted) {
|
||||||
|
encryptedThumbnail = await encryptAttachment(buffer);
|
||||||
|
msg.payload.info.thumbnail_file = encryptedFile.info;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await addThumbnail(encryptedThumbnail || buffer);
|
||||||
|
fs.rmSync(path); // delete temporary thumbnail file
|
||||||
|
resolve();
|
||||||
|
} catch(e) {
|
||||||
|
return reject(new Error("Thumbnail upload failure: " + e));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on('error', function(err) {
|
||||||
|
return reject(err);
|
||||||
|
})
|
||||||
|
.screenshots({
|
||||||
|
timestamps: [0],
|
||||||
|
filename: filename,
|
||||||
|
folder: '/tmp',
|
||||||
|
size: '320x?'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.payload = {};
|
||||||
|
if(msg.encrypted) {
|
||||||
|
msg.payload.file = encryptedFile?.info || {};
|
||||||
|
msg.payload.file.url = file.content_uri;
|
||||||
|
} else {
|
||||||
|
msg.payload.url = file.content_uri;
|
||||||
|
}
|
||||||
|
msg.payload.msgtype = msgtype;
|
||||||
|
msg.payload.body = msg.body || msg.filename || "";
|
||||||
|
msg.payload.info = {
|
||||||
|
"mimetype": contentType,
|
||||||
|
"size": getFileSize(bufferOrPath),
|
||||||
|
};
|
||||||
|
if(msgtype === 'm.image') {
|
||||||
|
// detect size of image
|
||||||
|
try {
|
||||||
|
let imageSize = getImageSize(buffer);
|
||||||
|
msg.payload.info.h = imageSize.height;
|
||||||
|
msg.payload.info.w = imageSize.width;
|
||||||
|
} catch(e) {
|
||||||
|
node.error("Failed to get image size: " + e, msg);
|
||||||
|
}
|
||||||
|
} else if(msgtype === 'm.audio' && detectedFileType) {
|
||||||
|
try {
|
||||||
|
// detect duration of audio clip
|
||||||
|
let filepath = getFile(bufferOrPath);
|
||||||
|
let metadata = await _ffprobe(filepath);
|
||||||
|
let audioStream = metadata?.streams.filter(function(stream){return stream.codec_type === "audio" || false;})[0];
|
||||||
|
if(audioStream?.duration) {
|
||||||
|
msg.payload.info.duration = audioStream?.duration * 1000;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
node.error(e, msg);
|
||||||
|
}
|
||||||
|
deleteTempFile();
|
||||||
|
} else if(msgtype === 'm.video' && detectedFileType) {
|
||||||
|
let filepath = getFile(bufferOrPath);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// detect duration & width/height of video clip
|
||||||
|
let metadata = await _ffprobe(filepath);
|
||||||
|
let videoStream = metadata?.streams.filter(function(stream){return stream.codec_type === "video" || false;})[0];
|
||||||
|
if(videoStream) {
|
||||||
|
msg.payload.info.duration = videoStream.duration * 1000;
|
||||||
|
msg.payload.info.w = videoStream.width;
|
||||||
|
msg.payload.info.h = videoStream.height;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
node.error("ffprobe error: " + e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(node.generateThumbnails) {
|
||||||
|
try {
|
||||||
|
await _ffmpegVideoThumbnail(filepath);
|
||||||
|
} catch(e) {
|
||||||
|
node.error("Screenshot generation error: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deleteTempFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
node.send(msg, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
node.on("close", function() {
|
||||||
|
node.server.deregister(node);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("matrix-upload-file", MatrixUploadFile);
|
||||||
|
|
||||||
|
// the following was taken & modified from https://github.com/matrix-org/browser-encrypt-attachment/blob/master/index.js
|
||||||
|
/**
|
||||||
|
* Encrypt an attachment.
|
||||||
|
* @param {ArrayBuffer} plaintextBuffer The attachment data buffer.
|
||||||
|
* @return {Promise} A promise that resolves with an object when the attachment is encrypted.
|
||||||
|
* The object has a "data" key with an ArrayBuffer of encrypted data and an "info" key
|
||||||
|
* with an object containing the info needed to decrypt the data.
|
||||||
|
*/
|
||||||
|
function encryptAttachment(plaintextBuffer) {
|
||||||
|
let cryptoKey; // The AES key object.
|
||||||
|
let exportedKey; // The AES key exported as JWK.
|
||||||
|
let ciphertextBuffer; // ArrayBuffer of encrypted data.
|
||||||
|
let sha256Buffer; // ArrayBuffer of digest.
|
||||||
|
let ivArray; // Uint8Array of AES IV
|
||||||
|
// Generate an IV where the first 8 bytes are random and the high 8 bytes
|
||||||
|
// are zero. We set the counter low bits to 0 since it makes it unlikely
|
||||||
|
// that the 64 bit counter will overflow.
|
||||||
|
ivArray = new Uint8Array(16);
|
||||||
|
crypto.getRandomValues(ivArray.subarray(0,8));
|
||||||
|
// Load the encryption key.
|
||||||
|
return crypto.subtle.generateKey(
|
||||||
|
{"name": "AES-CTR", length: 256}, true, ["encrypt", "decrypt"]
|
||||||
|
).then(function(generateKeyResult) {
|
||||||
|
cryptoKey = generateKeyResult;
|
||||||
|
// Export the Key as JWK.
|
||||||
|
return crypto.subtle.exportKey("jwk", cryptoKey);
|
||||||
|
}).then(function(exportKeyResult) {
|
||||||
|
exportedKey = exportKeyResult;
|
||||||
|
// Encrypt the input ArrayBuffer.
|
||||||
|
// Use half of the iv as the counter by setting the "length" to 64.
|
||||||
|
return crypto.subtle.encrypt(
|
||||||
|
{name: "AES-CTR", counter: ivArray, length: 64}, cryptoKey, plaintextBuffer
|
||||||
|
);
|
||||||
|
}).then(function(encryptResult) {
|
||||||
|
ciphertextBuffer = encryptResult;
|
||||||
|
// SHA-256 the encrypted data.
|
||||||
|
return crypto.subtle.digest("SHA-256", ciphertextBuffer);
|
||||||
|
}).then(function (digestResult) {
|
||||||
|
sha256Buffer = digestResult;
|
||||||
|
|
||||||
|
return {
|
||||||
|
data: ciphertextBuffer,
|
||||||
|
info: {
|
||||||
|
v: "v2",
|
||||||
|
key: exportedKey,
|
||||||
|
iv: encodeBase64(ivArray),
|
||||||
|
hashes: {
|
||||||
|
sha256: encodeBase64(new Uint8Array(sha256Buffer)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypt an attachment.
|
||||||
|
* @param {ArrayBuffer} ciphertextBuffer The encrypted attachment data buffer.
|
||||||
|
* @param {Object} info The information needed to decrypt the attachment.
|
||||||
|
* @param {Object} info.key AES-CTR JWK key object.
|
||||||
|
* @param {string} info.iv Base64 encoded 16 byte AES-CTR IV.
|
||||||
|
* @param {string} info.hashes.sha256 Base64 encoded SHA-256 hash of the ciphertext.
|
||||||
|
* @return {Promise} A promise that resolves with an ArrayBuffer when the attachment is decrypted.
|
||||||
|
*/
|
||||||
|
function decryptAttachment(ciphertextBuffer, info) {
|
||||||
|
|
||||||
|
if (info === undefined || info.key === undefined || info.iv === undefined
|
||||||
|
|| info.hashes === undefined || info.hashes.sha256 === undefined) {
|
||||||
|
throw new Error("Invalid info. Missing info.key, info.iv or info.hashes.sha256 key");
|
||||||
|
}
|
||||||
|
|
||||||
|
let cryptoKey; // The AES key object.
|
||||||
|
let ivArray = decodeBase64(info.iv);
|
||||||
|
let expectedSha256base64 = info.hashes.sha256;
|
||||||
|
// Load the AES from the "key" key of the info object.
|
||||||
|
return crypto.subtle.importKey(
|
||||||
|
"jwk", info.key, {"name": "AES-CTR"}, false, ["encrypt", "decrypt"]
|
||||||
|
).then(function (importKeyResult) {
|
||||||
|
cryptoKey = importKeyResult;
|
||||||
|
// Check the sha256 hash
|
||||||
|
return crypto.subtle.digest("SHA-256", ciphertextBuffer);
|
||||||
|
}).then(function (digestResult) {
|
||||||
|
if (encodeBase64(new Uint8Array(digestResult)) !== expectedSha256base64) {
|
||||||
|
throw new Error("Mismatched SHA-256 digest (expected: " + encodeBase64(new Uint8Array(digestResult)) + ") got (" + expectedSha256base64 + ")");
|
||||||
|
}
|
||||||
|
let counterLength;
|
||||||
|
if (info.v.toLowerCase() === "v1" || info.v.toLowerCase() === "v2") {
|
||||||
|
// Version 1 and 2 use a 64 bit counter.
|
||||||
|
counterLength = 64;
|
||||||
|
} else {
|
||||||
|
// Version 0 uses a 128 bit counter.
|
||||||
|
counterLength = 128;
|
||||||
|
}
|
||||||
|
return crypto.subtle.decrypt(
|
||||||
|
{name: "AES-CTR", counter: ivArray, length: counterLength}, cryptoKey, ciphertextBuffer
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a typed array of uint8 as base64.
|
||||||
|
* @param {Uint8Array} uint8Array The data to encode.
|
||||||
|
* @return {string} The base64 without padding.
|
||||||
|
*/
|
||||||
|
function encodeBase64(uint8Array) {
|
||||||
|
// Misinterpt the Uint8Array as Latin-1.
|
||||||
|
// window.btoa expects a unicode string with codepoints in the range 0-255.
|
||||||
|
// var latin1String = String.fromCharCode.apply(null, uint8Array);
|
||||||
|
// Use the builtin base64 encoder.
|
||||||
|
var paddedBase64 = btoa(uint8Array);
|
||||||
|
// Calculate the unpadded length.
|
||||||
|
var inputLength = uint8Array.length;
|
||||||
|
var outputLength = 4 * Math.floor((inputLength + 2) / 3) + (inputLength + 2) % 3 - 2;
|
||||||
|
// Return the unpadded base64.
|
||||||
|
return paddedBase64.slice(0, outputLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode a base64 string to a typed array of uint8.
|
||||||
|
* This will decode unpadded base64, but will also accept base64 with padding.
|
||||||
|
* @param {string} base64 The unpadded base64 to decode.
|
||||||
|
* @return {Uint8Array} The decoded data.
|
||||||
|
*/
|
||||||
|
function decodeBase64(base64) {
|
||||||
|
// Pad the base64 up to the next multiple of 4.
|
||||||
|
var paddedBase64 = base64 + "===".slice(0, (4 - base64.length % 4) % 4);
|
||||||
|
// Decode the base64 as a misinterpreted Latin-1 string.
|
||||||
|
// window.atob returns a unicode string with codepoints in the range 0-255.
|
||||||
|
var latin1String = atob(paddedBase64);
|
||||||
|
// Encode the string as a Uint8Array as Latin-1.
|
||||||
|
var uint8Array = new Uint8Array(latin1String.length);
|
||||||
|
for (var i = 0; i < latin1String.length; i++) {
|
||||||
|
uint8Array[i] = latin1String.charCodeAt(i);
|
||||||
|
}
|
||||||
|
return uint8Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
function autoDetectMatrixMessageType(fileType) {
|
||||||
|
switch(fileType ? fileType.mime.split('/')[0].toLowerCase() : undefined) {
|
||||||
|
case 'video': return 'm.video';
|
||||||
|
case 'image': return 'm.image';
|
||||||
|
case 'audio': return 'm.audio';
|
||||||
|
default: return 'm.file';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ffprobe method for getting metadata from a file wrapped in a promise
|
||||||
|
function _ffprobe(filepath){
|
||||||
|
return new Promise((resolve,reject) => {
|
||||||
|
ffmpeg.ffprobe(filepath, function(err, metadata) {
|
||||||
|
if(err) {
|
||||||
|
return reject(new Error(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(metadata);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user