Add Api for song upload

This commit is contained in:
Esa Kataja
2024-10-12 16:21:06 +03:00
parent 6bf57ff672
commit d47631abe9
6 changed files with 315 additions and 8 deletions
+4 -1
View File
@@ -27,5 +27,8 @@
"tailwindcss": "^3.4.13", "tailwindcss": "^3.4.13",
"vite": "^5.0.3" "vite": "^5.0.3"
}, },
"type": "module" "type": "module",
"dependencies": {
"music-metadata": "^10.5.0"
}
} }
+113
View File
@@ -7,6 +7,10 @@ settings:
importers: importers:
.: .:
dependencies:
music-metadata:
specifier: ^10.5.0
version: 10.5.0
devDependencies: devDependencies:
'@sveltejs/adapter-auto': '@sveltejs/adapter-auto':
specifier: ^3.0.0 specifier: ^3.0.0
@@ -493,6 +497,9 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@sec-ant/[email protected]':
resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==}
'@sveltejs/[email protected]': '@sveltejs/[email protected]':
resolution: {integrity: sha512-27LR+uKccZ62lgq4N/hvyU2G+hTP9fxWEAfnZcl70HnyfAjMSsGk1z/SjAPXNCD1mVJIE7IFu3TQ8cQ/UH3c0A==} resolution: {integrity: sha512-27LR+uKccZ62lgq4N/hvyU2G+hTP9fxWEAfnZcl70HnyfAjMSsGk1z/SjAPXNCD1mVJIE7IFu3TQ8cQ/UH3c0A==}
peerDependencies: peerDependencies:
@@ -528,6 +535,9 @@ packages:
svelte: ^4.0.0 || ^5.0.0-next.0 svelte: ^4.0.0 || ^5.0.0-next.0
vite: ^5.0.0 vite: ^5.0.0
'@tokenizer/[email protected]':
resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==}
'@types/[email protected]': '@types/[email protected]':
resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==}
@@ -662,6 +672,10 @@ packages:
[email protected]: [email protected]:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
[email protected]:
resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
engines: {node: '>= 0.6'}
[email protected]: [email protected]:
resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
engines: {node: '>= 0.6'} engines: {node: '>= 0.6'}
@@ -834,6 +848,10 @@ packages:
resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
engines: {node: '>=16.0.0'} engines: {node: '>=16.0.0'}
[email protected]:
resolution: {integrity: sha512-dMuq6WWnP6BpQY0zYJNpTtQWgeCImSMG0BTIzUBXvxbwc1HWP/E7AE4UWU9XSCOPGJuOHda0HpDnwM2FW+d90A==}
engines: {node: '>=18'}
[email protected]: [email protected]:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'} engines: {node: '>=8'}
@@ -864,6 +882,10 @@ packages:
[email protected]: [email protected]:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
[email protected]:
resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==}
engines: {node: '>=18'}
[email protected]: [email protected]:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
@@ -898,6 +920,9 @@ packages:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
[email protected]:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
[email protected]: [email protected]:
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
engines: {node: '>= 4'} engines: {node: '>= 4'}
@@ -947,6 +972,10 @@ packages:
[email protected]: [email protected]:
resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==} resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==}
[email protected]:
resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==}
engines: {node: '>=18'}
[email protected]: [email protected]:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
@@ -1014,6 +1043,10 @@ packages:
[email protected]: [email protected]:
resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==}
[email protected]:
resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==}
engines: {node: '>= 0.8'}
[email protected]: [email protected]:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
@@ -1044,6 +1077,10 @@ packages:
[email protected]: [email protected]:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
[email protected]:
resolution: {integrity: sha512-j9KDoFzud12gKtl6+SEX4nVMzJyASZ9XtcH04kHhi5Q7sWBnH6GtzgzRFFkOVEojSctBecj9JqTDqyrTAs5kOA==}
engines: {node: '>=16.0.0'}
[email protected]: [email protected]:
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
@@ -1108,6 +1145,10 @@ packages:
resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
engines: {node: '>=16 || 14 >=14.18'} engines: {node: '>=16 || 14 >=14.18'}
[email protected]:
resolution: {integrity: sha512-U94a+eXHzct7vAd19GH3UQ2dH4Satbng0MyYTMaQatL0pvYYL5CTPR25HBhKtecl+4bfu1/i3vC6k0hydO5Vcw==}
engines: {node: '>=14.16'}
[email protected]: [email protected]:
resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==}
@@ -1299,6 +1340,14 @@ packages:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'} engines: {node: '>=8'}
[email protected]:
resolution: {integrity: sha512-ExzDvHYPj6F6QkSNe/JxSlBxTh3OrI6wrAIz53ulxo1c4hBJ1bT9C/JrAthEKHWG9riVH3Xzg7B03Oxty6S2Lw==}
engines: {node: '>=16'}
[email protected]:
resolution: {integrity: sha512-fuapOUOgBhPh474Xx2pDSN/Kd5ACsLWF0nPKk9F9QfB+5iKxov1pNS9CqPv+t09cw6WRV+iRkH1gkCTDlM0kvw==}
engines: {node: '>=16'}
[email protected]: [email protected]:
resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
engines: {node: '>=16 || 14 >=14.17'} engines: {node: '>=16 || 14 >=14.17'}
@@ -1358,6 +1407,10 @@ packages:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'} engines: {node: '>=8.0'}
[email protected]:
resolution: {integrity: sha512-lbDrTLVsHhOMljPscd0yitpozq7Ga2M5Cvez5AjGg8GASBjtt6iERCAJ93yommPmz62fb45oFIXHEZ3u9bfJEA==}
engines: {node: '>=14.16'}
[email protected]: [email protected]:
resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
engines: {node: '>=6'} engines: {node: '>=6'}
@@ -1372,6 +1425,10 @@ packages:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.8.0'}
[email protected]:
resolution: {integrity: sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ==}
engines: {node: '>=18'}
[email protected]: [email protected]:
resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==}
hasBin: true hasBin: true
@@ -1764,6 +1821,8 @@ snapshots:
'@rollup/[email protected]': '@rollup/[email protected]':
optional: true optional: true
'@sec-ant/[email protected]': {}
'@sveltejs/[email protected](@sveltejs/[email protected](@sveltejs/[email protected]([email protected])([email protected]))([email protected])([email protected]))': '@sveltejs/[email protected](@sveltejs/[email protected](@sveltejs/[email protected]([email protected])([email protected]))([email protected])([email protected]))':
dependencies: dependencies:
'@sveltejs/kit': 2.7.0(@sveltejs/[email protected]([email protected])([email protected]))([email protected])([email protected]) '@sveltejs/kit': 2.7.0(@sveltejs/[email protected]([email protected])([email protected]))([email protected])([email protected])
@@ -1820,6 +1879,8 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@tokenizer/[email protected]': {}
'@types/[email protected]': {} '@types/[email protected]': {}
'@types/[email protected]': '@types/[email protected]':
@@ -1954,6 +2015,8 @@ snapshots:
[email protected]: {} [email protected]: {}
[email protected]: {}
[email protected]: {} [email protected]: {}
[email protected]: [email protected]:
@@ -2161,6 +2224,13 @@ snapshots:
dependencies: dependencies:
flat-cache: 4.0.1 flat-cache: 4.0.1
[email protected]:
dependencies:
get-stream: 9.0.1
strtok3: 8.1.0
token-types: 6.0.0
uint8array-extras: 1.4.0
[email protected]: [email protected]:
dependencies: dependencies:
to-regex-range: 5.0.1 to-regex-range: 5.0.1
@@ -2189,6 +2259,11 @@ snapshots:
[email protected]: {} [email protected]: {}
[email protected]:
dependencies:
'@sec-ant/readable-stream': 0.4.1
is-stream: 4.0.1
[email protected]: [email protected]:
dependencies: dependencies:
is-glob: 4.0.3 is-glob: 4.0.3
@@ -2220,6 +2295,8 @@ snapshots:
dependencies: dependencies:
function-bind: 1.1.2 function-bind: 1.1.2
[email protected]: {}
[email protected]: {} [email protected]: {}
[email protected]: {} [email protected]: {}
@@ -2257,6 +2334,8 @@ snapshots:
dependencies: dependencies:
'@types/estree': 1.0.6 '@types/estree': 1.0.6
[email protected]: {}
[email protected]: {} [email protected]: {}
[email protected]: [email protected]:
@@ -2312,6 +2391,8 @@ snapshots:
[email protected]: {} [email protected]: {}
[email protected]: {}
[email protected]: {} [email protected]: {}
[email protected]: [email protected]:
@@ -2335,6 +2416,19 @@ snapshots:
[email protected]: {} [email protected]: {}
[email protected]:
dependencies:
'@tokenizer/token': 0.3.0
content-type: 1.0.5
debug: 4.3.7
file-type: 19.5.0
media-typer: 1.1.0
strtok3: 9.0.0
token-types: 6.0.0
uint8array-extras: 1.4.0
transitivePeerDependencies:
- supports-color
[email protected]: [email protected]:
dependencies: dependencies:
any-promise: 1.3.0 any-promise: 1.3.0
@@ -2389,6 +2483,8 @@ snapshots:
lru-cache: 10.4.3 lru-cache: 10.4.3
minipass: 7.1.2 minipass: 7.1.2
[email protected]: {}
[email protected]: [email protected]:
dependencies: dependencies:
'@types/estree': 1.0.6 '@types/estree': 1.0.6
@@ -2588,6 +2684,16 @@ snapshots:
[email protected]: {} [email protected]: {}
[email protected]:
dependencies:
'@tokenizer/token': 0.3.0
peek-readable: 5.2.0
[email protected]:
dependencies:
'@tokenizer/token': 0.3.0
peek-readable: 5.2.0
[email protected]: [email protected]:
dependencies: dependencies:
'@jridgewell/gen-mapping': 0.3.5 '@jridgewell/gen-mapping': 0.3.5
@@ -2685,6 +2791,11 @@ snapshots:
dependencies: dependencies:
is-number: 7.0.0 is-number: 7.0.0
[email protected]:
dependencies:
'@tokenizer/token': 0.3.0
ieee754: 1.2.1
[email protected]: {} [email protected]: {}
[email protected]: {} [email protected]: {}
@@ -2696,6 +2807,8 @@ snapshots:
dependencies: dependencies:
prelude-ls: 1.2.1 prelude-ls: 1.2.1
[email protected]: {}
[email protected]([email protected]): [email protected]([email protected]):
dependencies: dependencies:
browserslist: 4.24.0 browserslist: 4.24.0
+87 -7
View File
@@ -1,27 +1,107 @@
<script> <script>
import NewEntryDetailForm from './newEntry/NewEntryDetailForm.svelte';
let artist = '';
let songName = '';
let isEntered = false;
async function handleUploadSubmit(event) {
event.preventDefault();
const formData = new FormData(event.target);
const response = await fetch('/api/fileUpload', {
method: 'POST',
body: formData
});
const data = await response.json();
if (data.error) {
console.error(data.error);
} else {
console.log(data.metadata);
artist = data.metadata.common.artist || '';
songName = data.metadata.common.title || '';
isEntered = true;
}
}
async function handleYTLinkSubmit(event) {
event.preventDefault();
const formData = new FormData(event.target);
const ytLink = formData.get('ytlink');
if (!ytLink) {
console.error('No YouTube link provided');
return;
}
try {
const id = extractYouTubeId(ytLink);
if (!id) {
console.error('Invalid YouTube link');
return;
}
const response = await fetch('/api/ytUpload', {
method: 'POST',
body: JSON.stringify({ id })
});
if (!response.ok) {
console.error('Error uploading YouTube link:', response.status, response.statusText);
return;
}
const data = await response.json();
if (data.error) {
console.error('Error uploading YouTube link:', data.error);
} else {
artist = data.body.metadata.author_name || 'Artisti';
songName = data.body.metadata.title || 'Kappale';
isEntered = true;
}
} catch (error) {
console.error('Error handling YouTube link submission:', error);
}
}
function extractYouTubeId(link) {
const regex = /^(?:https?:\/\/)?(?:www\.)?youtu(?:be\.com|\.be)\/(?:watch\?v=)?([^&\s]+)/;
const match = link.match(regex);
return match && match[1];
}
</script> </script>
<div class="my-20"> <div class="my-20">
<h2 class="text-center text-2xl font-semibold">🎉🎉🎉 Uusi kierros on alkanut! 🎉🎉🎉</h2> <h2 class="flex justify-center gap-4 items-center text-center text-2xl font-semibold">
<span class="hidden sm:inline">🎉🎉🎉</span><span>Uusi kierros on alkanut!</span><span
class="hidden sm:inline">🎉🎉🎉</span
>
</h2>
<p class="my-10"> <p class="my-10">
Uusi kierros on alkanut. Et ole kuitenkaan vielä laittanut omaa ehdokasta sisään. Voit tehdä sen Uusi kierros on alkanut. Et ole kuitenkaan vielä laittanut omaa ehdokasta sisään. Voit tehdä sen
alla olevan lomakkeen avulla. alla olevan lomakkeen avulla.
</p> </p>
<div id="upload-status" class={isEntered ? '' : 'hidden'}>
<NewEntryDetailForm {artist} {songName} />
</div>
<div <div
class="flex flex-col items-center border-2 border-zinc-500 rounded-xl p-10 text-center bg-zinc-700" class={`flex flex-col md:flex-row md:justify-between items-center border-2 border-zinc-500 rounded-xl p-10 text-center bg-zinc-700 ${isEntered ? 'hidden' : ''}`}
> >
<form action="/api/newentry" method="post"> <form on:submit|preventDefault={handleYTLinkSubmit} method="post" class="w-2/5">
<label for="ytlink" class="my-2">Youtube-linkki:</label> <label for="ytlink" class="my-2">Youtube-linkki:</label>
<input <input
type="text" type="text"
name="ytlink" name="ytlink"
class="input-text-field block w-full my-6" class="input-text-field block w-full my-6"
placeholder="https://www.youtube.com/watch?v=dQw4w9WgXcQ" placeholder="https://www.youtube.com/watch?v=nxMMElT61A8"
/> />
<p class="my-6 text-2xl font-bold">--- TAI ---</p> <button type="submit" class="button-primary mt-4">Lataa</button>
</form>
<p class="my-6 text-2xl font-bold">--- TAI ---</p>
<form on:submit|preventDefault={handleUploadSubmit} method="post" class="w-2/5 text-center">
<label for="upload" class="mb-2">Tiedosto:</label> <label for="upload" class="mb-2">Tiedosto:</label>
<input type="file" name="upload" accept="audio/*" class="block w-full my-6" /> <input type="file" name="upload" id="upload" accept="audio/*" class="block w-full my-6" />
<button type="submit" class="button-primary mt-4">Liity mukaan</button>
<button type="submit" class="button-primary mt-4">Lataa</button>
</form> </form>
</div> </div>
</div> </div>
@@ -0,0 +1,35 @@
<script>
export let artist = '';
export let songName = '';
export let isEntered;
function cancel() {
artist = '';
songName = '';
isEntered = false;
}
</script>
<div class="flex flex-col max-w-md mx-auto my-6 gap-4">
<label for="artist">Artisti:</label>
<input
type="text"
bind:value={artist}
name="artist"
id="artist"
class="input-text-field"
required
/>
<label for="songName">Kappale:</label>
<input
type="text"
bind:value={songName}
name="songName"
id="songName"
class="input-text-field"
required
/>
<button class="button-cancel mt-4" on:click={cancel}>Tyhjennä</button>
<button type="submit" class="button-primary">Läheta</button>
</div>
+39
View File
@@ -0,0 +1,39 @@
import { json } from '@sveltejs/kit';
import { parseBuffer } from 'music-metadata';
import { writeFile } from 'fs/promises';
import { join } from 'path';
import { unlink } from 'fs/promises';
export const config = {
api: {
bodyParser: false
}
};
export async function POST({ request }) {
try {
const formData = await request.formData();
const file = formData.get('upload');
if (!file) {
return json({ error: 'No file uploaded' }, { status: 400 });
}
// Save the file temporarily
const buffer = await file.arrayBuffer();
const tempPath = join('/tmp', `upload_${Date.now()}_${file.name}`);
await writeFile(tempPath, Buffer.from(buffer));
// Parse metadata
const metadata = await parseBuffer(Buffer.from(buffer));
// Clean up the temporary file
// You might want to handle this asynchronously or use a try-finally block
await unlink(tempPath);
return json({ metadata });
} catch (error) {
console.error('Error processing file:', error);
return json({ error: 'Failed to process file' }, { status: 500 });
}
}
+37
View File
@@ -0,0 +1,37 @@
export async function POST({ request }) {
console.log('ytUpload API endpoint hit');
const body = await request.json();
const ytId = body.id;
if (!ytId) {
return {
status: 400,
body: { error: 'No id provided' }
};
}
try {
console.log('Fetching YouTube metadata...');
const response = await fetch(
`https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=${ytId}&format=json`
);
const data = await response.json();
console.log('Response from YouTube:', data);
if (data.error) {
return Response.json({
status: 400,
body: { error: data.error.message }
});
}
return Response.json({
status: 200,
body: { metadata: data }
});
} catch (error) {
console.error('Error fetching YouTube metadata:', error);
return Response.json({
status: 500,
body: { error: 'Internal Server Error' }
});
}
}