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) {
var isProxyActive: boolean | undefined
;(window as any).myAPI.getProxyActive().then((result: boolean) => {
isProxyActive = result
})
@ -112,7 +111,6 @@ export async function searchCrunchy(q: string) {
export async function getCRSeries(q: string) {
var isProxyActive: boolean | undefined
;(window as any).myAPI.getProxyActive().then((result: boolean) => {
isProxyActive = result
})

View File

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

175
pnpm-lock.yaml generated
View File

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

View File

@ -4,21 +4,18 @@ import NodeCache from 'node-cache'
import crunchyrollRoutes from './routes/crunchyroll/crunchyroll.route'
import { sequelize } from './db/database'
import serviceRoutes from './routes/service/service.route'
;(async () => {
try {
await sequelize.authenticate()
console.log('Connection has been established successfully.')
} catch (error) {
console.error('Unable to connect to the database:', error)
}
import { app } from 'electron'
import winston from 'winston'
try {
await sequelize.sync()
console.log('All models were synchronized successfully.')
} catch (error) {
console.log('Failed to synchronize Models')
}
})()
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
defaultMeta: { service: 'user-service' },
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 })
@ -38,14 +35,26 @@ declare module 'fastify' {
}
}
// Logger Type
declare module 'fastify' {
interface FastifyInstance {
logger: winston.Logger
}
}
// Cache Controller
server.decorate('CacheController', CacheController)
// Logger
server.decorate('logger', logger)
// Routes
server.register(crunchyrollRoutes, { prefix: 'api/crunchyroll' })
server.register(serviceRoutes, { prefix: 'api/service' })
function startAPI() {
async function startAPI() {
await startDB()
server.listen({ port: 9941 }, (err, address) => {
if (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

View File

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

View File

@ -1,6 +1,7 @@
import type { FastifyReply, FastifyRequest } from 'fastify'
import { crunchyLogin } from './crunchyroll.service'
import { loggedInCheck } from '../service/service.service'
import { server } from '../../api'
export async function loginController(
request: FastifyRequest<{
@ -15,6 +16,10 @@ export async function loginController(
const account = await loggedInCheck('CR')
if (!account) {
server.logger.log({
level: 'error',
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',
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 }
}
if (!data) {
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' }
}
if (!data.access_token) {
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' }
}
@ -88,16 +112,40 @@ export async function crunchyLogin(user: string, passw: string, geo: string) {
'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)
)
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 }
}
if (!data) {
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' }
}
if (!data.access_token) {
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' }
}

View File

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

View File

@ -25,15 +25,27 @@ const exec = util.promisify(require('child_process').exec)
// Get All Accounts
export async function getAllAccounts() {
try {
const accounts = await Account.findAll({
attributes: { exclude: ['password'] }
})
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
export async function deleteAccountID(id: number) {
try {
const account = await Account.destroy({
where: {
id: id
@ -41,10 +53,21 @@ export async function deleteAccountID(id: number) {
})
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
export async function loggedInCheck(service: string) {
try {
const login = await Account.findOne({
where: {
service: service
@ -52,10 +75,21 @@ export async function loggedInCheck(service: string) {
})
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
export async function safeLoginData(user: string, password: string, service: string) {
try {
const login = await Account.create({
username: user,
password: password,
@ -63,23 +97,71 @@ export async function safeLoginData(user: string, password: string, service: str
})
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
export async function getPlaylist() {
try {
const episodes = await Playlist.findAll()
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
async function deletePlaylistandTMP() {
try {
await 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()
deleteTemporaryFolders()
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
export async function updatePlaylistByID(
@ -87,7 +169,27 @@ export async function updatePlaylistByID(
status?: 'waiting' | 'preparing' | 'downloading' | 'merging' | 'decrypting' | 'completed' | 'failed',
quality?: 1080 | 720 | 480 | 360 | 240
) {
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
@ -140,6 +242,7 @@ var isDownloading: number = 0
// Check Playlist every 2 seconds for new items
async function checkPlaylists() {
try {
const eps = await Playlist.findAll({ where: { status: 'waiting' } })
for (const e of eps) {
@ -147,6 +250,12 @@ async function checkPlaylists() {
updatePlaylistByID(e.dataValues.id, 'preparing')
isDownloading++
if (e.dataValues.service === 'CR') {
server.logger.log({
level: 'info',
message: `Added Playlist Item ${e.dataValues.id} to Download Process`,
timestamp: new Date().toISOString(),
section: 'playlistCheckCron'
})
downloadCrunchyrollPlaylist(
(e.dataValues.media as CrunchyEpisode).id,
(e as any).dataValues.dub.map((s: { locale: any }) => s.locale),
@ -179,6 +288,16 @@ async function checkPlaylists() {
}
}
}
} 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'
})
}
}
cron.schedule('*/2 * * * * *', () => {
@ -299,7 +418,7 @@ export async function downloadADNPlaylist(
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')
@ -357,6 +476,12 @@ export async function downloadCrunchyrollPlaylist(
'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'
)
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) {
await updatePlaylistByID(downloadID, 'failed')
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
}
@ -420,8 +552,20 @@ export async function downloadCrunchyrollPlaylist(
if (found) {
subDownloadList.push({ ...found, isDub: false })
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 {
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)
@ -507,6 +651,13 @@ export async function downloadCrunchyrollPlaylist(
console.log(playlist.mediaGroups.AUDIO.audio.main.playlists[0].segments[0].uri)
console.log('No AssetID found, exiting.')
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
}
@ -539,6 +690,13 @@ export async function downloadCrunchyrollPlaylist(
'Audio Widevine encrypted but no key provided',
'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
}
p.push({
@ -578,6 +736,14 @@ export async function downloadCrunchyrollPlaylist(
if (!code) {
await updatePlaylistByID(downloadID, 'failed')
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
}
@ -586,6 +752,13 @@ export async function downloadCrunchyrollPlaylist(
if (!play) {
await updatePlaylistByID(downloadID, 'failed')
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
}
@ -632,6 +805,13 @@ export async function downloadCrunchyrollPlaylist(
`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)
hq = mdp.playlists[0]
@ -640,7 +820,15 @@ export async function downloadCrunchyrollPlaylist(
const assetId = hq.segments[0].resolvedUri.match(/\/assets\/(?:p\/)?([^_,]+)/)
if (!assetId) {
await updatePlaylistByID(downloadID, 'failed')
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
}
@ -649,7 +837,23 @@ export async function downloadCrunchyrollPlaylist(
if (hq.contentProtection) {
if (!hq.contentProtection['com.widevine.alpha'].pssh) {
await updatePlaylistByID(downloadID, 'failed')
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
}
pssh = Uint8ArrayToBase64(hq.contentProtection['com.widevine.alpha'].pssh)
@ -663,10 +867,16 @@ export async function downloadCrunchyrollPlaylist(
'error',
['Cancel'],
2,
'Audio Widevine encrypted but no key provided',
'Audio Widevine encrypted but no key provided',
'Video 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'
)
server.logger.log({
level: 'error',
message: `Video Widevine encrypted but no key provided in Download ${downloadID}`,
timestamp: new Date().toISOString(),
section: 'crunchyrollDownloadProcessVideoDecryption'
})
return
}
@ -699,7 +909,7 @@ export async function downloadCrunchyrollPlaylist(
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')
@ -754,7 +964,20 @@ async function downloadParts(parts: { filename: string; url: string }[], downloa
success = true
} catch (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}...`)
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))
}
}
@ -816,10 +1039,19 @@ async function mergeParts(parts: { filename: string; url: string }[], downloadID
})
} catch (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<{
locale: string
name: string
@ -932,6 +1164,15 @@ async function mergeVideoFile(video: string, audios: Array<string>, subs: Array<
.saveToFile(path + `/${filename}.${format}`)
.on('error', (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)
})
.on('end', async () => {