diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
index b94f01f8e..77d35d2a1 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -99,6 +99,8 @@ jobs:
       - name: Functional tests
         run: |
           cd ../server
+          ./occ migrations:migrate news
+          ./occ maintenance:repair
           ./occ news:generate-explore --votes 100 "https://nextcloud.com/blog/feed/"
           ./occ news:folder:add 'admin' 'Something'
           ./occ news:folder:list 'admin' | grep 'Something'
diff --git a/appinfo/app.php b/appinfo/app.php
deleted file mode 100644
index 4abce5742..000000000
--- a/appinfo/app.php
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php
-/**
- * Nextcloud - News
- *
- * This file is licensed under the Affero General Public License version 3 or
- * later. See the COPYING file.
- *
- * @author Alessandro Cosentino <cosenal@gmail.com>
- * @author Bernhard Posselt <dev@bernhard-posselt.com>
- * @copyright 2012 Alessandro Cosentino
- * @copyright 2012-2014 Bernhard Posselt
- */
-
-namespace OCA\News\AppInfo;
-
-use OCA\News\Hooks\User;
-
-require_once __DIR__ . '/../vendor/autoload.php';
-
-\OCP\Util::connectHook('OC_User', 'pre_deleteUser', User::class, 'deleteUser');
\ No newline at end of file
diff --git a/composer.json b/composer.json
index 0acc198ae..a5cbc622e 100644
--- a/composer.json
+++ b/composer.json
@@ -45,19 +45,17 @@
     "ezyang/htmlpurifier": "^4.13.0",
     "pear/net_url2": "2.2.2",
     "riimu/kit-pathjoin": "1.2.0",
-    "debril/feed-io": "^v4.7.8",
-    "arthurhoaro/favicon": "^1.2",
+    "debril/feed-io": "^v4.7.9",
+    "arthurhoaro/favicon": "^1.3",
+    "andreskrey/readability.php": "^2.1",
     "ext-json": "*",
     "ext-simplexml": "*",
     "ext-libxml": "*",
-    "andreskrey/readability.php": "^2.1",
     "ext-dom": "*"
   },
   "require-dev": {
-    "phpunit/phpunit": "9.2.6",
+    "phpunit/phpunit": "9.2.*",
     "squizlabs/php_codesniffer": "^3.5.6",
-    "guzzlehttp/guzzle": "^6.3",
-    "symfony/service-contracts": "2.2.0",
     "phpstan/phpstan": "^0.12.43"
   },
   "replace": {
diff --git a/composer.lock b/composer.lock
index ada2160ad..f305f3294 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "0f4161d1df33ea0b72224da925f2f6b5",
+    "content-hash": "e553641d7a0ca7ff73af7bdbc2c47617",
     "packages": [
         {
             "name": "andreskrey/readability.php",
@@ -763,28 +763,28 @@
         },
         {
             "name": "phpspec/prophecy",
-            "version": "1.11.1",
+            "version": "1.12.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/phpspec/prophecy.git",
-                "reference": "b20034be5efcdab4fb60ca3a29cba2949aead160"
+                "reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/phpspec/prophecy/zipball/b20034be5efcdab4fb60ca3a29cba2949aead160",
-                "reference": "b20034be5efcdab4fb60ca3a29cba2949aead160",
+                "url": "https://api.github.com/repos/phpspec/prophecy/zipball/8ce87516be71aae9b956f81906aaf0338e0d8a2d",
+                "reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d",
                 "shasum": ""
             },
             "require": {
                 "doctrine/instantiator": "^1.2",
-                "php": "^7.2",
-                "phpdocumentor/reflection-docblock": "^5.0",
+                "php": "^7.2 || ~8.0, <8.1",
+                "phpdocumentor/reflection-docblock": "^5.2",
                 "sebastian/comparator": "^3.0 || ^4.0",
                 "sebastian/recursion-context": "^3.0 || ^4.0"
             },
             "require-dev": {
                 "phpspec/phpspec": "^6.0",
-                "phpunit/phpunit": "^8.0"
+                "phpunit/phpunit": "^8.0 || ^9.0 <9.3"
             },
             "type": "library",
             "extra": {
@@ -822,20 +822,20 @@
                 "spy",
                 "stub"
             ],
-            "time": "2020-07-08T12:44:21+00:00"
+            "time": "2020-09-29T09:10:42+00:00"
         },
         {
             "name": "phpstan/phpstan",
-            "version": "0.12.45",
+            "version": "0.12.46",
             "source": {
                 "type": "git",
                 "url": "https://github.com/phpstan/phpstan.git",
-                "reference": "90c67259212ed891ee86604a9368ef7d7bead3a4"
+                "reference": "9419738e20f0c49757be05d22969c1c44c1dff3b"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/phpstan/phpstan/zipball/90c67259212ed891ee86604a9368ef7d7bead3a4",
-                "reference": "90c67259212ed891ee86604a9368ef7d7bead3a4",
+                "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9419738e20f0c49757be05d22969c1c44c1dff3b",
+                "reference": "9419738e20f0c49757be05d22969c1c44c1dff3b",
                 "shasum": ""
             },
             "require": {
@@ -878,7 +878,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2020-09-26T19:19:00+00:00"
+            "time": "2020-09-28T09:48:55+00:00"
         },
         {
             "name": "phpunit/php-code-coverage",
@@ -952,23 +952,23 @@
         },
         {
             "name": "phpunit/php-file-iterator",
-            "version": "3.0.4",
+            "version": "3.0.5",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
-                "reference": "25fefc5b19835ca653877fe081644a3f8c1d915e"
+                "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/25fefc5b19835ca653877fe081644a3f8c1d915e",
-                "reference": "25fefc5b19835ca653877fe081644a3f8c1d915e",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/aa4be8575f26070b100fccb67faabb28f21f66f8",
+                "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.3 || ^8.0"
+                "php": ">=7.3"
             },
             "require-dev": {
-                "phpunit/phpunit": "^9.0"
+                "phpunit/phpunit": "^9.3"
             },
             "type": "library",
             "extra": {
@@ -1004,28 +1004,28 @@
                     "type": "github"
                 }
             ],
-            "time": "2020-07-11T05:18:21+00:00"
+            "time": "2020-09-28T05:57:25+00:00"
         },
         {
             "name": "phpunit/php-invoker",
-            "version": "3.1.0",
+            "version": "3.1.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/php-invoker.git",
-                "reference": "7a85b66acc48cacffdf87dadd3694e7123674298"
+                "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/7a85b66acc48cacffdf87dadd3694e7123674298",
-                "reference": "7a85b66acc48cacffdf87dadd3694e7123674298",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
+                "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.3 || ^8.0"
+                "php": ">=7.3"
             },
             "require-dev": {
                 "ext-pcntl": "*",
-                "phpunit/phpunit": "^9.0"
+                "phpunit/phpunit": "^9.3"
             },
             "suggest": {
                 "ext-pcntl": "*"
@@ -1063,27 +1063,27 @@
                     "type": "github"
                 }
             ],
-            "time": "2020-08-06T07:04:15+00:00"
+            "time": "2020-09-28T05:58:55+00:00"
         },
         {
             "name": "phpunit/php-text-template",
-            "version": "2.0.2",
+            "version": "2.0.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/php-text-template.git",
-                "reference": "6ff9c8ea4d3212b88fcf74e25e516e2c51c99324"
+                "reference": "18c887016e60e52477e54534956d7b47bc52cd84"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/6ff9c8ea4d3212b88fcf74e25e516e2c51c99324",
-                "reference": "6ff9c8ea4d3212b88fcf74e25e516e2c51c99324",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/18c887016e60e52477e54534956d7b47bc52cd84",
+                "reference": "18c887016e60e52477e54534956d7b47bc52cd84",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.3 || ^8.0"
+                "php": ">=7.3"
             },
             "require-dev": {
-                "phpunit/phpunit": "^9.0"
+                "phpunit/phpunit": "^9.3"
             },
             "type": "library",
             "extra": {
@@ -1118,27 +1118,27 @@
                     "type": "github"
                 }
             ],
-            "time": "2020-06-26T11:55:37+00:00"
+            "time": "2020-09-28T06:03:05+00:00"
         },
         {
             "name": "phpunit/php-timer",
-            "version": "5.0.1",
+            "version": "5.0.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/php-timer.git",
-                "reference": "cc49734779cbb302bf51a44297dab8c4bbf941e7"
+                "reference": "c9ff14f493699e2f6adee9fd06a0245b276643b7"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/cc49734779cbb302bf51a44297dab8c4bbf941e7",
-                "reference": "cc49734779cbb302bf51a44297dab8c4bbf941e7",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/c9ff14f493699e2f6adee9fd06a0245b276643b7",
+                "reference": "c9ff14f493699e2f6adee9fd06a0245b276643b7",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.3 || ^8.0"
+                "php": ">=7.3"
             },
             "require-dev": {
-                "phpunit/phpunit": "^9.2"
+                "phpunit/phpunit": "^9.3"
             },
             "type": "library",
             "extra": {
@@ -1173,7 +1173,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2020-06-26T11:58:13+00:00"
+            "time": "2020-09-28T06:00:25+00:00"
         },
         {
             "name": "phpunit/php-token-stream",
@@ -1329,74 +1329,25 @@
             ],
             "time": "2020-07-13T17:55:55+00:00"
         },
-        {
-            "name": "psr/container",
-            "version": "1.0.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/php-fig/container.git",
-                "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
-                "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.0"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Psr\\Container\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "PHP-FIG",
-                    "homepage": "http://www.php-fig.org/"
-                }
-            ],
-            "description": "Common Container Interface (PHP FIG PSR-11)",
-            "homepage": "https://github.com/php-fig/container",
-            "keywords": [
-                "PSR-11",
-                "container",
-                "container-interface",
-                "container-interop",
-                "psr"
-            ],
-            "time": "2017-02-14T16:28:37+00:00"
-        },
         {
             "name": "sebastian/code-unit",
-            "version": "1.0.5",
+            "version": "1.0.6",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/code-unit.git",
-                "reference": "c1e2df332c905079980b119c4db103117e5e5c90"
+                "reference": "d3a241b6028ff9d8e97d2b6ebd4090d01f92fad8"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/c1e2df332c905079980b119c4db103117e5e5c90",
-                "reference": "c1e2df332c905079980b119c4db103117e5e5c90",
+                "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/d3a241b6028ff9d8e97d2b6ebd4090d01f92fad8",
+                "reference": "d3a241b6028ff9d8e97d2b6ebd4090d01f92fad8",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.3 || ^8.0"
+                "php": ">=7.3"
             },
             "require-dev": {
-                "phpunit/phpunit": "^9.0"
+                "phpunit/phpunit": "^9.3"
             },
             "type": "library",
             "extra": {
@@ -1428,27 +1379,27 @@
                     "type": "github"
                 }
             ],
-            "time": "2020-06-26T12:50:45+00:00"
+            "time": "2020-09-28T05:28:46+00:00"
         },
         {
             "name": "sebastian/code-unit-reverse-lookup",
-            "version": "2.0.2",
+            "version": "2.0.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
-                "reference": "ee51f9bb0c6d8a43337055db3120829fa14da819"
+                "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ee51f9bb0c6d8a43337055db3120829fa14da819",
-                "reference": "ee51f9bb0c6d8a43337055db3120829fa14da819",
+                "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
+                "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.3 || ^8.0"
+                "php": ">=7.3"
             },
             "require-dev": {
-                "phpunit/phpunit": "^9.0"
+                "phpunit/phpunit": "^9.3"
             },
             "type": "library",
             "extra": {
@@ -1479,29 +1430,29 @@
                     "type": "github"
                 }
             ],
-            "time": "2020-06-26T12:04:00+00:00"
+            "time": "2020-09-28T05:30:19+00:00"
         },
         {
             "name": "sebastian/comparator",
-            "version": "4.0.3",
+            "version": "4.0.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/comparator.git",
-                "reference": "dcc580eadfaa4e7f9d2cf9ae1922134ea962e14f"
+                "reference": "e717aabeafe4eac045d3e947dad3207118664c72"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/dcc580eadfaa4e7f9d2cf9ae1922134ea962e14f",
-                "reference": "dcc580eadfaa4e7f9d2cf9ae1922134ea962e14f",
+                "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/e717aabeafe4eac045d3e947dad3207118664c72",
+                "reference": "e717aabeafe4eac045d3e947dad3207118664c72",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.3 || ^8.0",
+                "php": ">=7.3",
                 "sebastian/diff": "^4.0",
                 "sebastian/exporter": "^4.0"
             },
             "require-dev": {
-                "phpunit/phpunit": "^9.0"
+                "phpunit/phpunit": "^9.3"
             },
             "type": "library",
             "extra": {
@@ -1549,27 +1500,27 @@
                     "type": "github"
                 }
             ],
-            "time": "2020-06-26T12:05:46+00:00"
+            "time": "2020-09-28T05:31:46+00:00"
         },
         {
             "name": "sebastian/diff",
-            "version": "4.0.2",
+            "version": "4.0.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/diff.git",
-                "reference": "1e90b4cf905a7d06c420b1d2e9d11a4dc8a13113"
+                "reference": "ffc949a1a2aae270ea064453d7535b82e4c32092"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/1e90b4cf905a7d06c420b1d2e9d11a4dc8a13113",
-                "reference": "1e90b4cf905a7d06c420b1d2e9d11a4dc8a13113",
+                "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ffc949a1a2aae270ea064453d7535b82e4c32092",
+                "reference": "ffc949a1a2aae270ea064453d7535b82e4c32092",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.3 || ^8.0"
+                "php": ">=7.3"
             },
             "require-dev": {
-                "phpunit/phpunit": "^9.0",
+                "phpunit/phpunit": "^9.3",
                 "symfony/process": "^4.2 || ^5"
             },
             "type": "library",
@@ -1611,27 +1562,27 @@
                     "type": "github"
                 }
             ],
-            "time": "2020-06-30T04:46:02+00:00"
+            "time": "2020-09-28T05:32:55+00:00"
         },
         {
             "name": "sebastian/environment",
-            "version": "5.1.2",
+            "version": "5.1.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/environment.git",
-                "reference": "0a757cab9d5b7ef49a619f1143e6c9c1bc0fe9d2"
+                "reference": "388b6ced16caa751030f6a69e588299fa09200ac"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/0a757cab9d5b7ef49a619f1143e6c9c1bc0fe9d2",
-                "reference": "0a757cab9d5b7ef49a619f1143e6c9c1bc0fe9d2",
+                "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac",
+                "reference": "388b6ced16caa751030f6a69e588299fa09200ac",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.3 || ^8.0"
+                "php": ">=7.3"
             },
             "require-dev": {
-                "phpunit/phpunit": "^9.0"
+                "phpunit/phpunit": "^9.3"
             },
             "suggest": {
                 "ext-posix": "*"
@@ -1639,7 +1590,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "5.0-dev"
+                    "dev-master": "5.1-dev"
                 }
             },
             "autoload": {
@@ -1670,29 +1621,29 @@
                     "type": "github"
                 }
             ],
-            "time": "2020-06-26T12:07:24+00:00"
+            "time": "2020-09-28T05:52:38+00:00"
         },
         {
             "name": "sebastian/exporter",
-            "version": "4.0.2",
+            "version": "4.0.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/exporter.git",
-                "reference": "571d721db4aec847a0e59690b954af33ebf9f023"
+                "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/571d721db4aec847a0e59690b954af33ebf9f023",
-                "reference": "571d721db4aec847a0e59690b954af33ebf9f023",
+                "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/d89cc98761b8cb5a1a235a6b703ae50d34080e65",
+                "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.3 || ^8.0",
+                "php": ">=7.3",
                 "sebastian/recursion-context": "^4.0"
             },
             "require-dev": {
                 "ext-mbstring": "*",
-                "phpunit/phpunit": "^9.2"
+                "phpunit/phpunit": "^9.3"
             },
             "type": "library",
             "extra": {
@@ -1743,7 +1694,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2020-06-26T12:08:55+00:00"
+            "time": "2020-09-28T05:24:23+00:00"
         },
         {
             "name": "sebastian/global-state",
@@ -1801,25 +1752,25 @@
         },
         {
             "name": "sebastian/object-enumerator",
-            "version": "4.0.2",
+            "version": "4.0.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/object-enumerator.git",
-                "reference": "074fed2d0a6d08e1677dd8ce9d32aecb384917b8"
+                "reference": "f6f5957013d84725427d361507e13513702888a4"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/074fed2d0a6d08e1677dd8ce9d32aecb384917b8",
-                "reference": "074fed2d0a6d08e1677dd8ce9d32aecb384917b8",
+                "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f6f5957013d84725427d361507e13513702888a4",
+                "reference": "f6f5957013d84725427d361507e13513702888a4",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.3 || ^8.0",
+                "php": ">=7.3",
                 "sebastian/object-reflector": "^2.0",
                 "sebastian/recursion-context": "^4.0"
             },
             "require-dev": {
-                "phpunit/phpunit": "^9.0"
+                "phpunit/phpunit": "^9.3"
             },
             "type": "library",
             "extra": {
@@ -1850,27 +1801,27 @@
                     "type": "github"
                 }
             ],
-            "time": "2020-06-26T12:11:32+00:00"
+            "time": "2020-09-28T05:55:06+00:00"
         },
         {
             "name": "sebastian/object-reflector",
-            "version": "2.0.2",
+            "version": "2.0.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/object-reflector.git",
-                "reference": "127a46f6b057441b201253526f81d5406d6c7840"
+                "reference": "d9d0ab3b12acb1768bc1e0a89b23c90d2043cbe5"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/127a46f6b057441b201253526f81d5406d6c7840",
-                "reference": "127a46f6b057441b201253526f81d5406d6c7840",
+                "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/d9d0ab3b12acb1768bc1e0a89b23c90d2043cbe5",
+                "reference": "d9d0ab3b12acb1768bc1e0a89b23c90d2043cbe5",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.3 || ^8.0"
+                "php": ">=7.3"
             },
             "require-dev": {
-                "phpunit/phpunit": "^9.0"
+                "phpunit/phpunit": "^9.3"
             },
             "type": "library",
             "extra": {
@@ -1901,27 +1852,27 @@
                     "type": "github"
                 }
             ],
-            "time": "2020-06-26T12:12:55+00:00"
+            "time": "2020-09-28T05:56:16+00:00"
         },
         {
             "name": "sebastian/recursion-context",
-            "version": "4.0.2",
+            "version": "4.0.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/recursion-context.git",
-                "reference": "062231bf61d2b9448c4fa5a7643b5e1829c11d63"
+                "reference": "ed8c9cd355089134bc9cba421b5cfdd58f0eaef7"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/062231bf61d2b9448c4fa5a7643b5e1829c11d63",
-                "reference": "062231bf61d2b9448c4fa5a7643b5e1829c11d63",
+                "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/ed8c9cd355089134bc9cba421b5cfdd58f0eaef7",
+                "reference": "ed8c9cd355089134bc9cba421b5cfdd58f0eaef7",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.3 || ^8.0"
+                "php": ">=7.3"
             },
             "require-dev": {
-                "phpunit/phpunit": "^9.0"
+                "phpunit/phpunit": "^9.3"
             },
             "type": "library",
             "extra": {
@@ -1960,24 +1911,24 @@
                     "type": "github"
                 }
             ],
-            "time": "2020-06-26T12:14:17+00:00"
+            "time": "2020-09-28T05:17:32+00:00"
         },
         {
             "name": "sebastian/resource-operations",
-            "version": "3.0.2",
+            "version": "3.0.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/resource-operations.git",
-                "reference": "0653718a5a629b065e91f774595267f8dc32e213"
+                "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0653718a5a629b065e91f774595267f8dc32e213",
-                "reference": "0653718a5a629b065e91f774595267f8dc32e213",
+                "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
+                "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.3 || ^8.0"
+                "php": ">=7.3"
             },
             "require-dev": {
                 "phpunit/phpunit": "^9.0"
@@ -2011,27 +1962,27 @@
                     "type": "github"
                 }
             ],
-            "time": "2020-06-26T12:16:22+00:00"
+            "time": "2020-09-28T06:45:17+00:00"
         },
         {
             "name": "sebastian/type",
-            "version": "2.2.1",
+            "version": "2.2.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/type.git",
-                "reference": "86991e2b33446cd96e648c18bcdb1e95afb2c05a"
+                "reference": "e494dcaeb89d1458c9ccd8c819745245a1669aea"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/86991e2b33446cd96e648c18bcdb1e95afb2c05a",
-                "reference": "86991e2b33446cd96e648c18bcdb1e95afb2c05a",
+                "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/e494dcaeb89d1458c9ccd8c819745245a1669aea",
+                "reference": "e494dcaeb89d1458c9ccd8c819745245a1669aea",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.3 || ^8.0"
+                "php": ">=7.3"
             },
             "require-dev": {
-                "phpunit/phpunit": "^9.2"
+                "phpunit/phpunit": "^9.3"
             },
             "type": "library",
             "extra": {
@@ -2063,24 +2014,24 @@
                     "type": "github"
                 }
             ],
-            "time": "2020-07-05T08:31:53+00:00"
+            "time": "2020-09-28T06:01:38+00:00"
         },
         {
             "name": "sebastian/version",
-            "version": "3.0.1",
+            "version": "3.0.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/version.git",
-                "reference": "626586115d0ed31cb71483be55beb759b5af5a3c"
+                "reference": "c6c1022351a901512170118436c764e473f6de8c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/626586115d0ed31cb71483be55beb759b5af5a3c",
-                "reference": "626586115d0ed31cb71483be55beb759b5af5a3c",
+                "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c",
+                "reference": "c6c1022351a901512170118436c764e473f6de8c",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.3 || ^8.0"
+                "php": ">=7.3"
             },
             "type": "library",
             "extra": {
@@ -2112,7 +2063,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2020-06-26T12:18:43+00:00"
+            "time": "2020-09-28T06:39:44+00:00"
         },
         {
             "name": "squizlabs/php_codesniffer",
@@ -2241,82 +2192,6 @@
             ],
             "time": "2020-07-14T12:35:20+00:00"
         },
-        {
-            "name": "symfony/service-contracts",
-            "version": "v2.2.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/service-contracts.git",
-                "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d15da7ba4957ffb8f1747218be9e1a121fd298a1",
-                "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=7.2.5",
-                "psr/container": "^1.0"
-            },
-            "suggest": {
-                "symfony/service-implementation": ""
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.2-dev"
-                },
-                "thanks": {
-                    "name": "symfony/contracts",
-                    "url": "https://github.com/symfony/contracts"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Symfony\\Contracts\\Service\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Nicolas Grekas",
-                    "email": "p@tchwork.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "https://symfony.com/contributors"
-                }
-            ],
-            "description": "Generic abstractions related to writing services",
-            "homepage": "https://symfony.com",
-            "keywords": [
-                "abstractions",
-                "contracts",
-                "decoupling",
-                "interfaces",
-                "interoperability",
-                "standards"
-            ],
-            "funding": [
-                {
-                    "url": "https://symfony.com/sponsor",
-                    "type": "custom"
-                },
-                {
-                    "url": "https://github.com/fabpot",
-                    "type": "github"
-                },
-                {
-                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
-                    "type": "tidelift"
-                }
-            ],
-            "time": "2020-09-07T11:33:47+00:00"
-        },
         {
             "name": "theseer/tokenizer",
             "version": "1.2.0",
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php
index 005a264a4..f6a5dcdd2 100644
--- a/lib/AppInfo/Application.php
+++ b/lib/AppInfo/Application.php
@@ -18,19 +18,13 @@ use HTMLPurifier;
 use HTMLPurifier_Config;
 use Favicon\Favicon;
 
-use OC\Encryption\Update;
 use OCA\News\Config\LegacyConfig;
 use OCA\News\Config\FetcherConfig;
-use OCA\News\Db\FolderMapper;
-use OCA\News\Service\FeedService;
-use OCA\News\Service\FolderService;
-use OCA\News\Service\ItemService;
-use OCA\News\Utility\PsrLogger;
+use OCA\News\Hooks\UserDeleteHook;
 
-use OCA\News\Utility\Updater;
-use OCP\IContainer;
-use OCP\IConfig;
-use OCP\ILogger;
+use OCP\AppFramework\Bootstrap\IBootContext;
+use OCP\AppFramework\Bootstrap\IBootstrap;
+use OCP\AppFramework\Bootstrap\IRegistrationContext;
 use OCP\ITempManager;
 use OCP\AppFramework\App;
 use OCP\Files\IRootFolder;
@@ -42,7 +36,8 @@ use OCA\News\Db\ItemMapper;
 use OCA\News\Fetcher\FeedFetcher;
 use OCA\News\Fetcher\Fetcher;
 use OCA\News\Fetcher\YoutubeFetcher;
-use OCA\News\Scraper\Scraper;
+use OCP\User\Events\BeforeUserDeletedEvent;
+use Psr\Container\ContainerInterface;
 use Psr\Log\LoggerInterface;
 
 /**
@@ -50,7 +45,7 @@ use Psr\Log\LoggerInterface;
  *
  * @package OCA\News\AppInfo
  */
-class Application extends App
+class Application extends App implements IBootstrap
 {
 
     /**
@@ -71,64 +66,38 @@ class Application extends App
         'updateInterval'           => 3600,
     ];
 
-    /**
-     * Application constructor.
-     *
-     * @param array $urlParams Parameters
-     */
     public function __construct(array $urlParams = [])
     {
         parent::__construct(self::NAME, $urlParams);
+    }
 
-        $container = $this->getContainer();
+    public function register(IRegistrationContext $context): void
+    {
+        @include_once __DIR__ . '/../../vendor/autoload.php';
 
-        // files
-        $container->registerService('checksums', function () {
-            return file_get_contents(__DIR__ . '/checksum.json');
-        });
-        $container->registerService('info', function () {
-            return file_get_contents(__DIR__ . '/../../appinfo/info.xml');
+        $context->registerService(Fetcher::class, function (ContainerInterface $container): Fetcher {
+            $fetcher = new Fetcher();
+
+            // register fetchers in order, the most generic fetcher should be
+            // the last one
+            $fetcher->registerFetcher($container->get(YoutubeFetcher::class));
+            $fetcher->registerFetcher($container->get(FeedFetcher::class));
+            return $fetcher;
         });
 
+        $context->registerEventListener(BeforeUserDeletedEvent::class, UserDeleteHook::class);
+
         // parameters
-        $container->registerParameter('exploreDir', __DIR__ . '/../Explore/feeds');
-        $container->registerParameter('configFile', 'config.ini');
+        $context->registerParameter('exploreDir', __DIR__ . '/../Explore/feeds');
+        $context->registerParameter('configFile', 'config.ini');
 
         // factories
-        $container->registerService(ItemMapper::class, function (IContainer $c): ItemMapper {
-            return $c->query(MapperFactory::class)->build();
+        $context->registerService(ItemMapper::class, function (ContainerInterface $c): ItemMapper {
+            return $c->get(MapperFactory::class)->build();
         });
 
-        /**
-         * Core
-         */
-        $container->registerService('LoggerParameters', function (IContainer $c): array {
-            return ['app' => $c->query('AppName')];
-        });
-
-        $container->registerService('ConfigView', function (IContainer $c): ?Node {
-            /** @var IRootFolder $fs */
-            $fs = $c->query(IRootFolder::class);
-            $path = 'news/config';
-            if ($fs->nodeExists($path)) {
-                return $fs->get($path);
-            } else {
-                return null;
-            }
-        });
-
-        $container->registerService(LegacyConfig::class, function (IContainer $c): LegacyConfig {
-            $config = new LegacyConfig(
-                $c->query('ConfigView'),
-                $c->query(LoggerInterface::class),
-                $c->query('LoggerParameters')
-            );
-            $config->read($c->query('configFile'), false);
-            return $config;
-        });
-
-        $container->registerService(HTMLPurifier::class, function (IContainer $c): HTMLPurifier {
-            $directory = $c->query(IConfig::class)->getSystemValue('datadirectory') . '/news/cache/purifier';
+        $context->registerService(HTMLPurifier::class, function (ContainerInterface $c): HTMLPurifier {
+            $directory = $c->get(ITempManager::class)->getTempBaseDir() . '/news/cache/purifier';
 
             if (!is_dir($directory)) {
                 mkdir($directory, 0770, true);
@@ -164,47 +133,42 @@ class Application extends App
             return new HTMLPurifier($config);
         });
 
-        /**
-         * Fetchers
-         */
-        $container->registerService(FetcherConfig::class, function (IContainer $c): FetcherConfig {
-            $fConfig = new FetcherConfig();
-            $fConfig->setConfig($c->query(IConfig::class))
-                    ->setProxy($c->query(IConfig::class));
-
-            return $fConfig;
+        $context->registerService(FeedIo::class, function (ContainerInterface $c): FeedIo {
+            $config = $c->get(FetcherConfig::class);
+            return new FeedIo($config->getClient(), $c->get(LoggerInterface::class));
         });
 
-        $container->registerService(FeedIo::class, function (IContainer $c): FeedIo {
-            $config = $c->query(FetcherConfig::class);
-            return new FeedIo($config->getClient(), $c->query(LoggerInterface::class));
-        });
-
-        $container->registerService(Favicon::class, function (IContainer $c): Favicon {
+        $context->registerService(Favicon::class, function (ContainerInterface $c): Favicon {
             $favicon = new Favicon();
-            $tempManager = $c->query(ITempManager::class);
-            $settings = ['dir' => $tempManager->getTempBaseDir()];
-            $favicon->cache($settings);
+            $favicon->cache(['dir' => $c->get(ITempManager::class)->getTempBaseDir()]);
             return $favicon;
         });
 
-        $container->registerService(Fetcher::class, function (IContainer $c): Fetcher {
-            $fetcher = new Fetcher();
-
-            // register fetchers in order, the most generic fetcher should be
-            // the last one
-            $fetcher->registerFetcher($c->query(YoutubeFetcher::class));
-            $fetcher->registerFetcher($c->query(FeedFetcher::class));
-            return $fetcher;
+        //TODO: Remove code after 15.1
+        $context->registerService('ConfigView', function (ContainerInterface $c): ?Node {
+            /** @var IRootFolder $fs */
+            $fs = $c->get(IRootFolder::class);
+            $path = 'news/config';
+            if ($fs->nodeExists($path)) {
+                return $fs->get($path);
+            } else {
+                return null;
+            }
         });
 
-        /**
-         * Scrapers
-         */
-        $container->registerService(Scraper::class, function (IContainer $c): Scraper {
-            return new Scraper(
-                $c->query(LoggerInterface::class)
+        //TODO: Remove code after 15.1
+        $context->registerService(LegacyConfig::class, function (ContainerInterface $c): LegacyConfig {
+            $config = new LegacyConfig(
+                $c->get('ConfigView'),
+                $c->get(LoggerInterface::class)
             );
+            $config->read($c->get('configFile'), false);
+            return $config;
         });
     }
+
+    public function boot(IBootContext $context): void
+    {
+        //NO-OP
+    }
 }
diff --git a/lib/Config/DependencyException.php b/lib/Config/DependencyException.php
deleted file mode 100644
index 6f9d21be6..000000000
--- a/lib/Config/DependencyException.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-/**
- * Nextcloud - News
- *
- * This file is licensed under the Affero General Public License version 3 or
- * later. See the COPYING file.
- *
- * @author    Alessandro Cosentino <cosenal@gmail.com>
- * @author    Bernhard Posselt <dev@bernhard-posselt.com>
- * @copyright 2012 Alessandro Cosentino
- * @copyright 2012-2014 Bernhard Posselt
- */
-
-namespace OCA\News\Config;
-
-class DependencyException extends \Exception
-{
-
-
-    /**
-     * Constructor
-     *
-     * @param string $msg the error message
-     */
-    public function __construct($msg)
-    {
-        parent::__construct($msg);
-    }
-}
diff --git a/lib/Config/FetcherConfig.php b/lib/Config/FetcherConfig.php
index 1e9b7941e..4966f5b40 100644
--- a/lib/Config/FetcherConfig.php
+++ b/lib/Config/FetcherConfig.php
@@ -59,24 +59,48 @@ class FetcherConfig
                            'application/atom+xml;q=0.6, application/xml;q=0.4, ' .
                            'text/xml;q=0.4, */*;q=0.2';
 
+    /**
+     * FetcherConfig constructor.
+     *
+     * @param IConfig $config
+     */
+    public function __construct(IConfig $config)
+    {
+        $this->client_timeout = $config->getAppValue(
+            Application::NAME,
+            'feedFetcherTimeout',
+            Application::DEFAULT_SETTINGS['feedFetcherTimeout']
+        );
+        $this->redirects = $config->getAppValue(
+            Application::NAME,
+            'maxRedirects',
+            Application::DEFAULT_SETTINGS['maxRedirects']
+        );
+
+        $proxy = $config->getSystemValue('proxy', null);
+        if (is_null($proxy)) {
+            return $this;
+        }
+
+        $url = new \Net_URL2($proxy);
+
+        $creds = $config->getSystemValue('proxyuserpwd', null);
+        if ($creds) {
+            $auth = explode(':', $creds, 2);
+            $url->setUserinfo($auth[0], $auth[1]);
+        }
+
+        $this->proxy = $url->getNormalizedURL();
+
+        return $this;
+    }
+
     /**
      * Configure a guzzle client
      *
      * @return ClientInterface Legacy client to guzzle.
      */
     public function getClient()
-    {
-        if (!class_exists('GuzzleHttp\Collection')) {
-            return new FeedIoClient($this->getConfig());
-        }
-
-        return new LegacyGuzzleClient($this->getOldConfig());
-    }
-    /**
-     * Get configuration for modern guzzle.
-     * @return Client Guzzle client.
-     */
-    private function getConfig()
     {
         $config = [
             'timeout' => $this->client_timeout,
@@ -90,81 +114,7 @@ class FetcherConfig
             $config['redirect.max'] = $this->redirects;
         }
 
-        return new Client($config);
-    }
-
-    /**
-     * Get configuration for old guzzle.
-     * @return Client Guzzle client.
-     */
-    private function getOldConfig()
-    {
-        $config = [
-            'request.options' => [
-                'timeout' => $this->client_timeout,
-                'headers' =>  ['User-Agent' => static::DEFAULT_USER_AGENT],
-            ],
-        ];
-
-        if (!empty($this->proxy)) {
-            $config['request.options']['proxy'] = $this->proxy;
-        }
-
-        if (!empty($this->redirects)) {
-            $config['request.options']['redirect.max'] = $this->redirects;
-        }
-
-        return new Client($config);
-    }
-
-    /**
-     * Set settings for config.
-     *
-     * @param IConfig $config The shared configuration
-     *
-     * @return self
-     */
-    public function setConfig(IConfig $config)
-    {
-        $this->client_timeout = $config->getAppValue(
-            Application::NAME,
-            'feedFetcherTimeout',
-            Application::DEFAULT_SETTINGS['feedFetcherTimeout']
-        );
-        $this->redirects = $config->getAppValue(
-            Application::NAME,
-            'maxRedirects',
-            Application::DEFAULT_SETTINGS['maxRedirects']
-        );
-
-        return $this;
-    }
-
-    /**
-     * Set the proxy
-     *
-     * @param IConfig $config Nextcloud config.
-     *
-     * @return self
-     */
-    public function setProxy(IConfig $config)
-    {
-        $proxy = $config->getSystemValue('proxy', null);
-        $creds = $config->getSystemValue('proxyuserpwd', null);
-
-        if (is_null($proxy)) {
-            return $this;
-        }
-
-        $url = new \Net_URL2($proxy);
-
-        if ($creds) {
-            $auth = explode(':', $creds, 2);
-            $url->setUserinfo($auth[0], $auth[1]);
-        }
-
-        $this->proxy = $url->getNormalizedURL();
-
-        return $this;
+        $client = new Client($config);
+        return new FeedIoClient($client);
     }
 }
diff --git a/lib/Config/LegacyConfig.php b/lib/Config/LegacyConfig.php
index 71e19acfa..370638843 100644
--- a/lib/Config/LegacyConfig.php
+++ b/lib/Config/LegacyConfig.php
@@ -39,8 +39,7 @@ class LegacyConfig
 
     public function __construct(
         ?Folder $fileSystem,
-        LoggerInterface $logger,
-        $LoggerParameters
+        LoggerInterface $logger
     ) {
         $this->fileSystem = $fileSystem;
         $this->autoPurgeMinimumInterval = 60;
@@ -51,7 +50,7 @@ class LegacyConfig
         $this->useCronUpdates = true;
         $this->logger = $logger;
         $this->exploreUrl = '';
-        $this->loggerParams = $LoggerParameters;
+        $this->loggerParams = ['app' => Application::NAME];
         $this->updateInterval = 3600;
     }
 
diff --git a/lib/Controller/FeedApiController.php b/lib/Controller/FeedApiController.php
index f2b77c72b..c0b4f1a56 100644
--- a/lib/Controller/FeedApiController.php
+++ b/lib/Controller/FeedApiController.php
@@ -29,7 +29,7 @@ use Psr\Log\LoggerInterface;
 
 class FeedApiController extends ApiController
 {
-    use JSONHttpError;
+    use JSONHttpErrorTrait;
 
     /**
      * @var ItemService
diff --git a/lib/Controller/FeedController.php b/lib/Controller/FeedController.php
index 40aef909a..d0c25d55b 100644
--- a/lib/Controller/FeedController.php
+++ b/lib/Controller/FeedController.php
@@ -27,7 +27,7 @@ use OCA\News\Db\FeedType;
 
 class FeedController extends Controller
 {
-    use JSONHttpError;
+    use JSONHttpErrorTrait;
 
     private $feedService;
     private $folderService;
diff --git a/lib/Controller/FolderApiController.php b/lib/Controller/FolderApiController.php
index 3bafd81a0..ff61f3300 100644
--- a/lib/Controller/FolderApiController.php
+++ b/lib/Controller/FolderApiController.php
@@ -27,7 +27,7 @@ use \OCA\News\Service\Exceptions\ServiceValidationException;
 
 class FolderApiController extends ApiController
 {
-    use JSONHttpError;
+    use JSONHttpErrorTrait;
 
     private $folderService;
     private $itemService;
diff --git a/lib/Controller/FolderController.php b/lib/Controller/FolderController.php
index 22baf8db6..38c580ff0 100644
--- a/lib/Controller/FolderController.php
+++ b/lib/Controller/FolderController.php
@@ -26,7 +26,7 @@ use \OCA\News\Service\Exceptions\ServiceValidationException;
 
 class FolderController extends Controller
 {
-    use JSONHttpError;
+    use JSONHttpErrorTrait;
 
     private $folderService;
     private $feedService;
diff --git a/lib/Controller/ItemApiController.php b/lib/Controller/ItemApiController.php
index d5b1de680..dac2b0a5f 100644
--- a/lib/Controller/ItemApiController.php
+++ b/lib/Controller/ItemApiController.php
@@ -24,7 +24,7 @@ use \OCA\News\Service\Exceptions\ServiceNotFoundException;
 
 class ItemApiController extends ApiController
 {
-    use JSONHttpError;
+    use JSONHttpErrorTrait;
 
     private $itemService;
     private $serializer;
diff --git a/lib/Controller/ItemController.php b/lib/Controller/ItemController.php
index 658e92883..95a13ee21 100644
--- a/lib/Controller/ItemController.php
+++ b/lib/Controller/ItemController.php
@@ -25,7 +25,7 @@ use \OCA\News\Service\FeedService;
 
 class ItemController extends Controller
 {
-    use JSONHttpError;
+    use JSONHttpErrorTrait;
 
     private $itemService;
     private $feedService;
diff --git a/lib/Controller/JSONHttpError.php b/lib/Controller/JSONHttpErrorTrait.php
similarity index 96%
rename from lib/Controller/JSONHttpError.php
rename to lib/Controller/JSONHttpErrorTrait.php
index 6a66f9c29..785f3f02a 100644
--- a/lib/Controller/JSONHttpError.php
+++ b/lib/Controller/JSONHttpErrorTrait.php
@@ -13,10 +13,8 @@ namespace OCA\News\Controller;
 
 use \OCP\AppFramework\Http\JSONResponse;
 
-trait JSONHttpError
+trait JSONHttpErrorTrait
 {
-
-
     /**
      * @param \Exception $exception The exception to report
      * @param int        $code      The http error code
diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php
index d88f8181d..ffcf2e62d 100644
--- a/lib/Controller/PageController.php
+++ b/lib/Controller/PageController.php
@@ -31,7 +31,7 @@ use OCA\News\Db\FeedType;
 
 class PageController extends Controller
 {
-    use JSONHttpError;
+    use JSONHttpErrorTrait;
 
     /**
      * @var IConfig
diff --git a/lib/Explore/RecommendedSites.php b/lib/Explore/RecommendedSites.php
index 504d63497..38fa510da 100644
--- a/lib/Explore/RecommendedSites.php
+++ b/lib/Explore/RecommendedSites.php
@@ -22,13 +22,20 @@ class RecommendedSites
      * @param string $exploreDir the absolute path to where the recommendation
      *                           config files lie without a trailing slash
      */
-    public function __construct($exploreDir)
+    public function __construct(string $exploreDir)
     {
         $this->directory = $exploreDir;
     }
 
 
-    public function forLanguage($languageCode)
+    /**
+     * @param string $languageCode
+     *
+     * @return array
+     *
+     * @throws RecommendedSiteNotFoundException
+     */
+    public function forLanguage(string $languageCode)
     {
         $file = $this->directory . '/feeds.' . $languageCode . '.json';
 
diff --git a/lib/Fetcher/Client/LegacyGuzzleClient.php b/lib/Fetcher/Client/LegacyGuzzleClient.php
deleted file mode 100644
index 59bbc9dc4..000000000
--- a/lib/Fetcher/Client/LegacyGuzzleClient.php
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-/**
- * Nextcloud - News
- *
- * This file is licensed under the Affero General Public License version 3 or
- * later. See the COPYING file.
- *
- * @author    Sean Molenaar <smillernl@me.com>
- * @copyright 2018 Sean Molenaar
- */
-
-namespace OCA\News\Fetcher\Client;
-
-use FeedIo\Adapter\ClientInterface as FeedIoClientInterface;
-use FeedIo\Adapter\ResponseInterface;
-use FeedIo\Adapter\NotFoundException;
-use FeedIo\Adapter\ServerErrorException;
-use Guzzle\Service\ClientInterface;
-use GuzzleHttp\Exception\BadResponseException;
-
-/**
- * Guzzle dependent HTTP client
- */
-class LegacyGuzzleClient implements FeedIoClientInterface
-{
-    /**
-     * @var ClientInterface
-     */
-    protected $guzzleClient;
-
-    /**
-     * @param ClientInterface $guzzleClient
-     */
-    public function __construct(ClientInterface $guzzleClient)
-    {
-        $this->guzzleClient = $guzzleClient;
-    }
-
-    /**
-     * @param  string                               $url
-     * @param  \DateTime                            $modifiedSince
-     * @throws \FeedIo\Adapter\NotFoundException
-     * @throws \FeedIo\Adapter\ServerErrorException
-     * @return \FeedIo\Adapter\ResponseInterface
-     */
-    public function getResponse(string $url, \DateTime $modifiedSince) : ResponseInterface
-    {
-        $modifiedSince->setTimezone(new \DateTimeZone('GMT'));
-        try {
-            $options = [
-                'headers' => [
-                    'If-Modified-Since' => $modifiedSince->format('D, d M Y H:i:s e')
-                ]
-            ];
-
-            return new LegacyGuzzleResponse($this->guzzleClient->get($url, $options));
-        } catch (BadResponseException $e) {
-            switch ((int) $e->getResponse()->getStatusCode()) {
-                case 404:
-                    throw new NotFoundException($e->getMessage());
-                default:
-                    throw new ServerErrorException($e->getMessage());
-            }
-        }
-    }
-}
diff --git a/lib/Fetcher/Client/LegacyGuzzleResponse.php b/lib/Fetcher/Client/LegacyGuzzleResponse.php
deleted file mode 100644
index f8d6d7601..000000000
--- a/lib/Fetcher/Client/LegacyGuzzleResponse.php
+++ /dev/null
@@ -1,86 +0,0 @@
-<?php
-/**
- * Nextcloud - News
- *
- * This file is licensed under the Affero General Public License version 3 or
- * later. See the COPYING file.
- *
- * @author    Sean Molenaar <smillernl@me.com>
- * @copyright 2018 Sean Molenaar
- */
-
-namespace OCA\News\Fetcher\Client;
-
-use FeedIo\Adapter\ResponseInterface;
-use GuzzleHttp\Message\ResponseInterface as GuzzleResponseInterface;
-
-/**
- * Guzzle dependent HTTP Response
- */
-class LegacyGuzzleResponse implements ResponseInterface
-{
-    const HTTP_LAST_MODIFIED = 'Last-Modified';
-
-    /**
-     * @var \GuzzleHttp\Message\ResponseInterface
-     */
-    protected $response;
-
-    /**
-     * @param \GuzzleHttp\Message\ResponseInterface
-     */
-    public function __construct(GuzzleResponseInterface $psrResponse)
-    {
-        $this->response = $psrResponse;
-    }
-
-    /**
-     * @return boolean
-     */
-    public function isModified() : bool
-    {
-        return $this->response->getStatusCode() !== 304 && $this->response->getBody()->getSize() > 0;
-    }
-
-    /**
-     * @return \Psr\Http\Message\StreamInterface
-     */
-    public function getBody() : ? string
-    {
-        return $this->response->getBody();
-    }
-
-    /**
-     * @return \DateTime|null
-     */
-    public function getLastModified() : ?\DateTime
-    {
-        if ($this->response->hasHeader(static::HTTP_LAST_MODIFIED)) {
-            $lastModified = \DateTime::createFromFormat(
-                'D, d M Y H:i:s e',
-                $this->getHeader(static::HTTP_LAST_MODIFIED)
-            );
-
-            return false === $lastModified ? null : $lastModified;
-        }
-
-        return null;
-    }
-
-    /**
-     * @return array
-     */
-    public function getHeaders() : iterable
-    {
-        return $this->response->getHeaders();
-    }
-
-    /**
-     * @param  string       $name
-     * @return string[]
-     */
-    public function getHeader(string $name) : iterable
-    {
-        return current($this->response->getHeader($name));
-    }
-}
diff --git a/lib/Fetcher/FeedFetcher.php b/lib/Fetcher/FeedFetcher.php
index 4e93424ba..5a84e2170 100755
--- a/lib/Fetcher/FeedFetcher.php
+++ b/lib/Fetcher/FeedFetcher.php
@@ -75,8 +75,14 @@ class FeedFetcher implements IFeedFetcher
      *
      * @inheritdoc
      */
-    public function fetch(string $url, bool $favicon, $lastModified, bool $fullTextEnabled, $user, $password): array
-    {
+    public function fetch(
+        string $url,
+        bool $favicon,
+        ?string $lastModified,
+        bool $fullTextEnabled,
+        ?string $user,
+        ?string $password
+    ): array {
         $url2 = new Net_URL2($url);
         if (!empty($user) && !empty(trim($user))) {
             $url2->setUserinfo(urlencode($user), urlencode($password));
@@ -148,7 +154,7 @@ class FeedFetcher implements IFeedFetcher
      *
      * @return string
      */
-    private function decodeTwice($string): string
+    private function decodeTwice(string $string): string
     {
         return html_entity_decode(
             html_entity_decode(
@@ -195,12 +201,12 @@ class FeedFetcher implements IFeedFetcher
      * Build an item based on a feed.
      *
      * @param ItemInterface $parsedItem The item to use
-     * @param string        $body       Text of the item, if not provided use description from $parsedItem
+     * @param string|null   $body       Text of the item, if not provided use description from $parsedItem
      * @param bool          $RTL        True if the feed is RTL (Right-to-left)
      *
      * @return Item
      */
-    protected function buildItem(ItemInterface $parsedItem, string $body = null, bool $RTL = false): Item
+    protected function buildItem(ItemInterface $parsedItem, ?string $body = null, bool $RTL = false): Item
     {
         $item = new Item();
         $item->setUnread(true);
@@ -208,18 +214,18 @@ class FeedFetcher implements IFeedFetcher
         $item->setGuid($parsedItem->getPublicId());
         $item->setGuidHash(md5($item->getGuid()));
 
-        $lastmodified = $parsedItem->getLastModified() ?? new DateTime();
+        $lastModified = $parsedItem->getLastModified() ?? new DateTime();
         if ($parsedItem->getValue('pubDate') !== null) {
             $pubDT = new DateTime($parsedItem->getValue('pubDate'));
         } elseif ($parsedItem->getValue('published') !== null) {
             $pubDT = new DateTime($parsedItem->getValue('published'));
         } else {
-            $pubDT = $lastmodified;
+            $pubDT = $lastModified;
         }
 
         $item->setPubDate($pubDT->getTimestamp());
 
-        $item->setLastModified($lastmodified->getTimestamp());
+        $item->setLastModified($lastModified->getTimestamp());
         $item->setRtl($RTL);
 
         // unescape content because angularjs helps against XSS
diff --git a/lib/Fetcher/Fetcher.php b/lib/Fetcher/Fetcher.php
index f52141dda..955875084 100644
--- a/lib/Fetcher/Fetcher.php
+++ b/lib/Fetcher/Fetcher.php
@@ -43,25 +43,25 @@ class Fetcher
     /**
      * Fetch a feed from remote
      *
-     * @param  string  $url               remote url of the feed
-     * @param  boolean $getFavicon        if the favicon should also be fetched, defaults to true
-     * @param  string  $lastModified      a last modified value from an http header defaults to false.
+     * @param  string      $url               remote url of the feed
+     * @param  boolean     $getFavicon        if the favicon should also be fetched, defaults to true
+     * @param  string|null $lastModified      a last modified value from an http header defaults to false.
      *                                    If lastModified matches the http header from the feed no results are fetched
-     * @param  bool    $fullTextEnabled   If true use a scraper to download the full article
-     * @param  string  $user              if given, basic auth is set for this feed
-     * @param  string  $password          if given, basic auth is set for this feed. Ignored if user is empty
+     * @param  bool        $fullTextEnabled   If true use a scraper to download the full article
+     * @param  string|null $user              if given, basic auth is set for this feed
+     * @param  string|null $password          if given, basic auth is set for this feed. Ignored if user is empty
      *
      * @throws ReadErrorException if FeedIO fails
      * @return array an array containing the new feed and its items, first
      * element being the Feed and second element being an array of Items
      */
     public function fetch(
-        $url,
-        $getFavicon = true,
-        $lastModified = null,
-        $fullTextEnabled = false,
-        $user = null,
-        $password = null
+        string $url,
+        bool $getFavicon = true,
+        ?string $lastModified = null,
+        bool $fullTextEnabled = false,
+        ?string $user = null,
+        ?string $password = null
     ) {
         foreach ($this->fetchers as $fetcher) {
             if (!$fetcher->canHandle($url)) {
diff --git a/lib/Fetcher/IFeedFetcher.php b/lib/Fetcher/IFeedFetcher.php
index ce44ec104..aaba9de67 100644
--- a/lib/Fetcher/IFeedFetcher.php
+++ b/lib/Fetcher/IFeedFetcher.php
@@ -31,9 +31,17 @@ interface IFeedFetcher
      *
      * @return array an array containing the new feed and its items, first
      * element being the Feed and second element being an array of Items
+     *
      * @throws ReadErrorException if the Feed-IO fetcher encounters a problem
      */
-    public function fetch(string $url, bool $favicon, $lastModified, bool $fullTextEnabled, $user, $password): array;
+    public function fetch(
+        string $url,
+        bool $favicon,
+        ?string $lastModified,
+        bool $fullTextEnabled,
+        ?string $user,
+        ?string $password
+    ): array;
 
     /**
      * Can a fetcher handle a feed.
diff --git a/lib/Fetcher/YoutubeFetcher.php b/lib/Fetcher/YoutubeFetcher.php
index 85aad5d59..67a4d5afa 100644
--- a/lib/Fetcher/YoutubeFetcher.php
+++ b/lib/Fetcher/YoutubeFetcher.php
@@ -22,7 +22,14 @@ class YoutubeFetcher implements IFeedFetcher
     }
 
 
-    private function buildUrl($url)
+    /**
+     * Build YouTube URL
+     *
+     * @param string $url
+     *
+     * @return string
+     */
+    private function buildUrl(string $url)
     {
         $baseRegex = '%(?:https?://|//)?(?:www.)?youtube.com';
         $playRegex = $baseRegex . '.*?list=([^&]*)%';
@@ -54,8 +61,14 @@ class YoutubeFetcher implements IFeedFetcher
      *
      * @inheritdoc
      */
-    public function fetch(string $url, bool $favicon, $lastModified, bool $fullTextEnabled, $user, $password): array
-    {
+    public function fetch(
+        string $url,
+        bool $favicon,
+        ?string $lastModified,
+        bool $fullTextEnabled,
+        ?string $user,
+        ?string $password
+    ): array {
         $transformedUrl = $this->buildUrl($url);
 
         $result = $this->feedFetcher->fetch(
diff --git a/lib/Hooks/User.php b/lib/Hooks/UserDeleteHook.php
similarity index 53%
rename from lib/Hooks/User.php
rename to lib/Hooks/UserDeleteHook.php
index 1a494c5f2..491f84fcb 100644
--- a/lib/Hooks/User.php
+++ b/lib/Hooks/UserDeleteHook.php
@@ -17,20 +17,28 @@ use OCA\News\AppInfo\Application;
 use OCA\News\Service\ItemService;
 use OCA\News\Service\FeedService;
 use OCA\News\Service\FolderService;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use OCP\User\Events\BeforeUserDeletedEvent;
 
-class User
+class UserDeleteHook implements IEventListener
 {
 
-    public static function deleteUser($params)
+    /**
+     * Handle user deletion
+     *
+     * @param BeforeUserDeletedEvent $event
+     */
+    public function handle(Event $event): void
     {
-        $userId = $params['uid'];
+        $userId = $event->getUser()->getUID();
 
         $app = new Application();
         $container = $app->getContainer();
 
         // order is important!
-        $container->query(ItemService::class)->deleteUser($userId);
-        $container->query(FeedService::class)->deleteUser($userId);
-        $container->query(FolderService::class)->deleteUser($userId);
+        $container->get(ItemService::class)->deleteUser($userId);
+        $container->get(FeedService::class)->deleteUser($userId);
+        $container->get(FolderService::class)->deleteUser($userId);
     }
 }
diff --git a/lib/Migration/MigrateConfig.php b/lib/Migration/MigrateConfig.php
index b25fb8e75..e07760d64 100644
--- a/lib/Migration/MigrateConfig.php
+++ b/lib/Migration/MigrateConfig.php
@@ -52,7 +52,14 @@ class MigrateConfig implements IRepairStep
             return;
         }
 
+        $app_keys = $this->iConfig->getAppKeys(Application::NAME);
         foreach ($this->config as $key => $value) {
+            if (!isset(Application::DEFAULT_SETTINGS[$key])) {
+                continue;
+            }
+            if (in_array($key, $app_keys)) {
+                continue;
+            }
             $this->iConfig->setAppValue(Application::NAME, $key, $value);
         }
     }
diff --git a/phpunit.xml b/phpunit.xml
index 768e083b5..08a34a72f 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -8,14 +8,9 @@
         <whitelist processUncoveredFilesFromWhitelist="true">
             <directory suffix=".php">./lib/</directory>
             <exclude>
-                <file>./lib/Config/DependencyException.php</file>
-                <file>./lib/Explore/feeds/RecommendedSiteNotFoundException.php</file>
-                <file>./lib/Explore/feeds/RecommendedSiteNotFoundException.php</file>
-                <file>./lib/Fetcher/FetcherException.php</file>
-                <file>./lib/Service/ServiceConflictException.php</file>
-                <file>./lib/Service/ServiceException.php</file>
-                <file>./lib/Service/ServiceNotFoundException.php</file>
-                <file>./lib/Service/ServiceValidationException.php</file>
+                <file>./lib/AppInfo/Application.php</file>
+                <file>./lib/Controller/JSONHttpErrorTrait.php</file>
+                <file>./lib/**Exception.php</file>
             </exclude>
         </whitelist>
     </filter>
diff --git a/tests/Integration/IntegrationTest.php b/tests/Integration/IntegrationTest.php
index 276c6c394..1135bbd2e 100644
--- a/tests/Integration/IntegrationTest.php
+++ b/tests/Integration/IntegrationTest.php
@@ -30,6 +30,7 @@ use OCA\News\Tests\Integration\Fixtures\FolderFixture;
 use OCA\News\Db\FeedMapper;
 use OCA\News\Db\ItemMapper;
 use OCA\News\Db\FolderMapper;
+use Psr\Container\ContainerInterface;
 
 
 abstract class IntegrationTest extends \Test\TestCase
@@ -67,9 +68,9 @@ abstract class IntegrationTest extends \Test\TestCase
         $this->setupUser($this->user, $this->userPassword);
 
         // set up database layers
-        $this->itemMapper = $this->container->query(ItemMapper::class);
-        $this->feedMapper = $this->container->query(FeedMapper::class);
-        $this->folderMapper = $this->container->query(FolderMapper::class);
+        $this->itemMapper = $this->container->get(ItemMapper::class);
+        $this->feedMapper = $this->container->get(FeedMapper::class);
+        $this->folderMapper = $this->container->get(FolderMapper::class);
     }
 
     protected function findItemByTitle($title)
diff --git a/tests/Unit/Controller/JSONHttpErrorTest.php b/tests/Unit/Controller/JSONHttpErrorTest.php
index c02b60c9e..3b48bc36e 100644
--- a/tests/Unit/Controller/JSONHttpErrorTest.php
+++ b/tests/Unit/Controller/JSONHttpErrorTest.php
@@ -13,13 +13,13 @@
 
 namespace OCA\News\Tests\Unit\Controller;
 
-use OCA\News\Controller\JSONHttpError;
+use OCA\News\Controller\JSONHttpErrorTrait;
 
 use PHPUnit\Framework\TestCase;
 
 class Test
 {
-    use JSONHttpError;
+    use JSONHttpErrorTrait;
 }
 
 class JSONHttpErrorTest extends TestCase