added better error handeling for database stuff

This commit is contained in:
stratuma 2024-05-20 16:44:16 +02:00
parent bc93a04c80
commit a6f6c50345
9 changed files with 592 additions and 103 deletions

View File

@ -5,7 +5,6 @@ import type { CrunchyAnimeFetch, CrunchySearchFetch } from './Types'
export async function searchCrunchy(q: string) { export async function searchCrunchy(q: string) {
var isProxyActive: boolean | undefined var isProxyActive: boolean | undefined
;(window as any).myAPI.getProxyActive().then((result: boolean) => { ;(window as any).myAPI.getProxyActive().then((result: boolean) => {
isProxyActive = result isProxyActive = result
}) })
@ -112,7 +111,6 @@ export async function searchCrunchy(q: string) {
export async function getCRSeries(q: string) { export async function getCRSeries(q: string) {
var isProxyActive: boolean | undefined var isProxyActive: boolean | undefined
;(window as any).myAPI.getProxyActive().then((result: boolean) => { ;(window as any).myAPI.getProxyActive().then((result: boolean) => {
isProxyActive = result isProxyActive = result
}) })

View File

@ -61,7 +61,8 @@
"node-cron": "^3.0.3", "node-cron": "^3.0.3",
"protobufjs": "^7.2.6", "protobufjs": "^7.2.6",
"sequelize": "^6.37.3", "sequelize": "^6.37.3",
"sqlite3": "5.1.6" "sqlite3": "5.1.6",
"winston": "^3.13.0"
}, },
"build": { "build": {
"files": [ "files": [

175
pnpm-lock.yaml generated
View File

@ -56,6 +56,9 @@ importers:
sqlite3: sqlite3:
specifier: 5.1.6 specifier: 5.1.6
version: 5.1.6(encoding@0.1.13) version: 5.1.6(encoding@0.1.13)
winston:
specifier: ^3.13.0
version: 3.13.0
devDependencies: devDependencies:
7zip-bin: 7zip-bin:
specifier: ^5.2.0 specifier: ^5.2.0
@ -343,6 +346,10 @@ packages:
resolution: {integrity: sha512-EeEjMobfuJrwoctj7FA1y1KEbM0+Q1xSjobIEyie9k4haVEBB7vkDvsasw1pM3rO39mL2akxIAzLMUAtrMHZhA==} resolution: {integrity: sha512-EeEjMobfuJrwoctj7FA1y1KEbM0+Q1xSjobIEyie9k4haVEBB7vkDvsasw1pM3rO39mL2akxIAzLMUAtrMHZhA==}
engines: {node: '>=16.13'} engines: {node: '>=16.13'}
'@colors/colors@1.6.0':
resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==}
engines: {node: '>=0.1.90'}
'@csstools/selector-resolve-nested@1.1.0': '@csstools/selector-resolve-nested@1.1.0':
resolution: {integrity: sha512-uWvSaeRcHyeNenKg8tp17EVDRkpflmdyvbE0DHo6D/GdBb6PDnCYYU6gRpXhtICMGMcahQmj2zGxwFM/WC8hCg==} resolution: {integrity: sha512-uWvSaeRcHyeNenKg8tp17EVDRkpflmdyvbE0DHo6D/GdBb6PDnCYYU6gRpXhtICMGMcahQmj2zGxwFM/WC8hCg==}
engines: {node: ^14 || ^16 || >=18} engines: {node: ^14 || ^16 || >=18}
@ -355,6 +362,9 @@ packages:
peerDependencies: peerDependencies:
postcss-selector-parser: ^6.0.13 postcss-selector-parser: ^6.0.13
'@dabh/diagnostics@2.0.3':
resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==}
'@develar/schema-utils@2.6.5': '@develar/schema-utils@2.6.5':
resolution: {integrity: sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==} resolution: {integrity: sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==}
engines: {node: '>= 8.9.0'} engines: {node: '>= 8.9.0'}
@ -1298,6 +1308,9 @@ packages:
'@types/serve-static@1.15.7': '@types/serve-static@1.15.7':
resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==}
'@types/triple-beam@1.3.5':
resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==}
'@types/validator@13.11.9': '@types/validator@13.11.9':
resolution: {integrity: sha512-FCTsikRozryfayPuiI46QzH3fnrOoctTjvOYZkho9BTFLCOZ2rgZJHMOVgCOfttjPJcgOx52EpkY0CMfy87MIw==} resolution: {integrity: sha512-FCTsikRozryfayPuiI46QzH3fnrOoctTjvOYZkho9BTFLCOZ2rgZJHMOVgCOfttjPJcgOx52EpkY0CMfy87MIw==}
@ -2206,16 +2219,25 @@ packages:
color-name@1.1.4: color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
color-string@1.9.1:
resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==}
color-support@1.1.3: color-support@1.1.3:
resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==}
hasBin: true hasBin: true
color@3.2.1:
resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==}
colord@2.9.3: colord@2.9.3:
resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==}
colorette@2.0.20: colorette@2.0.20:
resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
colorspace@1.1.4:
resolution: {integrity: sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==}
combined-stream@1.0.8: combined-stream@1.0.8:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
@ -2670,6 +2692,9 @@ packages:
resolution: {integrity: sha512-97qcDM6mUA1jAeX6cktw7akc5awIGA+VIkA5MygKOKA+c2Vseo/xwKN0JNJTUhZUtPwZboKVD2p1xu+sV/F4xA==} resolution: {integrity: sha512-97qcDM6mUA1jAeX6cktw7akc5awIGA+VIkA5MygKOKA+c2Vseo/xwKN0JNJTUhZUtPwZboKVD2p1xu+sV/F4xA==}
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.8.0'}
enabled@2.0.0:
resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==}
encodeurl@1.0.2: encodeurl@1.0.2:
resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==}
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
@ -3031,6 +3056,9 @@ packages:
fd-slicer@1.1.0: fd-slicer@1.1.0:
resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==}
fecha@4.2.3:
resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==}
file-entry-cache@6.0.1: file-entry-cache@6.0.1:
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
engines: {node: ^10.12.0 || >=12.0.0} engines: {node: ^10.12.0 || >=12.0.0}
@ -3081,6 +3109,9 @@ packages:
resolution: {integrity: sha512-IZTB4kq5GK0DPp7sGQ0q/BWurGHffRtQQwVkiqDgeO6wYJLLV5ZhgNOQ65loZxxuPMKZKZcICCUnaGtlxBiR0Q==} resolution: {integrity: sha512-IZTB4kq5GK0DPp7sGQ0q/BWurGHffRtQQwVkiqDgeO6wYJLLV5ZhgNOQ65loZxxuPMKZKZcICCUnaGtlxBiR0Q==}
engines: {node: '>=0.8.0'} engines: {node: '>=0.8.0'}
fn.name@1.1.0:
resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==}
focus-trap@7.5.4: focus-trap@7.5.4:
resolution: {integrity: sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==} resolution: {integrity: sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==}
@ -3510,6 +3541,9 @@ packages:
is-arrayish@0.2.1: is-arrayish@0.2.1:
resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
is-arrayish@0.3.2:
resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
is-bigint@1.0.4: is-bigint@1.0.4:
resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
@ -3810,6 +3844,9 @@ packages:
kolorist@1.8.0: kolorist@1.8.0:
resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==}
kuler@2.0.0:
resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==}
launch-editor@2.6.1: launch-editor@2.6.1:
resolution: {integrity: sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==} resolution: {integrity: sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==}
@ -3905,6 +3942,10 @@ packages:
resolution: {integrity: sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==} resolution: {integrity: sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==}
engines: {node: '>=4'} engines: {node: '>=4'}
logform@2.6.0:
resolution: {integrity: sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==}
engines: {node: '>= 12.0.0'}
long@5.2.3: long@5.2.3:
resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==}
@ -4395,6 +4436,9 @@ packages:
once@1.4.0: once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
one-time@1.0.0:
resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==}
onetime@2.0.1: onetime@2.0.1:
resolution: {integrity: sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==} resolution: {integrity: sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==}
engines: {node: '>=4'} engines: {node: '>=4'}
@ -4570,11 +4614,11 @@ packages:
pino-abstract-transport@1.2.0: pino-abstract-transport@1.2.0:
resolution: {integrity: sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==} resolution: {integrity: sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==}
pino-std-serializers@6.2.2: pino-std-serializers@7.0.0:
resolution: {integrity: sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==} resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==}
pino@9.0.0: pino@9.1.0:
resolution: {integrity: sha512-uI1ThkzTShNSwvsUM6b4ND8ANzWURk9zTELMztFkmnCQeR/4wkomJ+echHee5GMWGovoSfjwdeu80DsFIt7mbA==} resolution: {integrity: sha512-qUcgfrlyOtjwhNLdbhoL7NR4NkHjzykAPw0V2QLFbvu/zss29h4NkRnibyFzBrNCbzCOY3WZ9hhKSwfOkNggYA==}
hasBin: true hasBin: true
pirates@4.0.6: pirates@4.0.6:
@ -5271,6 +5315,9 @@ packages:
simple-git@3.24.0: simple-git@3.24.0:
resolution: {integrity: sha512-QqAKee9Twv+3k8IFOFfPB2hnk6as6Y6ACUpwCtQvRYBAes23Wv3SZlHVobAzqcE8gfsisCvPw3HGW3HYM+VYYw==} resolution: {integrity: sha512-QqAKee9Twv+3k8IFOFfPB2hnk6as6Y6ACUpwCtQvRYBAes23Wv3SZlHVobAzqcE8gfsisCvPw3HGW3HYM+VYYw==}
simple-swizzle@0.2.2:
resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
simple-update-notifier@2.0.0: simple-update-notifier@2.0.0:
resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==}
engines: {node: '>=10'} engines: {node: '>=10'}
@ -5317,8 +5364,8 @@ packages:
resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==} resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==}
engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} engines: {node: '>= 10.0.0', npm: '>= 3.0.0'}
sonic-boom@3.8.1: sonic-boom@4.0.1:
resolution: {integrity: sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==} resolution: {integrity: sha512-hTSD/6JMLyT4r9zeof6UtuBDpjJ9sO08/nmS5djaA9eozT9oOlNdpXSnzcgj4FTqpk3nkLrs61l4gip9r1HCrQ==}
source-map-js@1.2.0: source-map-js@1.2.0:
resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==}
@ -5378,6 +5425,9 @@ packages:
resolution: {integrity: sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==} resolution: {integrity: sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
stack-trace@0.0.10:
resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==}
standard-as-callback@2.1.0: standard-as-callback@2.1.0:
resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==}
@ -5576,6 +5626,9 @@ packages:
engines: {node: '>=10'} engines: {node: '>=10'}
hasBin: true hasBin: true
text-hex@1.0.0:
resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==}
text-table@0.2.0: text-table@0.2.0:
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
@ -5586,8 +5639,8 @@ packages:
thenify@3.3.1: thenify@3.3.1:
resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
thread-stream@2.7.0: thread-stream@3.0.0:
resolution: {integrity: sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==} resolution: {integrity: sha512-oUIFjxaUT6knhPtWgDMc29zF1FcSl0yXpapkyrQrCGEfYA2HUZXCilUtKyYIv6HkCyqSPAMkY+EG0GbyIrNDQg==}
through@2.3.8: through@2.3.8:
resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
@ -5635,6 +5688,10 @@ packages:
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
hasBin: true hasBin: true
triple-beam@1.4.1:
resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==}
engines: {node: '>= 14.0.0'}
truncate-utf8-bytes@1.0.2: truncate-utf8-bytes@1.0.2:
resolution: {integrity: sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==} resolution: {integrity: sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==}
@ -6141,6 +6198,14 @@ packages:
wide-align@1.1.5: wide-align@1.1.5:
resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
winston-transport@4.7.0:
resolution: {integrity: sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==}
engines: {node: '>= 12.0.0'}
winston@3.13.0:
resolution: {integrity: sha512-rwidmA1w3SE4j0E5MuIufFhyJPBDG7Nu71RkZor1p2+qHvJSZ9GYDA81AyleQcZbh/+V6HjeBdfnTZJm9rSeQQ==}
engines: {node: '>= 12.0.0'}
wkx@0.5.0: wkx@0.5.0:
resolution: {integrity: sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==} resolution: {integrity: sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==}
@ -6479,6 +6544,8 @@ snapshots:
dependencies: dependencies:
mime: 3.0.0 mime: 3.0.0
'@colors/colors@1.6.0': {}
'@csstools/selector-resolve-nested@1.1.0(postcss-selector-parser@6.0.16)': '@csstools/selector-resolve-nested@1.1.0(postcss-selector-parser@6.0.16)':
dependencies: dependencies:
postcss-selector-parser: 6.0.16 postcss-selector-parser: 6.0.16
@ -6487,6 +6554,12 @@ snapshots:
dependencies: dependencies:
postcss-selector-parser: 6.0.16 postcss-selector-parser: 6.0.16
'@dabh/diagnostics@2.0.3':
dependencies:
colorspace: 1.1.4
enabled: 2.0.0
kuler: 2.0.0
'@develar/schema-utils@2.6.5': '@develar/schema-utils@2.6.5':
dependencies: dependencies:
ajv: 6.12.6 ajv: 6.12.6
@ -7656,6 +7729,8 @@ snapshots:
'@types/node': 20.12.11 '@types/node': 20.12.11
'@types/send': 0.17.4 '@types/send': 0.17.4
'@types/triple-beam@1.3.5': {}
'@types/validator@13.11.9': {} '@types/validator@13.11.9': {}
'@types/verror@1.10.10': '@types/verror@1.10.10':
@ -8948,12 +9023,27 @@ snapshots:
color-name@1.1.4: {} color-name@1.1.4: {}
color-string@1.9.1:
dependencies:
color-name: 1.1.4
simple-swizzle: 0.2.2
color-support@1.1.3: {} color-support@1.1.3: {}
color@3.2.1:
dependencies:
color-convert: 1.9.3
color-string: 1.9.1
colord@2.9.3: {} colord@2.9.3: {}
colorette@2.0.20: {} colorette@2.0.20: {}
colorspace@1.1.4:
dependencies:
color: 3.2.1
text-hex: 1.0.0
combined-stream@1.0.8: combined-stream@1.0.8:
dependencies: dependencies:
delayed-stream: 1.0.0 delayed-stream: 1.0.0
@ -9415,6 +9505,8 @@ snapshots:
empty-dir@1.0.0: {} empty-dir@1.0.0: {}
enabled@2.0.0: {}
encodeurl@1.0.2: {} encodeurl@1.0.2: {}
encoding@0.1.13: encoding@0.1.13:
@ -9970,7 +10062,7 @@ snapshots:
fast-json-stringify: 5.15.1 fast-json-stringify: 5.15.1
find-my-way: 8.2.0 find-my-way: 8.2.0
light-my-request: 5.13.0 light-my-request: 5.13.0
pino: 9.0.0 pino: 9.1.0
process-warning: 3.0.0 process-warning: 3.0.0
proxy-addr: 2.0.7 proxy-addr: 2.0.7
rfdc: 1.3.1 rfdc: 1.3.1
@ -9988,6 +10080,8 @@ snapshots:
dependencies: dependencies:
pend: 1.2.0 pend: 1.2.0
fecha@4.2.3: {}
file-entry-cache@6.0.1: file-entry-cache@6.0.1:
dependencies: dependencies:
flat-cache: 3.2.0 flat-cache: 3.2.0
@ -10051,6 +10145,8 @@ snapshots:
async: 3.2.5 async: 3.2.5
which: 1.3.1 which: 1.3.1
fn.name@1.1.0: {}
focus-trap@7.5.4: focus-trap@7.5.4:
dependencies: dependencies:
tabbable: 6.2.0 tabbable: 6.2.0
@ -10561,6 +10657,8 @@ snapshots:
is-arrayish@0.2.1: {} is-arrayish@0.2.1: {}
is-arrayish@0.3.2: {}
is-bigint@1.0.4: is-bigint@1.0.4:
dependencies: dependencies:
has-bigints: 1.0.2 has-bigints: 1.0.2
@ -10850,6 +10948,8 @@ snapshots:
kolorist@1.8.0: {} kolorist@1.8.0: {}
kuler@2.0.0: {}
launch-editor@2.6.1: launch-editor@2.6.1:
dependencies: dependencies:
picocolors: 1.0.0 picocolors: 1.0.0
@ -10948,6 +11048,15 @@ snapshots:
dependencies: dependencies:
chalk: 2.4.2 chalk: 2.4.2
logform@2.6.0:
dependencies:
'@colors/colors': 1.6.0
'@types/triple-beam': 1.3.5
fecha: 4.2.3
ms: 2.1.3
safe-stable-stringify: 2.4.3
triple-beam: 1.4.1
long@5.2.3: {} long@5.2.3: {}
lowercase-keys@2.0.0: {} lowercase-keys@2.0.0: {}
@ -11671,6 +11780,10 @@ snapshots:
dependencies: dependencies:
wrappy: 1.0.2 wrappy: 1.0.2
one-time@1.0.0:
dependencies:
fn.name: 1.1.0
onetime@2.0.1: onetime@2.0.1:
dependencies: dependencies:
mimic-fn: 1.2.0 mimic-fn: 1.2.0
@ -11859,21 +11972,21 @@ snapshots:
readable-stream: 4.5.2 readable-stream: 4.5.2
split2: 4.2.0 split2: 4.2.0
pino-std-serializers@6.2.2: {} pino-std-serializers@7.0.0: {}
pino@9.0.0: pino@9.1.0:
dependencies: dependencies:
atomic-sleep: 1.0.0 atomic-sleep: 1.0.0
fast-redact: 3.5.0 fast-redact: 3.5.0
on-exit-leak-free: 2.1.2 on-exit-leak-free: 2.1.2
pino-abstract-transport: 1.2.0 pino-abstract-transport: 1.2.0
pino-std-serializers: 6.2.2 pino-std-serializers: 7.0.0
process-warning: 3.0.0 process-warning: 3.0.0
quick-format-unescaped: 4.0.4 quick-format-unescaped: 4.0.4
real-require: 0.2.0 real-require: 0.2.0
safe-stable-stringify: 2.4.3 safe-stable-stringify: 2.4.3
sonic-boom: 3.8.1 sonic-boom: 4.0.1
thread-stream: 2.7.0 thread-stream: 3.0.0
pirates@4.0.6: {} pirates@4.0.6: {}
@ -12577,6 +12690,10 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
simple-swizzle@0.2.2:
dependencies:
is-arrayish: 0.3.2
simple-update-notifier@2.0.0: simple-update-notifier@2.0.0:
dependencies: dependencies:
semver: 7.6.1 semver: 7.6.1
@ -12628,7 +12745,7 @@ snapshots:
ip-address: 9.0.5 ip-address: 9.0.5
smart-buffer: 4.2.0 smart-buffer: 4.2.0
sonic-boom@3.8.1: sonic-boom@4.0.1:
dependencies: dependencies:
atomic-sleep: 1.0.0 atomic-sleep: 1.0.0
@ -12692,6 +12809,8 @@ snapshots:
minipass: 3.3.6 minipass: 3.3.6
optional: true optional: true
stack-trace@0.0.10: {}
standard-as-callback@2.1.0: {} standard-as-callback@2.1.0: {}
stat-mode@1.0.0: {} stat-mode@1.0.0: {}
@ -12933,6 +13052,8 @@ snapshots:
commander: 2.20.3 commander: 2.20.3
source-map-support: 0.5.21 source-map-support: 0.5.21
text-hex@1.0.0: {}
text-table@0.2.0: {} text-table@0.2.0: {}
thenify-all@1.6.0: thenify-all@1.6.0:
@ -12943,7 +13064,7 @@ snapshots:
dependencies: dependencies:
any-promise: 1.3.0 any-promise: 1.3.0
thread-stream@2.7.0: thread-stream@3.0.0:
dependencies: dependencies:
real-require: 0.2.0 real-require: 0.2.0
@ -12977,6 +13098,8 @@ snapshots:
tree-kill@1.2.2: {} tree-kill@1.2.2: {}
triple-beam@1.4.1: {}
truncate-utf8-bytes@1.0.2: truncate-utf8-bytes@1.0.2:
dependencies: dependencies:
utf8-byte-length: 1.0.4 utf8-byte-length: 1.0.4
@ -13569,6 +13692,26 @@ snapshots:
dependencies: dependencies:
string-width: 4.2.3 string-width: 4.2.3
winston-transport@4.7.0:
dependencies:
logform: 2.6.0
readable-stream: 3.6.2
triple-beam: 1.4.1
winston@3.13.0:
dependencies:
'@colors/colors': 1.6.0
'@dabh/diagnostics': 2.0.3
async: 3.2.5
is-stream: 2.0.1
logform: 2.6.0
one-time: 1.0.0
readable-stream: 3.6.2
safe-stable-stringify: 2.4.3
stack-trace: 0.0.10
triple-beam: 1.4.1
winston-transport: 4.7.0
wkx@0.5.0: wkx@0.5.0:
dependencies: dependencies:
'@types/node': 20.12.11 '@types/node': 20.12.11

View File

@ -4,21 +4,18 @@ import NodeCache from 'node-cache'
import crunchyrollRoutes from './routes/crunchyroll/crunchyroll.route' import crunchyrollRoutes from './routes/crunchyroll/crunchyroll.route'
import { sequelize } from './db/database' import { sequelize } from './db/database'
import serviceRoutes from './routes/service/service.route' import serviceRoutes from './routes/service/service.route'
;(async () => { import { app } from 'electron'
try { import winston from 'winston'
await sequelize.authenticate()
console.log('Connection has been established successfully.')
} catch (error) {
console.error('Unable to connect to the database:', error)
}
try { const logger = winston.createLogger({
await sequelize.sync() level: 'info',
console.log('All models were synchronized successfully.') format: winston.format.json(),
} catch (error) { defaultMeta: { service: 'user-service' },
console.log('Failed to synchronize Models') transports: [
} new winston.transports.File({ filename: app.getPath('documents') + '/Crunchyroll Downloader/logs/error.log', level: 'error' }),
})() new winston.transports.File({ filename: app.getPath('documents') + '/Crunchyroll Downloader/logs/combined.log' })
]
})
const CacheController = new NodeCache({ stdTTL: 100, checkperiod: 120 }) const CacheController = new NodeCache({ stdTTL: 100, checkperiod: 120 })
@ -38,14 +35,26 @@ declare module 'fastify' {
} }
} }
// Logger Type
declare module 'fastify' {
interface FastifyInstance {
logger: winston.Logger
}
}
// Cache Controller // Cache Controller
server.decorate('CacheController', CacheController) server.decorate('CacheController', CacheController)
// Logger
server.decorate('logger', logger)
// Routes // Routes
server.register(crunchyrollRoutes, { prefix: 'api/crunchyroll' }) server.register(crunchyrollRoutes, { prefix: 'api/crunchyroll' })
server.register(serviceRoutes, { prefix: 'api/service' }) server.register(serviceRoutes, { prefix: 'api/service' })
function startAPI() { async function startAPI() {
await startDB()
server.listen({ port: 9941 }, (err, address) => { server.listen({ port: 9941 }, (err, address) => {
if (err) { if (err) {
console.error(err) console.error(err)
@ -55,4 +64,46 @@ function startAPI() {
}) })
} }
async function startDB() {
try {
await sequelize.authenticate()
console.log('Connection has been established successfully.')
logger.log({
level: 'info',
message: 'Connection has been established successfully.',
timestamp: new Date().toISOString(),
section: 'databaseConnection'
})
} catch (error) {
console.error('Unable to connect to the database:', error)
logger.log({
level: 'error',
message: 'Unable to connect to the database',
error: error,
timestamp: new Date().toISOString(),
section: 'databaseConnection'
})
}
try {
await sequelize.sync()
console.log('All models were synchronized successfully.')
logger.log({
level: 'info',
message: 'All models were synchronized successfully.',
timestamp: new Date().toISOString(),
section: 'databaseSync'
})
} catch (error) {
console.log('Failed to synchronize Models')
logger.log({
level: 'error',
message: 'Failed to synchronize Models',
error: error,
timestamp: new Date().toISOString(),
section: 'databaseSync'
})
}
}
export default startAPI export default startAPI

View File

@ -5,7 +5,7 @@ import { ADNEpisode } from '../types/adn'
const sequelize = new Sequelize({ const sequelize = new Sequelize({
dialect: 'sqlite', dialect: 'sqlite',
storage: app.getPath('documents') + '/crd-dbv2.db' storage: app.getPath('documents') + '/Crunchyroll Downloader/databases/v1/data.db'
}) })
interface AccountAttributes { interface AccountAttributes {

View File

@ -1,6 +1,7 @@
import type { FastifyReply, FastifyRequest } from 'fastify' import type { FastifyReply, FastifyRequest } from 'fastify'
import { crunchyLogin } from './crunchyroll.service' import { crunchyLogin } from './crunchyroll.service'
import { loggedInCheck } from '../service/service.service' import { loggedInCheck } from '../service/service.service'
import { server } from '../../api'
export async function loginController( export async function loginController(
request: FastifyRequest<{ request: FastifyRequest<{
@ -15,6 +16,10 @@ export async function loginController(
const account = await loggedInCheck('CR') const account = await loggedInCheck('CR')
if (!account) { if (!account) {
server.logger.log({
level: 'error',
message: 'Not Logged in'
})
return reply.code(401).send({ message: 'Not Logged in' }) return reply.code(401).send({ message: 'Not Logged in' })
} }

View File

@ -58,16 +58,40 @@ export async function crunchyLogin(user: string, passw: string, geo: string) {
'Failed to login to Crunchyroll', 'Failed to login to Crunchyroll',
crErrors.find((r) => r.error === (error?.error as string)) ? crErrors.find((r) => r.error === (error?.error as string))?.response : (error.error as string) crErrors.find((r) => r.error === (error?.error as string)) ? crErrors.find((r) => r.error === (error?.error as string))?.response : (error.error as string)
) )
server.logger.log({
level: 'error',
message: 'Failed to login to Crunchyroll',
data: data,
error: error,
timestamp: new Date().toISOString(),
section: 'loginCrunchyrollFetch'
})
return { data: null, error: error.error } return { data: null, error: error.error }
} }
if (!data) { if (!data) {
messageBox('error', ['Cancel'], 2, 'Failed to login', 'Failed to login to Crunchyroll', 'Crunchyroll returned null') messageBox('error', ['Cancel'], 2, 'Failed to login', 'Failed to login to Crunchyroll', 'Crunchyroll returned null')
server.logger.log({
level: 'error',
message: 'Failed to login to Crunchyroll',
data: data,
error: error,
timestamp: new Date().toISOString(),
section: 'loginCrunchyrollFetch'
})
return { data: null, error: 'Crunchyroll returned null' } return { data: null, error: 'Crunchyroll returned null' }
} }
if (!data.access_token) { if (!data.access_token) {
messageBox('error', ['Cancel'], 2, 'Failed to login', 'Failed to login to Crunchyroll', 'Crunchyroll returned malformed data') messageBox('error', ['Cancel'], 2, 'Failed to login', 'Failed to login to Crunchyroll', 'Crunchyroll returned malformed data')
server.logger.log({
level: 'error',
message: 'Failed to login to Crunchyroll',
data: data,
error: error,
timestamp: new Date().toISOString(),
section: 'loginCrunchyrollFetch'
})
return { data: null, error: 'Crunchyroll returned malformed data' } return { data: null, error: 'Crunchyroll returned malformed data' }
} }
@ -88,16 +112,40 @@ export async function crunchyLogin(user: string, passw: string, geo: string) {
'Failed to login to Crunchyroll', 'Failed to login to Crunchyroll',
crErrors.find((r) => r.error === (error?.error as string)) ? crErrors.find((r) => r.error === (error?.error as string))?.response : (error.error as string) crErrors.find((r) => r.error === (error?.error as string)) ? crErrors.find((r) => r.error === (error?.error as string))?.response : (error.error as string)
) )
server.logger.log({
level: 'error',
message: 'Failed to login to Crunchyroll',
data: data,
error: error,
timestamp: new Date().toISOString(),
section: 'loginCrunchyrollFetch'
})
return { data: null, error: error.error } return { data: null, error: error.error }
} }
if (!data) { if (!data) {
messageBox('error', ['Cancel'], 2, 'Failed to login', 'Failed to login to Crunchyroll', 'Crunchyroll returned null') messageBox('error', ['Cancel'], 2, 'Failed to login', 'Failed to login to Crunchyroll', 'Crunchyroll returned null')
server.logger.log({
level: 'error',
message: 'Failed to login to Crunchyroll',
data: data,
error: error,
timestamp: new Date().toISOString(),
section: 'loginCrunchyrollFetch'
})
return { data: null, error: 'Crunchyroll returned null' } return { data: null, error: 'Crunchyroll returned null' }
} }
if (!data.access_token) { if (!data.access_token) {
messageBox('error', ['Cancel'], 2, 'Failed to login', 'Failed to login to Crunchyroll', 'Crunchyroll returned malformed data') messageBox('error', ['Cancel'], 2, 'Failed to login', 'Failed to login to Crunchyroll', 'Crunchyroll returned malformed data')
server.logger.log({
level: 'error',
message: 'Failed to login to Crunchyroll',
data: data,
error: error,
timestamp: new Date().toISOString(),
section: 'loginCrunchyrollFetch'
})
return { data: null, error: 'Crunchyroll returned malformed data' } return { data: null, error: 'Crunchyroll returned malformed data' }
} }

View File

@ -117,6 +117,8 @@ export async function addPlaylistController(
export async function getPlaylistController(request: FastifyRequest, reply: FastifyReply) { export async function getPlaylistController(request: FastifyRequest, reply: FastifyReply) {
const playlist = await getPlaylist() const playlist = await getPlaylist()
if (!playlist) return
for (const v of playlist) { for (const v of playlist) {
if (v.dataValues.status === 'downloading') { if (v.dataValues.status === 'downloading') {
const found = await getDownloading(v.dataValues.id) const found = await getDownloading(v.dataValues.id)

View File

@ -25,61 +25,143 @@ const exec = util.promisify(require('child_process').exec)
// Get All Accounts // Get All Accounts
export async function getAllAccounts() { export async function getAllAccounts() {
const accounts = await Account.findAll({ try {
attributes: { exclude: ['password'] } const accounts = await Account.findAll({
}) attributes: { exclude: ['password'] }
})
return accounts return accounts
} catch (e) {
messageBox('error', ['Cancel'], 2, 'Database Error', 'Failed to get all accounts', JSON.stringify(e))
server.logger.log({
level: 'error',
message: 'Failed to get all accounts',
error: e,
timestamp: new Date().toISOString(),
section: 'loginGetAccountsDatabase'
})
}
} }
// Delete Account // Delete Account
export async function deleteAccountID(id: number) { export async function deleteAccountID(id: number) {
const account = await Account.destroy({ try {
where: { const account = await Account.destroy({
id: id where: {
} id: id
}) }
})
return account return account
} catch (e) {
messageBox('error', ['Cancel'], 2, 'Database Error', 'Failed to delete account', JSON.stringify(e))
server.logger.log({
level: 'error',
message: 'Failed to delete account',
error: e,
timestamp: new Date().toISOString(),
section: 'loginDeleteDatabase'
})
}
} }
// DB Account existence check // DB Account existence check
export async function loggedInCheck(service: string) { export async function loggedInCheck(service: string) {
const login = await Account.findOne({ try {
where: { const login = await Account.findOne({
service: service where: {
} service: service
}) }
})
return login?.get() return login?.get()
} catch (e) {
messageBox('error', ['Cancel'], 2, 'Database Error', 'Failed to check if logged in', JSON.stringify(e))
server.logger.log({
level: 'error',
message: 'Failed to check if logged in',
error: e,
timestamp: new Date().toISOString(),
section: 'loginCheckDatabase'
})
}
} }
// Save Login Data in DB // Save Login Data in DB
export async function safeLoginData(user: string, password: string, service: string) { export async function safeLoginData(user: string, password: string, service: string) {
const login = await Account.create({ try {
username: user, const login = await Account.create({
password: password, username: user,
service: service password: password,
}) service: service
})
return login?.get() return login?.get()
} catch (e) {
messageBox('error', ['Cancel'], 2, 'Database Error', 'Failed to save login data', JSON.stringify(e))
server.logger.log({
level: 'error',
message: 'Failed to save login data',
error: e,
timestamp: new Date().toISOString(),
section: 'loginSaveDatabase'
})
}
} }
// Get Playlist // Get Playlist
export async function getPlaylist() { export async function getPlaylist() {
const episodes = await Playlist.findAll() try {
const episodes = await Playlist.findAll()
return episodes return episodes
} catch (e) {
messageBox('error', ['Cancel'], 2, 'Database Error', 'Failed to get Playlist', JSON.stringify(e))
server.logger.log({
level: 'error',
message: 'Failed to get Playlist',
error: e,
timestamp: new Date().toISOString(),
section: 'playlistGetDatabase'
})
}
} }
// Delete Playlist and TEMP folders After Start // Delete Playlist and TEMP folders After Start
async function deletePlaylistandTMP() { async function deletePlaylistandTMP() {
await Playlist.truncate() try {
await deleteTemporaryFolders()
deleteTemporaryFolders() console.log('All TMP Folders and Files deleted')
server.logger.log({
level: 'info',
message: 'All TMP Folders and Files deleted',
timestamp: new Date().toISOString(),
section: 'playlistClearDatabase'
})
await Playlist.truncate()
console.log('Playlist cleared')
server.logger.log({
level: 'info',
message: 'Playlist cleared',
timestamp: new Date().toISOString(),
section: 'playlistClearDatabase'
})
} catch (e) {
messageBox('error', ['Cancel'], 2, 'Database Error', 'Failed to delete Playlist and tmp folders', JSON.stringify(e))
server.logger.log({
level: 'error',
message: 'Failed to delete Playlist and tmp folders',
error: e,
timestamp: new Date().toISOString(),
section: 'playlistClearDatabase'
})
}
} }
deletePlaylistandTMP() setTimeout(deletePlaylistandTMP, 500)
// Update Playlist Item // Update Playlist Item
export async function updatePlaylistByID( export async function updatePlaylistByID(
@ -87,7 +169,27 @@ export async function updatePlaylistByID(
status?: 'waiting' | 'preparing' | 'downloading' | 'merging' | 'decrypting' | 'completed' | 'failed', status?: 'waiting' | 'preparing' | 'downloading' | 'merging' | 'decrypting' | 'completed' | 'failed',
quality?: 1080 | 720 | 480 | 360 | 240 quality?: 1080 | 720 | 480 | 360 | 240
) { ) {
await Playlist.update({ status: status, quality: quality }, { where: { id: id } }) try {
await Playlist.update({ status: status, quality: quality }, { where: { id: id } })
server.logger.log({
level: 'info',
message: `Updated Playlist Item ${id}`,
status: status || undefined,
quality: quality || undefined,
timestamp: new Date().toISOString(),
section: 'playlistItemUpdateDatabase'
})
} catch (e) {
messageBox('error', ['Cancel'], 2, 'Database Error', 'Failed to update playlist item', JSON.stringify(e))
server.logger.log({
level: 'error',
message: 'Failed to update playlist item',
error: e,
timestamp: new Date().toISOString(),
section: 'playlistItemUpdateDatabase'
})
}
} }
// Add Episode to Playlist // Add Episode to Playlist
@ -140,44 +242,61 @@ var isDownloading: number = 0
// Check Playlist every 2 seconds for new items // Check Playlist every 2 seconds for new items
async function checkPlaylists() { async function checkPlaylists() {
const eps = await Playlist.findAll({ where: { status: 'waiting' } }) try {
const eps = await Playlist.findAll({ where: { status: 'waiting' } })
for (const e of eps) { for (const e of eps) {
if (isDownloading < 3 && e.dataValues.status === 'waiting') { if (isDownloading < 3 && e.dataValues.status === 'waiting') {
updatePlaylistByID(e.dataValues.id, 'preparing') updatePlaylistByID(e.dataValues.id, 'preparing')
isDownloading++ isDownloading++
if (e.dataValues.service === 'CR') { if (e.dataValues.service === 'CR') {
downloadCrunchyrollPlaylist( server.logger.log({
(e.dataValues.media as CrunchyEpisode).id, level: 'info',
(e as any).dataValues.dub.map((s: { locale: any }) => s.locale), message: `Added Playlist Item ${e.dataValues.id} to Download Process`,
(e as any).dataValues.sub.map((s: { locale: any }) => s.locale), timestamp: new Date().toISOString(),
e.dataValues.hardsub, section: 'playlistCheckCron'
(e.dataValues.media as CrunchyEpisode).id, })
e.dataValues.id, downloadCrunchyrollPlaylist(
(e.dataValues.media as CrunchyEpisode).series_title, (e.dataValues.media as CrunchyEpisode).id,
(e.dataValues.media as CrunchyEpisode).season_number, (e as any).dataValues.dub.map((s: { locale: any }) => s.locale),
(e.dataValues.media as CrunchyEpisode).episode_number, (e as any).dataValues.sub.map((s: { locale: any }) => s.locale),
e.dataValues.quality, e.dataValues.hardsub,
e.dataValues.dir, (e.dataValues.media as CrunchyEpisode).id,
e.dataValues.format, e.dataValues.id,
(e.dataValues.media as CrunchyEpisode).geo (e.dataValues.media as CrunchyEpisode).series_title,
) (e.dataValues.media as CrunchyEpisode).season_number,
} (e.dataValues.media as CrunchyEpisode).episode_number,
if (e.dataValues.service === 'ADN') { e.dataValues.quality,
downloadADNPlaylist( e.dataValues.dir,
(e.dataValues.media as ADNEpisode).id, e.dataValues.format,
(e as any).dataValues.dub.map((s: { locale: any }) => s.locale), (e.dataValues.media as CrunchyEpisode).geo
(e as any).dataValues.sub.map((s: { locale: any }) => s.locale), )
e.dataValues.id, }
(e.dataValues.media as ADNEpisode).show.title, if (e.dataValues.service === 'ADN') {
(e.dataValues.media as ADNEpisode).season, downloadADNPlaylist(
(e.dataValues.media as ADNEpisode).shortNumber, (e.dataValues.media as ADNEpisode).id,
e.dataValues.quality, (e as any).dataValues.dub.map((s: { locale: any }) => s.locale),
e.dataValues.dir, (e as any).dataValues.sub.map((s: { locale: any }) => s.locale),
e.dataValues.format e.dataValues.id,
) (e.dataValues.media as ADNEpisode).show.title,
(e.dataValues.media as ADNEpisode).season,
(e.dataValues.media as ADNEpisode).shortNumber,
e.dataValues.quality,
e.dataValues.dir,
e.dataValues.format
)
}
} }
} }
} catch (e) {
messageBox('error', ['Cancel'], 2, 'Database Error', 'Failed check Playlist', JSON.stringify(e))
server.logger.log({
level: 'error',
message: 'Failed check Playlist',
error: e,
timestamp: new Date().toISOString(),
section: 'playlistCheckCron'
})
} }
} }
@ -299,7 +418,7 @@ export async function downloadADNPlaylist(
return return
} }
await mergeVideoFile(file as string, [], subss, seasonFolder, `${name.replace(/[/\\?%*:|"<>]/g, '')} Season ${season} Episode ${episode}`, format) await mergeVideoFile(file as string, [], subss, seasonFolder, `${name.replace(/[/\\?%*:|"<>]/g, '')} Season ${season} Episode ${episode}`, format, downloadID)
await updatePlaylistByID(downloadID, 'completed') await updatePlaylistByID(downloadID, 'completed')
@ -357,6 +476,12 @@ export async function downloadCrunchyrollPlaylist(
'Not found japanese stream', 'Not found japanese stream',
'This usually happens when Crunchyroll displays JP as dub on a language but its not available. The download will fail, just start a new download and remove JP from dubs' 'This usually happens when Crunchyroll displays JP as dub on a language but its not available. The download will fail, just start a new download and remove JP from dubs'
) )
server.logger.log({
level: 'error',
message: 'Not found japanese stream',
timestamp: new Date().toISOString(),
section: 'crunchyrollDownloadProcess'
})
} }
} }
} }
@ -413,6 +538,13 @@ export async function downloadCrunchyrollPlaylist(
if (!subPlaylist) { if (!subPlaylist) {
await updatePlaylistByID(downloadID, 'failed') await updatePlaylistByID(downloadID, 'failed')
console.log('Subtitle Playlist not found') console.log('Subtitle Playlist not found')
messageBox('error', ['Cancel'], 2, 'Subtitle Playlist not found', 'Subtitle Playlist not found', 'Subtitle Playlist not found')
server.logger.log({
level: 'error',
message: 'Subtitle Playlist not found',
timestamp: new Date().toISOString(),
section: 'crunchyrollDownloadProcess'
})
return return
} }
@ -420,8 +552,20 @@ export async function downloadCrunchyrollPlaylist(
if (found) { if (found) {
subDownloadList.push({ ...found, isDub: false }) subDownloadList.push({ ...found, isDub: false })
console.log(`Subtitle ${s}.ass found, adding to download`) console.log(`Subtitle ${s}.ass found, adding to download`)
server.logger.log({
level: 'info',
message: `Subtitle ${s}.ass found in Download ${downloadID}, adding to download`,
timestamp: new Date().toISOString(),
section: 'crunchyrollDownloadProcessSubtitles'
})
} else { } else {
console.warn(`Subtitle ${s}.ass not found, skipping`) console.warn(`Subtitle ${s}.ass not found, skipping`)
server.logger.log({
level: 'warn',
message: `Subtitle ${s}.ass not found in Download ${downloadID}, skipping`,
timestamp: new Date().toISOString(),
section: 'crunchyrollDownloadProcessSubtitles'
})
} }
await deleteVideoToken(episodeID, playlist.data.token) await deleteVideoToken(episodeID, playlist.data.token)
@ -507,6 +651,13 @@ export async function downloadCrunchyrollPlaylist(
console.log(playlist.mediaGroups.AUDIO.audio.main.playlists[0].segments[0].uri) console.log(playlist.mediaGroups.AUDIO.audio.main.playlists[0].segments[0].uri)
console.log('No AssetID found, exiting.') console.log('No AssetID found, exiting.')
await updatePlaylistByID(downloadID, 'failed') await updatePlaylistByID(downloadID, 'failed')
messageBox('error', ['Cancel'], 2, 'No AssetID found', 'No AssetID found', "No AssetID found, can't download MPD.")
server.logger.log({
level: 'error',
message: `No AssetID found, can't download MPD of Download ${downloadID}`,
timestamp: new Date().toISOString(),
section: 'crunchyrollDownloadProcessAudio'
})
return return
} }
@ -539,6 +690,13 @@ export async function downloadCrunchyrollPlaylist(
'Audio Widevine encrypted but no key provided', 'Audio Widevine encrypted but no key provided',
'To download Widevine encrypted videos add the L3 Widevine keys in Settings > Widewine > L3 Keys' 'To download Widevine encrypted videos add the L3 Widevine keys in Settings > Widewine > L3 Keys'
) )
server.logger.log({
level: 'error',
message: `Audio Widevine encrypted but no key provided in Download ${downloadID}`,
error: 'To download Widevine encrypted videos add the L3 Widevine keys in Settings > Widewine > L3 Keys',
timestamp: new Date().toISOString(),
section: 'crunchyrollDownloadProcessVideo'
})
return return
} }
p.push({ p.push({
@ -578,6 +736,14 @@ export async function downloadCrunchyrollPlaylist(
if (!code) { if (!code) {
await updatePlaylistByID(downloadID, 'failed') await updatePlaylistByID(downloadID, 'failed')
console.log('No Clean stream found') console.log('No Clean stream found')
messageBox('error', ['Cancel'], 2, 'No Clean video stream found', 'No Clean video stream found', 'No Clean video stream found')
server.logger.log({
level: 'error',
message: `No Clean video stream found in Download ${downloadID}`,
stream: code,
timestamp: new Date().toISOString(),
section: 'crunchyrollDownloadProcessVideo'
})
return return
} }
@ -586,6 +752,13 @@ export async function downloadCrunchyrollPlaylist(
if (!play) { if (!play) {
await updatePlaylistByID(downloadID, 'failed') await updatePlaylistByID(downloadID, 'failed')
console.log('Failed to get Playlist in download Video') console.log('Failed to get Playlist in download Video')
messageBox('error', ['Cancel'], 2, 'Failed to get Playlist in download Video', 'Failed to get Playlist in download Video', 'Failed to get Playlist in download Video')
server.logger.log({
level: 'error',
message: `Failed to get Playlist in download Video in Download ${downloadID}`,
timestamp: new Date().toISOString(),
section: 'crunchyrollDownloadProcessVideo'
})
return return
} }
@ -632,6 +805,13 @@ export async function downloadCrunchyrollPlaylist(
`Resolution ${quality}p not found, using resolution ${mdp.playlists[0].attributes.RESOLUTION?.height}p instead` `Resolution ${quality}p not found, using resolution ${mdp.playlists[0].attributes.RESOLUTION?.height}p instead`
) )
server.logger.log({
level: 'warn',
message: `Resolution ${quality}p not found in Download ${downloadID}, using resolution ${mdp.playlists[0].attributes.RESOLUTION?.height}p instead`,
timestamp: new Date().toISOString(),
section: 'crunchyrollDownloadProcessVideo'
})
await updatePlaylistByID(downloadID, undefined, mdp.playlists[0].attributes.RESOLUTION?.height as 1080 | 720 | 480 | 360 | 240) await updatePlaylistByID(downloadID, undefined, mdp.playlists[0].attributes.RESOLUTION?.height as 1080 | 720 | 480 | 360 | 240)
hq = mdp.playlists[0] hq = mdp.playlists[0]
@ -640,7 +820,15 @@ export async function downloadCrunchyrollPlaylist(
const assetId = hq.segments[0].resolvedUri.match(/\/assets\/(?:p\/)?([^_,]+)/) const assetId = hq.segments[0].resolvedUri.match(/\/assets\/(?:p\/)?([^_,]+)/)
if (!assetId) { if (!assetId) {
await updatePlaylistByID(downloadID, 'failed')
console.log('No AssetID found, exiting.') console.log('No AssetID found, exiting.')
messageBox('error', ['Cancel'], 2, 'No AssetID found', 'No AssetID found', 'No AssetID found in Video Playlist')
server.logger.log({
level: 'error',
message: `No AssetID found in Video Playlist in Download ${downloadID}`,
timestamp: new Date().toISOString(),
section: 'crunchyrollDownloadProcessVideo'
})
return return
} }
@ -649,7 +837,23 @@ export async function downloadCrunchyrollPlaylist(
if (hq.contentProtection) { if (hq.contentProtection) {
if (!hq.contentProtection['com.widevine.alpha'].pssh) { if (!hq.contentProtection['com.widevine.alpha'].pssh) {
await updatePlaylistByID(downloadID, 'failed')
console.log('No PSSH found, exiting.') console.log('No PSSH found, exiting.')
messageBox(
'error',
['Cancel'],
2,
'Encryption Detect error',
'Encryption Detect error',
'Video file is decrypted, but it looks like not with widevine. Stopping Download. Contact Developer'
)
server.logger.log({
level: 'error',
message: `Video file is decrypted, but it looks like not with widevine in Download ${downloadID}`,
error: 'No PSSH found',
timestamp: new Date().toISOString(),
section: 'crunchyrollDownloadProcessVideoDecryption'
})
return return
} }
pssh = Uint8ArrayToBase64(hq.contentProtection['com.widevine.alpha'].pssh) pssh = Uint8ArrayToBase64(hq.contentProtection['com.widevine.alpha'].pssh)
@ -663,10 +867,16 @@ export async function downloadCrunchyrollPlaylist(
'error', 'error',
['Cancel'], ['Cancel'],
2, 2,
'Audio Widevine encrypted but no key provided', 'Video Widevine encrypted but no key provided',
'Audio Widevine encrypted but no key provided', 'Video Widevine encrypted but no key provided',
'To download Widevine encrypted videos add the L3 Widevine keys in Settings > Widewine > L3 Keys' 'To download Widevine encrypted videos add the L3 Widevine keys in Settings > Widewine > L3 Keys'
) )
server.logger.log({
level: 'error',
message: `Video Widevine encrypted but no key provided in Download ${downloadID}`,
timestamp: new Date().toISOString(),
section: 'crunchyrollDownloadProcessVideoDecryption'
})
return return
} }
@ -699,7 +909,7 @@ export async function downloadCrunchyrollPlaylist(
if (!audios) return if (!audios) return
await mergeVideoFile(file as string, audios, subss, seasonFolder, `${name.replace(/[/\\?%*:|"<>]/g, '')} Season ${season} Episode ${episode}`, format) await mergeVideoFile(file as string, audios, subss, seasonFolder, `${name.replace(/[/\\?%*:|"<>]/g, '')} Season ${season} Episode ${episode}`, format, downloadID)
await updatePlaylistByID(downloadID, 'completed') await updatePlaylistByID(downloadID, 'completed')
@ -754,7 +964,20 @@ async function downloadParts(parts: { filename: string; url: string }[], downloa
success = true success = true
} catch (error) { } catch (error) {
console.error(`Error occurred during download of fragment ${index + 1}:`, error) console.error(`Error occurred during download of fragment ${index + 1}:`, error)
server.logger.log({
level: 'error',
message: `Error occurred during download of fragment ${index + 1}`,
error: error,
timestamp: new Date().toISOString(),
section: 'crunchyrollDownloadProcessVideoDownload'
})
console.log(`Retrying download of fragment ${index + 1}...`) console.log(`Retrying download of fragment ${index + 1}...`)
server.logger.log({
level: 'warn',
message: `Retrying download of fragment ${index + 1} because failed`,
timestamp: new Date().toISOString(),
section: 'crunchyrollDownloadProcessVideoDownload'
})
await new Promise((resolve) => setTimeout(resolve, 5000)) await new Promise((resolve) => setTimeout(resolve, 5000))
} }
} }
@ -816,10 +1039,19 @@ async function mergeParts(parts: { filename: string; url: string }[], downloadID
}) })
} catch (error) { } catch (error) {
console.error('Error merging parts:', error) console.error('Error merging parts:', error)
await updatePlaylistByID(downloadID, 'failed')
messageBox('error', ['Cancel'], 2, 'Error merging video parts', 'Error merging video parts', 'Error merging video parts')
server.logger.log({
level: 'error',
message: `Error merging video parts of Download ${downloadID}`,
error: error,
timestamp: new Date().toISOString(),
section: 'crunchyrollDownloadProcessVideoMerging'
})
} }
} }
async function mergeVideoFile(video: string, audios: Array<string>, subs: Array<string>, path: string, filename: string, format: 'mp4' | 'mkv') { async function mergeVideoFile(video: string, audios: Array<string>, subs: Array<string>, path: string, filename: string, format: 'mp4' | 'mkv', downloadID: number) {
const locales: Array<{ const locales: Array<{
locale: string locale: string
name: string name: string
@ -932,6 +1164,15 @@ async function mergeVideoFile(video: string, audios: Array<string>, subs: Array<
.saveToFile(path + `/${filename}.${format}`) .saveToFile(path + `/${filename}.${format}`)
.on('error', (error) => { .on('error', (error) => {
console.log(error) console.log(error)
updatePlaylistByID(downloadID, 'failed')
messageBox('error', ['Cancel'], 2, 'Error merging videos and audios', 'Error merging videos and audios', 'Error merging videos and audios')
server.logger.log({
level: 'error',
message: `Error merging videos and audios of Download ${downloadID}`,
error: error,
timestamp: new Date().toISOString(),
section: 'crunchyrollDownloadProcessVideoMergingFFMPEG'
})
reject(error) reject(error)
}) })
.on('end', async () => { .on('end', async () => {