From d09f806a41f8aa2387f44b011cdcd18c2ac3d3ff Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Fri, 25 Sep 2020 00:16:17 +0200
Subject: [PATCH] Fixed issues with the data fetching

---
 package-lock.json       | 463 +++++++++++++++++++++++++---------------
 package.json            |  12 +-
 src/api/fanart_api.js   |  13 +-
 src/api/imdb_api.js     | 111 ++++++----
 src/api/tmdb_api.js     |  10 +-
 src/directory_walker.js |  51 ++---
 src/index.js            |  10 +-
 src/metadata_loader.js  |  46 ++--
 src/process_content.js  |  18 +-
 src/storage.js          |  16 +-
 10 files changed, 472 insertions(+), 278 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 3ca2f92..137ba6f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5,9 +5,9 @@
   "requires": true,
   "dependencies": {
     "@types/node": {
-      "version": "13.13.5",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.5.tgz",
-      "integrity": "sha512-3ySmiBYJPqgjiHA7oEaIo2Rzz0HrOZ7yrNO5HWyaE5q0lQ3BppDZ3N53Miz8bw2I7gh1/zir2MGVZBvpb1zq9g=="
+      "version": "14.6.4",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.4.tgz",
+      "integrity": "sha512-Wk7nG1JSaMfMpoMJDKUsWYugliB2Vy55pdjLpmLixeyMi7HizW2I/9QoxsPCkXl3dO+ZOVqPumKaDUv5zJu2uQ=="
     },
     "abbrev": {
       "version": "1.1.1",
@@ -15,9 +15,10 @@
       "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
     },
     "ajv": {
-      "version": "6.12.2",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
-      "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==",
+      "version": "6.12.4",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz",
+      "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==",
+      "optional": true,
       "requires": {
         "fast-deep-equal": "^3.1.1",
         "fast-json-stable-stringify": "^2.0.0",
@@ -53,6 +54,7 @@
       "version": "0.2.4",
       "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
       "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
+      "optional": true,
       "requires": {
         "safer-buffer": "~2.1.0"
       }
@@ -60,22 +62,26 @@
     "assert-plus": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
-      "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+      "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+      "optional": true
     },
     "asynckit": {
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
-      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
+      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+      "optional": true
     },
     "aws-sign2": {
       "version": "0.7.0",
       "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
-      "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
+      "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
+      "optional": true
     },
     "aws4": {
-      "version": "1.9.1",
-      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz",
-      "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug=="
+      "version": "1.10.1",
+      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz",
+      "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==",
+      "optional": true
     },
     "balanced-match": {
       "version": "1.0.0",
@@ -86,6 +92,7 @@
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
       "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+      "optional": true,
       "requires": {
         "tweetnacl": "^0.14.3"
       }
@@ -98,10 +105,14 @@
         "file-uri-to-path": "1.0.0"
       }
     },
-    "bluebird": {
-      "version": "3.7.2",
-      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
-      "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
+    "block-stream": {
+      "version": "0.0.9",
+      "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
+      "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
+      "optional": true,
+      "requires": {
+        "inherits": "~2.0.0"
+      }
     },
     "brace-expansion": {
       "version": "1.1.11",
@@ -120,22 +131,14 @@
     "caseless": {
       "version": "0.12.0",
       "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
-      "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
+      "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+      "optional": true
     },
     "chownr": {
       "version": "1.1.4",
       "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
       "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
     },
-    "cls-bluebird": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.1.0.tgz",
-      "integrity": "sha1-N+8eCAqP+1XC9BZPU28ZGeeWiu4=",
-      "requires": {
-        "is-bluebird": "^1.0.2",
-        "shimmer": "^1.1.0"
-      }
-    },
     "code-point-at": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
@@ -145,6 +148,7 @@
       "version": "1.0.8",
       "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
       "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "optional": true,
       "requires": {
         "delayed-stream": "~1.0.0"
       }
@@ -168,14 +172,15 @@
       "version": "1.14.1",
       "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
       "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+      "optional": true,
       "requires": {
         "assert-plus": "^1.0.0"
       }
     },
     "debug": {
-      "version": "3.2.6",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
-      "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+      "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
       "requires": {
         "ms": "^2.1.1"
       }
@@ -188,7 +193,8 @@
     "delayed-stream": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
-      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
+      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+      "optional": true
     },
     "delegates": {
       "version": "1.0.0",
@@ -209,6 +215,7 @@
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
       "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+      "optional": true,
       "requires": {
         "jsbn": "~0.1.0",
         "safer-buffer": "^2.1.0"
@@ -217,22 +224,26 @@
     "extend": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
-      "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
+      "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+      "optional": true
     },
     "extsprintf": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
-      "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
+      "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+      "optional": true
     },
     "fast-deep-equal": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
-      "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA=="
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+      "optional": true
     },
     "fast-json-stable-stringify": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
-      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
+      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+      "optional": true
     },
     "file-uri-to-path": {
       "version": "1.0.0",
@@ -242,12 +253,14 @@
     "forever-agent": {
       "version": "0.6.1",
       "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
-      "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
+      "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+      "optional": true
     },
     "form-data": {
       "version": "2.3.3",
       "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
       "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+      "optional": true,
       "requires": {
         "asynckit": "^0.4.0",
         "combined-stream": "^1.0.6",
@@ -272,6 +285,18 @@
       "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
       "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
     },
+    "fstream": {
+      "version": "1.0.12",
+      "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
+      "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
+      "optional": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "inherits": "~2.0.0",
+        "mkdirp": ">=0.5 0",
+        "rimraf": "2"
+      }
+    },
     "gauge": {
       "version": "2.7.4",
       "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
@@ -291,6 +316,7 @@
       "version": "0.1.7",
       "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
       "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+      "optional": true,
       "requires": {
         "assert-plus": "^1.0.0"
       }
@@ -308,17 +334,25 @@
         "path-is-absolute": "^1.0.0"
       }
     },
+    "graceful-fs": {
+      "version": "4.2.4",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+      "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+      "optional": true
+    },
     "har-schema": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
-      "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
+      "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
+      "optional": true
     },
     "har-validator": {
-      "version": "5.1.3",
-      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
-      "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
+      "version": "5.1.5",
+      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
+      "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
+      "optional": true,
       "requires": {
-        "ajv": "^6.5.5",
+        "ajv": "^6.12.3",
         "har-schema": "^2.0.0"
       }
     },
@@ -336,6 +370,7 @@
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
       "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+      "optional": true,
       "requires": {
         "assert-plus": "^1.0.0",
         "jsprim": "^1.2.2",
@@ -382,11 +417,6 @@
       "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
       "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
     },
-    "is-bluebird": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-bluebird/-/is-bluebird-1.0.2.tgz",
-      "integrity": "sha1-CWQ5Bg9KpBGr7hkUOoTWpVNG1uI="
-    },
     "is-fullwidth-code-point": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
@@ -398,7 +428,8 @@
     "is-typedarray": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
-      "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
+      "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+      "optional": true
     },
     "isarray": {
       "version": "1.0.0",
@@ -413,10 +444,17 @@
         "punycode": "2.x.x"
       }
     },
+    "isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+      "optional": true
+    },
     "isstream": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
-      "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
+      "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+      "optional": true
     },
     "joi": {
       "version": "13.7.0",
@@ -438,27 +476,32 @@
     "jsbn": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
-      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
+      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+      "optional": true
     },
     "json-schema": {
       "version": "0.2.3",
       "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
-      "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
+      "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
+      "optional": true
     },
     "json-schema-traverse": {
       "version": "0.4.1",
       "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
-      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
+      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+      "optional": true
     },
     "json-stringify-safe": {
       "version": "5.0.1",
       "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
-      "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
+      "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+      "optional": true
     },
     "jsprim": {
       "version": "1.4.1",
       "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
       "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+      "optional": true,
       "requires": {
         "assert-plus": "1.0.0",
         "extsprintf": "1.3.0",
@@ -467,19 +510,21 @@
       }
     },
     "lodash": {
-      "version": "4.17.15",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
-      "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
+      "version": "4.17.20",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
+      "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
     },
     "mime-db": {
       "version": "1.44.0",
       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
-      "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
+      "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==",
+      "optional": true
     },
     "mime-types": {
       "version": "2.1.27",
       "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
       "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
+      "optional": true,
       "requires": {
         "mime-db": "1.44.0"
       }
@@ -523,14 +568,14 @@
       }
     },
     "moment": {
-      "version": "2.25.3",
-      "resolved": "https://registry.npmjs.org/moment/-/moment-2.25.3.tgz",
-      "integrity": "sha512-PuYv0PHxZvzc15Sp8ybUCoQ+xpyPWvjOuK72a5ovzp2LI32rJXOiIfyoFoYvG3s6EwwrdkMyWuRiEHSZRLJNdg=="
+      "version": "2.27.0",
+      "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz",
+      "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ=="
     },
     "moment-timezone": {
-      "version": "0.5.28",
-      "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.28.tgz",
-      "integrity": "sha512-TDJkZvAyKIVWg5EtVqRzU97w0Rb0YVbfpqyjgu6GwXCAohVRqwZjf4fOzDE6p1Ch98Sro/8hQQi65WDXW5STPw==",
+      "version": "0.5.31",
+      "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz",
+      "integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==",
       "requires": {
         "moment": ">= 2.9.0"
       }
@@ -546,15 +591,30 @@
       "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw=="
     },
     "needle": {
-      "version": "2.4.1",
-      "resolved": "https://registry.npmjs.org/needle/-/needle-2.4.1.tgz",
-      "integrity": "sha512-x/gi6ijr4B7fwl6WYL9FwlCvRQKGlUNvnceho8wxkwXqN8jvVmmmATTmZPRRG7b/yC1eode26C2HO9jl78Du9g==",
+      "version": "2.5.2",
+      "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.2.tgz",
+      "integrity": "sha512-LbRIwS9BfkPvNwNHlsA41Q29kL2L/6VaOJ0qisM5lLWsTV3nP15abO5ITL6L81zqFhzjRKDAYjpcBcwM0AVvLQ==",
       "requires": {
         "debug": "^3.2.6",
         "iconv-lite": "^0.4.4",
         "sax": "^1.2.4"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "3.2.6",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        }
       }
     },
+    "node-addon-api": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.0.tgz",
+      "integrity": "sha512-ASCL5U13as7HhOExbT6OlWJJUV/lLzL2voOSP1UVehpRD8FbSrSDjfScK/KwAvVTI5AS6r4VwbOMlIqtvRidnA=="
+    },
     "node-expat": {
       "version": "2.3.18",
       "resolved": "https://registry.npmjs.org/node-expat/-/node-expat-2.3.18.tgz",
@@ -569,6 +629,34 @@
       "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
       "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
     },
+    "node-gyp": {
+      "version": "3.8.0",
+      "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz",
+      "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==",
+      "optional": true,
+      "requires": {
+        "fstream": "^1.0.0",
+        "glob": "^7.0.3",
+        "graceful-fs": "^4.1.2",
+        "mkdirp": "^0.5.0",
+        "nopt": "2 || 3",
+        "npmlog": "0 || 1 || 2 || 3 || 4",
+        "osenv": "0",
+        "request": "^2.87.0",
+        "rimraf": "2",
+        "semver": "~5.3.0",
+        "tar": "^2.0.0",
+        "which": "1"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
+          "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
+          "optional": true
+        }
+      }
+    },
     "node-pre-gyp": {
       "version": "0.11.0",
       "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz",
@@ -584,6 +672,36 @@
         "rimraf": "^2.6.1",
         "semver": "^5.3.0",
         "tar": "^4"
+      },
+      "dependencies": {
+        "nopt": {
+          "version": "4.0.3",
+          "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz",
+          "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==",
+          "requires": {
+            "abbrev": "1",
+            "osenv": "^0.1.4"
+          }
+        },
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+        },
+        "tar": {
+          "version": "4.4.13",
+          "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz",
+          "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==",
+          "requires": {
+            "chownr": "^1.1.1",
+            "fs-minipass": "^1.2.5",
+            "minipass": "^2.8.6",
+            "minizlib": "^1.2.1",
+            "mkdirp": "^0.5.0",
+            "safe-buffer": "^5.1.2",
+            "yallist": "^3.0.3"
+          }
+        }
       }
     },
     "node-tvdb": {
@@ -596,12 +714,12 @@
       }
     },
     "nopt": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz",
-      "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==",
+      "version": "3.0.6",
+      "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+      "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
+      "optional": true,
       "requires": {
-        "abbrev": "1",
-        "osenv": "^0.1.4"
+        "abbrev": "1"
       }
     },
     "npm-bundled": {
@@ -646,7 +764,8 @@
     "oauth-sign": {
       "version": "0.9.0",
       "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
-      "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
+      "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
+      "optional": true
     },
     "object-assign": {
       "version": "4.1.1",
@@ -702,34 +821,28 @@
     "performance-now": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
-      "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
+      "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
+      "optional": true
     },
     "pg": {
-      "version": "7.18.2",
-      "resolved": "https://registry.npmjs.org/pg/-/pg-7.18.2.tgz",
-      "integrity": "sha512-Mvt0dGYMwvEADNKy5PMQGlzPudKcKKzJds/VbOeZJpb6f/pI3mmoXX0JksPgI3l3JPP/2Apq7F36O63J7mgveA==",
+      "version": "8.3.3",
+      "resolved": "https://registry.npmjs.org/pg/-/pg-8.3.3.tgz",
+      "integrity": "sha512-wmUyoQM/Xzmo62wgOdQAn5tl7u+IA1ZYK7qbuppi+3E+Gj4hlUxVHjInulieWrd0SfHi/ADriTb5ILJ/lsJrSg==",
       "requires": {
         "buffer-writer": "2.0.0",
         "packet-reader": "1.0.0",
-        "pg-connection-string": "0.1.3",
-        "pg-packet-stream": "^1.1.0",
-        "pg-pool": "^2.0.10",
+        "pg-connection-string": "^2.3.0",
+        "pg-pool": "^3.2.1",
+        "pg-protocol": "^1.2.5",
         "pg-types": "^2.1.0",
         "pgpass": "1.x",
         "semver": "4.3.2"
-      },
-      "dependencies": {
-        "semver": {
-          "version": "4.3.2",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz",
-          "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c="
-        }
       }
     },
     "pg-connection-string": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz",
-      "integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc="
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.3.0.tgz",
+      "integrity": "sha512-ukMTJXLI7/hZIwTW7hGMZJ0Lj0S2XQBCJ4Shv4y1zgQ/vqVea+FLhzywvPj0ujSuofu+yA4MYHGZPTsgjBgJ+w=="
     },
     "pg-hstore": {
       "version": "2.3.3",
@@ -744,15 +857,15 @@
       "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
       "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="
     },
-    "pg-packet-stream": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/pg-packet-stream/-/pg-packet-stream-1.1.0.tgz",
-      "integrity": "sha512-kRBH0tDIW/8lfnnOyTwKD23ygJ/kexQVXZs7gEyBljw4FYqimZFxnMMx50ndZ8In77QgfGuItS5LLclC2TtjYg=="
-    },
     "pg-pool": {
-      "version": "2.0.10",
-      "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.10.tgz",
-      "integrity": "sha512-qdwzY92bHf3nwzIUcj+zJ0Qo5lpG/YxchahxIN8+ZVmXqkahKXsnl2aiJPHLYN9o5mB/leG+Xh6XKxtP7e0sjg=="
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.1.tgz",
+      "integrity": "sha512-BQDPWUeKenVrMMDN9opfns/kZo4lxmSWhIqo+cSAF7+lfi9ZclQbr9vfnlNaPr8wYF3UYjm5X0yPAhbcgqNOdA=="
+    },
+    "pg-protocol": {
+      "version": "1.2.5",
+      "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.2.5.tgz",
+      "integrity": "sha512-1uYCckkuTfzz/FCefvavRywkowa6M5FohNMF5OjKrqo9PSR8gYc8poVmwwYQaBxhmQdBjhtP514eXy9/Us2xKg=="
     },
     "pg-types": {
       "version": "2.2.0",
@@ -775,9 +888,9 @@
       }
     },
     "pnormaldist": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/pnormaldist/-/pnormaldist-1.0.1.tgz",
-      "integrity": "sha1-pda4vyF1xQhOvvJDDHn3N5+EMM4="
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/pnormaldist/-/pnormaldist-1.0.2.tgz",
+      "integrity": "sha512-wtYTJ+ZRB/lVa+y2rn9G4rAXMlQ7p/nCv2UOsErbzcMlitcMQWhWpzqWHEYzqvRN0+Nu3jgRh2CPTOk83lQ1sw=="
     },
     "postgres-array": {
       "version": "2.0.0",
@@ -790,9 +903,9 @@
       "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU="
     },
     "postgres-date": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.5.tgz",
-      "integrity": "sha512-pdau6GRPERdAYUQwkBnGKxEfPyhVZXG/JiS44iZWiNdSOWE09N2lUgN6yshuq6fVSon4Pm0VMXd1srUUkLe9iA=="
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
+      "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="
     },
     "postgres-interval": {
       "version": "1.2.0",
@@ -815,7 +928,8 @@
     "psl": {
       "version": "1.8.0",
       "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
-      "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
+      "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==",
+      "optional": true
     },
     "punycode": {
       "version": "2.1.1",
@@ -825,7 +939,8 @@
     "qs": {
       "version": "6.5.2",
       "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
-      "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
+      "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
+      "optional": true
     },
     "rc": {
       "version": "1.2.8",
@@ -856,6 +971,7 @@
       "version": "2.88.2",
       "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
       "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
+      "optional": true,
       "requires": {
         "aws-sign2": "~0.7.0",
         "aws4": "^1.8.0",
@@ -882,7 +998,8 @@
         "uuid": {
           "version": "3.4.0",
           "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
-          "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
+          "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+          "optional": true
         }
       }
     },
@@ -918,67 +1035,47 @@
       "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
     },
     "semver": {
-      "version": "5.7.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+      "version": "4.3.2",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz",
+      "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c="
     },
     "sequelize": {
-      "version": "5.21.7",
-      "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-5.21.7.tgz",
-      "integrity": "sha512-+JrS5Co7CN53cOFFFaUb+xqQP00wD1Ag9xGLBLoUko2KhRZxjm+UDkqAVPHTUp87McLwJaCPkKv61GPhBVloRQ==",
+      "version": "6.3.5",
+      "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.3.5.tgz",
+      "integrity": "sha512-MiwiPkYSA8NWttRKAXdU9h0TxP6HAc1fl7qZmMO/VQqQOND83G4nZLXd0kWILtAoT9cxtZgFqeb/MPYgEeXwsw==",
       "requires": {
-        "bluebird": "^3.5.0",
-        "cls-bluebird": "^2.1.0",
         "debug": "^4.1.1",
         "dottie": "^2.0.0",
         "inflection": "1.12.0",
         "lodash": "^4.17.15",
-        "moment": "^2.24.0",
-        "moment-timezone": "^0.5.21",
+        "moment": "^2.26.0",
+        "moment-timezone": "^0.5.31",
         "retry-as-promised": "^3.2.0",
-        "semver": "^6.3.0",
-        "sequelize-pool": "^2.3.0",
+        "semver": "^7.3.2",
+        "sequelize-pool": "^6.0.0",
         "toposort-class": "^1.0.1",
-        "uuid": "^3.3.3",
+        "uuid": "^8.1.0",
         "validator": "^10.11.0",
-        "wkx": "^0.4.8"
+        "wkx": "^0.5.0"
       },
       "dependencies": {
-        "debug": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
-          "requires": {
-            "ms": "^2.1.1"
-          }
-        },
         "semver": {
-          "version": "6.3.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
-        },
-        "uuid": {
-          "version": "3.4.0",
-          "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
-          "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
+          "version": "7.3.2",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
+          "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ=="
         }
       }
     },
     "sequelize-pool": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-2.3.0.tgz",
-      "integrity": "sha512-Ibz08vnXvkZ8LJTiUOxRcj1Ckdn7qafNZ2t59jYHMX1VIebTAOYefWdRYFt6z6+hy52WGthAHAoLc9hvk3onqA=="
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz",
+      "integrity": "sha512-4YwEw3ZgK/tY/so+GfnSgXkdwIJJ1I32uZJztIEgZeAO6HMgj64OzySbWLgxj+tXhZCJnzRfkY9gINw8Ft8ZMg=="
     },
     "set-blocking": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
       "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
     },
-    "shimmer": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz",
-      "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw=="
-    },
     "signal-exit": {
       "version": "3.0.3",
       "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
@@ -993,19 +1090,20 @@
       }
     },
     "sqlite3": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.1.1.tgz",
-      "integrity": "sha512-CvT5XY+MWnn0HkbwVKJAyWEMfzpAPwnTiB3TobA5Mri44SrTovmmh499NPQP+gatkeOipqPlBLel7rn4E/PCQg==",
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.0.0.tgz",
+      "integrity": "sha512-rjvqHFUaSGnzxDy2AHCwhHy6Zp6MNJzCPGYju4kD8yi6bze4d1/zMTg6C7JI49b7/EM7jKMTvyfN/4ylBKdwfw==",
       "requires": {
-        "nan": "^2.12.1",
-        "node-pre-gyp": "^0.11.0",
-        "request": "^2.87.0"
+        "node-addon-api": "2.0.0",
+        "node-gyp": "3.x",
+        "node-pre-gyp": "^0.11.0"
       }
     },
     "sshpk": {
       "version": "1.16.1",
       "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
       "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
+      "optional": true,
       "requires": {
         "asn1": "~0.2.3",
         "assert-plus": "^1.0.0",
@@ -1050,17 +1148,14 @@
       "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
     },
     "tar": {
-      "version": "4.4.13",
-      "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz",
-      "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==",
-      "requires": {
-        "chownr": "^1.1.1",
-        "fs-minipass": "^1.2.5",
-        "minipass": "^2.8.6",
-        "minizlib": "^1.2.1",
-        "mkdirp": "^0.5.0",
-        "safe-buffer": "^5.1.2",
-        "yallist": "^3.0.3"
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
+      "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
+      "optional": true,
+      "requires": {
+        "block-stream": "*",
+        "fstream": "^1.0.12",
+        "inherits": "2"
       }
     },
     "through": {
@@ -1092,6 +1187,7 @@
       "version": "2.5.0",
       "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
       "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
+      "optional": true,
       "requires": {
         "psl": "^1.1.28",
         "punycode": "^2.1.1"
@@ -1101,6 +1197,7 @@
       "version": "0.6.0",
       "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
       "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+      "optional": true,
       "requires": {
         "safe-buffer": "^5.0.1"
       }
@@ -1108,22 +1205,24 @@
     "tweetnacl": {
       "version": "0.14.5",
       "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
-      "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
+      "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+      "optional": true
     },
     "typescript": {
-      "version": "3.8.3",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz",
-      "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w=="
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.2.tgz",
+      "integrity": "sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ=="
     },
     "underscore": {
-      "version": "1.10.2",
-      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz",
-      "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg=="
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.11.0.tgz",
+      "integrity": "sha512-xY96SsN3NA461qIRKZ/+qox37YXPtSBswMGfiNptr+wrt6ds4HaMw23TP612fEyGekRE6LNRiLYr/aqbHXNedw=="
     },
     "uri-js": {
-      "version": "4.2.2",
-      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
-      "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz",
+      "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==",
+      "optional": true,
       "requires": {
         "punycode": "^2.1.0"
       }
@@ -1142,9 +1241,9 @@
       "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
     },
     "uuid": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz",
-      "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg=="
+      "version": "8.3.0",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz",
+      "integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ=="
     },
     "validator": {
       "version": "10.11.0",
@@ -1155,12 +1254,22 @@
       "version": "1.10.0",
       "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
       "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+      "optional": true,
       "requires": {
         "assert-plus": "^1.0.0",
         "core-util-is": "1.0.2",
         "extsprintf": "^1.2.0"
       }
     },
+    "which": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+      "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+      "optional": true,
+      "requires": {
+        "isexe": "^2.0.0"
+      }
+    },
     "wide-align": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
@@ -1170,9 +1279,9 @@
       }
     },
     "wkx": {
-      "version": "0.4.8",
-      "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.4.8.tgz",
-      "integrity": "sha512-ikPXMM9IR/gy/LwiOSqWlSL3X/J5uk9EO2hHNRXS41eTLXaUFEVw9fn/593jW/tE5tedNg8YjT5HkCa4FqQZyQ==",
+      "version": "0.5.0",
+      "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz",
+      "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==",
       "requires": {
         "@types/node": "*"
       }
diff --git a/package.json b/package.json
index a15dd80..3175dfc 100644
--- a/package.json
+++ b/package.json
@@ -14,13 +14,13 @@
     "node-fetch": "^2.6.0",
     "node-tvdb": "^4.1.0",
     "path": "^0.12.7",
-    "pg": "^7.18.2",
+    "pg": "^8.3.3",
     "pg-hstore": "^2.3.3",
-    "pnormaldist": "^1.0.1",
-    "sequelize": "^5.21.7",
-    "sqlite3": "^4.1.1",
-    "typescript": "^3.8.3",
-    "uuid": "^7.0.3",
+    "pnormaldist": "^1.0.2",
+    "sequelize": "^6.3.5",
+    "sqlite3": "^5.0.0",
+    "typescript": "^4.0.2",
+    "uuid": "^8.3.0",
     "xml2json": "^0.12.0"
   }
 }
diff --git a/src/api/fanart_api.js b/src/api/fanart_api.js
index 4a98cd3..75f7258 100644
--- a/src/api/fanart_api.js
+++ b/src/api/fanart_api.js
@@ -14,9 +14,11 @@ class FanartApi {
         const params = new URLSearchParams(options || {});
         params.append("api_key", this.apiKey);
         url.search = params.toString();
-        return fetch(
-            url.href
-        ).then((response) => {
+        return fetch(url.href, {
+            options: {
+                timeout: 2000,
+            },
+        }).then((response) => {
             return response.text().then(text => {
                 return {
                     ok: response.ok,
@@ -29,8 +31,11 @@ class FanartApi {
                 throw new Error(`${url}: ${body}`);
             }
             return JSON.parse(body);
+        }).catch(err => {
+            console.error(err);
+            return null;
         });
     }
 }
 
-export default FanartApi;
\ No newline at end of file
+export default FanartApi;
diff --git a/src/api/imdb_api.js b/src/api/imdb_api.js
index ac641b6..33fdc85 100644
--- a/src/api/imdb_api.js
+++ b/src/api/imdb_api.js
@@ -29,6 +29,24 @@ class ImdbApi {
         });
     }
 
+    findByIdAka(id) {
+        return this.queryJson(ImdbApi.queryGetAka, {
+            1: id
+        });
+    }
+
+    findByIdEpisodes(id) {
+        return this.queryJson(ImdbApi.queryGetEpisodes, {
+            1: id
+        });
+    }
+
+    findByIdPrincipals(id) {
+        return this.queryJson(ImdbApi.queryGetPrincipals, {
+            1: id
+        });
+    }
+
     findEpisodeById(id, seasonNumber, episodeNumber) {
         return this.queryJson(ImdbApi.queryGetEpisode, {
             1: id,
@@ -78,56 +96,61 @@ class ImdbApi {
                        'crew', json_object(
                                'directors', json('["' || replace(title_crew.directors, ',', '","') || '"]'),
                                'writers', json('["' || replace(title_crew.writers, ',', '","') || '"]')
-                           ),
-                       'aka', json(aka.aka),
-                       'principals', json(principals.principals),
-                       'episodes', json(episode.episode)
+                           )
                    ) AS json
         FROM title
-                 LEFT OUTER JOIN (SELECT title_principals.tconst,
-                                         json_group_array(json_object(
-                                                 'person', json_object(
-                                                         'nconst', name.nconst,
-                                                         'primaryName', name.primaryName,
-                                                         'birthYear', name.birthYear,
-                                                         'deathYear', name.deathYear,
-                                                         'primaryProfession',
-                                                         json('["' || replace(name.primaryProfession, ',', '","') || '"]'),
-                                                         'knownForTitles',
-                                                         json('["' || replace(name.knownForTitles, ',', '","') || '"]')
-                                                     ),
-                                                 'category', title_principals.category,
-                                                 'job', title_principals.job,
-                                                 'characters', json(title_principals.characters)
-                                             )) AS principals
-                                  FROM title_principals
-                                           LEFT OUTER JOIN name on title_principals.nconst = name.nconst
-                                  GROUP BY title_principals.tconst) AS principals ON title.tconst = principals.tconst
-                 LEFT OUTER JOIN (SELECT title_aka.titleId,
-                                         json_group_array(json_object(
-                                                 'title', title_aka.title,
-                                                 'region', title_aka.region,
-                                                 'languages', title_aka.language,
-                                                 'types', json('["' || replace(title_aka.types, ',', '","') || '"]'),
-                                                 'attributes', json('["' || replace(title_aka.attributes, ',', '","') || '"]'),
-                                                 'isOriginalTitle',
-                                                 json(case when title_aka.isOriginalTitle = 0 then 'false' else 'true' end)
-                                             )) AS aka
-                                  FROM title_aka
-                                  GROUP BY title_aka.titleId) AS aka ON title.tconst = aka.titleId
-                 LEFT OUTER JOIN (SELECT title_episode.parentTconst,
-                                         json_group_array(json_object(
-                                                 'tconst', title_episode.tconst,
-                                                 'season', title_episode.seasonNumber,
-                                                 'episode', title_episode.episodeNumber
-                                             )) AS episode
-                                  FROM title_episode
-                                  GROUP BY title_episode.parentTconst) AS episode ON title.tconst = episode.parentTconst
                  LEFT OUTER JOIN title_ratings on title.tconst = title_ratings.tconst
                  LEFT OUTER JOIN title_crew on title.tconst = title_crew.tconst
         WHERE title.tconst = ?
     `;
 
+    static queryGetAka = `
+        SELECT json_group_array(json_object(
+                'title', title_aka.title,
+                'region', title_aka.region,
+                'languages', title_aka.language,
+                'types', json('["' || replace(title_aka.types, ',', '","') || '"]'),
+                'attributes', json('["' || replace(title_aka.attributes, ',', '","') || '"]'),
+                'isOriginalTitle', json(case when title_aka.isOriginalTitle = 0 then 'false' else 'true' end)
+            )) AS json
+        FROM title_aka
+        WHERE title_aka.titleId = ?
+        GROUP BY title_aka.titleId;
+    `;
+
+    static queryGetEpisodes = `
+        SELECT json_group_array(json_object(
+                 'tconst', title_episode.tconst,
+                 'season', title_episode.seasonNumber,
+                 'episode', title_episode.episodeNumber
+            )) AS json
+        FROM title_episode
+        WHERE title_episode.parentTconst = ?
+        GROUP BY title_episode.parentTconst;
+    `;
+
+    static queryGetPrincipals = `
+        SELECT json_group_array(json_object(
+                 'person', json_object(
+                         'nconst', name.nconst,
+                         'primaryName', name.primaryName,
+                         'birthYear', name.birthYear,
+                         'deathYear', name.deathYear,
+                         'primaryProfession',
+                         json('["' || replace(name.primaryProfession, ',', '","') || '"]'),
+                         'knownForTitles',
+                         json('["' || replace(name.knownForTitles, ',', '","') || '"]')
+                     ),
+                 'category', title_principals.category,
+                 'job', title_principals.job,
+                 'characters', json(title_principals.characters)
+            )) AS json
+        FROM title_principals
+        LEFT OUTER JOIN name on title_principals.nconst = name.nconst
+        WHERE title_principals.tconst = ?
+        GROUP BY title_principals.tconst;
+    `;
+
     static queryGetEpisode = `
         SELECT json_object(
                        'id', title.tconst,
@@ -156,4 +179,4 @@ function promisify(db, fun) {
     });
 }
 
-export default ImdbApi;
\ No newline at end of file
+export default ImdbApi;
diff --git a/src/api/tmdb_api.js b/src/api/tmdb_api.js
index cf57bb7..a93236a 100644
--- a/src/api/tmdb_api.js
+++ b/src/api/tmdb_api.js
@@ -25,7 +25,10 @@ class TmdbApi {
             headers: {
                 'Authorization': `Bearer ${this.apiKey}`,
                 'Content-Type': 'application/json;charset=utf-8',
-            }
+            },
+            options: {
+                timeout: 2000,
+            },
         }).then((response) => {
             return response.text().then(text => {
                 return {
@@ -39,8 +42,11 @@ class TmdbApi {
                 throw new Error(`${url}: ${body}`);
             }
             return JSON.parse(body);
+        }).catch(err => {
+            console.error(err);
+            return null;
         });
     }
 }
 
-export default TmdbApi;
\ No newline at end of file
+export default TmdbApi;
diff --git a/src/directory_walker.js b/src/directory_walker.js
index e840f60..f20145b 100644
--- a/src/directory_walker.js
+++ b/src/directory_walker.js
@@ -52,29 +52,32 @@ class FileManager {
     }
 
     async listEpisodes(showPath) {
-        return fsPromises
-            .readdir(showPath, {withFileTypes: true})
-            .then(result => result
-                .filter(dir => dir.isDirectory())
-                .map(dir => {
-                    const match = /^(?:(?:(?<year>\d+)-(?<month>\d+)-(?<day>\d+))|(?:(?:S(?<season>\d+(?:[.\-–—&]\d+)?))?\p{L}*[\t\f ]*(?<episode>\d+(?:[.\-–—&]\d+)?)))(?:(?:[\t\f ]+(?:[\-–—:][\t\f ]*)?)(?<title>\S.*))?$/u.exec(dir.name);
-                    if (!match) {
-                        return null;
-                    }
-                    const {season, episode, year, month, day} = match.groups
-                    return {
-                        filePath: path.join(showPath, dir.name),
-                        src: encodePath(path.relative(this.basePath, path.join(showPath, dir.name))),
-                        episodeIdentifier: {
-                            season: season,
-                            episode: episode,
-                            year: year,
-                            month: month,
-                            day: day,
-                        },
-                    }
-                }).filter(el => el !== null)
-            );
+        const files = await fsPromises
+            .readdir(showPath, {withFileTypes: true});
+        const dirs = files.filter(it => {
+            return it.isDirectory();
+        });
+        const matched = dirs.map(it => {
+            return {
+                name: it.name,
+                match: /^(?:(?:(?<year>\d+)-(?<month>\d+)-(?<day>\d+))|(?:(?:S(?<season>\d+(?:[.\-–—&]\d+)?))?\p{L}*[\t\f ]*(?<episode>\d+(?:[.\-–—&]\d+)?)))(?:(?:[\t\f ]+(?:[\-–—:][\t\f ]*)?)(?<title>\S.*))?$/u.exec(it.name)?.groups
+            };
+        }).filter(it => it.match !== undefined);
+        const mapped = matched.map(it => {
+            const {season, episode, year, month, day} = it.match
+            return {
+                filePath: path.join(showPath, it.name),
+                src: encodePath(path.relative(this.basePath, path.join(showPath, it.name))),
+                episodeIdentifier: {
+                    season: season,
+                    episode: episode,
+                    year: year,
+                    month: month,
+                    day: day,
+                },
+            }
+        });
+        return mapped;
     }
 
     async findIds(filePath) {
@@ -140,4 +143,4 @@ class FileManager {
     }
 }
 
-export default FileManager;
\ No newline at end of file
+export default FileManager;
diff --git a/src/index.js b/src/index.js
index e42d80a..4678796 100644
--- a/src/index.js
+++ b/src/index.js
@@ -12,17 +12,21 @@ import VideoMimeParser from "./util/video-mime";
 
 import Backend from "./storage";
 import processContent from "./process_content";
+import {Genre} from "./model";
 
 async function main() {
+    console.info("Processing arguments");
     const args = process.argv.slice(2);
     const basePath = args[0];
 
+    console.info("Setting up API clients");
     const imdbApi = new ImdbApi(process.env.IMDB_PATH);
     const tmdbApi = new TmdbApi(process.env.TMDB_API_KEY);
     await tmdbApi.updateConfiguration();
     const tvdbApi = new TvdbApi(process.env.TVDB_API_KEY);
     const fanartApi = new FanartApi(process.env.FANART_API_KEY);
 
+    console.info("Setting up backend");
     const storage = new Backend(new sequelize.Sequelize(
         process.env.DB_DATABASE,
         process.env.DB_USERNAME,
@@ -34,16 +38,20 @@ async function main() {
             ssl: !!process.env.DB_SSL,
         }
     ));
+    console.info("Migrating backend database");
+    console.log(await Genre.sync());
     await storage.sync();
 
+    console.info("Setting up media ingestion tools");
     const videoMimeParser = new VideoMimeParser(process.env.MP4INFO_PATH || "mp4info", process.env.FFPROBE_PATH || "ffprobe");
     const loader = new MetadataLoader(imdbApi, tmdbApi, tvdbApi, fanartApi, storage);
     const fileManager = new FileManager(basePath, videoMimeParser);
     await fileManager.updateConfiguration();
 
+    console.info("Processing content");
     await processContent(basePath, fileManager, loader);
 }
 
 (async function () {
     await main()
-}());
\ No newline at end of file
+}());
diff --git a/src/metadata_loader.js b/src/metadata_loader.js
index c4be27f..3229e2b 100644
--- a/src/metadata_loader.js
+++ b/src/metadata_loader.js
@@ -1,5 +1,5 @@
 import ranking_confidence from './util/statistics';
-import uuid from 'uuid';
+import {v4 as uuidv4} from 'uuid';
 import path from "path";
 import downloadFile from "./util/download-file";
 import encodePath from "./util/encode-path";
@@ -11,7 +11,8 @@ import {
     TitleDescription,
     TitleEpisode,
     TitleGenre,
-    TitleImage, TitleMedia,
+    TitleImage,
+    TitleMedia,
     TitleName,
     TitleRating,
     TitleSubtitles
@@ -172,7 +173,7 @@ class MetadataLoader {
                 episode_number: episodeIdentifier.episode,
             },
             defaults: {
-                episode_id: uuid.v4(),
+                episode_id: uuidv4,
             }
         })
         const [episodeTitle] = await Title.upsert({
@@ -312,7 +313,7 @@ class MetadataLoader {
         if (!tmdbResult) return null;
 
         return {
-            uuid: uuid.v4(),
+            uuid: uuidv4(),
             imdb: tmdbResult.imdb_id,
             tmdb: result.id,
             tvdb: null,
@@ -349,7 +350,7 @@ class MetadataLoader {
         const tmdbId = tmdbSeries.id;
 
         return {
-            uuid: uuid.v4(),
+            uuid: uuidv4(),
             imdb: imdbId,
             tvdb: tvdbId,
             tmdb: tmdbId,
@@ -472,17 +473,36 @@ class MetadataLoader {
             }
         }
 
-        const fanartSource = titleType === "tvSeries" ?
+        const isShow = titleType === "tvSeries";
+        const fanartSource = isShow ?
             `tv/${ids.tmdb}` :
             `movies/${ids.tmdb}`;
 
-        const [imdbResult, tmdbResult, tmdbTranslations, tmdbContentRatings, tmdbImages, fanartImages] = await Promise.all([
-            this.imdb.findById(ids.imdb).catch(_ => null),
-            ...tmdbSources().map(url => this.tmdb.request(url).catch(_ => null)),
-            this.fanart.request(fanartSource).catch(_ => null) // do nothing, it just means it wasn’t found
-        ].filter(el => el !== null));
+        const [
+            imdbResult, imdbAka, imdbPrincipals, imdbEpisodes,
+            tmdbResult, tmdbTranslations, tmdbContentRatings, tmdbImages,
+            fanartImages
+        ] = await Promise.all([
+            this.imdb.findById(ids.imdb),
+            this.imdb.findByIdAka(ids.imdb),
+            this.imdb.findByIdPrincipals(ids.imdb),
+            isShow ? this.imdb.findByIdEpisodes(ids.imdb) : new Promise((resolve) => resolve([])),
+            ...tmdbSources().map(url => this.tmdb.request(url)),
+            this.fanart.request(fanartSource),
+        ].map(it => it.catch(err => {
+            console.error(`Error while processing ${ids.imdb}`, err);
+            process.abort();
+            return null;
+        })));
+        const imdbData = {
+            ...imdbResult,
+            aka: imdbAka,
+            principals: imdbPrincipals,
+            episodes: imdbEpisodes,
+        };
+
+        const title = await this.transformData(ids, imdbData, tmdbResult, tmdbContentRatings, tmdbTranslations);
 
-        const title = await this.transformData(ids, imdbResult, tmdbResult, tmdbContentRatings, tmdbTranslations);
         return {
             title: title,
             images: this.chooseImages(title.original_language, tmdbImages, fanartImages)
@@ -490,4 +510,4 @@ class MetadataLoader {
     }
 }
 
-export default MetadataLoader;
\ No newline at end of file
+export default MetadataLoader;
diff --git a/src/process_content.js b/src/process_content.js
index ba62138..8c925c2 100644
--- a/src/process_content.js
+++ b/src/process_content.js
@@ -10,18 +10,21 @@ async function processContent(basePath, fileManager, loader) {
             console.error(`Could not identify movie ${name} (${year}) at ${filePath}`)
             return;
         }
+        console.info(`Processing movie ${name} (${year})`);
         const [media, {title, images}] = await Promise.all([
             fileManager.findMedia(filePath),
             loader.loadMetadata(ids),
         ]);
         const imageData = await loader.processImages(basePath, filePath, images);
         await loader.processImageMetadata(title, imageData);
-await loader.processMediaMetadata(title, media);
+        await loader.processMediaMetadata(title, media);
 
         await fsPromises.writeFile(path.join(filePath, "ids.json"), JSON.stringify(ids, null, 2));
+        console.info(`Finished movie ${name} (${year})`);
     }
 
     async function processEpisode(showIds, episodeIdentifier, filePath) {
+        console.info(`Processing episode`, episodeIdentifier);
         const [media, {title, images}] = await Promise.all([
             fileManager.findMedia(filePath),
             loader.loadEpisodeMetadata(showIds, episodeIdentifier),
@@ -29,28 +32,37 @@ await loader.processMediaMetadata(title, media);
         const imageData = await loader.processImages(basePath, filePath, images);
         await loader.processImageMetadata(title, imageData);
         await loader.processMediaMetadata(title, media);
+        console.info(`Finished episode`, episodeIdentifier);
     }
 
     async function processShow(filePath) {
         const {name, year} = /^(?<name>.+) \((?<year>\d+)\)$/.exec(path.basename(filePath)).groups;
         const ids = (await fileManager.findIds(filePath)) || (await loader.identifyShow(name, year));
         if (!ids) {
-            console.error(`Could not identify show ${name} (${year}) at ${filePath}`)
+            console.error(`Could not identify show ${name} (${year}) ${ids.imdb} at ${filePath}`)
             return;
         }
+        console.info(`Processing show ${name} (${year}) ${ids.imdb}`);
         const episodes = await fileManager.listEpisodes(filePath);
 
+        console.info(`Loading metadata ${name} (${year}) ${ids.imdb}`);
         const {title, images} = await loader.loadMetadata(ids);
+        console.info(`Processing images ${name} (${year}) ${ids.imdb}`);
         const imageData = await loader.processImages(basePath, filePath, images);
+        console.info(`Processing image metadata ${name} (${year}) ${ids.imdb}`);
         await loader.processImageMetadata(title, imageData);
+        console.info(`Processing episode data ${name} (${year}) ${ids.imdb}`);
         await Promise.all([
             ...episodes.map(async ({episodeIdentifier, filePath}) => await processEpisode(ids, episodeIdentifier, filePath).catch(err => {
                 console.error(`Error processing episode ${JSON.stringify(episodeIdentifier)} of show ${JSON.stringify(ids)}: `, err);
             })),
             fsPromises.writeFile(path.join(filePath, "ids.json"), JSON.stringify(ids, null, 2)),
         ]);
+        console.log(`Finished show  ${name} (${year}) ${ids.imdb}`);
     }
 
+    console.info("Processing content");
+
     const [movies, shows] = await Promise.all([fileManager.listMovies(), fileManager.listShows()]);
     await Promise.all([
         ...movies.map(processMovie),
@@ -58,4 +70,4 @@ await loader.processMediaMetadata(title, media);
     ]);
 }
 
-export default processContent;
\ No newline at end of file
+export default processContent;
diff --git a/src/storage.js b/src/storage.js
index 48491c6..16f7570 100644
--- a/src/storage.js
+++ b/src/storage.js
@@ -30,7 +30,11 @@ class Backend {
                 allowNull: false,
                 primaryKey: true
             },
-            tmdb_id: sequelize.DataTypes.INTEGER,
+            tmdb_id: {
+                type: sequelize.DataTypes.INTEGER,
+                allowNull: false,
+                unique: true,
+            },
             name: {
                 type: sequelize.DataTypes.TEXT,
                 allowNull: false,
@@ -48,7 +52,11 @@ class Backend {
                 allowNull: false,
                 primaryKey: true
             },
-            imdb_id: sequelize.DataTypes.TEXT,
+            imdb_id: {
+                type: sequelize.DataTypes.TEXT,
+                allowNull: false,
+                unique: true,
+            },
             name: {
                 type: sequelize.DataTypes.TEXT,
                 allowNull: false,
@@ -194,7 +202,7 @@ class Backend {
                 allowNull: false,
             }
         })
-        Title.belongsTo(TitleEpisode, {
+        Title.hasMany(TitleEpisode, {
             as: "Parent",
             foreignKey: {
                 name: "parent_id",
@@ -389,4 +397,4 @@ class Backend {
 
 }
 
-export default Backend;
\ No newline at end of file
+export default Backend;
-- 
GitLab